From 9f72595ae01777e37839afef2f6bc211713b9864 Mon Sep 17 00:00:00 2001
From: MobiusDevelopment <8391001+MobiusDevelopment@users.noreply.github.com>
Date: Fri, 22 Mar 2019 23:34:26 +0000
Subject: [PATCH] Fishing rework based on L2jUnity free files. Contributed by
facab.
---
.../dist/game/config/Custom/PremiumSystem.ini | 4 +
.../dist/game/data/Fishing.xml | 46 +-
.../dist/game/data/xsd/Fishing.xsd | 28 +-
.../java/com/l2jmobius/Config.java | 12 +-
.../gameserver/data/xml/impl/FishingData.java | 80 +-
.../model/actor/instance/L2PcInstance.java | 2 +-
.../model/{ => fishing}/Fishing.java | 914 +++++++++---------
.../gameserver/model/fishing/FishingBait.java | 226 +++--
.../model/fishing/FishingCatch.java | 49 +
.../gameserver/model/fishing/FishingRod.java | 56 ++
.../model/zone/type/L2FishingZone.java | 2 +-
.../serverpackets/fishing/ExFishingStart.java | 7 +-
.../dist/game/config/Custom/PremiumSystem.ini | 4 +
.../dist/game/data/Fishing.xml | 58 +-
.../dist/game/data/xsd/Fishing.xsd | 28 +-
.../java/com/l2jmobius/Config.java | 12 +-
.../gameserver/data/xml/impl/FishingData.java | 80 +-
.../model/actor/instance/L2PcInstance.java | 2 +-
.../model/{ => fishing}/Fishing.java | 914 +++++++++---------
.../gameserver/model/fishing/FishingBait.java | 226 +++--
.../model/fishing/FishingCatch.java | 49 +
.../gameserver/model/fishing/FishingRod.java | 56 ++
.../model/zone/type/L2FishingZone.java | 2 +-
.../serverpackets/fishing/ExFishingStart.java | 7 +-
.../dist/game/config/Custom/PremiumSystem.ini | 4 +
.../dist/game/data/Fishing.xml | 67 +-
.../dist/game/data/html/default/34156-1.htm | 7 +
.../dist/game/data/html/default/34156.htm | 11 +
.../dist/game/data/html/fisherman/31563.htm | 21 +-
.../dist/game/data/html/fisherman/31567.htm | 21 +-
.../dist/game/data/html/fisherman/31568.htm | 21 +-
.../dist/game/data/html/fisherman/31570.htm | 22 +-
.../dist/game/data/html/fisherman/31571.htm | 21 +-
.../dist/game/data/html/fisherman/31572.htm | 21 +-
.../dist/game/data/html/fisherman/31573.htm | 21 +-
.../dist/game/data/html/fisherman/31574.htm | 20 +-
.../dist/game/data/html/fisherman/31575.htm | 21 +-
.../dist/game/data/html/fisherman/31576.htm | 22 +-
.../dist/game/data/html/fisherman/31577.htm | 21 +-
.../dist/game/data/html/fisherman/31578.htm | 21 +-
.../dist/game/data/html/fisherman/31579.htm | 21 +-
.../dist/game/data/html/fisherman/31696.htm | 21 +-
.../dist/game/data/html/fisherman/31697.htm | 21 +-
.../dist/game/data/html/fisherman/31989.htm | 21 +-
.../dist/game/data/html/fisherman/32007.htm | 21 +-
.../fisherman/fish_appearance_exchange.htm | 11 +
.../data/html/fisherman/fishing_manual001.htm | 8 +-
.../data/html/fisherman/fishing_manual002.htm | 3 +-
.../data/html/fisherman/fishing_manual003.htm | 6 +-
.../data/html/fisherman/fishing_manual004.htm | 10 +-
.../data/html/fisherman/fishing_manual008.htm | 3 +-
.../data/html/fisherman/fishing_manual009.htm | 10 +-
.../data/html/fisherman/fishing_manual010.htm | 40 +-
.../dist/game/data/multisell/2144.xml | 39 +
.../dist/game/data/multisell/2194.xml | 70 ++
.../dist/game/data/multisell/2195.xml | 138 +++
.../dist/game/data/multisell/2203.xml | 62 ++
.../dist/game/data/multisell/2207.xml | 62 ++
.../dist/game/data/multisell/2208.xml | 94 ++
.../dist/game/data/multisell/3034.xml | 22 +
.../dist/game/data/spawns/Innadril/Heine.xml | 3 +-
.../dist/game/data/xsd/Fishing.xsd | 28 +-
.../java/com/l2jmobius/Config.java | 12 +-
.../gameserver/data/xml/impl/FishingData.java | 80 +-
.../model/actor/instance/L2PcInstance.java | 2 +-
.../model/{ => fishing}/Fishing.java | 914 +++++++++---------
.../gameserver/model/fishing/FishingBait.java | 226 +++--
.../model/fishing/FishingCatch.java | 49 +
.../gameserver/model/fishing/FishingRod.java | 56 ++
.../model/zone/type/L2FishingZone.java | 2 +-
.../serverpackets/fishing/ExFishingStart.java | 7 +-
.../dist/game/config/Custom/PremiumSystem.ini | 4 +
.../dist/game/data/Fishing.xml | 67 +-
.../dist/game/data/html/default/34156-1.htm | 7 +
.../dist/game/data/html/default/34156.htm | 11 +
.../dist/game/data/html/fisherman/31563.htm | 21 +-
.../dist/game/data/html/fisherman/31567.htm | 21 +-
.../dist/game/data/html/fisherman/31568.htm | 21 +-
.../dist/game/data/html/fisherman/31570.htm | 22 +-
.../dist/game/data/html/fisherman/31571.htm | 21 +-
.../dist/game/data/html/fisherman/31572.htm | 21 +-
.../dist/game/data/html/fisherman/31573.htm | 21 +-
.../dist/game/data/html/fisherman/31574.htm | 20 +-
.../dist/game/data/html/fisherman/31575.htm | 21 +-
.../dist/game/data/html/fisherman/31576.htm | 22 +-
.../dist/game/data/html/fisherman/31577.htm | 21 +-
.../dist/game/data/html/fisherman/31578.htm | 21 +-
.../dist/game/data/html/fisherman/31579.htm | 21 +-
.../dist/game/data/html/fisherman/31696.htm | 21 +-
.../dist/game/data/html/fisherman/31697.htm | 21 +-
.../dist/game/data/html/fisherman/31989.htm | 21 +-
.../dist/game/data/html/fisherman/32007.htm | 21 +-
.../fisherman/fish_appearance_exchange.htm | 11 +
.../data/html/fisherman/fishing_manual001.htm | 8 +-
.../data/html/fisherman/fishing_manual002.htm | 3 +-
.../data/html/fisherman/fishing_manual003.htm | 6 +-
.../data/html/fisherman/fishing_manual004.htm | 10 +-
.../data/html/fisherman/fishing_manual008.htm | 3 +-
.../data/html/fisherman/fishing_manual009.htm | 10 +-
.../data/html/fisherman/fishing_manual010.htm | 40 +-
.../dist/game/data/multisell/2144.xml | 39 +
.../dist/game/data/multisell/2194.xml | 70 ++
.../dist/game/data/multisell/2195.xml | 138 +++
.../dist/game/data/multisell/2203.xml | 62 ++
.../dist/game/data/multisell/2207.xml | 62 ++
.../dist/game/data/multisell/2208.xml | 94 ++
.../dist/game/data/multisell/3034.xml | 22 +
.../dist/game/data/spawns/Innadril/Heine.xml | 3 +-
.../dist/game/data/xsd/Fishing.xsd | 28 +-
.../java/com/l2jmobius/Config.java | 12 +-
.../gameserver/data/xml/impl/FishingData.java | 80 +-
.../model/actor/instance/L2PcInstance.java | 2 +-
.../model/{ => fishing}/Fishing.java | 914 +++++++++---------
.../gameserver/model/fishing/FishingBait.java | 226 +++--
.../model/fishing/FishingCatch.java | 49 +
.../gameserver/model/fishing/FishingRod.java | 56 ++
.../model/zone/type/L2FishingZone.java | 2 +-
.../serverpackets/fishing/ExFishingStart.java | 7 +-
.../dist/game/config/Custom/PremiumSystem.ini | 4 +
.../dist/game/data/Fishing.xml | 67 +-
.../dist/game/data/html/default/34156-1.htm | 7 +
.../dist/game/data/html/default/34156.htm | 11 +
.../dist/game/data/html/fisherman/31563.htm | 21 +-
.../dist/game/data/html/fisherman/31567.htm | 21 +-
.../dist/game/data/html/fisherman/31568.htm | 21 +-
.../dist/game/data/html/fisherman/31570.htm | 22 +-
.../dist/game/data/html/fisherman/31571.htm | 21 +-
.../dist/game/data/html/fisherman/31572.htm | 21 +-
.../dist/game/data/html/fisherman/31573.htm | 21 +-
.../dist/game/data/html/fisherman/31574.htm | 20 +-
.../dist/game/data/html/fisherman/31575.htm | 21 +-
.../dist/game/data/html/fisherman/31576.htm | 22 +-
.../dist/game/data/html/fisherman/31577.htm | 21 +-
.../dist/game/data/html/fisherman/31578.htm | 21 +-
.../dist/game/data/html/fisherman/31579.htm | 21 +-
.../dist/game/data/html/fisherman/31696.htm | 21 +-
.../dist/game/data/html/fisherman/31697.htm | 21 +-
.../dist/game/data/html/fisherman/31989.htm | 21 +-
.../dist/game/data/html/fisherman/32007.htm | 21 +-
.../fisherman/fish_appearance_exchange.htm | 11 +
.../data/html/fisherman/fishing_manual001.htm | 8 +-
.../data/html/fisherman/fishing_manual002.htm | 3 +-
.../data/html/fisherman/fishing_manual003.htm | 6 +-
.../data/html/fisherman/fishing_manual004.htm | 10 +-
.../data/html/fisherman/fishing_manual008.htm | 3 +-
.../data/html/fisherman/fishing_manual009.htm | 10 +-
.../data/html/fisherman/fishing_manual010.htm | 40 +-
.../dist/game/data/multisell/2144.xml | 39 +
.../dist/game/data/multisell/2194.xml | 70 ++
.../dist/game/data/multisell/2195.xml | 138 +++
.../dist/game/data/multisell/2203.xml | 62 ++
.../dist/game/data/multisell/2207.xml | 62 ++
.../dist/game/data/multisell/2208.xml | 94 ++
.../dist/game/data/multisell/3034.xml | 22 +
.../dist/game/data/spawns/Innadril/Heine.xml | 3 +-
.../dist/game/data/xsd/Fishing.xsd | 28 +-
.../java/com/l2jmobius/Config.java | 12 +-
.../gameserver/data/xml/impl/FishingData.java | 80 +-
.../gameserver/model/FishingBaitData.java | 98 --
.../model/actor/instance/L2PcInstance.java | 2 +-
.../model/{ => fishing}/Fishing.java | 914 +++++++++---------
.../gameserver/model/fishing/FishingBait.java | 128 +++
.../model/fishing/FishingCatch.java | 49 +
.../gameserver/model/fishing/FishingRod.java | 56 ++
.../model/zone/type/L2FishingZone.java | 2 +-
.../serverpackets/fishing/ExFishingStart.java | 7 +-
.../dist/game/config/Custom/PremiumSystem.ini | 4 +
.../dist/game/data/Fishing.xml | 67 +-
.../dist/game/data/html/default/34156-1.htm | 7 +
.../dist/game/data/html/default/34156.htm | 11 +
.../dist/game/data/html/fisherman/31563.htm | 21 +-
.../dist/game/data/html/fisherman/31567.htm | 21 +-
.../dist/game/data/html/fisherman/31568.htm | 21 +-
.../dist/game/data/html/fisherman/31570.htm | 22 +-
.../dist/game/data/html/fisherman/31571.htm | 21 +-
.../dist/game/data/html/fisherman/31572.htm | 21 +-
.../dist/game/data/html/fisherman/31573.htm | 21 +-
.../dist/game/data/html/fisherman/31574.htm | 20 +-
.../dist/game/data/html/fisherman/31575.htm | 21 +-
.../dist/game/data/html/fisherman/31576.htm | 22 +-
.../dist/game/data/html/fisherman/31577.htm | 21 +-
.../dist/game/data/html/fisherman/31578.htm | 21 +-
.../dist/game/data/html/fisherman/31579.htm | 21 +-
.../dist/game/data/html/fisherman/31696.htm | 21 +-
.../dist/game/data/html/fisherman/31697.htm | 21 +-
.../dist/game/data/html/fisherman/31989.htm | 21 +-
.../dist/game/data/html/fisherman/32007.htm | 21 +-
.../fisherman/fish_appearance_exchange.htm | 11 +
.../data/html/fisherman/fishing_manual001.htm | 8 +-
.../data/html/fisherman/fishing_manual002.htm | 3 +-
.../data/html/fisherman/fishing_manual003.htm | 6 +-
.../data/html/fisherman/fishing_manual004.htm | 10 +-
.../data/html/fisherman/fishing_manual008.htm | 3 +-
.../data/html/fisherman/fishing_manual009.htm | 10 +-
.../data/html/fisherman/fishing_manual010.htm | 40 +-
.../dist/game/data/multisell/2144.xml | 39 +
.../dist/game/data/multisell/2194.xml | 70 ++
.../dist/game/data/multisell/2195.xml | 138 +++
.../dist/game/data/multisell/2203.xml | 62 ++
.../dist/game/data/multisell/2207.xml | 62 ++
.../dist/game/data/multisell/2208.xml | 94 ++
.../dist/game/data/multisell/3034.xml | 22 +
.../dist/game/data/spawns/Innadril/Heine.xml | 3 +-
.../dist/game/data/xsd/Fishing.xsd | 28 +-
.../java/com/l2jmobius/Config.java | 12 +-
.../gameserver/data/xml/impl/FishingData.java | 80 +-
.../gameserver/model/FishingBaitData.java | 98 --
.../model/actor/instance/L2PcInstance.java | 2 +-
.../gameserver/model/fishing}/Fishing.java | 914 +++++++++---------
.../gameserver/model/fishing/FishingBait.java | 128 +++
.../model/fishing/FishingCatch.java | 49 +
.../gameserver/model/fishing/FishingRod.java | 56 ++
.../model/zone/type/L2FishingZone.java | 2 +-
.../serverpackets/fishing/ExFishingStart.java | 7 +-
.../dist/game/config/Custom/PremiumSystem.ini | 4 +
.../dist/game/data/Fishing.xml | 67 +-
.../dist/game/data/html/default/34156-1.htm | 7 +
.../dist/game/data/html/default/34156.htm | 11 +
.../dist/game/data/html/fisherman/31563.htm | 21 +-
.../dist/game/data/html/fisherman/31567.htm | 21 +-
.../dist/game/data/html/fisherman/31568.htm | 21 +-
.../dist/game/data/html/fisherman/31570.htm | 22 +-
.../dist/game/data/html/fisherman/31571.htm | 21 +-
.../dist/game/data/html/fisherman/31572.htm | 21 +-
.../dist/game/data/html/fisherman/31573.htm | 21 +-
.../dist/game/data/html/fisherman/31574.htm | 20 +-
.../dist/game/data/html/fisherman/31575.htm | 21 +-
.../dist/game/data/html/fisherman/31576.htm | 22 +-
.../dist/game/data/html/fisherman/31577.htm | 21 +-
.../dist/game/data/html/fisherman/31578.htm | 21 +-
.../dist/game/data/html/fisherman/31579.htm | 21 +-
.../dist/game/data/html/fisherman/31696.htm | 21 +-
.../dist/game/data/html/fisherman/31697.htm | 21 +-
.../dist/game/data/html/fisherman/31989.htm | 21 +-
.../dist/game/data/html/fisherman/32007.htm | 21 +-
.../fisherman/fish_appearance_exchange.htm | 11 +
.../data/html/fisherman/fishing_manual001.htm | 8 +-
.../data/html/fisherman/fishing_manual002.htm | 3 +-
.../data/html/fisherman/fishing_manual003.htm | 6 +-
.../data/html/fisherman/fishing_manual004.htm | 10 +-
.../data/html/fisherman/fishing_manual008.htm | 3 +-
.../data/html/fisherman/fishing_manual009.htm | 10 +-
.../data/html/fisherman/fishing_manual010.htm | 40 +-
.../dist/game/data/multisell/2144.xml | 39 +
.../dist/game/data/multisell/2194.xml | 70 ++
.../dist/game/data/multisell/2195.xml | 138 +++
.../dist/game/data/multisell/2203.xml | 62 ++
.../dist/game/data/multisell/2207.xml | 62 ++
.../dist/game/data/multisell/2208.xml | 94 ++
.../dist/game/data/multisell/3034.xml | 22 +
.../dist/game/data/spawns/Innadril/Heine.xml | 161 +--
.../dist/game/data/xsd/Fishing.xsd | 28 +-
.../java/com/l2jmobius/Config.java | 12 +-
.../gameserver/data/xml/impl/FishingData.java | 80 +-
.../gameserver/model/FishingBaitData.java | 98 --
.../model/actor/instance/L2PcInstance.java | 2 +-
.../gameserver/model/fishing}/Fishing.java | 914 +++++++++---------
.../gameserver/model/fishing/FishingBait.java | 128 +++
.../model/fishing/FishingCatch.java | 49 +
.../gameserver/model/fishing/FishingRod.java | 56 ++
.../model/zone/type/L2FishingZone.java | 2 +-
.../serverpackets/fishing/ExFishingStart.java | 7 +-
.../dist/game/config/Custom/PremiumSystem.ini | 4 +
.../dist/game/data/Fishing.xml | 20 +-
.../dist/game/data/xsd/Fishing.xsd | 28 +-
.../java/com/l2jmobius/Config.java | 2 +
.../gameserver/data/xml/impl/FishingData.java | 80 +-
.../gameserver/model/FishingBaitData.java | 98 --
.../model/actor/instance/L2PcInstance.java | 2 +-
.../gameserver/model/fishing}/Fishing.java | 914 +++++++++---------
.../gameserver/model/fishing/FishingBait.java | 128 +++
.../model/fishing/FishingCatch.java | 49 +
.../gameserver/model/fishing/FishingRod.java | 56 ++
.../model/zone/type/L2FishingZone.java | 2 +-
.../serverpackets/fishing/ExFishingStart.java | 7 +-
.../dist/game/config/Custom/PremiumSystem.ini | 4 +
.../dist/game/data/Fishing.xml | 20 +-
.../dist/game/data/xsd/Fishing.xsd | 28 +-
.../java/com/l2jmobius/Config.java | 2 +
.../gameserver/data/xml/impl/FishingData.java | 80 +-
.../gameserver/model/FishingBaitData.java | 98 --
.../model/actor/instance/L2PcInstance.java | 2 +-
.../gameserver/model/fishing}/Fishing.java | 914 +++++++++---------
.../gameserver/model/fishing/FishingBait.java | 128 +++
.../model/fishing/FishingCatch.java | 49 +
.../gameserver/model/fishing/FishingRod.java | 56 ++
.../model/zone/type/L2FishingZone.java | 2 +-
.../serverpackets/fishing/ExFishingStart.java | 7 +-
.../dist/game/config/Custom/PremiumSystem.ini | 4 +
.../dist/game/data/Fishing.xml | 20 +-
.../dist/game/data/xsd/Fishing.xsd | 28 +-
.../java/com/l2jmobius/Config.java | 2 +
.../gameserver/data/xml/impl/FishingData.java | 80 +-
.../gameserver/model/FishingBaitData.java | 98 --
.../model/actor/instance/L2PcInstance.java | 2 +-
.../gameserver/model/fishing}/Fishing.java | 914 +++++++++---------
.../gameserver/model/fishing/FishingBait.java | 128 +++
.../model/fishing/FishingCatch.java | 49 +
.../gameserver/model/fishing/FishingRod.java | 56 ++
.../model/zone/type/L2FishingZone.java | 2 +-
.../serverpackets/fishing/ExFishingStart.java | 7 +-
.../dist/game/config/Custom/PremiumSystem.ini | 4 +
.../dist/game/data/Fishing.xml | 20 +-
.../dist/game/data/xsd/Fishing.xsd | 28 +-
.../java/com/l2jmobius/Config.java | 2 +
.../gameserver/data/xml/impl/FishingData.java | 80 +-
.../gameserver/model/FishingBaitData.java | 98 --
.../model/actor/instance/L2PcInstance.java | 2 +-
.../gameserver/model/fishing}/Fishing.java | 914 +++++++++---------
.../gameserver/model/fishing/FishingBait.java | 128 +++
.../model/fishing/FishingCatch.java | 49 +
.../gameserver/model/fishing/FishingRod.java | 56 ++
.../model/zone/type/L2FishingZone.java | 2 +-
.../serverpackets/fishing/ExFishingStart.java | 7 +-
314 files changed, 12904 insertions(+), 7698 deletions(-)
rename L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/{ => fishing}/Fishing.java (80%)
rename L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/FishingBaitData.java => L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java (55%)
create mode 100644 L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
create mode 100644 L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
rename L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/{ => fishing}/Fishing.java (80%)
rename L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/FishingBaitData.java => L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java (55%)
create mode 100644 L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
create mode 100644 L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/html/default/34156-1.htm
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/html/default/34156.htm
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fish_appearance_exchange.htm
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/multisell/2144.xml
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/multisell/2194.xml
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/multisell/2195.xml
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/multisell/2203.xml
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/multisell/2207.xml
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/multisell/2208.xml
create mode 100644 L2J_Mobius_3.0_Helios/dist/game/data/multisell/3034.xml
rename L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/{ => fishing}/Fishing.java (80%)
rename L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/FishingBaitData.java => L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java (55%)
create mode 100644 L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
create mode 100644 L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/default/34156-1.htm
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/default/34156.htm
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fish_appearance_exchange.htm
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2144.xml
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2194.xml
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2195.xml
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2203.xml
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2207.xml
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2208.xml
create mode 100644 L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/3034.xml
rename L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/{ => fishing}/Fishing.java (80%)
rename L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/FishingBaitData.java => L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java (55%)
create mode 100644 L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
create mode 100644 L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/html/default/34156-1.htm
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/html/default/34156.htm
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fish_appearance_exchange.htm
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2144.xml
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2194.xml
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2195.xml
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2203.xml
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2207.xml
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2208.xml
create mode 100644 L2J_Mobius_5.0_Salvation/dist/game/data/multisell/3034.xml
delete mode 100644 L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/FishingBaitData.java
rename L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/{ => fishing}/Fishing.java (80%)
create mode 100644 L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
create mode 100644 L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
create mode 100644 L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/html/default/34156-1.htm
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/html/default/34156.htm
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fish_appearance_exchange.htm
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2144.xml
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2194.xml
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2195.xml
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2203.xml
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2207.xml
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2208.xml
create mode 100644 L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/3034.xml
delete mode 100644 L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/FishingBaitData.java
rename {L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model => L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/fishing}/Fishing.java (80%)
create mode 100644 L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
create mode 100644 L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/html/default/34156-1.htm
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/html/default/34156.htm
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fish_appearance_exchange.htm
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2144.xml
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2194.xml
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2195.xml
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2203.xml
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2207.xml
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2208.xml
create mode 100644 L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/3034.xml
delete mode 100644 L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/FishingBaitData.java
rename {L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model => L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/fishing}/Fishing.java (80%)
create mode 100644 L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
create mode 100644 L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
create mode 100644 L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
delete mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/FishingBaitData.java
rename {L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model => L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/fishing}/Fishing.java (79%)
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
delete mode 100644 L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/FishingBaitData.java
rename {L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model => L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/fishing}/Fishing.java (79%)
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
delete mode 100644 L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/FishingBaitData.java
rename {L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model => L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/fishing}/Fishing.java (79%)
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
delete mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/FishingBaitData.java
rename {L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model => L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/fishing}/Fishing.java (79%)
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/config/Custom/PremiumSystem.ini b/L2J_Mobius_1.0_Ertheia/dist/game/config/Custom/PremiumSystem.ini
index 8b5d1f1f06..7b0874c29d 100644
--- a/L2J_Mobius_1.0_Ertheia/dist/game/config/Custom/PremiumSystem.ini
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/config/Custom/PremiumSystem.ini
@@ -45,3 +45,7 @@ EnablePremiumHennaSlotforNonPremium = True
# Also premium henna drawn at normal slots.
# Retail: False
EnableAnyHennaAtPremiumSlot = False
+
+# Enable Fishing only for premium players.
+# Retail: True
+PremiumOnlyFishing = False
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/Fishing.xml b/L2J_Mobius_1.0_Ertheia/dist/game/data/Fishing.xml
index b05d37b7a7..973e554e39 100644
--- a/L2J_Mobius_1.0_Ertheia/dist/game/data/Fishing.xml
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/Fishing.xml
@@ -1,28 +1,32 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/xsd/Fishing.xsd b/L2J_Mobius_1.0_Ertheia/dist/game/data/xsd/Fishing.xsd
index 16e5ed9699..1078ed7f77 100644
--- a/L2J_Mobius_1.0_Ertheia/dist/game/data/xsd/Fishing.xsd
+++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/xsd/Fishing.xsd
@@ -9,13 +9,13 @@
-
+
-
+
@@ -30,17 +30,35 @@
+
+
-
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/Config.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/Config.java
index 541e33b06f..3081441ccd 100644
--- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/Config.java
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/Config.java
@@ -1130,11 +1130,12 @@ public final class Config
public static float PREMIUM_RATE_DROP_AMOUNT;
public static float PREMIUM_RATE_SPOIL_CHANCE;
public static float PREMIUM_RATE_SPOIL_AMOUNT;
+ public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
+ public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
public static boolean PREMIUM_HENNA_SLOT_ENABLED;
public static boolean PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL;
public static boolean PREMIUM_HENNA_SLOT_ALL_DYES;
- public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
- public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
+ public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
public static int PC_CAFE_MAX_POINTS;
@@ -2612,9 +2613,6 @@ public final class Config
PREMIUM_RATE_DROP_AMOUNT = PremiumSystem.getFloat("PremiumRateDropAmount", 1);
PREMIUM_RATE_SPOIL_CHANCE = PremiumSystem.getFloat("PremiumRateSpoilChance", 2);
PREMIUM_RATE_SPOIL_AMOUNT = PremiumSystem.getFloat("PremiumRateSpoilAmount", 1);
- PREMIUM_HENNA_SLOT_ENABLED = PremiumSystem.getBoolean("EnablePremiumHennaSlot", true);
- PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL = PremiumSystem.getBoolean("EnablePremiumHennaSlotforNonPremium", true);
- PREMIUM_HENNA_SLOT_ALL_DYES = PremiumSystem.getBoolean("EnableAnyHennaAtPremiumSlot", false);
final String[] premiumDropChanceMultiplier = PremiumSystem.getString("PremiumRateDropChanceByItemId", "").split(";");
PREMIUM_RATE_DROP_CHANCE_BY_ID = new HashMap<>(premiumDropChanceMultiplier.length);
if (!premiumDropChanceMultiplier[0].isEmpty())
@@ -2669,6 +2667,10 @@ public final class Config
}
}
}
+ PREMIUM_HENNA_SLOT_ENABLED = PremiumSystem.getBoolean("EnablePremiumHennaSlot", true);
+ PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL = PremiumSystem.getBoolean("EnablePremiumHennaSlotforNonPremium", true);
+ PREMIUM_HENNA_SLOT_ALL_DYES = PremiumSystem.getBoolean("EnableAnyHennaAtPremiumSlot", false);
+ PREMIUM_ONLY_FISHING = PremiumSystem.getBoolean("PremiumOnlyFishing", true);
// Load PrivateStoreRange config file (if exists)
final PropertiesParser PrivateStoreRange = new PropertiesParser(CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE);
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
index 91b5f9c43e..bacf1ed08c 100644
--- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
@@ -25,8 +25,12 @@ import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
+import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
-import com.l2jmobius.gameserver.model.FishingBaitData;
+import com.l2jmobius.gameserver.datatables.ItemTable;
+import com.l2jmobius.gameserver.model.fishing.FishingBait;
+import com.l2jmobius.gameserver.model.fishing.FishingCatch;
+import com.l2jmobius.gameserver.model.fishing.FishingRod;
/**
* This class holds the Fishing information.
@@ -35,7 +39,8 @@ import com.l2jmobius.gameserver.model.FishingBaitData;
public final class FishingData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(FishingData.class.getName());
- private final Map _baitData = new HashMap<>();
+ private final Map _baitData = new HashMap<>();
+ private final Map _rodData = new HashMap<>();
private int _baitDistanceMin;
private int _baitDistanceMax;
private double _expRateMin;
@@ -56,7 +61,7 @@ public final class FishingData implements IGameXmlReader
{
_baitData.clear();
parseDatapackFile("data/Fishing.xml");
- LOGGER.info(getClass().getSimpleName() + ": Loaded Fishing Data.");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _baitData.size() + " bait and " + _rodData.size() + " rod data.");
}
@Override
@@ -76,13 +81,13 @@ public final class FishingData implements IGameXmlReader
_baitDistanceMax = parseInteger(listItem.getAttributes(), "max");
break;
}
- case "experienceRate":
+ case "xpRate":
{
_expRateMin = parseDouble(listItem.getAttributes(), "min");
_expRateMax = parseDouble(listItem.getAttributes(), "max");
break;
}
- case "skillPointsRate":
+ case "spRate":
{
_spRateMin = parseDouble(listItem.getAttributes(), "min");
_spRateMax = parseDouble(listItem.getAttributes(), "max");
@@ -96,20 +101,39 @@ public final class FishingData implements IGameXmlReader
{
final NamedNodeMap attrs = bait.getAttributes();
final int itemId = parseInteger(attrs, "itemId");
- final int level = parseInteger(attrs, "level");
- final int minPlayerLevel = parseInteger(attrs, "minPlayerLevel");
+ final byte level = parseByte(attrs, "level", (byte) 1);
+ final byte minPlayerLevel = parseByte(attrs, "minPlayerLevel");
+ final byte maxPlayerLevel = parseByte(attrs, "minPlayerLevel", Config.PLAYER_MAXIMUM_LEVEL);
final double chance = parseDouble(attrs, "chance");
final int timeMin = parseInteger(attrs, "timeMin");
- final int timeMax = parseInteger(attrs, "timeMax");
+ final int timeMax = parseInteger(attrs, "timeMax", timeMin);
final int waitMin = parseInteger(attrs, "waitMin");
- final int waitMax = parseInteger(attrs, "waitMax");
- final FishingBaitData baitData = new FishingBaitData(itemId, level, minPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax);
+ final int waitMax = parseInteger(attrs, "waitMax", waitMin);
+ final boolean isPremiumOnly = parseBoolean(attrs, "isPremiumOnly", false);
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ final FishingBait baitData = new FishingBait(itemId, level, minPlayerLevel, maxPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax, isPremiumOnly);
for (Node c = bait.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("catch".equalsIgnoreCase(c.getNodeName()))
{
- baitData.addReward(parseInteger(c.getAttributes(), "itemId"));
+ final NamedNodeMap cAttrs = c.getAttributes();
+ final int cId = parseInteger(cAttrs, "itemId");
+ final float cChance = parseFloat(cAttrs, "chance");
+ final float cMultiplier = parseFloat(cAttrs, "multiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(cId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ baitData.addReward(new FishingCatch(cId, cChance, cMultiplier));
}
}
_baitData.put(baitData.getItemId(), baitData);
@@ -117,22 +141,44 @@ public final class FishingData implements IGameXmlReader
}
break;
}
+ case "rods":
+ {
+ for (Node rod = listItem.getFirstChild(); rod != null; rod = rod.getNextSibling())
+ {
+ if ("rod".equalsIgnoreCase(rod.getNodeName()))
+ {
+ final NamedNodeMap attrs = rod.getAttributes();
+ final int itemId = parseInteger(attrs, "itemId");
+ final int reduceFishingTime = parseInteger(attrs, "reduceFishingTime", 0);
+ final float xpMultiplier = parseFloat(attrs, "xpMultiplier", 1f);
+ final float spMultiplier = parseFloat(attrs, "spMultiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ _rodData.put(itemId, new FishingRod(itemId, reduceFishingTime, xpMultiplier, spMultiplier));
+ }
+ }
+ }
}
}
}
}
}
- /**
- * Gets the fishing rod.
- * @param baitItemId the item id
- * @return A list of reward item ids
- */
- public FishingBaitData getBaitData(int baitItemId)
+ public FishingBait getBaitData(int baitItemId)
{
return _baitData.get(baitItemId);
}
+ public FishingRod getRodData(int rodItemId)
+ {
+ return _rodData.get(rodItemId);
+ }
+
public int getBaitDistanceMin()
{
return _baitDistanceMin;
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
index a5e890c536..9afa5296aa 100644
--- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
@@ -120,7 +120,6 @@ import com.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import com.l2jmobius.gameserver.model.BlockList;
import com.l2jmobius.gameserver.model.ClanPrivilege;
import com.l2jmobius.gameserver.model.ClanWar;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.L2AccessLevel;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
@@ -208,6 +207,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPCh
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPKill;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerReputationChanged;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerSubChange;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.MovieHolder;
import com.l2jmobius.gameserver.model.holders.PlayerEventHolder;
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/Fishing.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
similarity index 80%
rename from L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/Fishing.java
rename to L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
index 7caefa2ddd..646bbdd827 100644
--- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/Fishing.java
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
@@ -1,443 +1,471 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.concurrent.ScheduledFuture;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.commons.util.Rnd;
-import com.l2jmobius.gameserver.data.xml.impl.FishingData;
-import com.l2jmobius.gameserver.enums.ShotType;
-import com.l2jmobius.gameserver.geoengine.GeoEngine;
-import com.l2jmobius.gameserver.instancemanager.ZoneManager;
-import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jmobius.gameserver.model.events.EventDispatcher;
-import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
-import com.l2jmobius.gameserver.model.interfaces.ILocational;
-import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
-import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
-import com.l2jmobius.gameserver.model.items.type.WeaponType;
-import com.l2jmobius.gameserver.model.zone.L2ZoneType;
-import com.l2jmobius.gameserver.model.zone.ZoneId;
-import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
-import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
-import com.l2jmobius.gameserver.network.SystemMessageId;
-import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
-import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
-import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
-import com.l2jmobius.gameserver.util.Util;
-
-/**
- * @author bit
- */
-public class Fishing
-{
- protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
- private volatile ILocational _baitLocation = new Location(0, 0, 0);
-
- private final L2PcInstance _player;
- private ScheduledFuture> _reelInTask;
- private ScheduledFuture> _startFishingTask;
- private boolean _isFishing = false;
-
- public Fishing(L2PcInstance player)
- {
- _player = player;
- }
-
- public synchronized boolean isFishing()
- {
- return _isFishing;
- }
-
- public boolean isAtValidLocation()
- {
- // TODO: implement checking direction
- // if (calculateBaitLocation() == null)
- // {
- // return false;
- // }
- return _player.isInsideZone(ZoneId.FISHING);
- }
-
- public boolean canFish()
- {
- return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
- }
-
- private FishingBaitData getCurrentBaitData()
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
- }
-
- private void cancelTasks()
- {
- if (_reelInTask != null)
- {
- _reelInTask.cancel(false);
- _reelInTask = null;
- }
-
- if (_startFishingTask != null)
- {
- _startFishingTask.cancel(false);
- _startFishingTask = null;
- }
- }
-
- public synchronized void startFishing()
- {
- if (_isFishing)
- {
- return;
- }
- _isFishing = true;
- castLine();
- }
-
- private void castLine()
- {
- if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
- {
- _player.sendMessage("Fishing is disabled.");
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- cancelTasks();
-
- if (!canFish())
- {
- if (_isFishing)
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final FishingBaitData baitData = getCurrentBaitData();
- final int minPlayerLevel = baitData == null ? 85 : baitData.getMinPlayerLevel();
- if (_player.getLevel() < minPlayerLevel)
- {
- if (minPlayerLevel == 85)
- {
- _player.sendMessage("Fishing is available to characters Lv. 85 or above.");
- }
- else // In case of custom fishing level.
- {
- _player.sendMessage("You do not meet the fishing level requirements.");
- }
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final L2ItemInstance rod = _player.getActiveWeaponInstance();
- if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (baitData == null)
- {
- _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isTransformed() || _player.isInBoat())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHEN_TRANSFORMED_OR_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_IT_S_AGAINST_THE_RULES);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isCrafting() || _player.isInStoreMode())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- _baitLocation = calculateBaitLocation();
- if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
- {
- if (_isFishing)
- {
- // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- else
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- _player.rechargeShots(false, false, true);
- }
-
- _reelInTask = ThreadPool.schedule(() ->
- {
- _player.getFishing().reelInWithReward();
- _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), Rnd.get(baitData.getWaitMin(), baitData.getWaitMax()));
- }, Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()));
- _player.stopMove(null);
- _player.broadcastPacket(new ExFishingStart(_player, -1, baitData.getLevel(), _baitLocation));
- _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
- _player.sendPacket(new PlaySound("SF_P_01"));
- _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
- }
-
- public void reelInWithReward()
- {
- // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
- // Then player may or may not catch the fish. Using fishing shots increases chance to win.
- final FishingBaitData baitData = getCurrentBaitData();
- if (baitData == null)
- {
- reelIn(FishingEndReason.LOSE, false);
- LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
- return;
- }
-
- double chance = baitData.getChance();
- if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- chance *= 1.5; // +50 % chance to win
- }
-
- if (Rnd.get(0, 100) <= chance)
- {
- reelIn(FishingEndReason.WIN, true);
- }
- else
- {
- reelIn(FishingEndReason.LOSE, true);
- }
- }
-
- private void reelIn(FishingEndReason reason, boolean consumeBait)
- {
- if (!_isFishing)
- {
- return;
- }
-
- cancelTasks();
-
- try
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- if (consumeBait)
- {
- if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
- {
- reason = FishingEndReason.LOSE; // no bait - no reward
- return;
- }
- }
-
- if ((reason == FishingEndReason.WIN) && (bait != null))
- {
- final FishingBaitData baitData = FishingData.getInstance().getBaitData(bait.getId());
- final int numRewards = baitData.getRewards().size();
- if (numRewards > 0)
- {
- final FishingData fishingData = FishingData.getInstance();
- final int lvlModifier = _player.getLevel() * _player.getLevel();
- _player.addExpAndSp(Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier, Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier, true);
- final int fishId = baitData.getRewards().get(Rnd.get(0, numRewards - 1));
- _player.getInventory().addItem("Fishing Reward", fishId, 1, _player, null);
- final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
- msg.addItemName(fishId);
- _player.sendPacket(msg);
- _player.unchargeShot(ShotType.FISH_SOULSHOTS);
- _player.rechargeShots(false, false, true);
- }
- else
- {
- LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
- }
- }
- else if (reason == FishingEndReason.LOSE)
- {
- _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
- }
-
- if (consumeBait)
- {
- EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
- }
- }
- finally
- {
- _player.broadcastPacket(new ExFishingEnd(_player, reason));
- _player.sendPacket(new ExUserInfoFishing(_player, false));
- }
- }
-
- public void stopFishing()
- {
- stopFishing(FishingEndType.PLAYER_STOP);
- }
-
- public synchronized void stopFishing(FishingEndType endType)
- {
- if (_isFishing)
- {
- reelIn(FishingEndReason.STOP, false);
- _isFishing = false;
- switch (endType)
- {
- case PLAYER_STOP:
- {
- _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
- break;
- }
- case PLAYER_CANCEL:
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- break;
- }
- }
- }
- }
-
- public ILocational getBaitLocation()
- {
- return _baitLocation;
- }
-
- private Location calculateBaitLocation()
- {
- // calculate a position in front of the player with a random distance
- final int distMin = FishingData.getInstance().getBaitDistanceMin();
- final int distMax = FishingData.getInstance().getBaitDistanceMax();
- int distance = Rnd.get(distMin, distMax);
- final double angle = Util.convertHeadingToDegree(_player.getHeading());
- final double radian = Math.toRadians(angle);
- final double sin = Math.sin(radian);
- final double cos = Math.cos(radian);
- int baitX = (int) (_player.getX() + (cos * distance));
- int baitY = (int) (_player.getY() + (sin * distance));
-
- // search for fishing zone
- L2FishingZone fishingZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
- {
- if (zone instanceof L2FishingZone)
- {
- fishingZone = (L2FishingZone) zone;
- break;
- }
- }
- // search for water zone
- L2WaterZone waterZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
- {
- if (zone instanceof L2WaterZone)
- {
- waterZone = (L2WaterZone) zone;
- break;
- }
- }
-
- int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
- if (baitZ == Integer.MIN_VALUE)
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
- return null;
- }
-
- return new Location(baitX, baitY, baitZ);
- }
-
- /**
- * Computes the Z of the bait.
- * @param player the player
- * @param baitX the bait x
- * @param baitY the bait y
- * @param fishingZone the fishing zone
- * @param waterZone the water zone
- * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
- */
- private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
- {
- if ((fishingZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- if ((waterZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- // always use water zone, fishing zone high z is high in the air...
- final int baitZ = waterZone.getWaterZ();
-
- // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
- //
- // return Integer.MIN_VALUE;
- // }
-
- if (GeoEngine.getInstance().hasGeo(baitX, baitY))
- {
- if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
-
- if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
- }
-
- return baitZ;
- }
-}
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.commons.util.Rnd;
+import com.l2jmobius.gameserver.data.xml.impl.FishingData;
+import com.l2jmobius.gameserver.enums.ShotType;
+import com.l2jmobius.gameserver.geoengine.GeoEngine;
+import com.l2jmobius.gameserver.instancemanager.ZoneManager;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.PcCondOverride;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.events.EventDispatcher;
+import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
+import com.l2jmobius.gameserver.model.interfaces.ILocational;
+import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.model.items.type.WeaponType;
+import com.l2jmobius.gameserver.model.zone.L2ZoneType;
+import com.l2jmobius.gameserver.model.zone.ZoneId;
+import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
+import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
+import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author bit
+ */
+public class Fishing
+{
+ protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
+ private volatile ILocational _baitLocation = new Location(0, 0, 0);
+
+ private final L2PcInstance _player;
+ private ScheduledFuture> _reelInTask;
+ private ScheduledFuture> _startFishingTask;
+ private boolean _isFishing = false;
+
+ public Fishing(L2PcInstance player)
+ {
+ _player = player;
+ }
+
+ public synchronized boolean isFishing()
+ {
+ return _isFishing;
+ }
+
+ public boolean isAtValidLocation()
+ {
+ // TODO: implement checking direction
+ // if (calculateBaitLocation() == null)
+ // {
+ // return false;
+ // }
+ return _player.isInsideZone(ZoneId.FISHING);
+ }
+
+ public boolean canFish()
+ {
+ return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
+ }
+
+ private FishingBait getCurrentBaitData()
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
+ }
+
+ private void cancelTasks()
+ {
+ if (_reelInTask != null)
+ {
+ _reelInTask.cancel(false);
+ _reelInTask = null;
+ }
+
+ if (_startFishingTask != null)
+ {
+ _startFishingTask.cancel(false);
+ _startFishingTask = null;
+ }
+ }
+
+ public synchronized void startFishing()
+ {
+ if (_isFishing)
+ {
+ return;
+ }
+ _isFishing = true;
+ castLine();
+ }
+
+ private void castLine()
+ {
+ if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
+ {
+ _player.sendMessage("Fishing is disabled.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ cancelTasks();
+
+ if (!canFish())
+ {
+ if (_isFishing)
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (Config.PREMIUM_SYSTEM_ENABLED)
+ {
+ if (Config.PREMIUM_ONLY_FISHING && !_player.hasPremiumStatus())
+ {
+ _player.sendMessage("Fishing is available to premium users only.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (baitData.isPremiumOnly() && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.FAILED_PLEASE_TRY_AGAIN_USING_THE_CORRECT_BAIT);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+ }
+
+ final int minPlayerLevel = baitData.getMinPlayerLevel();
+ final int maxPLayerLevel = baitData.getMaxPlayerLevel();
+ if ((_player.getLevel() < minPlayerLevel) && (_player.getLevel() > maxPLayerLevel))
+ {
+ _player.sendMessage("You do not meet the fishing level requirements.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final L2ItemInstance rod = _player.getActiveWeaponInstance();
+ if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingRod rodData = FishingData.getInstance().getRodData(rod.getId());
+ if (rodData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isTransformed() || _player.isInBoat())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHEN_TRANSFORMED_OR_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_IT_S_AGAINST_THE_RULES);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isCrafting() || _player.isInStoreMode())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ _baitLocation = calculateBaitLocation();
+ if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
+ {
+ if (_isFishing)
+ {
+ // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ else
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ _player.rechargeShots(false, false, true);
+ }
+
+ final long fishingTime = Math.max(Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()) - rodData.getReduceFishingTime(), 1000);
+ final long fishingWaitTime = Rnd.get(baitData.getWaitMin(), baitData.getWaitMax());
+
+ _reelInTask = ThreadPool.schedule(() ->
+ {
+ _player.getFishing().reelInWithReward();
+ _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), fishingWaitTime);
+ }, fishingTime);
+ _player.stopMove(null);
+ _player.broadcastPacket(new ExFishingStart(_player, -1, _baitLocation));
+ _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
+ _player.sendPacket(new PlaySound("SF_P_01"));
+ _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
+ }
+
+ public void reelInWithReward()
+ {
+ // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
+ // Then player may or may not catch the fish. Using fishing shots increases chance to win.
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ reelIn(FishingEndReason.LOSE, false);
+ LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
+ return;
+ }
+
+ double chance = baitData.getChance();
+ if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ chance *= 2;
+ }
+
+ if (Rnd.get(100) <= chance)
+ {
+ reelIn(FishingEndReason.WIN, true);
+ }
+ else
+ {
+ reelIn(FishingEndReason.LOSE, true);
+ }
+ }
+
+ private void reelIn(FishingEndReason reason, boolean consumeBait)
+ {
+ if (!_isFishing)
+ {
+ return;
+ }
+
+ cancelTasks();
+
+ try
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ if (consumeBait)
+ {
+ if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
+ {
+ reason = FishingEndReason.LOSE; // no bait - no reward
+ return;
+ }
+ }
+
+ if ((reason == FishingEndReason.WIN) && (bait != null))
+ {
+ final FishingBait baitData = FishingData.getInstance().getBaitData(bait.getId());
+ final FishingCatch fishingCatchData = baitData.getRandom();
+ if (fishingCatchData != null)
+ {
+ final FishingData fishingData = FishingData.getInstance();
+ final double lvlModifier = (Math.pow(_player.getLevel(), 2.2) * fishingCatchData.getMultiplier());
+ final long xp = (long) (Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier);
+ final long sp = (long) (Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier);
+ _player.addExpAndSp(xp, sp, true);
+ _player.getInventory().addItem("Fishing Reward", fishingCatchData.getItemId(), 1, _player, null);
+ final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
+ msg.addItemName(fishingCatchData.getItemId());
+ _player.sendPacket(msg);
+ _player.unchargeShot(ShotType.FISH_SOULSHOTS);
+ _player.rechargeShots(false, false, true);
+ }
+ else
+ {
+ LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
+ }
+ }
+ else if (reason == FishingEndReason.LOSE)
+ {
+ _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
+ }
+
+ if (consumeBait)
+ {
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
+ }
+ }
+ finally
+ {
+ _player.broadcastPacket(new ExFishingEnd(_player, reason));
+ _player.sendPacket(new ExUserInfoFishing(_player, false));
+ }
+ }
+
+ public void stopFishing()
+ {
+ stopFishing(FishingEndType.PLAYER_STOP);
+ }
+
+ public synchronized void stopFishing(FishingEndType endType)
+ {
+ if (_isFishing)
+ {
+ reelIn(FishingEndReason.STOP, false);
+ _isFishing = false;
+ switch (endType)
+ {
+ case PLAYER_STOP:
+ {
+ _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
+ break;
+ }
+ case PLAYER_CANCEL:
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ break;
+ }
+ }
+ }
+ }
+
+ public ILocational getBaitLocation()
+ {
+ return _baitLocation;
+ }
+
+ private Location calculateBaitLocation()
+ {
+ // calculate a position in front of the player with a random distance
+ final int distMin = FishingData.getInstance().getBaitDistanceMin();
+ final int distMax = FishingData.getInstance().getBaitDistanceMax();
+ int distance = Rnd.get(distMin, distMax);
+ final double angle = Util.convertHeadingToDegree(_player.getHeading());
+ final double radian = Math.toRadians(angle);
+ final double sin = Math.sin(radian);
+ final double cos = Math.cos(radian);
+ int baitX = (int) (_player.getX() + (cos * distance));
+ int baitY = (int) (_player.getY() + (sin * distance));
+
+ // search for fishing zone
+ L2FishingZone fishingZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
+ {
+ if (zone instanceof L2FishingZone)
+ {
+ fishingZone = (L2FishingZone) zone;
+ break;
+ }
+ }
+ // search for water zone
+ L2WaterZone waterZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
+ {
+ if (zone instanceof L2WaterZone)
+ {
+ waterZone = (L2WaterZone) zone;
+ break;
+ }
+ }
+
+ int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
+ if (baitZ == Integer.MIN_VALUE)
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
+ return null;
+ }
+
+ return new Location(baitX, baitY, baitZ);
+ }
+
+ /**
+ * Computes the Z of the bait.
+ * @param player the player
+ * @param baitX the bait x
+ * @param baitY the bait y
+ * @param fishingZone the fishing zone
+ * @param waterZone the water zone
+ * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
+ */
+ private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
+ {
+ if ((fishingZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if ((waterZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ // always use water zone, fishing zone high z is high in the air...
+ final int baitZ = waterZone.getWaterZ();
+
+ // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
+ //
+ // return Integer.MIN_VALUE;
+ // }
+
+ if (GeoEngine.getInstance().hasGeo(baitX, baitY))
+ {
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+ }
+
+ return baitZ;
+ }
+}
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/FishingBaitData.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
similarity index 55%
rename from L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/FishingBaitData.java
rename to L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
index 9cf4893d66..f5a5764254 100644
--- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/FishingBaitData.java
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
@@ -1,98 +1,128 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author bit
- */
-public class FishingBaitData
-{
- private final int _itemId;
- private final int _level;
- private final int _minPlayerLevel;
- private final double _chance;
- private final int _timeMin;
- private final int _timeMax;
- private final int _waitMin;
- private final int _waitMax;
- private final List _rewards = new ArrayList<>();
-
- public FishingBaitData(int itemId, int level, int minPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax)
- {
- _itemId = itemId;
- _level = level;
- _minPlayerLevel = minPlayerLevel;
- _chance = chance;
- _timeMin = timeMin;
- _timeMax = timeMax;
- _waitMin = waitMin;
- _waitMax = waitMax;
- }
-
- public int getItemId()
- {
- return _itemId;
- }
-
- public int getLevel()
- {
- return _level;
- }
-
- public int getMinPlayerLevel()
- {
- return _minPlayerLevel;
- }
-
- public double getChance()
- {
- return _chance;
- }
-
- public int getTimeMin()
- {
- return _timeMin;
- }
-
- public int getTimeMax()
- {
- return _timeMax;
- }
-
- public int getWaitMin()
- {
- return _waitMin;
- }
-
- public int getWaitMax()
- {
- return _waitMax;
- }
-
- public List getRewards()
- {
- return _rewards;
- }
-
- public void addReward(int itemId)
- {
- _rewards.add(itemId);
- }
-}
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.l2jmobius.commons.util.Rnd;
+
+/**
+ * @author bit
+ */
+public class FishingBait
+{
+ private final int _itemId;
+ private final byte _level;
+ private final byte _minPlayerLevel;
+ private final byte _maxPlayerLevel;
+ private final double _chance;
+ private final int _timeMin;
+ private final int _timeMax;
+ private final int _waitMin;
+ private final int _waitMax;
+ private final boolean _isPremiumOnly;
+ private final List _rewards = new ArrayList<>();
+
+ public FishingBait(int itemId, byte level, byte minPlayerLevel, byte maxPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax, boolean isPremiumOnly)
+ {
+ _itemId = itemId;
+ _level = level;
+ _minPlayerLevel = minPlayerLevel;
+ _maxPlayerLevel = maxPlayerLevel;
+ _chance = chance;
+ _timeMin = timeMin;
+ _timeMax = timeMax;
+ _waitMin = waitMin;
+ _waitMax = waitMax;
+ _isPremiumOnly = isPremiumOnly;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public byte getLevel()
+ {
+ return _level;
+ }
+
+ public byte getMinPlayerLevel()
+ {
+ return _minPlayerLevel;
+ }
+
+ public byte getMaxPlayerLevel()
+ {
+ return _maxPlayerLevel;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public int getTimeMin()
+ {
+ return _timeMin;
+ }
+
+ public int getTimeMax()
+ {
+ return _timeMax;
+ }
+
+ public int getWaitMin()
+ {
+ return _waitMin;
+ }
+
+ public int getWaitMax()
+ {
+ return _waitMax;
+ }
+
+ public boolean isPremiumOnly()
+ {
+ return _isPremiumOnly;
+ }
+
+ public List getRewards()
+ {
+ return _rewards;
+ }
+
+ public void addReward(FishingCatch catchData)
+ {
+ _rewards.add(catchData);
+ }
+
+ public FishingCatch getRandom()
+ {
+ float random = Rnd.get(100);
+ for (FishingCatch fishingCatchData : _rewards)
+ {
+ if (fishingCatchData.getChance() > random)
+ {
+ return fishingCatchData;
+ }
+ random -= fishingCatchData.getChance();
+ }
+ return null;
+ }
+}
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
new file mode 100644
index 0000000000..85c2e42e5a
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
@@ -0,0 +1,49 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingCatch
+{
+ private final int _itemId;
+ private final float _chance;
+ private final float _multiplier;
+
+ public FishingCatch(int itemId, float chance, float multiplier)
+ {
+ _itemId = itemId;
+ _chance = chance;
+ _multiplier = multiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public float getChance()
+ {
+ return _chance;
+ }
+
+ public float getMultiplier()
+ {
+ return _multiplier;
+ }
+}
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
new file mode 100644
index 0000000000..93b5fb9b8e
--- /dev/null
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingRod
+{
+ private final int _itemId;
+ private final int _reduceFishingTime;
+ private final float _xpMultiplier;
+ private final float _spMultiplier;
+
+ public FishingRod(int itemId, int reduceFishingTime, float xpMultiplier, float spMultiplier)
+ {
+ _itemId = itemId;
+ _reduceFishingTime = reduceFishingTime;
+ _xpMultiplier = xpMultiplier;
+ _spMultiplier = spMultiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public int getReduceFishingTime()
+ {
+ return _reduceFishingTime;
+ }
+
+ public float getXpMultiplier()
+ {
+ return _xpMultiplier;
+ }
+
+ public float getSpMultiplier()
+ {
+ return _spMultiplier;
+ }
+}
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
index 71d8f10b3e..dfcf4d7f56 100644
--- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
@@ -20,10 +20,10 @@ import java.lang.ref.WeakReference;
import com.l2jmobius.Config;
import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.PcCondOverride;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.serverpackets.fishing.ExAutoFishAvailable;
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
index dea11bad61..cebaa3c7a5 100644
--- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
+++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
@@ -29,20 +29,17 @@ public class ExFishingStart implements IClientOutgoingPacket
{
private final L2PcInstance _player;
private final int _fishType;
- private final int _baitType;
private final ILocational _baitLocation;
/**
* @param player
* @param fishType
- * @param baitType - 0 = newbie, 1 = normal, 2 = night
* @param baitLocation
*/
- public ExFishingStart(L2PcInstance player, int fishType, int baitType, ILocational baitLocation)
+ public ExFishingStart(L2PcInstance player, int fishType, ILocational baitLocation)
{
_player = player;
_fishType = fishType;
- _baitType = baitType;
_baitLocation = baitLocation;
}
@@ -55,7 +52,7 @@ public class ExFishingStart implements IClientOutgoingPacket
packet.writeD(_baitLocation.getX());
packet.writeD(_baitLocation.getY());
packet.writeD(_baitLocation.getZ());
- packet.writeC(_baitType);
+ packet.writeC(0x01); // 0 = newbie, 1 = normal, 2 = night
return true;
}
}
diff --git a/L2J_Mobius_2.5_Underground/dist/game/config/Custom/PremiumSystem.ini b/L2J_Mobius_2.5_Underground/dist/game/config/Custom/PremiumSystem.ini
index 8b5d1f1f06..7b0874c29d 100644
--- a/L2J_Mobius_2.5_Underground/dist/game/config/Custom/PremiumSystem.ini
+++ b/L2J_Mobius_2.5_Underground/dist/game/config/Custom/PremiumSystem.ini
@@ -45,3 +45,7 @@ EnablePremiumHennaSlotforNonPremium = True
# Also premium henna drawn at normal slots.
# Retail: False
EnableAnyHennaAtPremiumSlot = False
+
+# Enable Fishing only for premium players.
+# Retail: True
+PremiumOnlyFishing = False
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/Fishing.xml b/L2J_Mobius_2.5_Underground/dist/game/data/Fishing.xml
index 79773e619c..338e40d400 100644
--- a/L2J_Mobius_2.5_Underground/dist/game/data/Fishing.xml
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/Fishing.xml
@@ -1,35 +1,39 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/xsd/Fishing.xsd b/L2J_Mobius_2.5_Underground/dist/game/data/xsd/Fishing.xsd
index 16e5ed9699..1078ed7f77 100644
--- a/L2J_Mobius_2.5_Underground/dist/game/data/xsd/Fishing.xsd
+++ b/L2J_Mobius_2.5_Underground/dist/game/data/xsd/Fishing.xsd
@@ -9,13 +9,13 @@
-
+
-
+
@@ -30,17 +30,35 @@
+
+
-
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/Config.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/Config.java
index f9d06c3b63..8a2336729a 100644
--- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/Config.java
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/Config.java
@@ -1137,11 +1137,12 @@ public final class Config
public static float PREMIUM_RATE_DROP_AMOUNT;
public static float PREMIUM_RATE_SPOIL_CHANCE;
public static float PREMIUM_RATE_SPOIL_AMOUNT;
+ public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
+ public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
public static boolean PREMIUM_HENNA_SLOT_ENABLED;
public static boolean PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL;
public static boolean PREMIUM_HENNA_SLOT_ALL_DYES;
- public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
- public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
+ public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
public static int PC_CAFE_MAX_POINTS;
@@ -2628,9 +2629,6 @@ public final class Config
PREMIUM_RATE_DROP_AMOUNT = PremiumSystem.getFloat("PremiumRateDropAmount", 1);
PREMIUM_RATE_SPOIL_CHANCE = PremiumSystem.getFloat("PremiumRateSpoilChance", 2);
PREMIUM_RATE_SPOIL_AMOUNT = PremiumSystem.getFloat("PremiumRateSpoilAmount", 1);
- PREMIUM_HENNA_SLOT_ENABLED = PremiumSystem.getBoolean("EnablePremiumHennaSlot", true);
- PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL = PremiumSystem.getBoolean("EnablePremiumHennaSlotforNonPremium", true);
- PREMIUM_HENNA_SLOT_ALL_DYES = PremiumSystem.getBoolean("EnableAnyHennaAtPremiumSlot", false);
final String[] premiumDropChanceMultiplier = PremiumSystem.getString("PremiumRateDropChanceByItemId", "").split(";");
PREMIUM_RATE_DROP_CHANCE_BY_ID = new HashMap<>(premiumDropChanceMultiplier.length);
if (!premiumDropChanceMultiplier[0].isEmpty())
@@ -2685,6 +2683,10 @@ public final class Config
}
}
}
+ PREMIUM_HENNA_SLOT_ENABLED = PremiumSystem.getBoolean("EnablePremiumHennaSlot", true);
+ PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL = PremiumSystem.getBoolean("EnablePremiumHennaSlotforNonPremium", true);
+ PREMIUM_HENNA_SLOT_ALL_DYES = PremiumSystem.getBoolean("EnableAnyHennaAtPremiumSlot", false);
+ PREMIUM_ONLY_FISHING = PremiumSystem.getBoolean("PremiumOnlyFishing", true);
// Load PrivateStoreRange config file (if exists)
final PropertiesParser PrivateStoreRange = new PropertiesParser(CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE);
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
index 91b5f9c43e..bacf1ed08c 100644
--- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
@@ -25,8 +25,12 @@ import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
+import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
-import com.l2jmobius.gameserver.model.FishingBaitData;
+import com.l2jmobius.gameserver.datatables.ItemTable;
+import com.l2jmobius.gameserver.model.fishing.FishingBait;
+import com.l2jmobius.gameserver.model.fishing.FishingCatch;
+import com.l2jmobius.gameserver.model.fishing.FishingRod;
/**
* This class holds the Fishing information.
@@ -35,7 +39,8 @@ import com.l2jmobius.gameserver.model.FishingBaitData;
public final class FishingData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(FishingData.class.getName());
- private final Map _baitData = new HashMap<>();
+ private final Map _baitData = new HashMap<>();
+ private final Map _rodData = new HashMap<>();
private int _baitDistanceMin;
private int _baitDistanceMax;
private double _expRateMin;
@@ -56,7 +61,7 @@ public final class FishingData implements IGameXmlReader
{
_baitData.clear();
parseDatapackFile("data/Fishing.xml");
- LOGGER.info(getClass().getSimpleName() + ": Loaded Fishing Data.");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _baitData.size() + " bait and " + _rodData.size() + " rod data.");
}
@Override
@@ -76,13 +81,13 @@ public final class FishingData implements IGameXmlReader
_baitDistanceMax = parseInteger(listItem.getAttributes(), "max");
break;
}
- case "experienceRate":
+ case "xpRate":
{
_expRateMin = parseDouble(listItem.getAttributes(), "min");
_expRateMax = parseDouble(listItem.getAttributes(), "max");
break;
}
- case "skillPointsRate":
+ case "spRate":
{
_spRateMin = parseDouble(listItem.getAttributes(), "min");
_spRateMax = parseDouble(listItem.getAttributes(), "max");
@@ -96,20 +101,39 @@ public final class FishingData implements IGameXmlReader
{
final NamedNodeMap attrs = bait.getAttributes();
final int itemId = parseInteger(attrs, "itemId");
- final int level = parseInteger(attrs, "level");
- final int minPlayerLevel = parseInteger(attrs, "minPlayerLevel");
+ final byte level = parseByte(attrs, "level", (byte) 1);
+ final byte minPlayerLevel = parseByte(attrs, "minPlayerLevel");
+ final byte maxPlayerLevel = parseByte(attrs, "minPlayerLevel", Config.PLAYER_MAXIMUM_LEVEL);
final double chance = parseDouble(attrs, "chance");
final int timeMin = parseInteger(attrs, "timeMin");
- final int timeMax = parseInteger(attrs, "timeMax");
+ final int timeMax = parseInteger(attrs, "timeMax", timeMin);
final int waitMin = parseInteger(attrs, "waitMin");
- final int waitMax = parseInteger(attrs, "waitMax");
- final FishingBaitData baitData = new FishingBaitData(itemId, level, minPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax);
+ final int waitMax = parseInteger(attrs, "waitMax", waitMin);
+ final boolean isPremiumOnly = parseBoolean(attrs, "isPremiumOnly", false);
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ final FishingBait baitData = new FishingBait(itemId, level, minPlayerLevel, maxPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax, isPremiumOnly);
for (Node c = bait.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("catch".equalsIgnoreCase(c.getNodeName()))
{
- baitData.addReward(parseInteger(c.getAttributes(), "itemId"));
+ final NamedNodeMap cAttrs = c.getAttributes();
+ final int cId = parseInteger(cAttrs, "itemId");
+ final float cChance = parseFloat(cAttrs, "chance");
+ final float cMultiplier = parseFloat(cAttrs, "multiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(cId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ baitData.addReward(new FishingCatch(cId, cChance, cMultiplier));
}
}
_baitData.put(baitData.getItemId(), baitData);
@@ -117,22 +141,44 @@ public final class FishingData implements IGameXmlReader
}
break;
}
+ case "rods":
+ {
+ for (Node rod = listItem.getFirstChild(); rod != null; rod = rod.getNextSibling())
+ {
+ if ("rod".equalsIgnoreCase(rod.getNodeName()))
+ {
+ final NamedNodeMap attrs = rod.getAttributes();
+ final int itemId = parseInteger(attrs, "itemId");
+ final int reduceFishingTime = parseInteger(attrs, "reduceFishingTime", 0);
+ final float xpMultiplier = parseFloat(attrs, "xpMultiplier", 1f);
+ final float spMultiplier = parseFloat(attrs, "spMultiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ _rodData.put(itemId, new FishingRod(itemId, reduceFishingTime, xpMultiplier, spMultiplier));
+ }
+ }
+ }
}
}
}
}
}
- /**
- * Gets the fishing rod.
- * @param baitItemId the item id
- * @return A list of reward item ids
- */
- public FishingBaitData getBaitData(int baitItemId)
+ public FishingBait getBaitData(int baitItemId)
{
return _baitData.get(baitItemId);
}
+ public FishingRod getRodData(int rodItemId)
+ {
+ return _rodData.get(rodItemId);
+ }
+
public int getBaitDistanceMin()
{
return _baitDistanceMin;
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
index fb61e1d675..5be47e3b6d 100644
--- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
@@ -121,7 +121,6 @@ import com.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import com.l2jmobius.gameserver.model.BlockList;
import com.l2jmobius.gameserver.model.ClanPrivilege;
import com.l2jmobius.gameserver.model.ClanWar;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.L2AccessLevel;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
@@ -209,6 +208,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPCh
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPKill;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerReputationChanged;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerSubChange;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.MovieHolder;
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/Fishing.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
similarity index 80%
rename from L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/Fishing.java
rename to L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
index 2de664a571..646bbdd827 100644
--- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/Fishing.java
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
@@ -1,443 +1,471 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.concurrent.ScheduledFuture;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.commons.util.Rnd;
-import com.l2jmobius.gameserver.data.xml.impl.FishingData;
-import com.l2jmobius.gameserver.enums.ShotType;
-import com.l2jmobius.gameserver.geoengine.GeoEngine;
-import com.l2jmobius.gameserver.instancemanager.ZoneManager;
-import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jmobius.gameserver.model.events.EventDispatcher;
-import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
-import com.l2jmobius.gameserver.model.interfaces.ILocational;
-import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
-import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
-import com.l2jmobius.gameserver.model.items.type.WeaponType;
-import com.l2jmobius.gameserver.model.zone.L2ZoneType;
-import com.l2jmobius.gameserver.model.zone.ZoneId;
-import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
-import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
-import com.l2jmobius.gameserver.network.SystemMessageId;
-import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
-import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
-import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
-import com.l2jmobius.gameserver.util.Util;
-
-/**
- * @author bit
- */
-public class Fishing
-{
- protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
- private volatile ILocational _baitLocation = new Location(0, 0, 0);
-
- private final L2PcInstance _player;
- private ScheduledFuture> _reelInTask;
- private ScheduledFuture> _startFishingTask;
- private boolean _isFishing = false;
-
- public Fishing(L2PcInstance player)
- {
- _player = player;
- }
-
- public synchronized boolean isFishing()
- {
- return _isFishing;
- }
-
- public boolean isAtValidLocation()
- {
- // TODO: implement checking direction
- // if (calculateBaitLocation() == null)
- // {
- // return false;
- // }
- return _player.isInsideZone(ZoneId.FISHING);
- }
-
- public boolean canFish()
- {
- return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
- }
-
- private FishingBaitData getCurrentBaitData()
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
- }
-
- private void cancelTasks()
- {
- if (_reelInTask != null)
- {
- _reelInTask.cancel(false);
- _reelInTask = null;
- }
-
- if (_startFishingTask != null)
- {
- _startFishingTask.cancel(false);
- _startFishingTask = null;
- }
- }
-
- public synchronized void startFishing()
- {
- if (_isFishing)
- {
- return;
- }
- _isFishing = true;
- castLine();
- }
-
- private void castLine()
- {
- if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
- {
- _player.sendMessage("Fishing is disabled.");
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- cancelTasks();
-
- if (!canFish())
- {
- if (_isFishing)
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final FishingBaitData baitData = getCurrentBaitData();
- final int minPlayerLevel = baitData == null ? 85 : baitData.getMinPlayerLevel();
- if (_player.getLevel() < minPlayerLevel)
- {
- if (minPlayerLevel == 85)
- {
- _player.sendPacket(SystemMessageId.FISHING_IS_AVAILABLE_TO_CHARACTERS_LV_85_OR_ABOVE);
- }
- else // In case of custom fishing level.
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
- }
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final L2ItemInstance rod = _player.getActiveWeaponInstance();
- if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (baitData == null)
- {
- _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isTransformed() || _player.isInBoat())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHEN_TRANSFORMED_OR_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_IT_S_AGAINST_THE_RULES);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isCrafting() || _player.isInStoreMode())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- _baitLocation = calculateBaitLocation();
- if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
- {
- if (_isFishing)
- {
- // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- else
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- _player.rechargeShots(false, false, true);
- }
-
- _reelInTask = ThreadPool.schedule(() ->
- {
- _player.getFishing().reelInWithReward();
- _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), Rnd.get(baitData.getWaitMin(), baitData.getWaitMax()));
- }, Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()));
- _player.stopMove(null);
- _player.broadcastPacket(new ExFishingStart(_player, -1, baitData.getLevel(), _baitLocation));
- _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
- _player.sendPacket(new PlaySound("SF_P_01"));
- _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
- }
-
- public void reelInWithReward()
- {
- // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
- // Then player may or may not catch the fish. Using fishing shots increases chance to win.
- final FishingBaitData baitData = getCurrentBaitData();
- if (baitData == null)
- {
- reelIn(FishingEndReason.LOSE, false);
- LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
- return;
- }
-
- double chance = baitData.getChance();
- if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- chance *= 1.5; // +50 % chance to win
- }
-
- if (Rnd.get(0, 100) <= chance)
- {
- reelIn(FishingEndReason.WIN, true);
- }
- else
- {
- reelIn(FishingEndReason.LOSE, true);
- }
- }
-
- private void reelIn(FishingEndReason reason, boolean consumeBait)
- {
- if (!_isFishing)
- {
- return;
- }
-
- cancelTasks();
-
- try
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- if (consumeBait)
- {
- if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
- {
- reason = FishingEndReason.LOSE; // no bait - no reward
- return;
- }
- }
-
- if ((reason == FishingEndReason.WIN) && (bait != null))
- {
- final FishingBaitData baitData = FishingData.getInstance().getBaitData(bait.getId());
- final int numRewards = baitData.getRewards().size();
- if (numRewards > 0)
- {
- final FishingData fishingData = FishingData.getInstance();
- final int lvlModifier = _player.getLevel() * _player.getLevel();
- _player.addExpAndSp(Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier, Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier, true);
- final int fishId = baitData.getRewards().get(Rnd.get(0, numRewards - 1));
- _player.getInventory().addItem("Fishing Reward", fishId, 1, _player, null);
- final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
- msg.addItemName(fishId);
- _player.sendPacket(msg);
- _player.unchargeShot(ShotType.FISH_SOULSHOTS);
- _player.rechargeShots(false, false, true);
- }
- else
- {
- LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
- }
- }
- else if (reason == FishingEndReason.LOSE)
- {
- _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
- }
-
- if (consumeBait)
- {
- EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
- }
- }
- finally
- {
- _player.broadcastPacket(new ExFishingEnd(_player, reason));
- _player.sendPacket(new ExUserInfoFishing(_player, false));
- }
- }
-
- public void stopFishing()
- {
- stopFishing(FishingEndType.PLAYER_STOP);
- }
-
- public synchronized void stopFishing(FishingEndType endType)
- {
- if (_isFishing)
- {
- reelIn(FishingEndReason.STOP, false);
- _isFishing = false;
- switch (endType)
- {
- case PLAYER_STOP:
- {
- _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
- break;
- }
- case PLAYER_CANCEL:
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- break;
- }
- }
- }
- }
-
- public ILocational getBaitLocation()
- {
- return _baitLocation;
- }
-
- private Location calculateBaitLocation()
- {
- // calculate a position in front of the player with a random distance
- final int distMin = FishingData.getInstance().getBaitDistanceMin();
- final int distMax = FishingData.getInstance().getBaitDistanceMax();
- int distance = Rnd.get(distMin, distMax);
- final double angle = Util.convertHeadingToDegree(_player.getHeading());
- final double radian = Math.toRadians(angle);
- final double sin = Math.sin(radian);
- final double cos = Math.cos(radian);
- int baitX = (int) (_player.getX() + (cos * distance));
- int baitY = (int) (_player.getY() + (sin * distance));
-
- // search for fishing zone
- L2FishingZone fishingZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
- {
- if (zone instanceof L2FishingZone)
- {
- fishingZone = (L2FishingZone) zone;
- break;
- }
- }
- // search for water zone
- L2WaterZone waterZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
- {
- if (zone instanceof L2WaterZone)
- {
- waterZone = (L2WaterZone) zone;
- break;
- }
- }
-
- int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
- if (baitZ == Integer.MIN_VALUE)
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
- return null;
- }
-
- return new Location(baitX, baitY, baitZ);
- }
-
- /**
- * Computes the Z of the bait.
- * @param player the player
- * @param baitX the bait x
- * @param baitY the bait y
- * @param fishingZone the fishing zone
- * @param waterZone the water zone
- * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
- */
- private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
- {
- if ((fishingZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- if ((waterZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- // always use water zone, fishing zone high z is high in the air...
- final int baitZ = waterZone.getWaterZ();
-
- // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
- //
- // return Integer.MIN_VALUE;
- // }
-
- if (GeoEngine.getInstance().hasGeo(baitX, baitY))
- {
- if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
-
- if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
- }
-
- return baitZ;
- }
-}
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.commons.util.Rnd;
+import com.l2jmobius.gameserver.data.xml.impl.FishingData;
+import com.l2jmobius.gameserver.enums.ShotType;
+import com.l2jmobius.gameserver.geoengine.GeoEngine;
+import com.l2jmobius.gameserver.instancemanager.ZoneManager;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.PcCondOverride;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.events.EventDispatcher;
+import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
+import com.l2jmobius.gameserver.model.interfaces.ILocational;
+import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.model.items.type.WeaponType;
+import com.l2jmobius.gameserver.model.zone.L2ZoneType;
+import com.l2jmobius.gameserver.model.zone.ZoneId;
+import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
+import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
+import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author bit
+ */
+public class Fishing
+{
+ protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
+ private volatile ILocational _baitLocation = new Location(0, 0, 0);
+
+ private final L2PcInstance _player;
+ private ScheduledFuture> _reelInTask;
+ private ScheduledFuture> _startFishingTask;
+ private boolean _isFishing = false;
+
+ public Fishing(L2PcInstance player)
+ {
+ _player = player;
+ }
+
+ public synchronized boolean isFishing()
+ {
+ return _isFishing;
+ }
+
+ public boolean isAtValidLocation()
+ {
+ // TODO: implement checking direction
+ // if (calculateBaitLocation() == null)
+ // {
+ // return false;
+ // }
+ return _player.isInsideZone(ZoneId.FISHING);
+ }
+
+ public boolean canFish()
+ {
+ return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
+ }
+
+ private FishingBait getCurrentBaitData()
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
+ }
+
+ private void cancelTasks()
+ {
+ if (_reelInTask != null)
+ {
+ _reelInTask.cancel(false);
+ _reelInTask = null;
+ }
+
+ if (_startFishingTask != null)
+ {
+ _startFishingTask.cancel(false);
+ _startFishingTask = null;
+ }
+ }
+
+ public synchronized void startFishing()
+ {
+ if (_isFishing)
+ {
+ return;
+ }
+ _isFishing = true;
+ castLine();
+ }
+
+ private void castLine()
+ {
+ if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
+ {
+ _player.sendMessage("Fishing is disabled.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ cancelTasks();
+
+ if (!canFish())
+ {
+ if (_isFishing)
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (Config.PREMIUM_SYSTEM_ENABLED)
+ {
+ if (Config.PREMIUM_ONLY_FISHING && !_player.hasPremiumStatus())
+ {
+ _player.sendMessage("Fishing is available to premium users only.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (baitData.isPremiumOnly() && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.FAILED_PLEASE_TRY_AGAIN_USING_THE_CORRECT_BAIT);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+ }
+
+ final int minPlayerLevel = baitData.getMinPlayerLevel();
+ final int maxPLayerLevel = baitData.getMaxPlayerLevel();
+ if ((_player.getLevel() < minPlayerLevel) && (_player.getLevel() > maxPLayerLevel))
+ {
+ _player.sendMessage("You do not meet the fishing level requirements.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final L2ItemInstance rod = _player.getActiveWeaponInstance();
+ if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingRod rodData = FishingData.getInstance().getRodData(rod.getId());
+ if (rodData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isTransformed() || _player.isInBoat())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHEN_TRANSFORMED_OR_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_IT_S_AGAINST_THE_RULES);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isCrafting() || _player.isInStoreMode())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ _baitLocation = calculateBaitLocation();
+ if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
+ {
+ if (_isFishing)
+ {
+ // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ else
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ _player.rechargeShots(false, false, true);
+ }
+
+ final long fishingTime = Math.max(Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()) - rodData.getReduceFishingTime(), 1000);
+ final long fishingWaitTime = Rnd.get(baitData.getWaitMin(), baitData.getWaitMax());
+
+ _reelInTask = ThreadPool.schedule(() ->
+ {
+ _player.getFishing().reelInWithReward();
+ _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), fishingWaitTime);
+ }, fishingTime);
+ _player.stopMove(null);
+ _player.broadcastPacket(new ExFishingStart(_player, -1, _baitLocation));
+ _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
+ _player.sendPacket(new PlaySound("SF_P_01"));
+ _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
+ }
+
+ public void reelInWithReward()
+ {
+ // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
+ // Then player may or may not catch the fish. Using fishing shots increases chance to win.
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ reelIn(FishingEndReason.LOSE, false);
+ LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
+ return;
+ }
+
+ double chance = baitData.getChance();
+ if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ chance *= 2;
+ }
+
+ if (Rnd.get(100) <= chance)
+ {
+ reelIn(FishingEndReason.WIN, true);
+ }
+ else
+ {
+ reelIn(FishingEndReason.LOSE, true);
+ }
+ }
+
+ private void reelIn(FishingEndReason reason, boolean consumeBait)
+ {
+ if (!_isFishing)
+ {
+ return;
+ }
+
+ cancelTasks();
+
+ try
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ if (consumeBait)
+ {
+ if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
+ {
+ reason = FishingEndReason.LOSE; // no bait - no reward
+ return;
+ }
+ }
+
+ if ((reason == FishingEndReason.WIN) && (bait != null))
+ {
+ final FishingBait baitData = FishingData.getInstance().getBaitData(bait.getId());
+ final FishingCatch fishingCatchData = baitData.getRandom();
+ if (fishingCatchData != null)
+ {
+ final FishingData fishingData = FishingData.getInstance();
+ final double lvlModifier = (Math.pow(_player.getLevel(), 2.2) * fishingCatchData.getMultiplier());
+ final long xp = (long) (Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier);
+ final long sp = (long) (Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier);
+ _player.addExpAndSp(xp, sp, true);
+ _player.getInventory().addItem("Fishing Reward", fishingCatchData.getItemId(), 1, _player, null);
+ final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
+ msg.addItemName(fishingCatchData.getItemId());
+ _player.sendPacket(msg);
+ _player.unchargeShot(ShotType.FISH_SOULSHOTS);
+ _player.rechargeShots(false, false, true);
+ }
+ else
+ {
+ LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
+ }
+ }
+ else if (reason == FishingEndReason.LOSE)
+ {
+ _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
+ }
+
+ if (consumeBait)
+ {
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
+ }
+ }
+ finally
+ {
+ _player.broadcastPacket(new ExFishingEnd(_player, reason));
+ _player.sendPacket(new ExUserInfoFishing(_player, false));
+ }
+ }
+
+ public void stopFishing()
+ {
+ stopFishing(FishingEndType.PLAYER_STOP);
+ }
+
+ public synchronized void stopFishing(FishingEndType endType)
+ {
+ if (_isFishing)
+ {
+ reelIn(FishingEndReason.STOP, false);
+ _isFishing = false;
+ switch (endType)
+ {
+ case PLAYER_STOP:
+ {
+ _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
+ break;
+ }
+ case PLAYER_CANCEL:
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ break;
+ }
+ }
+ }
+ }
+
+ public ILocational getBaitLocation()
+ {
+ return _baitLocation;
+ }
+
+ private Location calculateBaitLocation()
+ {
+ // calculate a position in front of the player with a random distance
+ final int distMin = FishingData.getInstance().getBaitDistanceMin();
+ final int distMax = FishingData.getInstance().getBaitDistanceMax();
+ int distance = Rnd.get(distMin, distMax);
+ final double angle = Util.convertHeadingToDegree(_player.getHeading());
+ final double radian = Math.toRadians(angle);
+ final double sin = Math.sin(radian);
+ final double cos = Math.cos(radian);
+ int baitX = (int) (_player.getX() + (cos * distance));
+ int baitY = (int) (_player.getY() + (sin * distance));
+
+ // search for fishing zone
+ L2FishingZone fishingZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
+ {
+ if (zone instanceof L2FishingZone)
+ {
+ fishingZone = (L2FishingZone) zone;
+ break;
+ }
+ }
+ // search for water zone
+ L2WaterZone waterZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
+ {
+ if (zone instanceof L2WaterZone)
+ {
+ waterZone = (L2WaterZone) zone;
+ break;
+ }
+ }
+
+ int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
+ if (baitZ == Integer.MIN_VALUE)
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
+ return null;
+ }
+
+ return new Location(baitX, baitY, baitZ);
+ }
+
+ /**
+ * Computes the Z of the bait.
+ * @param player the player
+ * @param baitX the bait x
+ * @param baitY the bait y
+ * @param fishingZone the fishing zone
+ * @param waterZone the water zone
+ * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
+ */
+ private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
+ {
+ if ((fishingZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if ((waterZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ // always use water zone, fishing zone high z is high in the air...
+ final int baitZ = waterZone.getWaterZ();
+
+ // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
+ //
+ // return Integer.MIN_VALUE;
+ // }
+
+ if (GeoEngine.getInstance().hasGeo(baitX, baitY))
+ {
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+ }
+
+ return baitZ;
+ }
+}
diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/FishingBaitData.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
similarity index 55%
rename from L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/FishingBaitData.java
rename to L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
index 9cf4893d66..f5a5764254 100644
--- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/FishingBaitData.java
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
@@ -1,98 +1,128 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author bit
- */
-public class FishingBaitData
-{
- private final int _itemId;
- private final int _level;
- private final int _minPlayerLevel;
- private final double _chance;
- private final int _timeMin;
- private final int _timeMax;
- private final int _waitMin;
- private final int _waitMax;
- private final List _rewards = new ArrayList<>();
-
- public FishingBaitData(int itemId, int level, int minPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax)
- {
- _itemId = itemId;
- _level = level;
- _minPlayerLevel = minPlayerLevel;
- _chance = chance;
- _timeMin = timeMin;
- _timeMax = timeMax;
- _waitMin = waitMin;
- _waitMax = waitMax;
- }
-
- public int getItemId()
- {
- return _itemId;
- }
-
- public int getLevel()
- {
- return _level;
- }
-
- public int getMinPlayerLevel()
- {
- return _minPlayerLevel;
- }
-
- public double getChance()
- {
- return _chance;
- }
-
- public int getTimeMin()
- {
- return _timeMin;
- }
-
- public int getTimeMax()
- {
- return _timeMax;
- }
-
- public int getWaitMin()
- {
- return _waitMin;
- }
-
- public int getWaitMax()
- {
- return _waitMax;
- }
-
- public List getRewards()
- {
- return _rewards;
- }
-
- public void addReward(int itemId)
- {
- _rewards.add(itemId);
- }
-}
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.l2jmobius.commons.util.Rnd;
+
+/**
+ * @author bit
+ */
+public class FishingBait
+{
+ private final int _itemId;
+ private final byte _level;
+ private final byte _minPlayerLevel;
+ private final byte _maxPlayerLevel;
+ private final double _chance;
+ private final int _timeMin;
+ private final int _timeMax;
+ private final int _waitMin;
+ private final int _waitMax;
+ private final boolean _isPremiumOnly;
+ private final List _rewards = new ArrayList<>();
+
+ public FishingBait(int itemId, byte level, byte minPlayerLevel, byte maxPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax, boolean isPremiumOnly)
+ {
+ _itemId = itemId;
+ _level = level;
+ _minPlayerLevel = minPlayerLevel;
+ _maxPlayerLevel = maxPlayerLevel;
+ _chance = chance;
+ _timeMin = timeMin;
+ _timeMax = timeMax;
+ _waitMin = waitMin;
+ _waitMax = waitMax;
+ _isPremiumOnly = isPremiumOnly;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public byte getLevel()
+ {
+ return _level;
+ }
+
+ public byte getMinPlayerLevel()
+ {
+ return _minPlayerLevel;
+ }
+
+ public byte getMaxPlayerLevel()
+ {
+ return _maxPlayerLevel;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public int getTimeMin()
+ {
+ return _timeMin;
+ }
+
+ public int getTimeMax()
+ {
+ return _timeMax;
+ }
+
+ public int getWaitMin()
+ {
+ return _waitMin;
+ }
+
+ public int getWaitMax()
+ {
+ return _waitMax;
+ }
+
+ public boolean isPremiumOnly()
+ {
+ return _isPremiumOnly;
+ }
+
+ public List getRewards()
+ {
+ return _rewards;
+ }
+
+ public void addReward(FishingCatch catchData)
+ {
+ _rewards.add(catchData);
+ }
+
+ public FishingCatch getRandom()
+ {
+ float random = Rnd.get(100);
+ for (FishingCatch fishingCatchData : _rewards)
+ {
+ if (fishingCatchData.getChance() > random)
+ {
+ return fishingCatchData;
+ }
+ random -= fishingCatchData.getChance();
+ }
+ return null;
+ }
+}
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
new file mode 100644
index 0000000000..85c2e42e5a
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
@@ -0,0 +1,49 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingCatch
+{
+ private final int _itemId;
+ private final float _chance;
+ private final float _multiplier;
+
+ public FishingCatch(int itemId, float chance, float multiplier)
+ {
+ _itemId = itemId;
+ _chance = chance;
+ _multiplier = multiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public float getChance()
+ {
+ return _chance;
+ }
+
+ public float getMultiplier()
+ {
+ return _multiplier;
+ }
+}
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
new file mode 100644
index 0000000000..93b5fb9b8e
--- /dev/null
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingRod
+{
+ private final int _itemId;
+ private final int _reduceFishingTime;
+ private final float _xpMultiplier;
+ private final float _spMultiplier;
+
+ public FishingRod(int itemId, int reduceFishingTime, float xpMultiplier, float spMultiplier)
+ {
+ _itemId = itemId;
+ _reduceFishingTime = reduceFishingTime;
+ _xpMultiplier = xpMultiplier;
+ _spMultiplier = spMultiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public int getReduceFishingTime()
+ {
+ return _reduceFishingTime;
+ }
+
+ public float getXpMultiplier()
+ {
+ return _xpMultiplier;
+ }
+
+ public float getSpMultiplier()
+ {
+ return _spMultiplier;
+ }
+}
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
index 71d8f10b3e..dfcf4d7f56 100644
--- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
@@ -20,10 +20,10 @@ import java.lang.ref.WeakReference;
import com.l2jmobius.Config;
import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.PcCondOverride;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.serverpackets.fishing.ExAutoFishAvailable;
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
index dea11bad61..cebaa3c7a5 100644
--- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
+++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
@@ -29,20 +29,17 @@ public class ExFishingStart implements IClientOutgoingPacket
{
private final L2PcInstance _player;
private final int _fishType;
- private final int _baitType;
private final ILocational _baitLocation;
/**
* @param player
* @param fishType
- * @param baitType - 0 = newbie, 1 = normal, 2 = night
* @param baitLocation
*/
- public ExFishingStart(L2PcInstance player, int fishType, int baitType, ILocational baitLocation)
+ public ExFishingStart(L2PcInstance player, int fishType, ILocational baitLocation)
{
_player = player;
_fishType = fishType;
- _baitType = baitType;
_baitLocation = baitLocation;
}
@@ -55,7 +52,7 @@ public class ExFishingStart implements IClientOutgoingPacket
packet.writeD(_baitLocation.getX());
packet.writeD(_baitLocation.getY());
packet.writeD(_baitLocation.getZ());
- packet.writeC(_baitType);
+ packet.writeC(0x01); // 0 = newbie, 1 = normal, 2 = night
return true;
}
}
diff --git a/L2J_Mobius_3.0_Helios/dist/game/config/Custom/PremiumSystem.ini b/L2J_Mobius_3.0_Helios/dist/game/config/Custom/PremiumSystem.ini
index 8b5d1f1f06..7b0874c29d 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/config/Custom/PremiumSystem.ini
+++ b/L2J_Mobius_3.0_Helios/dist/game/config/Custom/PremiumSystem.ini
@@ -45,3 +45,7 @@ EnablePremiumHennaSlotforNonPremium = True
# Also premium henna drawn at normal slots.
# Retail: False
EnableAnyHennaAtPremiumSlot = False
+
+# Enable Fishing only for premium players.
+# Retail: True
+PremiumOnlyFishing = False
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/Fishing.xml b/L2J_Mobius_3.0_Helios/dist/game/data/Fishing.xml
index 42f6633d60..0152888ab6 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/Fishing.xml
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/Fishing.xml
@@ -1,44 +1,41 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/default/34156-1.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/default/34156-1.htm
new file mode 100644
index 0000000000..44a2ea74ad
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/default/34156-1.htm
@@ -0,0 +1,7 @@
+Fisher Peeves:
+Heine Exclusive Bait is really great! It must be a gift from the fishing gods!
+There are some items that can only be caught with Heine Exclusive Bait. Isn't that amazing?
+No doubt the fishing gods heard about this place that gets filled with fishers and decided to grace us with this amazing bait.
+You should try it out!
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/default/34156.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/default/34156.htm
new file mode 100644
index 0000000000..09f6982054
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/default/34156.htm
@@ -0,0 +1,11 @@
+Fisher Peeves:
+Oh, nice to meet you! I'm Peeves, a fisher.
+When I was young, my parents didn't want me to fish since it's dangerous... But how could I stop doing something so fun?
+Are you interested in fishing? Have you heard of the Heine Exclusive Bait?
+If you have a Heine Exclusive Bait Coupon, I can exchange it for Heine Exclusive Bait.
+Oh yeah, I also got a special fishing rod. Bring me some Heine Fishing Coins and I'll give you a Fancy Fishing Rod.
+You can get them from the Exclusive Reward Chest that you can get when you fish with Heine Exclusive Bait.
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31563.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31563.htm
index 25b6b4b199..cfd0217738 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31563.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31563.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Perelin:
-Do you like fishing? I love it.
-Fishing is such a great hobby, don't you think? Sure, it's not very exerting, but...that's the point. I don't like to run around sweating, you know? You can just sit quietly and enjoy the silence.
-
-
-
-
-
-
-
-
-
+Fishing is such a great hobby, don't you think? Sure, it's not very exerting, but...that's the point. I don't like to run around sweating, you know? You can just sit quietly and enjoy silence.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31567.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31567.htm
index 70eb2e221b..9500514c8e 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31567.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31567.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Bleaker:
-Nice to meet you! They call me Bleaker.
-Besides teaching you how to fish, I also sell the fishing gear you'll need. Oh, and I'll buy any fish you catch. In other words, this is your one-stop fishing shop!
-
-
-
-
-
-
-
-
-
+Nice to meet you! They call me Bleaker. I am with the Fishing Guild. If it has to do with fishing, I'm your man. Most of the time, anyway.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31568.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31568.htm
index 49f54d15d9..b2d1001145 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31568.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31568.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Pamfus:
-Do you like fishing? I love it.
-Fishing is such a great hobby, don't you think? Sure, it's not very exerting, but...that's the point. I don't like to run around sweating, you know? You can just sit quietly and enjoy the silence.
-
-
-
-
-
-
-
-
-
+There's no hobby other than fishing that lets you enjoy the nature around you so much. I really do love fishing.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31570.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31570.htm
index e6b7859e93..e92d40e6fb 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31570.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31570.htm
@@ -1,15 +1,13 @@
Fishing Guild Member Lanosco:
-Did you catch one?
-Heh, fishing is harder than it looks, right? You need to be prepared at all times.
-Which is why I'm here! Come see me whenever you need something, and I'll set you right up.
-
-
-
-
-
-
-
-
-
+Hi, I'm Fishing Guild Member Lanosco. Did you catch anything today? Fishing is not as easy as you might, you know. You need to prepare thoroughly.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31571.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31571.htm
index 0f55831347..ce281416f3 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31571.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31571.htm
@@ -1,14 +1,13 @@
Fishermen's Guild Member Huffs:
-Welcome! Are you here to fish?
-There's no better way to relax and decompress after a stressful day, week, or life! Haha!
-
-
-
-
-
-
-
-
-
+Hello, and welcome. Are you here to learn about fishing? There's no better way to relax and decompress after a stressful day, week, or life! Haha! It's quite the experience, wrestling huge fish along the coast or on the riverbanks, armed with little more than a rod and some string.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31572.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31572.htm
index b8434accc2..2d82c9fa59 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31572.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31572.htm
@@ -1,14 +1,13 @@
Fishing Guild Member O'Fulle:
-Everything is plentiful here in Giran, which is why so many people spend their leisure time fishing. It's a sign of abundance!
-Oh, pardon me -- I'm O'Fulle, the only officially licensed fishing gear merchant in this territory! See me if you need to buy bait or sell fish. Fish only -- no mermaids! Haha!
-
-
-
-
-
-
-
-
-
+I'm Fishing Guild Member O'Fulle. Try your luck at fishing in Giran, the land of plenty! Watch out, catching mermaids might get you into trouble! Stick with the fish! Hahaha!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31573.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31573.htm
index 7a9d68571a..2903e2c1d0 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31573.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31573.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Monakan:
-Well, hello there. I'm Monakan.
-I can teach you about fishing items as well as how to fish. Oh, I'll also buy any fish you catch. In other words, this is your one-stop fishing shop!
-
-
-
-
-
-
-
-
-
+Well, hello there. I'm Monakan, a member of the Fishing Guild. I'm the one to come to when it comes to fishing, since I deal not only in fishing supplies but also the fish that are caught.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31574.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31574.htm
index 021707372b..fb24509ac6 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31574.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31574.htm
@@ -1,13 +1,13 @@
Fishing Guild Member Willie:
-Fishing has become all the rage in these parts! I think it's because of all the brainy people around here -- the Ivory Tower, for example! Lots of them just sit there thinking, and forget to actually catch the fish!
-
-
-
-
-
-
-
-
-
+Oren is a city of culture, to which many intelligent ones flock. That's why we have so many fishing enthusiasts!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31575.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31575.htm
index 5381af429a..58f12301c3 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31575.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31575.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Litulon:
-There's no better place for fishing than Innadril. Wet and warm all year round, beautiful scenery, the best place in the whole world.
-I mean, Goddess Eva watches over us after all. The City of Waters! Haha!
-
-
-
-
-
-
-
-
-
+The Innadril Territory is just the spot for fishing. I mean, Goddess Eva watches over us after all. The City of Waters! Haha!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31576.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31576.htm
index 40daf36a06..dc3fe17673 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31576.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31576.htm
@@ -1,14 +1,14 @@
Fishing Guild Member Berix:
-I'm quite happy to be holding the fishing contest in my native town. It's good to know I can do what I love, where I live.
-I think it's time we got to it, perfect weather for fishing!
-
-
-
-
-
-
-
-
-
+Pleased to meet you. I'm Berix, a member of the Fishing Guild. See, people tend to think that there are only hunters in the Hunter's Village, but we have a lot of great fishers as well! I'm one of them, you see. Hahahaha.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31577.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31577.htm
index 42e3023192..dcf0570a3a 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31577.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31577.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Linnaeus:
-Did you know that the king is an avid fisher himself? Haha!
-Aden is filled with prime fishing zones. How about spending this beautiful day on one of them?
-
-
-
-
-
-
-
-
-
+Did you know that the King is an avid fisher himself? Haha! We at the Fishing Guild are quite proud of this fact. He's actually quite the Master!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31578.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31578.htm
index 22424bd71f..9a39b5209d 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31578.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31578.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Hilgendorf:
-Welcome! Beautiful day for fishing, dontcha' think?
-My family has been in the Guild for generations, ever since my great-grandfather joined.
-
-
-
-
-
-
-
-
-
+Welcome, and good to see you! The weather's perfect for fishing, wouldn't you agree? My family has been in the Guild for generations, ever since my great-grandfather joined.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31579.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31579.htm
index 4905012750..d19e501e8e 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31579.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31579.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Klaus:
-Well, well, well! Another fisher, huh?
-You know how lucky you are to be here, right? With its many mountain streams and lakes, Goddard is a prime fishing land. People come from all over to test their skill and try their luck here.
-
-
-
-
-
-
-
-
-
+I am Klaus, one of Fishing Guild members. If you have anything you need related with fishing, fine me.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31696.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31696.htm
index afb7f7612b..10fc8d9b1e 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31696.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31696.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Platis:
-This area is a rare spot in Elmore where you can catch actual saltwater fish. It used to be a famous fishing site in the Elmoreden years, and now that things have slowed down, the fish population is back.
-Care to give it a try? Let me know if you need any equipment!
-
-
-
-
-
-
-
-
-
+This has been a very popular fishing dock since the age of the Elmoreden. This is the tranquil and beautiful fishing spot you've been searching high and low for, I tell you!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31697.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31697.htm
index b78f53e3e4..77ef12b6d8 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31697.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31697.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Eindarkner:
-Do you know about these hot springs? The effects of the nearby Forge of the Gods have created a whole network of them around here. There are special species of fish living in these hot springs! It's the opportunity of a lifetime.
-Let me know if you need anything!
-
-
-
-
-
-
-
-
-
+Have you heard about the Hot Springs in the area? There are natural hot springs everywhere, thanks to the Forge of the Gods. Before, there were fish to be caught in the hot springs as well, but they have all disappeared now. What a pity.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31989.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31989.htm
index f8b1a88ccd..c032d201fa 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31989.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/31989.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Batidae:
-You came here to fish, right? Who am I kidding, of course you did!
-No better way to spend an afternoon than casting the line!
-
-
-
-
-
-
-
-
-
+Welcome. Want to learn how to fish, do you? You must have really been running out of things to learn to come all the way here to learn about fishing, of all things. Frankly, you'd be doing yourself more good by learning how to mine ore in the mines over there. Anyways, since you're here, really, there's no better way to spend an afternoon than casting the line!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/32007.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/32007.htm
index 939f2f8362..f65b882bdc 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/32007.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/32007.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Galba:
-Rainbow Springs -- ahh, heaven!
-You should try fishing around here. The fish here are huge. Let me know if you need any fishing items or want to sell something.
-
-
-
-
-
-
-
-
-
+Since you've come to find me, I reckon you know that the Rainbow Springs are a veritable heaven on earth for us fishing enthusiasts. That's right, this is some of the best fishing you'll find anywhere.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fish_appearance_exchange.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fish_appearance_exchange.htm
new file mode 100644
index 0000000000..8d25e5d848
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fish_appearance_exchange.htm
@@ -0,0 +1,11 @@
+
+
+ Exchange for appearance items:
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual001.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual001.htm
index dc66dd577c..d7badfef10 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual001.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual001.htm
@@ -1,10 +1,8 @@
Fishing Manual:
-
-
+
-
-
-
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual002.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual002.htm
index 3c1bb703da..a37c28a0da 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual002.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual002.htm
@@ -1,6 +1,5 @@
Fishing Manual:
-In order to fish, you need to find a fishing area. Once you arrive at the right spot, you'll see the button on the right side of your screen that alerts you that you can fish.
+In order to fish, you need to find a fishing area. Once you arrive at the right spot, you'll see the button on the right side of your screen that alerts you that you can fish.
Then check if you can actually fish. Check that you have a Fishing Rod and Bait equipped. You can set the Fishing Shots to be used automatically when you fish.
-
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual003.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual003.htm
index da8ab5942b..910782fc81 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual003.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual003.htm
@@ -1,6 +1,4 @@
-Fishing Manual:
-A fishing zone refers to a place with enough fish to be caught.
-The places that are good for fishing are the following: around Lake Iris, Narsell Lake where the Coliseum is, Giran Harbor's coast, around the Plains of the Lizardmen, waterside in the Town of Gludio, the Neutral Zone, Heine, Fellmere Lake, and the bridge near the Town of Giran.
+Fishing Manual:
+In order to fish, you need to find a fishing area. Once you arrive at the right spot, you'll see the button on the right side of your screen that alerts you that you can fish. Then check if you can actually fish. Check that you have a Fishing Rod and Bait equipped. You can set the Fishing Shots to be used automatically when you fish.
-
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual004.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual004.htm
index 7d4dbce9a9..a45c766c9a 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual004.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual004.htm
@@ -1,7 +1,7 @@
-Fishing Manual:
-There are two types of bait.
-The Normal Bait, you can buy from me.
-If you want to catch more expensive fish, I recommend you use the Special Bait. I have never seen Special Bait, but I heard that you can get it from the boxes you get from fishing.
+Fishing Manual:
+There are three types of bait.
+These are the basic bait, the R99 bait which can be used by characters of Lv. 99 and above and he PC Cafe bait, which can be purchased using PC Cafe Points.
+Of these, the Fishing Guild sells the basic bait and the R99 bait.
+With each type of bait, you can catch different types of fish. The conditions for purchasing and use vary among bait types as well. The Powerful Fish, which is the most expensive fish you can catch, can be caught using the R99 bait or the PC Cafe bait.
-
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual008.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual008.htm
index 4a56fdac27..5063653e3a 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual008.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual008.htm
@@ -1,7 +1,6 @@
-Fishing Manual:
+Fishing Manual:
Created by the Black Anvil Guild at the request of Ampitri, the founder of the Fishing Guild, Fishing Shots are variations of Soulshots made for fishing.
But while Soulshots amplify a hit, Fishing Shots increase the fisher's chances of catching a fish.
It's an item that will help you catch fish more efficiently.
-
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual009.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual009.htm
index 3094aa089d..29fe921d82 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual009.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual009.htm
@@ -1,7 +1,7 @@
-Fishing Manual:
-You can sell the fish whole, take it apart to sell a portion, or use it to craft items. You can also exchange it for Elcyum Powder through our Fishing Guild.
-Keep in mind that you might lose everything when cutting up your fish though! It depends on your luck.
-You can also bring Elcyum Powder to our guild to learn some legendary fishing skills. You decide what to do with your fish.
+Fishing Manual:
+Bring the fish you catch to us to exchange for various items that the Fishing Guild deals in.
+The Ugly Fish and Nimble Fish can be exchanged for Fish Stew, Appearance Stones, Hair Accessories, Transformation Scrolls, and Weapon Appearance Stones.
+If you have caught a Powerful Fish, it may be exchanged for a Stardust item or Elcyum Powder which is needed when exchanging for a Zodiac Agathion Treasure Chest. You may also sell the fish to the shop.
+If you bring us Elcyum Powder, we can let you in on a few secret techniques that have been handed down in our guild through the generation. Please think carefully about what you want to do with the fish that you catch.
-
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual010.htm b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual010.htm
index 4769d79268..21fb4dec2d 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual010.htm
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/html/fisherman/fishing_manual010.htm
@@ -1,6 +1,38 @@
-Fishing Manual:
-You can buy Normal Bait from the Fishing Guild.
-As for the Special Bait, you can get it from the wooden boxes that you get from fishing. Use the Special Bait to catch shiny fish.
-
+Fishing Manual:
+The time required for fishing, and the rate of success vary according to the type of bait, the type of rod, and whether or not Fishing Shot is used.
+
+
+
+
Bait - Fishing Time and Standby Time
+
+
+
+For each bait, the time required until fish bite is preset.
+As for the basic bait sold in the shop,Fishing Time is 105 seconds, and Standby Time is 15 seconds.This means catching a single fish takes a total of 120 seconds.
+
+
+
+
+
Fishing Rod - Fishing Time reduced
+
+
+
+
+A better fishing rod will reduce Fishing Time.
+The Normal Fishing Rod and Sturdy Fishing Rodwill not reduce Fishing Time.When you obtain Master Fishing Rod Stage 1,your Fishing Time will begin to decrease.
+
+
+
+
+
Fishing Shot - Fishing Probability increased
+
+
+
+
+
+Fishing Shot increases your odds of catching a fish.
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2144.xml b/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2144.xml
new file mode 100644
index 0000000000..b763fcb01e
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2144.xml
@@ -0,0 +1,39 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+ 34156
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2194.xml b/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2194.xml
new file mode 100644
index 0000000000..52d33e59e4
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2194.xml
@@ -0,0 +1,70 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2195.xml b/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2195.xml
new file mode 100644
index 0000000000..e73c2546f1
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2195.xml
@@ -0,0 +1,138 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2203.xml b/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2203.xml
new file mode 100644
index 0000000000..82d49aba41
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2203.xml
@@ -0,0 +1,62 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2207.xml b/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2207.xml
new file mode 100644
index 0000000000..a0521b646d
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2207.xml
@@ -0,0 +1,62 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2208.xml b/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2208.xml
new file mode 100644
index 0000000000..0c8953f318
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/multisell/2208.xml
@@ -0,0 +1,94 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/multisell/3034.xml b/L2J_Mobius_3.0_Helios/dist/game/data/multisell/3034.xml
new file mode 100644
index 0000000000..6bd81e7b08
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/multisell/3034.xml
@@ -0,0 +1,22 @@
+
+
+
+ 34156
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/spawns/Innadril/Heine.xml b/L2J_Mobius_3.0_Helios/dist/game/data/spawns/Innadril/Heine.xml
index 7a35b26c4e..8a89d9a86e 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/spawns/Innadril/Heine.xml
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/spawns/Innadril/Heine.xml
@@ -75,6 +75,7 @@
+
-
\ No newline at end of file
+
diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/xsd/Fishing.xsd b/L2J_Mobius_3.0_Helios/dist/game/data/xsd/Fishing.xsd
index 16e5ed9699..1078ed7f77 100644
--- a/L2J_Mobius_3.0_Helios/dist/game/data/xsd/Fishing.xsd
+++ b/L2J_Mobius_3.0_Helios/dist/game/data/xsd/Fishing.xsd
@@ -9,13 +9,13 @@
-
+
-
+
@@ -30,17 +30,35 @@
+
+
-
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/Config.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/Config.java
index 17f3269c91..93eced46ef 100644
--- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/Config.java
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/Config.java
@@ -1145,11 +1145,12 @@ public final class Config
public static float PREMIUM_RATE_DROP_AMOUNT;
public static float PREMIUM_RATE_SPOIL_CHANCE;
public static float PREMIUM_RATE_SPOIL_AMOUNT;
+ public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
+ public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
public static boolean PREMIUM_HENNA_SLOT_ENABLED;
public static boolean PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL;
public static boolean PREMIUM_HENNA_SLOT_ALL_DYES;
- public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
- public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
+ public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
public static int PC_CAFE_MAX_POINTS;
@@ -2643,9 +2644,6 @@ public final class Config
PREMIUM_RATE_DROP_AMOUNT = PremiumSystem.getFloat("PremiumRateDropAmount", 1);
PREMIUM_RATE_SPOIL_CHANCE = PremiumSystem.getFloat("PremiumRateSpoilChance", 2);
PREMIUM_RATE_SPOIL_AMOUNT = PremiumSystem.getFloat("PremiumRateSpoilAmount", 1);
- PREMIUM_HENNA_SLOT_ENABLED = PremiumSystem.getBoolean("EnablePremiumHennaSlot", true);
- PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL = PremiumSystem.getBoolean("EnablePremiumHennaSlotforNonPremium", true);
- PREMIUM_HENNA_SLOT_ALL_DYES = PremiumSystem.getBoolean("EnableAnyHennaAtPremiumSlot", false);
final String[] premiumDropChanceMultiplier = PremiumSystem.getString("PremiumRateDropChanceByItemId", "").split(";");
PREMIUM_RATE_DROP_CHANCE_BY_ID = new HashMap<>(premiumDropChanceMultiplier.length);
if (!premiumDropChanceMultiplier[0].isEmpty())
@@ -2700,6 +2698,10 @@ public final class Config
}
}
}
+ PREMIUM_HENNA_SLOT_ENABLED = PremiumSystem.getBoolean("EnablePremiumHennaSlot", true);
+ PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL = PremiumSystem.getBoolean("EnablePremiumHennaSlotforNonPremium", true);
+ PREMIUM_HENNA_SLOT_ALL_DYES = PremiumSystem.getBoolean("EnableAnyHennaAtPremiumSlot", false);
+ PREMIUM_ONLY_FISHING = PremiumSystem.getBoolean("PremiumOnlyFishing", true);
// Load PrivateStoreRange config file (if exists)
final PropertiesParser PrivateStoreRange = new PropertiesParser(CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE);
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
index 91b5f9c43e..bacf1ed08c 100644
--- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
@@ -25,8 +25,12 @@ import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
+import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
-import com.l2jmobius.gameserver.model.FishingBaitData;
+import com.l2jmobius.gameserver.datatables.ItemTable;
+import com.l2jmobius.gameserver.model.fishing.FishingBait;
+import com.l2jmobius.gameserver.model.fishing.FishingCatch;
+import com.l2jmobius.gameserver.model.fishing.FishingRod;
/**
* This class holds the Fishing information.
@@ -35,7 +39,8 @@ import com.l2jmobius.gameserver.model.FishingBaitData;
public final class FishingData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(FishingData.class.getName());
- private final Map _baitData = new HashMap<>();
+ private final Map _baitData = new HashMap<>();
+ private final Map _rodData = new HashMap<>();
private int _baitDistanceMin;
private int _baitDistanceMax;
private double _expRateMin;
@@ -56,7 +61,7 @@ public final class FishingData implements IGameXmlReader
{
_baitData.clear();
parseDatapackFile("data/Fishing.xml");
- LOGGER.info(getClass().getSimpleName() + ": Loaded Fishing Data.");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _baitData.size() + " bait and " + _rodData.size() + " rod data.");
}
@Override
@@ -76,13 +81,13 @@ public final class FishingData implements IGameXmlReader
_baitDistanceMax = parseInteger(listItem.getAttributes(), "max");
break;
}
- case "experienceRate":
+ case "xpRate":
{
_expRateMin = parseDouble(listItem.getAttributes(), "min");
_expRateMax = parseDouble(listItem.getAttributes(), "max");
break;
}
- case "skillPointsRate":
+ case "spRate":
{
_spRateMin = parseDouble(listItem.getAttributes(), "min");
_spRateMax = parseDouble(listItem.getAttributes(), "max");
@@ -96,20 +101,39 @@ public final class FishingData implements IGameXmlReader
{
final NamedNodeMap attrs = bait.getAttributes();
final int itemId = parseInteger(attrs, "itemId");
- final int level = parseInteger(attrs, "level");
- final int minPlayerLevel = parseInteger(attrs, "minPlayerLevel");
+ final byte level = parseByte(attrs, "level", (byte) 1);
+ final byte minPlayerLevel = parseByte(attrs, "minPlayerLevel");
+ final byte maxPlayerLevel = parseByte(attrs, "minPlayerLevel", Config.PLAYER_MAXIMUM_LEVEL);
final double chance = parseDouble(attrs, "chance");
final int timeMin = parseInteger(attrs, "timeMin");
- final int timeMax = parseInteger(attrs, "timeMax");
+ final int timeMax = parseInteger(attrs, "timeMax", timeMin);
final int waitMin = parseInteger(attrs, "waitMin");
- final int waitMax = parseInteger(attrs, "waitMax");
- final FishingBaitData baitData = new FishingBaitData(itemId, level, minPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax);
+ final int waitMax = parseInteger(attrs, "waitMax", waitMin);
+ final boolean isPremiumOnly = parseBoolean(attrs, "isPremiumOnly", false);
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ final FishingBait baitData = new FishingBait(itemId, level, minPlayerLevel, maxPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax, isPremiumOnly);
for (Node c = bait.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("catch".equalsIgnoreCase(c.getNodeName()))
{
- baitData.addReward(parseInteger(c.getAttributes(), "itemId"));
+ final NamedNodeMap cAttrs = c.getAttributes();
+ final int cId = parseInteger(cAttrs, "itemId");
+ final float cChance = parseFloat(cAttrs, "chance");
+ final float cMultiplier = parseFloat(cAttrs, "multiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(cId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ baitData.addReward(new FishingCatch(cId, cChance, cMultiplier));
}
}
_baitData.put(baitData.getItemId(), baitData);
@@ -117,22 +141,44 @@ public final class FishingData implements IGameXmlReader
}
break;
}
+ case "rods":
+ {
+ for (Node rod = listItem.getFirstChild(); rod != null; rod = rod.getNextSibling())
+ {
+ if ("rod".equalsIgnoreCase(rod.getNodeName()))
+ {
+ final NamedNodeMap attrs = rod.getAttributes();
+ final int itemId = parseInteger(attrs, "itemId");
+ final int reduceFishingTime = parseInteger(attrs, "reduceFishingTime", 0);
+ final float xpMultiplier = parseFloat(attrs, "xpMultiplier", 1f);
+ final float spMultiplier = parseFloat(attrs, "spMultiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ _rodData.put(itemId, new FishingRod(itemId, reduceFishingTime, xpMultiplier, spMultiplier));
+ }
+ }
+ }
}
}
}
}
}
- /**
- * Gets the fishing rod.
- * @param baitItemId the item id
- * @return A list of reward item ids
- */
- public FishingBaitData getBaitData(int baitItemId)
+ public FishingBait getBaitData(int baitItemId)
{
return _baitData.get(baitItemId);
}
+ public FishingRod getRodData(int rodItemId)
+ {
+ return _rodData.get(rodItemId);
+ }
+
public int getBaitDistanceMin()
{
return _baitDistanceMin;
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
index 0bcb167d8c..75d169b374 100644
--- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
@@ -122,7 +122,6 @@ import com.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import com.l2jmobius.gameserver.model.BlockList;
import com.l2jmobius.gameserver.model.ClanPrivilege;
import com.l2jmobius.gameserver.model.ClanWar;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.L2AccessLevel;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
@@ -210,6 +209,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPCh
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPKill;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerReputationChanged;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerSubChange;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.MovieHolder;
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/Fishing.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
similarity index 80%
rename from L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/Fishing.java
rename to L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
index 4ce988cca5..f233b4ebdd 100644
--- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/Fishing.java
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
@@ -1,443 +1,471 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.concurrent.ScheduledFuture;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.commons.util.Rnd;
-import com.l2jmobius.gameserver.data.xml.impl.FishingData;
-import com.l2jmobius.gameserver.enums.ShotType;
-import com.l2jmobius.gameserver.geoengine.GeoEngine;
-import com.l2jmobius.gameserver.instancemanager.ZoneManager;
-import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jmobius.gameserver.model.events.EventDispatcher;
-import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
-import com.l2jmobius.gameserver.model.interfaces.ILocational;
-import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
-import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
-import com.l2jmobius.gameserver.model.items.type.WeaponType;
-import com.l2jmobius.gameserver.model.zone.L2ZoneType;
-import com.l2jmobius.gameserver.model.zone.ZoneId;
-import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
-import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
-import com.l2jmobius.gameserver.network.SystemMessageId;
-import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
-import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
-import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
-import com.l2jmobius.gameserver.util.Util;
-
-/**
- * @author bit
- */
-public class Fishing
-{
- protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
- private volatile ILocational _baitLocation = new Location(0, 0, 0);
-
- private final L2PcInstance _player;
- private ScheduledFuture> _reelInTask;
- private ScheduledFuture> _startFishingTask;
- private boolean _isFishing = false;
-
- public Fishing(L2PcInstance player)
- {
- _player = player;
- }
-
- public synchronized boolean isFishing()
- {
- return _isFishing;
- }
-
- public boolean isAtValidLocation()
- {
- // TODO: implement checking direction
- // if (calculateBaitLocation() == null)
- // {
- // return false;
- // }
- return _player.isInsideZone(ZoneId.FISHING);
- }
-
- public boolean canFish()
- {
- return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
- }
-
- private FishingBaitData getCurrentBaitData()
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
- }
-
- private void cancelTasks()
- {
- if (_reelInTask != null)
- {
- _reelInTask.cancel(false);
- _reelInTask = null;
- }
-
- if (_startFishingTask != null)
- {
- _startFishingTask.cancel(false);
- _startFishingTask = null;
- }
- }
-
- public synchronized void startFishing()
- {
- if (_isFishing)
- {
- return;
- }
- _isFishing = true;
- castLine();
- }
-
- private void castLine()
- {
- if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
- {
- _player.sendMessage("Fishing is disabled.");
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- cancelTasks();
-
- if (!canFish())
- {
- if (_isFishing)
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final FishingBaitData baitData = getCurrentBaitData();
- final int minPlayerLevel = baitData == null ? 85 : baitData.getMinPlayerLevel();
- if (_player.getLevel() < minPlayerLevel)
- {
- if (minPlayerLevel == 85)
- {
- _player.sendPacket(SystemMessageId.FISHING_IS_AVAILABLE_TO_CHARACTERS_LV_85_OR_ABOVE);
- }
- else // In case of custom fishing level.
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
- }
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final L2ItemInstance rod = _player.getActiveWeaponInstance();
- if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (baitData == null)
- {
- _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isTransformed() || _player.isInBoat())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHEN_TRANSFORMED_OR_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_IT_S_AGAINST_THE_RULES);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isCrafting() || _player.isInStoreMode())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- _baitLocation = calculateBaitLocation();
- if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
- {
- if (_isFishing)
- {
- // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- else
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- _player.rechargeShots(false, false, true);
- }
-
- _reelInTask = ThreadPool.schedule(() ->
- {
- _player.getFishing().reelInWithReward();
- _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), Rnd.get(baitData.getWaitMin(), baitData.getWaitMax()));
- }, Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()));
- _player.stopMove(null);
- _player.broadcastPacket(new ExFishingStart(_player, -1, baitData.getLevel(), _baitLocation));
- _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
- _player.sendPacket(new PlaySound("SF_P_01"));
- _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
- }
-
- public void reelInWithReward()
- {
- // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
- // Then player may or may not catch the fish. Using fishing shots increases chance to win.
- final FishingBaitData baitData = getCurrentBaitData();
- if (baitData == null)
- {
- reelIn(FishingEndReason.LOSE, false);
- LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
- return;
- }
-
- double chance = baitData.getChance();
- if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- chance *= 1.5; // +50 % chance to win
- }
-
- if (Rnd.get(0, 100) <= chance)
- {
- reelIn(FishingEndReason.WIN, true);
- }
- else
- {
- reelIn(FishingEndReason.LOSE, true);
- }
- }
-
- private void reelIn(FishingEndReason reason, boolean consumeBait)
- {
- if (!_isFishing)
- {
- return;
- }
-
- cancelTasks();
-
- try
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- if (consumeBait)
- {
- if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
- {
- reason = FishingEndReason.LOSE; // no bait - no reward
- return;
- }
- }
-
- if ((reason == FishingEndReason.WIN) && (bait != null))
- {
- final FishingBaitData baitData = FishingData.getInstance().getBaitData(bait.getId());
- final int numRewards = baitData.getRewards().size();
- if (numRewards > 0)
- {
- final FishingData fishingData = FishingData.getInstance();
- final int lvlModifier = _player.getLevel() * _player.getLevel();
- _player.addExpAndSp(Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier, Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier, true);
- final int fishId = baitData.getRewards().get(Rnd.get(0, numRewards - 1));
- _player.getInventory().addItem("Fishing Reward", fishId, 1, _player, null);
- final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
- msg.addItemName(fishId);
- _player.sendPacket(msg);
- _player.unchargeShot(ShotType.FISH_SOULSHOTS);
- _player.rechargeShots(false, false, true);
- }
- else
- {
- LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
- }
- }
- else if (reason == FishingEndReason.LOSE)
- {
- _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
- }
-
- if (consumeBait)
- {
- EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
- }
- }
- finally
- {
- _player.broadcastPacket(new ExFishingEnd(_player, reason));
- _player.sendPacket(new ExUserInfoFishing(_player, false));
- }
- }
-
- public void stopFishing()
- {
- stopFishing(FishingEndType.PLAYER_STOP);
- }
-
- public synchronized void stopFishing(FishingEndType endType)
- {
- if (_isFishing)
- {
- reelIn(FishingEndReason.STOP, false);
- _isFishing = false;
- switch (endType)
- {
- case PLAYER_STOP:
- {
- _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
- break;
- }
- case PLAYER_CANCEL:
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- break;
- }
- }
- }
- }
-
- public ILocational getBaitLocation()
- {
- return _baitLocation;
- }
-
- private Location calculateBaitLocation()
- {
- // calculate a position in front of the player with a random distance
- final int distMin = FishingData.getInstance().getBaitDistanceMin();
- final int distMax = FishingData.getInstance().getBaitDistanceMax();
- int distance = Rnd.get(distMin, distMax);
- final double angle = Util.convertHeadingToDegree(_player.getHeading());
- final double radian = Math.toRadians(angle);
- final double sin = Math.sin(radian);
- final double cos = Math.cos(radian);
- int baitX = (int) (_player.getX() + (cos * distance));
- int baitY = (int) (_player.getY() + (sin * distance));
-
- // search for fishing zone
- L2FishingZone fishingZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
- {
- if (zone instanceof L2FishingZone)
- {
- fishingZone = (L2FishingZone) zone;
- break;
- }
- }
- // search for water zone
- L2WaterZone waterZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
- {
- if (zone instanceof L2WaterZone)
- {
- waterZone = (L2WaterZone) zone;
- break;
- }
- }
-
- int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
- if (baitZ == Integer.MIN_VALUE)
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
- return null;
- }
-
- return new Location(baitX, baitY, baitZ);
- }
-
- /**
- * Computes the Z of the bait.
- * @param player the player
- * @param baitX the bait x
- * @param baitY the bait y
- * @param fishingZone the fishing zone
- * @param waterZone the water zone
- * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
- */
- private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
- {
- if ((fishingZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- if ((waterZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- // always use water zone, fishing zone high z is high in the air...
- final int baitZ = waterZone.getWaterZ();
-
- // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
- //
- // return Integer.MIN_VALUE;
- // }
-
- if (GeoEngine.getInstance().hasGeo(baitX, baitY))
- {
- if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
-
- if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
- }
-
- return baitZ;
- }
-}
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.commons.util.Rnd;
+import com.l2jmobius.gameserver.data.xml.impl.FishingData;
+import com.l2jmobius.gameserver.enums.ShotType;
+import com.l2jmobius.gameserver.geoengine.GeoEngine;
+import com.l2jmobius.gameserver.instancemanager.ZoneManager;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.PcCondOverride;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.events.EventDispatcher;
+import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
+import com.l2jmobius.gameserver.model.interfaces.ILocational;
+import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.model.items.type.WeaponType;
+import com.l2jmobius.gameserver.model.zone.L2ZoneType;
+import com.l2jmobius.gameserver.model.zone.ZoneId;
+import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
+import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
+import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author bit
+ */
+public class Fishing
+{
+ protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
+ private volatile ILocational _baitLocation = new Location(0, 0, 0);
+
+ private final L2PcInstance _player;
+ private ScheduledFuture> _reelInTask;
+ private ScheduledFuture> _startFishingTask;
+ private boolean _isFishing = false;
+
+ public Fishing(L2PcInstance player)
+ {
+ _player = player;
+ }
+
+ public synchronized boolean isFishing()
+ {
+ return _isFishing;
+ }
+
+ public boolean isAtValidLocation()
+ {
+ // TODO: implement checking direction
+ // if (calculateBaitLocation() == null)
+ // {
+ // return false;
+ // }
+ return _player.isInsideZone(ZoneId.FISHING);
+ }
+
+ public boolean canFish()
+ {
+ return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
+ }
+
+ private FishingBait getCurrentBaitData()
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
+ }
+
+ private void cancelTasks()
+ {
+ if (_reelInTask != null)
+ {
+ _reelInTask.cancel(false);
+ _reelInTask = null;
+ }
+
+ if (_startFishingTask != null)
+ {
+ _startFishingTask.cancel(false);
+ _startFishingTask = null;
+ }
+ }
+
+ public synchronized void startFishing()
+ {
+ if (_isFishing)
+ {
+ return;
+ }
+ _isFishing = true;
+ castLine();
+ }
+
+ private void castLine()
+ {
+ if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
+ {
+ _player.sendMessage("Fishing is disabled.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ cancelTasks();
+
+ if (!canFish())
+ {
+ if (_isFishing)
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (Config.PREMIUM_SYSTEM_ENABLED)
+ {
+ if (Config.PREMIUM_ONLY_FISHING && !_player.hasPremiumStatus())
+ {
+ _player.sendMessage("Fishing is available to premium users only.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (baitData.isPremiumOnly() && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.FAILED_PLEASE_TRY_AGAIN_USING_THE_CORRECT_BAIT);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+ }
+
+ final int minPlayerLevel = baitData.getMinPlayerLevel();
+ final int maxPLayerLevel = baitData.getMaxPlayerLevel();
+ if ((_player.getLevel() < minPlayerLevel) && (_player.getLevel() > maxPLayerLevel))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final L2ItemInstance rod = _player.getActiveWeaponInstance();
+ if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingRod rodData = FishingData.getInstance().getRodData(rod.getId());
+ if (rodData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isTransformed() || _player.isInBoat())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHEN_TRANSFORMED_OR_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_IT_S_AGAINST_THE_RULES);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isCrafting() || _player.isInStoreMode())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ _baitLocation = calculateBaitLocation();
+ if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
+ {
+ if (_isFishing)
+ {
+ // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ else
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ _player.rechargeShots(false, false, true);
+ }
+
+ final long fishingTime = Math.max(Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()) - rodData.getReduceFishingTime(), 1000);
+ final long fishingWaitTime = Rnd.get(baitData.getWaitMin(), baitData.getWaitMax());
+
+ _reelInTask = ThreadPool.schedule(() ->
+ {
+ _player.getFishing().reelInWithReward();
+ _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), fishingWaitTime);
+ }, fishingTime);
+ _player.stopMove(null);
+ _player.broadcastPacket(new ExFishingStart(_player, -1, _baitLocation));
+ _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
+ _player.sendPacket(new PlaySound("SF_P_01"));
+ _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
+ }
+
+ public void reelInWithReward()
+ {
+ // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
+ // Then player may or may not catch the fish. Using fishing shots increases chance to win.
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ reelIn(FishingEndReason.LOSE, false);
+ LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
+ return;
+ }
+
+ double chance = baitData.getChance();
+ if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ chance *= 2;
+ }
+
+ if (Rnd.get(100) <= chance)
+ {
+ reelIn(FishingEndReason.WIN, true);
+ }
+ else
+ {
+ reelIn(FishingEndReason.LOSE, true);
+ }
+ }
+
+ private void reelIn(FishingEndReason reason, boolean consumeBait)
+ {
+ if (!_isFishing)
+ {
+ return;
+ }
+
+ cancelTasks();
+
+ try
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ if (consumeBait)
+ {
+ if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
+ {
+ reason = FishingEndReason.LOSE; // no bait - no reward
+ return;
+ }
+ }
+
+ if ((reason == FishingEndReason.WIN) && (bait != null))
+ {
+ final FishingBait baitData = FishingData.getInstance().getBaitData(bait.getId());
+ final FishingCatch fishingCatchData = baitData.getRandom();
+ if (fishingCatchData != null)
+ {
+ final FishingData fishingData = FishingData.getInstance();
+ final double lvlModifier = (Math.pow(_player.getLevel(), 2.2) * fishingCatchData.getMultiplier());
+ final long xp = (long) (Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier);
+ final long sp = (long) (Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier);
+ _player.addExpAndSp(xp, sp, true);
+ _player.getInventory().addItem("Fishing Reward", fishingCatchData.getItemId(), 1, _player, null);
+ final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
+ msg.addItemName(fishingCatchData.getItemId());
+ _player.sendPacket(msg);
+ _player.unchargeShot(ShotType.FISH_SOULSHOTS);
+ _player.rechargeShots(false, false, true);
+ }
+ else
+ {
+ LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
+ }
+ }
+ else if (reason == FishingEndReason.LOSE)
+ {
+ _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
+ }
+
+ if (consumeBait)
+ {
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
+ }
+ }
+ finally
+ {
+ _player.broadcastPacket(new ExFishingEnd(_player, reason));
+ _player.sendPacket(new ExUserInfoFishing(_player, false));
+ }
+ }
+
+ public void stopFishing()
+ {
+ stopFishing(FishingEndType.PLAYER_STOP);
+ }
+
+ public synchronized void stopFishing(FishingEndType endType)
+ {
+ if (_isFishing)
+ {
+ reelIn(FishingEndReason.STOP, false);
+ _isFishing = false;
+ switch (endType)
+ {
+ case PLAYER_STOP:
+ {
+ _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
+ break;
+ }
+ case PLAYER_CANCEL:
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ break;
+ }
+ }
+ }
+ }
+
+ public ILocational getBaitLocation()
+ {
+ return _baitLocation;
+ }
+
+ private Location calculateBaitLocation()
+ {
+ // calculate a position in front of the player with a random distance
+ final int distMin = FishingData.getInstance().getBaitDistanceMin();
+ final int distMax = FishingData.getInstance().getBaitDistanceMax();
+ int distance = Rnd.get(distMin, distMax);
+ final double angle = Util.convertHeadingToDegree(_player.getHeading());
+ final double radian = Math.toRadians(angle);
+ final double sin = Math.sin(radian);
+ final double cos = Math.cos(radian);
+ int baitX = (int) (_player.getX() + (cos * distance));
+ int baitY = (int) (_player.getY() + (sin * distance));
+
+ // search for fishing zone
+ L2FishingZone fishingZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
+ {
+ if (zone instanceof L2FishingZone)
+ {
+ fishingZone = (L2FishingZone) zone;
+ break;
+ }
+ }
+ // search for water zone
+ L2WaterZone waterZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
+ {
+ if (zone instanceof L2WaterZone)
+ {
+ waterZone = (L2WaterZone) zone;
+ break;
+ }
+ }
+
+ int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
+ if (baitZ == Integer.MIN_VALUE)
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
+ return null;
+ }
+
+ return new Location(baitX, baitY, baitZ);
+ }
+
+ /**
+ * Computes the Z of the bait.
+ * @param player the player
+ * @param baitX the bait x
+ * @param baitY the bait y
+ * @param fishingZone the fishing zone
+ * @param waterZone the water zone
+ * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
+ */
+ private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
+ {
+ if ((fishingZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if ((waterZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ // always use water zone, fishing zone high z is high in the air...
+ final int baitZ = waterZone.getWaterZ();
+
+ // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
+ //
+ // return Integer.MIN_VALUE;
+ // }
+
+ if (GeoEngine.getInstance().hasGeo(baitX, baitY))
+ {
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+ }
+
+ return baitZ;
+ }
+}
diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/FishingBaitData.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
similarity index 55%
rename from L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/FishingBaitData.java
rename to L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
index 9cf4893d66..f5a5764254 100644
--- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/FishingBaitData.java
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
@@ -1,98 +1,128 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author bit
- */
-public class FishingBaitData
-{
- private final int _itemId;
- private final int _level;
- private final int _minPlayerLevel;
- private final double _chance;
- private final int _timeMin;
- private final int _timeMax;
- private final int _waitMin;
- private final int _waitMax;
- private final List _rewards = new ArrayList<>();
-
- public FishingBaitData(int itemId, int level, int minPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax)
- {
- _itemId = itemId;
- _level = level;
- _minPlayerLevel = minPlayerLevel;
- _chance = chance;
- _timeMin = timeMin;
- _timeMax = timeMax;
- _waitMin = waitMin;
- _waitMax = waitMax;
- }
-
- public int getItemId()
- {
- return _itemId;
- }
-
- public int getLevel()
- {
- return _level;
- }
-
- public int getMinPlayerLevel()
- {
- return _minPlayerLevel;
- }
-
- public double getChance()
- {
- return _chance;
- }
-
- public int getTimeMin()
- {
- return _timeMin;
- }
-
- public int getTimeMax()
- {
- return _timeMax;
- }
-
- public int getWaitMin()
- {
- return _waitMin;
- }
-
- public int getWaitMax()
- {
- return _waitMax;
- }
-
- public List getRewards()
- {
- return _rewards;
- }
-
- public void addReward(int itemId)
- {
- _rewards.add(itemId);
- }
-}
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.l2jmobius.commons.util.Rnd;
+
+/**
+ * @author bit
+ */
+public class FishingBait
+{
+ private final int _itemId;
+ private final byte _level;
+ private final byte _minPlayerLevel;
+ private final byte _maxPlayerLevel;
+ private final double _chance;
+ private final int _timeMin;
+ private final int _timeMax;
+ private final int _waitMin;
+ private final int _waitMax;
+ private final boolean _isPremiumOnly;
+ private final List _rewards = new ArrayList<>();
+
+ public FishingBait(int itemId, byte level, byte minPlayerLevel, byte maxPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax, boolean isPremiumOnly)
+ {
+ _itemId = itemId;
+ _level = level;
+ _minPlayerLevel = minPlayerLevel;
+ _maxPlayerLevel = maxPlayerLevel;
+ _chance = chance;
+ _timeMin = timeMin;
+ _timeMax = timeMax;
+ _waitMin = waitMin;
+ _waitMax = waitMax;
+ _isPremiumOnly = isPremiumOnly;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public byte getLevel()
+ {
+ return _level;
+ }
+
+ public byte getMinPlayerLevel()
+ {
+ return _minPlayerLevel;
+ }
+
+ public byte getMaxPlayerLevel()
+ {
+ return _maxPlayerLevel;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public int getTimeMin()
+ {
+ return _timeMin;
+ }
+
+ public int getTimeMax()
+ {
+ return _timeMax;
+ }
+
+ public int getWaitMin()
+ {
+ return _waitMin;
+ }
+
+ public int getWaitMax()
+ {
+ return _waitMax;
+ }
+
+ public boolean isPremiumOnly()
+ {
+ return _isPremiumOnly;
+ }
+
+ public List getRewards()
+ {
+ return _rewards;
+ }
+
+ public void addReward(FishingCatch catchData)
+ {
+ _rewards.add(catchData);
+ }
+
+ public FishingCatch getRandom()
+ {
+ float random = Rnd.get(100);
+ for (FishingCatch fishingCatchData : _rewards)
+ {
+ if (fishingCatchData.getChance() > random)
+ {
+ return fishingCatchData;
+ }
+ random -= fishingCatchData.getChance();
+ }
+ return null;
+ }
+}
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
new file mode 100644
index 0000000000..85c2e42e5a
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
@@ -0,0 +1,49 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingCatch
+{
+ private final int _itemId;
+ private final float _chance;
+ private final float _multiplier;
+
+ public FishingCatch(int itemId, float chance, float multiplier)
+ {
+ _itemId = itemId;
+ _chance = chance;
+ _multiplier = multiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public float getChance()
+ {
+ return _chance;
+ }
+
+ public float getMultiplier()
+ {
+ return _multiplier;
+ }
+}
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
new file mode 100644
index 0000000000..93b5fb9b8e
--- /dev/null
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingRod
+{
+ private final int _itemId;
+ private final int _reduceFishingTime;
+ private final float _xpMultiplier;
+ private final float _spMultiplier;
+
+ public FishingRod(int itemId, int reduceFishingTime, float xpMultiplier, float spMultiplier)
+ {
+ _itemId = itemId;
+ _reduceFishingTime = reduceFishingTime;
+ _xpMultiplier = xpMultiplier;
+ _spMultiplier = spMultiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public int getReduceFishingTime()
+ {
+ return _reduceFishingTime;
+ }
+
+ public float getXpMultiplier()
+ {
+ return _xpMultiplier;
+ }
+
+ public float getSpMultiplier()
+ {
+ return _spMultiplier;
+ }
+}
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
index 71d8f10b3e..dfcf4d7f56 100644
--- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
@@ -20,10 +20,10 @@ import java.lang.ref.WeakReference;
import com.l2jmobius.Config;
import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.PcCondOverride;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.serverpackets.fishing.ExAutoFishAvailable;
diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
index dea11bad61..cebaa3c7a5 100644
--- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
+++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
@@ -29,20 +29,17 @@ public class ExFishingStart implements IClientOutgoingPacket
{
private final L2PcInstance _player;
private final int _fishType;
- private final int _baitType;
private final ILocational _baitLocation;
/**
* @param player
* @param fishType
- * @param baitType - 0 = newbie, 1 = normal, 2 = night
* @param baitLocation
*/
- public ExFishingStart(L2PcInstance player, int fishType, int baitType, ILocational baitLocation)
+ public ExFishingStart(L2PcInstance player, int fishType, ILocational baitLocation)
{
_player = player;
_fishType = fishType;
- _baitType = baitType;
_baitLocation = baitLocation;
}
@@ -55,7 +52,7 @@ public class ExFishingStart implements IClientOutgoingPacket
packet.writeD(_baitLocation.getX());
packet.writeD(_baitLocation.getY());
packet.writeD(_baitLocation.getZ());
- packet.writeC(_baitType);
+ packet.writeC(0x01); // 0 = newbie, 1 = normal, 2 = night
return true;
}
}
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/config/Custom/PremiumSystem.ini b/L2J_Mobius_4.0_GrandCrusade/dist/game/config/Custom/PremiumSystem.ini
index 8b5d1f1f06..7b0874c29d 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/config/Custom/PremiumSystem.ini
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/config/Custom/PremiumSystem.ini
@@ -45,3 +45,7 @@ EnablePremiumHennaSlotforNonPremium = True
# Also premium henna drawn at normal slots.
# Retail: False
EnableAnyHennaAtPremiumSlot = False
+
+# Enable Fishing only for premium players.
+# Retail: True
+PremiumOnlyFishing = False
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/Fishing.xml b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/Fishing.xml
index 42f6633d60..0152888ab6 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/Fishing.xml
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/Fishing.xml
@@ -1,44 +1,41 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/default/34156-1.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/default/34156-1.htm
new file mode 100644
index 0000000000..44a2ea74ad
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/default/34156-1.htm
@@ -0,0 +1,7 @@
+Fisher Peeves:
+Heine Exclusive Bait is really great! It must be a gift from the fishing gods!
+There are some items that can only be caught with Heine Exclusive Bait. Isn't that amazing?
+No doubt the fishing gods heard about this place that gets filled with fishers and decided to grace us with this amazing bait.
+You should try it out!
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/default/34156.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/default/34156.htm
new file mode 100644
index 0000000000..09f6982054
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/default/34156.htm
@@ -0,0 +1,11 @@
+Fisher Peeves:
+Oh, nice to meet you! I'm Peeves, a fisher.
+When I was young, my parents didn't want me to fish since it's dangerous... But how could I stop doing something so fun?
+Are you interested in fishing? Have you heard of the Heine Exclusive Bait?
+If you have a Heine Exclusive Bait Coupon, I can exchange it for Heine Exclusive Bait.
+Oh yeah, I also got a special fishing rod. Bring me some Heine Fishing Coins and I'll give you a Fancy Fishing Rod.
+You can get them from the Exclusive Reward Chest that you can get when you fish with Heine Exclusive Bait.
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31563.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31563.htm
index 25b6b4b199..cfd0217738 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31563.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31563.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Perelin:
-Do you like fishing? I love it.
-Fishing is such a great hobby, don't you think? Sure, it's not very exerting, but...that's the point. I don't like to run around sweating, you know? You can just sit quietly and enjoy the silence.
-
-
-
-
-
-
-
-
-
+Fishing is such a great hobby, don't you think? Sure, it's not very exerting, but...that's the point. I don't like to run around sweating, you know? You can just sit quietly and enjoy silence.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31567.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31567.htm
index 70eb2e221b..9500514c8e 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31567.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31567.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Bleaker:
-Nice to meet you! They call me Bleaker.
-Besides teaching you how to fish, I also sell the fishing gear you'll need. Oh, and I'll buy any fish you catch. In other words, this is your one-stop fishing shop!
-
-
-
-
-
-
-
-
-
+Nice to meet you! They call me Bleaker. I am with the Fishing Guild. If it has to do with fishing, I'm your man. Most of the time, anyway.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31568.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31568.htm
index 49f54d15d9..b2d1001145 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31568.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31568.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Pamfus:
-Do you like fishing? I love it.
-Fishing is such a great hobby, don't you think? Sure, it's not very exerting, but...that's the point. I don't like to run around sweating, you know? You can just sit quietly and enjoy the silence.
-
-
-
-
-
-
-
-
-
+There's no hobby other than fishing that lets you enjoy the nature around you so much. I really do love fishing.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31570.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31570.htm
index e6b7859e93..e92d40e6fb 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31570.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31570.htm
@@ -1,15 +1,13 @@
Fishing Guild Member Lanosco:
-Did you catch one?
-Heh, fishing is harder than it looks, right? You need to be prepared at all times.
-Which is why I'm here! Come see me whenever you need something, and I'll set you right up.
-
-
-
-
-
-
-
-
-
+Hi, I'm Fishing Guild Member Lanosco. Did you catch anything today? Fishing is not as easy as you might, you know. You need to prepare thoroughly.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31571.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31571.htm
index 0f55831347..ce281416f3 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31571.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31571.htm
@@ -1,14 +1,13 @@
Fishermen's Guild Member Huffs:
-Welcome! Are you here to fish?
-There's no better way to relax and decompress after a stressful day, week, or life! Haha!
-
-
-
-
-
-
-
-
-
+Hello, and welcome. Are you here to learn about fishing? There's no better way to relax and decompress after a stressful day, week, or life! Haha! It's quite the experience, wrestling huge fish along the coast or on the riverbanks, armed with little more than a rod and some string.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31572.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31572.htm
index b8434accc2..2d82c9fa59 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31572.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31572.htm
@@ -1,14 +1,13 @@
Fishing Guild Member O'Fulle:
-Everything is plentiful here in Giran, which is why so many people spend their leisure time fishing. It's a sign of abundance!
-Oh, pardon me -- I'm O'Fulle, the only officially licensed fishing gear merchant in this territory! See me if you need to buy bait or sell fish. Fish only -- no mermaids! Haha!
-
-
-
-
-
-
-
-
-
+I'm Fishing Guild Member O'Fulle. Try your luck at fishing in Giran, the land of plenty! Watch out, catching mermaids might get you into trouble! Stick with the fish! Hahaha!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31573.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31573.htm
index 7a9d68571a..2903e2c1d0 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31573.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31573.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Monakan:
-Well, hello there. I'm Monakan.
-I can teach you about fishing items as well as how to fish. Oh, I'll also buy any fish you catch. In other words, this is your one-stop fishing shop!
-
-
-
-
-
-
-
-
-
+Well, hello there. I'm Monakan, a member of the Fishing Guild. I'm the one to come to when it comes to fishing, since I deal not only in fishing supplies but also the fish that are caught.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31574.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31574.htm
index 021707372b..fb24509ac6 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31574.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31574.htm
@@ -1,13 +1,13 @@
Fishing Guild Member Willie:
-Fishing has become all the rage in these parts! I think it's because of all the brainy people around here -- the Ivory Tower, for example! Lots of them just sit there thinking, and forget to actually catch the fish!
-
-
-
-
-
-
-
-
-
+Oren is a city of culture, to which many intelligent ones flock. That's why we have so many fishing enthusiasts!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31575.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31575.htm
index 5381af429a..58f12301c3 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31575.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31575.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Litulon:
-There's no better place for fishing than Innadril. Wet and warm all year round, beautiful scenery, the best place in the whole world.
-I mean, Goddess Eva watches over us after all. The City of Waters! Haha!
-
-
-
-
-
-
-
-
-
+The Innadril Territory is just the spot for fishing. I mean, Goddess Eva watches over us after all. The City of Waters! Haha!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31576.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31576.htm
index 40daf36a06..dc3fe17673 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31576.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31576.htm
@@ -1,14 +1,14 @@
Fishing Guild Member Berix:
-I'm quite happy to be holding the fishing contest in my native town. It's good to know I can do what I love, where I live.
-I think it's time we got to it, perfect weather for fishing!
-
-
-
-
-
-
-
-
-
+Pleased to meet you. I'm Berix, a member of the Fishing Guild. See, people tend to think that there are only hunters in the Hunter's Village, but we have a lot of great fishers as well! I'm one of them, you see. Hahahaha.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31577.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31577.htm
index 42e3023192..dcf0570a3a 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31577.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31577.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Linnaeus:
-Did you know that the king is an avid fisher himself? Haha!
-Aden is filled with prime fishing zones. How about spending this beautiful day on one of them?
-
-
-
-
-
-
-
-
-
+Did you know that the King is an avid fisher himself? Haha! We at the Fishing Guild are quite proud of this fact. He's actually quite the Master!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31578.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31578.htm
index 22424bd71f..9a39b5209d 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31578.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31578.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Hilgendorf:
-Welcome! Beautiful day for fishing, dontcha' think?
-My family has been in the Guild for generations, ever since my great-grandfather joined.
-
-
-
-
-
-
-
-
-
+Welcome, and good to see you! The weather's perfect for fishing, wouldn't you agree? My family has been in the Guild for generations, ever since my great-grandfather joined.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31579.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31579.htm
index 4905012750..d19e501e8e 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31579.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31579.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Klaus:
-Well, well, well! Another fisher, huh?
-You know how lucky you are to be here, right? With its many mountain streams and lakes, Goddard is a prime fishing land. People come from all over to test their skill and try their luck here.
-
-
-
-
-
-
-
-
-
+I am Klaus, one of Fishing Guild members. If you have anything you need related with fishing, fine me.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31696.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31696.htm
index afb7f7612b..10fc8d9b1e 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31696.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31696.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Platis:
-This area is a rare spot in Elmore where you can catch actual saltwater fish. It used to be a famous fishing site in the Elmoreden years, and now that things have slowed down, the fish population is back.
-Care to give it a try? Let me know if you need any equipment!
-
-
-
-
-
-
-
-
-
+This has been a very popular fishing dock since the age of the Elmoreden. This is the tranquil and beautiful fishing spot you've been searching high and low for, I tell you!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31697.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31697.htm
index b78f53e3e4..77ef12b6d8 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31697.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31697.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Eindarkner:
-Do you know about these hot springs? The effects of the nearby Forge of the Gods have created a whole network of them around here. There are special species of fish living in these hot springs! It's the opportunity of a lifetime.
-Let me know if you need anything!
-
-
-
-
-
-
-
-
-
+Have you heard about the Hot Springs in the area? There are natural hot springs everywhere, thanks to the Forge of the Gods. Before, there were fish to be caught in the hot springs as well, but they have all disappeared now. What a pity.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31989.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31989.htm
index f8b1a88ccd..c032d201fa 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31989.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/31989.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Batidae:
-You came here to fish, right? Who am I kidding, of course you did!
-No better way to spend an afternoon than casting the line!
-
-
-
-
-
-
-
-
-
+Welcome. Want to learn how to fish, do you? You must have really been running out of things to learn to come all the way here to learn about fishing, of all things. Frankly, you'd be doing yourself more good by learning how to mine ore in the mines over there. Anyways, since you're here, really, there's no better way to spend an afternoon than casting the line!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/32007.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/32007.htm
index 939f2f8362..f65b882bdc 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/32007.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/32007.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Galba:
-Rainbow Springs -- ahh, heaven!
-You should try fishing around here. The fish here are huge. Let me know if you need any fishing items or want to sell something.
-
-
-
-
-
-
-
-
-
+Since you've come to find me, I reckon you know that the Rainbow Springs are a veritable heaven on earth for us fishing enthusiasts. That's right, this is some of the best fishing you'll find anywhere.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fish_appearance_exchange.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fish_appearance_exchange.htm
new file mode 100644
index 0000000000..8d25e5d848
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fish_appearance_exchange.htm
@@ -0,0 +1,11 @@
+
+
+ Exchange for appearance items:
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual001.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual001.htm
index dc66dd577c..d7badfef10 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual001.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual001.htm
@@ -1,10 +1,8 @@
Fishing Manual:
-
-
+
-
-
-
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual002.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual002.htm
index 3c1bb703da..a37c28a0da 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual002.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual002.htm
@@ -1,6 +1,5 @@
Fishing Manual:
-In order to fish, you need to find a fishing area. Once you arrive at the right spot, you'll see the button on the right side of your screen that alerts you that you can fish.
+In order to fish, you need to find a fishing area. Once you arrive at the right spot, you'll see the button on the right side of your screen that alerts you that you can fish.
Then check if you can actually fish. Check that you have a Fishing Rod and Bait equipped. You can set the Fishing Shots to be used automatically when you fish.
-
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual003.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual003.htm
index da8ab5942b..910782fc81 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual003.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual003.htm
@@ -1,6 +1,4 @@
-Fishing Manual:
-A fishing zone refers to a place with enough fish to be caught.
-The places that are good for fishing are the following: around Lake Iris, Narsell Lake where the Coliseum is, Giran Harbor's coast, around the Plains of the Lizardmen, waterside in the Town of Gludio, the Neutral Zone, Heine, Fellmere Lake, and the bridge near the Town of Giran.
+Fishing Manual:
+In order to fish, you need to find a fishing area. Once you arrive at the right spot, you'll see the button on the right side of your screen that alerts you that you can fish. Then check if you can actually fish. Check that you have a Fishing Rod and Bait equipped. You can set the Fishing Shots to be used automatically when you fish.
-
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual004.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual004.htm
index 7d4dbce9a9..a45c766c9a 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual004.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual004.htm
@@ -1,7 +1,7 @@
-Fishing Manual:
-There are two types of bait.
-The Normal Bait, you can buy from me.
-If you want to catch more expensive fish, I recommend you use the Special Bait. I have never seen Special Bait, but I heard that you can get it from the boxes you get from fishing.
+Fishing Manual:
+There are three types of bait.
+These are the basic bait, the R99 bait which can be used by characters of Lv. 99 and above and he PC Cafe bait, which can be purchased using PC Cafe Points.
+Of these, the Fishing Guild sells the basic bait and the R99 bait.
+With each type of bait, you can catch different types of fish. The conditions for purchasing and use vary among bait types as well. The Powerful Fish, which is the most expensive fish you can catch, can be caught using the R99 bait or the PC Cafe bait.
-
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual008.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual008.htm
index 4a56fdac27..5063653e3a 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual008.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual008.htm
@@ -1,7 +1,6 @@
-Fishing Manual:
+Fishing Manual:
Created by the Black Anvil Guild at the request of Ampitri, the founder of the Fishing Guild, Fishing Shots are variations of Soulshots made for fishing.
But while Soulshots amplify a hit, Fishing Shots increase the fisher's chances of catching a fish.
It's an item that will help you catch fish more efficiently.
-
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual009.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual009.htm
index 3094aa089d..29fe921d82 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual009.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual009.htm
@@ -1,7 +1,7 @@
-Fishing Manual:
-You can sell the fish whole, take it apart to sell a portion, or use it to craft items. You can also exchange it for Elcyum Powder through our Fishing Guild.
-Keep in mind that you might lose everything when cutting up your fish though! It depends on your luck.
-You can also bring Elcyum Powder to our guild to learn some legendary fishing skills. You decide what to do with your fish.
+Fishing Manual:
+Bring the fish you catch to us to exchange for various items that the Fishing Guild deals in.
+The Ugly Fish and Nimble Fish can be exchanged for Fish Stew, Appearance Stones, Hair Accessories, Transformation Scrolls, and Weapon Appearance Stones.
+If you have caught a Powerful Fish, it may be exchanged for a Stardust item or Elcyum Powder which is needed when exchanging for a Zodiac Agathion Treasure Chest. You may also sell the fish to the shop.
+If you bring us Elcyum Powder, we can let you in on a few secret techniques that have been handed down in our guild through the generation. Please think carefully about what you want to do with the fish that you catch.
-
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual010.htm b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual010.htm
index 4769d79268..21fb4dec2d 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual010.htm
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/html/fisherman/fishing_manual010.htm
@@ -1,6 +1,38 @@
-Fishing Manual:
-You can buy Normal Bait from the Fishing Guild.
-As for the Special Bait, you can get it from the wooden boxes that you get from fishing. Use the Special Bait to catch shiny fish.
-
+Fishing Manual:
+The time required for fishing, and the rate of success vary according to the type of bait, the type of rod, and whether or not Fishing Shot is used.
+
+
+
+
Bait - Fishing Time and Standby Time
+
+
+
+For each bait, the time required until fish bite is preset.
+As for the basic bait sold in the shop,Fishing Time is 105 seconds, and Standby Time is 15 seconds.This means catching a single fish takes a total of 120 seconds.
+
+
+
+
+
Fishing Rod - Fishing Time reduced
+
+
+
+
+A better fishing rod will reduce Fishing Time.
+The Normal Fishing Rod and Sturdy Fishing Rodwill not reduce Fishing Time.When you obtain Master Fishing Rod Stage 1,your Fishing Time will begin to decrease.
+
+
+
+
+
Fishing Shot - Fishing Probability increased
+
+
+
+
+
+Fishing Shot increases your odds of catching a fish.
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2144.xml b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2144.xml
new file mode 100644
index 0000000000..b763fcb01e
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2144.xml
@@ -0,0 +1,39 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+ 34156
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2194.xml b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2194.xml
new file mode 100644
index 0000000000..52d33e59e4
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2194.xml
@@ -0,0 +1,70 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2195.xml b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2195.xml
new file mode 100644
index 0000000000..e73c2546f1
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2195.xml
@@ -0,0 +1,138 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2203.xml b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2203.xml
new file mode 100644
index 0000000000..82d49aba41
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2203.xml
@@ -0,0 +1,62 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2207.xml b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2207.xml
new file mode 100644
index 0000000000..a0521b646d
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2207.xml
@@ -0,0 +1,62 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2208.xml b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2208.xml
new file mode 100644
index 0000000000..0c8953f318
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/2208.xml
@@ -0,0 +1,94 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/3034.xml b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/3034.xml
new file mode 100644
index 0000000000..6bd81e7b08
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/multisell/3034.xml
@@ -0,0 +1,22 @@
+
+
+
+ 34156
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/spawns/Innadril/Heine.xml b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/spawns/Innadril/Heine.xml
index 7a35b26c4e..8a89d9a86e 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/spawns/Innadril/Heine.xml
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/spawns/Innadril/Heine.xml
@@ -75,6 +75,7 @@
+
-
\ No newline at end of file
+
diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/xsd/Fishing.xsd b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/xsd/Fishing.xsd
index 16e5ed9699..1078ed7f77 100644
--- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/xsd/Fishing.xsd
+++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/xsd/Fishing.xsd
@@ -9,13 +9,13 @@
-
+
-
+
@@ -30,17 +30,35 @@
+
+
-
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/Config.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/Config.java
index ef5eccccae..cf3474f16d 100644
--- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/Config.java
+++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/Config.java
@@ -1138,11 +1138,12 @@ public final class Config
public static float PREMIUM_RATE_DROP_AMOUNT;
public static float PREMIUM_RATE_SPOIL_CHANCE;
public static float PREMIUM_RATE_SPOIL_AMOUNT;
+ public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
+ public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
public static boolean PREMIUM_HENNA_SLOT_ENABLED;
public static boolean PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL;
public static boolean PREMIUM_HENNA_SLOT_ALL_DYES;
- public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
- public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
+ public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
public static int PC_CAFE_MAX_POINTS;
@@ -2629,9 +2630,6 @@ public final class Config
PREMIUM_RATE_DROP_AMOUNT = PremiumSystem.getFloat("PremiumRateDropAmount", 1);
PREMIUM_RATE_SPOIL_CHANCE = PremiumSystem.getFloat("PremiumRateSpoilChance", 2);
PREMIUM_RATE_SPOIL_AMOUNT = PremiumSystem.getFloat("PremiumRateSpoilAmount", 1);
- PREMIUM_HENNA_SLOT_ENABLED = PremiumSystem.getBoolean("EnablePremiumHennaSlot", true);
- PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL = PremiumSystem.getBoolean("EnablePremiumHennaSlotforNonPremium", true);
- PREMIUM_HENNA_SLOT_ALL_DYES = PremiumSystem.getBoolean("EnableAnyHennaAtPremiumSlot", false);
final String[] premiumDropChanceMultiplier = PremiumSystem.getString("PremiumRateDropChanceByItemId", "").split(";");
PREMIUM_RATE_DROP_CHANCE_BY_ID = new HashMap<>(premiumDropChanceMultiplier.length);
if (!premiumDropChanceMultiplier[0].isEmpty())
@@ -2686,6 +2684,10 @@ public final class Config
}
}
}
+ PREMIUM_HENNA_SLOT_ENABLED = PremiumSystem.getBoolean("EnablePremiumHennaSlot", true);
+ PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL = PremiumSystem.getBoolean("EnablePremiumHennaSlotforNonPremium", true);
+ PREMIUM_HENNA_SLOT_ALL_DYES = PremiumSystem.getBoolean("EnableAnyHennaAtPremiumSlot", false);
+ PREMIUM_ONLY_FISHING = PremiumSystem.getBoolean("PremiumOnlyFishing", true);
// Load PrivateStoreRange config file (if exists)
final PropertiesParser PrivateStoreRange = new PropertiesParser(CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE);
diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
index 91b5f9c43e..bacf1ed08c 100644
--- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
+++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
@@ -25,8 +25,12 @@ import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
+import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
-import com.l2jmobius.gameserver.model.FishingBaitData;
+import com.l2jmobius.gameserver.datatables.ItemTable;
+import com.l2jmobius.gameserver.model.fishing.FishingBait;
+import com.l2jmobius.gameserver.model.fishing.FishingCatch;
+import com.l2jmobius.gameserver.model.fishing.FishingRod;
/**
* This class holds the Fishing information.
@@ -35,7 +39,8 @@ import com.l2jmobius.gameserver.model.FishingBaitData;
public final class FishingData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(FishingData.class.getName());
- private final Map _baitData = new HashMap<>();
+ private final Map _baitData = new HashMap<>();
+ private final Map _rodData = new HashMap<>();
private int _baitDistanceMin;
private int _baitDistanceMax;
private double _expRateMin;
@@ -56,7 +61,7 @@ public final class FishingData implements IGameXmlReader
{
_baitData.clear();
parseDatapackFile("data/Fishing.xml");
- LOGGER.info(getClass().getSimpleName() + ": Loaded Fishing Data.");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _baitData.size() + " bait and " + _rodData.size() + " rod data.");
}
@Override
@@ -76,13 +81,13 @@ public final class FishingData implements IGameXmlReader
_baitDistanceMax = parseInteger(listItem.getAttributes(), "max");
break;
}
- case "experienceRate":
+ case "xpRate":
{
_expRateMin = parseDouble(listItem.getAttributes(), "min");
_expRateMax = parseDouble(listItem.getAttributes(), "max");
break;
}
- case "skillPointsRate":
+ case "spRate":
{
_spRateMin = parseDouble(listItem.getAttributes(), "min");
_spRateMax = parseDouble(listItem.getAttributes(), "max");
@@ -96,20 +101,39 @@ public final class FishingData implements IGameXmlReader
{
final NamedNodeMap attrs = bait.getAttributes();
final int itemId = parseInteger(attrs, "itemId");
- final int level = parseInteger(attrs, "level");
- final int minPlayerLevel = parseInteger(attrs, "minPlayerLevel");
+ final byte level = parseByte(attrs, "level", (byte) 1);
+ final byte minPlayerLevel = parseByte(attrs, "minPlayerLevel");
+ final byte maxPlayerLevel = parseByte(attrs, "minPlayerLevel", Config.PLAYER_MAXIMUM_LEVEL);
final double chance = parseDouble(attrs, "chance");
final int timeMin = parseInteger(attrs, "timeMin");
- final int timeMax = parseInteger(attrs, "timeMax");
+ final int timeMax = parseInteger(attrs, "timeMax", timeMin);
final int waitMin = parseInteger(attrs, "waitMin");
- final int waitMax = parseInteger(attrs, "waitMax");
- final FishingBaitData baitData = new FishingBaitData(itemId, level, minPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax);
+ final int waitMax = parseInteger(attrs, "waitMax", waitMin);
+ final boolean isPremiumOnly = parseBoolean(attrs, "isPremiumOnly", false);
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ final FishingBait baitData = new FishingBait(itemId, level, minPlayerLevel, maxPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax, isPremiumOnly);
for (Node c = bait.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("catch".equalsIgnoreCase(c.getNodeName()))
{
- baitData.addReward(parseInteger(c.getAttributes(), "itemId"));
+ final NamedNodeMap cAttrs = c.getAttributes();
+ final int cId = parseInteger(cAttrs, "itemId");
+ final float cChance = parseFloat(cAttrs, "chance");
+ final float cMultiplier = parseFloat(cAttrs, "multiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(cId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ baitData.addReward(new FishingCatch(cId, cChance, cMultiplier));
}
}
_baitData.put(baitData.getItemId(), baitData);
@@ -117,22 +141,44 @@ public final class FishingData implements IGameXmlReader
}
break;
}
+ case "rods":
+ {
+ for (Node rod = listItem.getFirstChild(); rod != null; rod = rod.getNextSibling())
+ {
+ if ("rod".equalsIgnoreCase(rod.getNodeName()))
+ {
+ final NamedNodeMap attrs = rod.getAttributes();
+ final int itemId = parseInteger(attrs, "itemId");
+ final int reduceFishingTime = parseInteger(attrs, "reduceFishingTime", 0);
+ final float xpMultiplier = parseFloat(attrs, "xpMultiplier", 1f);
+ final float spMultiplier = parseFloat(attrs, "spMultiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ _rodData.put(itemId, new FishingRod(itemId, reduceFishingTime, xpMultiplier, spMultiplier));
+ }
+ }
+ }
}
}
}
}
}
- /**
- * Gets the fishing rod.
- * @param baitItemId the item id
- * @return A list of reward item ids
- */
- public FishingBaitData getBaitData(int baitItemId)
+ public FishingBait getBaitData(int baitItemId)
{
return _baitData.get(baitItemId);
}
+ public FishingRod getRodData(int rodItemId)
+ {
+ return _rodData.get(rodItemId);
+ }
+
public int getBaitDistanceMin()
{
return _baitDistanceMin;
diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
index 91e36c32ab..3f68adf47a 100644
--- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
+++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
@@ -125,7 +125,6 @@ import com.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import com.l2jmobius.gameserver.model.BlockList;
import com.l2jmobius.gameserver.model.ClanPrivilege;
import com.l2jmobius.gameserver.model.ClanWar;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.L2AccessLevel;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
@@ -209,6 +208,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPCh
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPKill;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerReputationChanged;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerSubChange;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.MonsterBookCardHolder;
diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/Fishing.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
similarity index 80%
rename from L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/Fishing.java
rename to L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
index 4ce988cca5..f233b4ebdd 100644
--- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/Fishing.java
+++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
@@ -1,443 +1,471 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.concurrent.ScheduledFuture;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.commons.util.Rnd;
-import com.l2jmobius.gameserver.data.xml.impl.FishingData;
-import com.l2jmobius.gameserver.enums.ShotType;
-import com.l2jmobius.gameserver.geoengine.GeoEngine;
-import com.l2jmobius.gameserver.instancemanager.ZoneManager;
-import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jmobius.gameserver.model.events.EventDispatcher;
-import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
-import com.l2jmobius.gameserver.model.interfaces.ILocational;
-import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
-import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
-import com.l2jmobius.gameserver.model.items.type.WeaponType;
-import com.l2jmobius.gameserver.model.zone.L2ZoneType;
-import com.l2jmobius.gameserver.model.zone.ZoneId;
-import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
-import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
-import com.l2jmobius.gameserver.network.SystemMessageId;
-import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
-import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
-import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
-import com.l2jmobius.gameserver.util.Util;
-
-/**
- * @author bit
- */
-public class Fishing
-{
- protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
- private volatile ILocational _baitLocation = new Location(0, 0, 0);
-
- private final L2PcInstance _player;
- private ScheduledFuture> _reelInTask;
- private ScheduledFuture> _startFishingTask;
- private boolean _isFishing = false;
-
- public Fishing(L2PcInstance player)
- {
- _player = player;
- }
-
- public synchronized boolean isFishing()
- {
- return _isFishing;
- }
-
- public boolean isAtValidLocation()
- {
- // TODO: implement checking direction
- // if (calculateBaitLocation() == null)
- // {
- // return false;
- // }
- return _player.isInsideZone(ZoneId.FISHING);
- }
-
- public boolean canFish()
- {
- return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
- }
-
- private FishingBaitData getCurrentBaitData()
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
- }
-
- private void cancelTasks()
- {
- if (_reelInTask != null)
- {
- _reelInTask.cancel(false);
- _reelInTask = null;
- }
-
- if (_startFishingTask != null)
- {
- _startFishingTask.cancel(false);
- _startFishingTask = null;
- }
- }
-
- public synchronized void startFishing()
- {
- if (_isFishing)
- {
- return;
- }
- _isFishing = true;
- castLine();
- }
-
- private void castLine()
- {
- if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
- {
- _player.sendMessage("Fishing is disabled.");
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- cancelTasks();
-
- if (!canFish())
- {
- if (_isFishing)
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final FishingBaitData baitData = getCurrentBaitData();
- final int minPlayerLevel = baitData == null ? 85 : baitData.getMinPlayerLevel();
- if (_player.getLevel() < minPlayerLevel)
- {
- if (minPlayerLevel == 85)
- {
- _player.sendPacket(SystemMessageId.FISHING_IS_AVAILABLE_TO_CHARACTERS_LV_85_OR_ABOVE);
- }
- else // In case of custom fishing level.
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
- }
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final L2ItemInstance rod = _player.getActiveWeaponInstance();
- if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (baitData == null)
- {
- _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isTransformed() || _player.isInBoat())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHEN_TRANSFORMED_OR_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_IT_S_AGAINST_THE_RULES);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isCrafting() || _player.isInStoreMode())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- _baitLocation = calculateBaitLocation();
- if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
- {
- if (_isFishing)
- {
- // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- else
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- _player.rechargeShots(false, false, true);
- }
-
- _reelInTask = ThreadPool.schedule(() ->
- {
- _player.getFishing().reelInWithReward();
- _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), Rnd.get(baitData.getWaitMin(), baitData.getWaitMax()));
- }, Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()));
- _player.stopMove(null);
- _player.broadcastPacket(new ExFishingStart(_player, -1, baitData.getLevel(), _baitLocation));
- _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
- _player.sendPacket(new PlaySound("SF_P_01"));
- _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
- }
-
- public void reelInWithReward()
- {
- // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
- // Then player may or may not catch the fish. Using fishing shots increases chance to win.
- final FishingBaitData baitData = getCurrentBaitData();
- if (baitData == null)
- {
- reelIn(FishingEndReason.LOSE, false);
- LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
- return;
- }
-
- double chance = baitData.getChance();
- if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- chance *= 1.5; // +50 % chance to win
- }
-
- if (Rnd.get(0, 100) <= chance)
- {
- reelIn(FishingEndReason.WIN, true);
- }
- else
- {
- reelIn(FishingEndReason.LOSE, true);
- }
- }
-
- private void reelIn(FishingEndReason reason, boolean consumeBait)
- {
- if (!_isFishing)
- {
- return;
- }
-
- cancelTasks();
-
- try
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- if (consumeBait)
- {
- if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
- {
- reason = FishingEndReason.LOSE; // no bait - no reward
- return;
- }
- }
-
- if ((reason == FishingEndReason.WIN) && (bait != null))
- {
- final FishingBaitData baitData = FishingData.getInstance().getBaitData(bait.getId());
- final int numRewards = baitData.getRewards().size();
- if (numRewards > 0)
- {
- final FishingData fishingData = FishingData.getInstance();
- final int lvlModifier = _player.getLevel() * _player.getLevel();
- _player.addExpAndSp(Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier, Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier, true);
- final int fishId = baitData.getRewards().get(Rnd.get(0, numRewards - 1));
- _player.getInventory().addItem("Fishing Reward", fishId, 1, _player, null);
- final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
- msg.addItemName(fishId);
- _player.sendPacket(msg);
- _player.unchargeShot(ShotType.FISH_SOULSHOTS);
- _player.rechargeShots(false, false, true);
- }
- else
- {
- LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
- }
- }
- else if (reason == FishingEndReason.LOSE)
- {
- _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
- }
-
- if (consumeBait)
- {
- EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
- }
- }
- finally
- {
- _player.broadcastPacket(new ExFishingEnd(_player, reason));
- _player.sendPacket(new ExUserInfoFishing(_player, false));
- }
- }
-
- public void stopFishing()
- {
- stopFishing(FishingEndType.PLAYER_STOP);
- }
-
- public synchronized void stopFishing(FishingEndType endType)
- {
- if (_isFishing)
- {
- reelIn(FishingEndReason.STOP, false);
- _isFishing = false;
- switch (endType)
- {
- case PLAYER_STOP:
- {
- _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
- break;
- }
- case PLAYER_CANCEL:
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- break;
- }
- }
- }
- }
-
- public ILocational getBaitLocation()
- {
- return _baitLocation;
- }
-
- private Location calculateBaitLocation()
- {
- // calculate a position in front of the player with a random distance
- final int distMin = FishingData.getInstance().getBaitDistanceMin();
- final int distMax = FishingData.getInstance().getBaitDistanceMax();
- int distance = Rnd.get(distMin, distMax);
- final double angle = Util.convertHeadingToDegree(_player.getHeading());
- final double radian = Math.toRadians(angle);
- final double sin = Math.sin(radian);
- final double cos = Math.cos(radian);
- int baitX = (int) (_player.getX() + (cos * distance));
- int baitY = (int) (_player.getY() + (sin * distance));
-
- // search for fishing zone
- L2FishingZone fishingZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
- {
- if (zone instanceof L2FishingZone)
- {
- fishingZone = (L2FishingZone) zone;
- break;
- }
- }
- // search for water zone
- L2WaterZone waterZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
- {
- if (zone instanceof L2WaterZone)
- {
- waterZone = (L2WaterZone) zone;
- break;
- }
- }
-
- int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
- if (baitZ == Integer.MIN_VALUE)
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
- return null;
- }
-
- return new Location(baitX, baitY, baitZ);
- }
-
- /**
- * Computes the Z of the bait.
- * @param player the player
- * @param baitX the bait x
- * @param baitY the bait y
- * @param fishingZone the fishing zone
- * @param waterZone the water zone
- * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
- */
- private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
- {
- if ((fishingZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- if ((waterZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- // always use water zone, fishing zone high z is high in the air...
- final int baitZ = waterZone.getWaterZ();
-
- // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
- //
- // return Integer.MIN_VALUE;
- // }
-
- if (GeoEngine.getInstance().hasGeo(baitX, baitY))
- {
- if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
-
- if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
- }
-
- return baitZ;
- }
-}
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.commons.util.Rnd;
+import com.l2jmobius.gameserver.data.xml.impl.FishingData;
+import com.l2jmobius.gameserver.enums.ShotType;
+import com.l2jmobius.gameserver.geoengine.GeoEngine;
+import com.l2jmobius.gameserver.instancemanager.ZoneManager;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.PcCondOverride;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.events.EventDispatcher;
+import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
+import com.l2jmobius.gameserver.model.interfaces.ILocational;
+import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.model.items.type.WeaponType;
+import com.l2jmobius.gameserver.model.zone.L2ZoneType;
+import com.l2jmobius.gameserver.model.zone.ZoneId;
+import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
+import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
+import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author bit
+ */
+public class Fishing
+{
+ protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
+ private volatile ILocational _baitLocation = new Location(0, 0, 0);
+
+ private final L2PcInstance _player;
+ private ScheduledFuture> _reelInTask;
+ private ScheduledFuture> _startFishingTask;
+ private boolean _isFishing = false;
+
+ public Fishing(L2PcInstance player)
+ {
+ _player = player;
+ }
+
+ public synchronized boolean isFishing()
+ {
+ return _isFishing;
+ }
+
+ public boolean isAtValidLocation()
+ {
+ // TODO: implement checking direction
+ // if (calculateBaitLocation() == null)
+ // {
+ // return false;
+ // }
+ return _player.isInsideZone(ZoneId.FISHING);
+ }
+
+ public boolean canFish()
+ {
+ return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
+ }
+
+ private FishingBait getCurrentBaitData()
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
+ }
+
+ private void cancelTasks()
+ {
+ if (_reelInTask != null)
+ {
+ _reelInTask.cancel(false);
+ _reelInTask = null;
+ }
+
+ if (_startFishingTask != null)
+ {
+ _startFishingTask.cancel(false);
+ _startFishingTask = null;
+ }
+ }
+
+ public synchronized void startFishing()
+ {
+ if (_isFishing)
+ {
+ return;
+ }
+ _isFishing = true;
+ castLine();
+ }
+
+ private void castLine()
+ {
+ if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
+ {
+ _player.sendMessage("Fishing is disabled.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ cancelTasks();
+
+ if (!canFish())
+ {
+ if (_isFishing)
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (Config.PREMIUM_SYSTEM_ENABLED)
+ {
+ if (Config.PREMIUM_ONLY_FISHING && !_player.hasPremiumStatus())
+ {
+ _player.sendMessage("Fishing is available to premium users only.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (baitData.isPremiumOnly() && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.FAILED_PLEASE_TRY_AGAIN_USING_THE_CORRECT_BAIT);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+ }
+
+ final int minPlayerLevel = baitData.getMinPlayerLevel();
+ final int maxPLayerLevel = baitData.getMaxPlayerLevel();
+ if ((_player.getLevel() < minPlayerLevel) && (_player.getLevel() > maxPLayerLevel))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final L2ItemInstance rod = _player.getActiveWeaponInstance();
+ if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingRod rodData = FishingData.getInstance().getRodData(rod.getId());
+ if (rodData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isTransformed() || _player.isInBoat())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHEN_TRANSFORMED_OR_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_IT_S_AGAINST_THE_RULES);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isCrafting() || _player.isInStoreMode())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ _baitLocation = calculateBaitLocation();
+ if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
+ {
+ if (_isFishing)
+ {
+ // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ else
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ _player.rechargeShots(false, false, true);
+ }
+
+ final long fishingTime = Math.max(Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()) - rodData.getReduceFishingTime(), 1000);
+ final long fishingWaitTime = Rnd.get(baitData.getWaitMin(), baitData.getWaitMax());
+
+ _reelInTask = ThreadPool.schedule(() ->
+ {
+ _player.getFishing().reelInWithReward();
+ _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), fishingWaitTime);
+ }, fishingTime);
+ _player.stopMove(null);
+ _player.broadcastPacket(new ExFishingStart(_player, -1, _baitLocation));
+ _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
+ _player.sendPacket(new PlaySound("SF_P_01"));
+ _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
+ }
+
+ public void reelInWithReward()
+ {
+ // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
+ // Then player may or may not catch the fish. Using fishing shots increases chance to win.
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ reelIn(FishingEndReason.LOSE, false);
+ LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
+ return;
+ }
+
+ double chance = baitData.getChance();
+ if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ chance *= 2;
+ }
+
+ if (Rnd.get(100) <= chance)
+ {
+ reelIn(FishingEndReason.WIN, true);
+ }
+ else
+ {
+ reelIn(FishingEndReason.LOSE, true);
+ }
+ }
+
+ private void reelIn(FishingEndReason reason, boolean consumeBait)
+ {
+ if (!_isFishing)
+ {
+ return;
+ }
+
+ cancelTasks();
+
+ try
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ if (consumeBait)
+ {
+ if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
+ {
+ reason = FishingEndReason.LOSE; // no bait - no reward
+ return;
+ }
+ }
+
+ if ((reason == FishingEndReason.WIN) && (bait != null))
+ {
+ final FishingBait baitData = FishingData.getInstance().getBaitData(bait.getId());
+ final FishingCatch fishingCatchData = baitData.getRandom();
+ if (fishingCatchData != null)
+ {
+ final FishingData fishingData = FishingData.getInstance();
+ final double lvlModifier = (Math.pow(_player.getLevel(), 2.2) * fishingCatchData.getMultiplier());
+ final long xp = (long) (Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier);
+ final long sp = (long) (Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier);
+ _player.addExpAndSp(xp, sp, true);
+ _player.getInventory().addItem("Fishing Reward", fishingCatchData.getItemId(), 1, _player, null);
+ final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
+ msg.addItemName(fishingCatchData.getItemId());
+ _player.sendPacket(msg);
+ _player.unchargeShot(ShotType.FISH_SOULSHOTS);
+ _player.rechargeShots(false, false, true);
+ }
+ else
+ {
+ LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
+ }
+ }
+ else if (reason == FishingEndReason.LOSE)
+ {
+ _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
+ }
+
+ if (consumeBait)
+ {
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
+ }
+ }
+ finally
+ {
+ _player.broadcastPacket(new ExFishingEnd(_player, reason));
+ _player.sendPacket(new ExUserInfoFishing(_player, false));
+ }
+ }
+
+ public void stopFishing()
+ {
+ stopFishing(FishingEndType.PLAYER_STOP);
+ }
+
+ public synchronized void stopFishing(FishingEndType endType)
+ {
+ if (_isFishing)
+ {
+ reelIn(FishingEndReason.STOP, false);
+ _isFishing = false;
+ switch (endType)
+ {
+ case PLAYER_STOP:
+ {
+ _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
+ break;
+ }
+ case PLAYER_CANCEL:
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ break;
+ }
+ }
+ }
+ }
+
+ public ILocational getBaitLocation()
+ {
+ return _baitLocation;
+ }
+
+ private Location calculateBaitLocation()
+ {
+ // calculate a position in front of the player with a random distance
+ final int distMin = FishingData.getInstance().getBaitDistanceMin();
+ final int distMax = FishingData.getInstance().getBaitDistanceMax();
+ int distance = Rnd.get(distMin, distMax);
+ final double angle = Util.convertHeadingToDegree(_player.getHeading());
+ final double radian = Math.toRadians(angle);
+ final double sin = Math.sin(radian);
+ final double cos = Math.cos(radian);
+ int baitX = (int) (_player.getX() + (cos * distance));
+ int baitY = (int) (_player.getY() + (sin * distance));
+
+ // search for fishing zone
+ L2FishingZone fishingZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
+ {
+ if (zone instanceof L2FishingZone)
+ {
+ fishingZone = (L2FishingZone) zone;
+ break;
+ }
+ }
+ // search for water zone
+ L2WaterZone waterZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
+ {
+ if (zone instanceof L2WaterZone)
+ {
+ waterZone = (L2WaterZone) zone;
+ break;
+ }
+ }
+
+ int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
+ if (baitZ == Integer.MIN_VALUE)
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
+ return null;
+ }
+
+ return new Location(baitX, baitY, baitZ);
+ }
+
+ /**
+ * Computes the Z of the bait.
+ * @param player the player
+ * @param baitX the bait x
+ * @param baitY the bait y
+ * @param fishingZone the fishing zone
+ * @param waterZone the water zone
+ * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
+ */
+ private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
+ {
+ if ((fishingZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if ((waterZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ // always use water zone, fishing zone high z is high in the air...
+ final int baitZ = waterZone.getWaterZ();
+
+ // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
+ //
+ // return Integer.MIN_VALUE;
+ // }
+
+ if (GeoEngine.getInstance().hasGeo(baitX, baitY))
+ {
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+ }
+
+ return baitZ;
+ }
+}
diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/FishingBaitData.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
similarity index 55%
rename from L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/FishingBaitData.java
rename to L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
index 9cf4893d66..f5a5764254 100644
--- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/FishingBaitData.java
+++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
@@ -1,98 +1,128 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author bit
- */
-public class FishingBaitData
-{
- private final int _itemId;
- private final int _level;
- private final int _minPlayerLevel;
- private final double _chance;
- private final int _timeMin;
- private final int _timeMax;
- private final int _waitMin;
- private final int _waitMax;
- private final List _rewards = new ArrayList<>();
-
- public FishingBaitData(int itemId, int level, int minPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax)
- {
- _itemId = itemId;
- _level = level;
- _minPlayerLevel = minPlayerLevel;
- _chance = chance;
- _timeMin = timeMin;
- _timeMax = timeMax;
- _waitMin = waitMin;
- _waitMax = waitMax;
- }
-
- public int getItemId()
- {
- return _itemId;
- }
-
- public int getLevel()
- {
- return _level;
- }
-
- public int getMinPlayerLevel()
- {
- return _minPlayerLevel;
- }
-
- public double getChance()
- {
- return _chance;
- }
-
- public int getTimeMin()
- {
- return _timeMin;
- }
-
- public int getTimeMax()
- {
- return _timeMax;
- }
-
- public int getWaitMin()
- {
- return _waitMin;
- }
-
- public int getWaitMax()
- {
- return _waitMax;
- }
-
- public List getRewards()
- {
- return _rewards;
- }
-
- public void addReward(int itemId)
- {
- _rewards.add(itemId);
- }
-}
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.l2jmobius.commons.util.Rnd;
+
+/**
+ * @author bit
+ */
+public class FishingBait
+{
+ private final int _itemId;
+ private final byte _level;
+ private final byte _minPlayerLevel;
+ private final byte _maxPlayerLevel;
+ private final double _chance;
+ private final int _timeMin;
+ private final int _timeMax;
+ private final int _waitMin;
+ private final int _waitMax;
+ private final boolean _isPremiumOnly;
+ private final List _rewards = new ArrayList<>();
+
+ public FishingBait(int itemId, byte level, byte minPlayerLevel, byte maxPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax, boolean isPremiumOnly)
+ {
+ _itemId = itemId;
+ _level = level;
+ _minPlayerLevel = minPlayerLevel;
+ _maxPlayerLevel = maxPlayerLevel;
+ _chance = chance;
+ _timeMin = timeMin;
+ _timeMax = timeMax;
+ _waitMin = waitMin;
+ _waitMax = waitMax;
+ _isPremiumOnly = isPremiumOnly;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public byte getLevel()
+ {
+ return _level;
+ }
+
+ public byte getMinPlayerLevel()
+ {
+ return _minPlayerLevel;
+ }
+
+ public byte getMaxPlayerLevel()
+ {
+ return _maxPlayerLevel;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public int getTimeMin()
+ {
+ return _timeMin;
+ }
+
+ public int getTimeMax()
+ {
+ return _timeMax;
+ }
+
+ public int getWaitMin()
+ {
+ return _waitMin;
+ }
+
+ public int getWaitMax()
+ {
+ return _waitMax;
+ }
+
+ public boolean isPremiumOnly()
+ {
+ return _isPremiumOnly;
+ }
+
+ public List getRewards()
+ {
+ return _rewards;
+ }
+
+ public void addReward(FishingCatch catchData)
+ {
+ _rewards.add(catchData);
+ }
+
+ public FishingCatch getRandom()
+ {
+ float random = Rnd.get(100);
+ for (FishingCatch fishingCatchData : _rewards)
+ {
+ if (fishingCatchData.getChance() > random)
+ {
+ return fishingCatchData;
+ }
+ random -= fishingCatchData.getChance();
+ }
+ return null;
+ }
+}
diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
new file mode 100644
index 0000000000..85c2e42e5a
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
@@ -0,0 +1,49 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingCatch
+{
+ private final int _itemId;
+ private final float _chance;
+ private final float _multiplier;
+
+ public FishingCatch(int itemId, float chance, float multiplier)
+ {
+ _itemId = itemId;
+ _chance = chance;
+ _multiplier = multiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public float getChance()
+ {
+ return _chance;
+ }
+
+ public float getMultiplier()
+ {
+ return _multiplier;
+ }
+}
diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
new file mode 100644
index 0000000000..93b5fb9b8e
--- /dev/null
+++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingRod
+{
+ private final int _itemId;
+ private final int _reduceFishingTime;
+ private final float _xpMultiplier;
+ private final float _spMultiplier;
+
+ public FishingRod(int itemId, int reduceFishingTime, float xpMultiplier, float spMultiplier)
+ {
+ _itemId = itemId;
+ _reduceFishingTime = reduceFishingTime;
+ _xpMultiplier = xpMultiplier;
+ _spMultiplier = spMultiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public int getReduceFishingTime()
+ {
+ return _reduceFishingTime;
+ }
+
+ public float getXpMultiplier()
+ {
+ return _xpMultiplier;
+ }
+
+ public float getSpMultiplier()
+ {
+ return _spMultiplier;
+ }
+}
diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
index 71d8f10b3e..dfcf4d7f56 100644
--- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
+++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
@@ -20,10 +20,10 @@ import java.lang.ref.WeakReference;
import com.l2jmobius.Config;
import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.PcCondOverride;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.serverpackets.fishing.ExAutoFishAvailable;
diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
index dea11bad61..cebaa3c7a5 100644
--- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
+++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
@@ -29,20 +29,17 @@ public class ExFishingStart implements IClientOutgoingPacket
{
private final L2PcInstance _player;
private final int _fishType;
- private final int _baitType;
private final ILocational _baitLocation;
/**
* @param player
* @param fishType
- * @param baitType - 0 = newbie, 1 = normal, 2 = night
* @param baitLocation
*/
- public ExFishingStart(L2PcInstance player, int fishType, int baitType, ILocational baitLocation)
+ public ExFishingStart(L2PcInstance player, int fishType, ILocational baitLocation)
{
_player = player;
_fishType = fishType;
- _baitType = baitType;
_baitLocation = baitLocation;
}
@@ -55,7 +52,7 @@ public class ExFishingStart implements IClientOutgoingPacket
packet.writeD(_baitLocation.getX());
packet.writeD(_baitLocation.getY());
packet.writeD(_baitLocation.getZ());
- packet.writeC(_baitType);
+ packet.writeC(0x01); // 0 = newbie, 1 = normal, 2 = night
return true;
}
}
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/config/Custom/PremiumSystem.ini b/L2J_Mobius_5.0_Salvation/dist/game/config/Custom/PremiumSystem.ini
index 8b5d1f1f06..7b0874c29d 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/config/Custom/PremiumSystem.ini
+++ b/L2J_Mobius_5.0_Salvation/dist/game/config/Custom/PremiumSystem.ini
@@ -45,3 +45,7 @@ EnablePremiumHennaSlotforNonPremium = True
# Also premium henna drawn at normal slots.
# Retail: False
EnableAnyHennaAtPremiumSlot = False
+
+# Enable Fishing only for premium players.
+# Retail: True
+PremiumOnlyFishing = False
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/Fishing.xml b/L2J_Mobius_5.0_Salvation/dist/game/data/Fishing.xml
index 42f6633d60..0152888ab6 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/Fishing.xml
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/Fishing.xml
@@ -1,44 +1,41 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/default/34156-1.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/default/34156-1.htm
new file mode 100644
index 0000000000..44a2ea74ad
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/default/34156-1.htm
@@ -0,0 +1,7 @@
+Fisher Peeves:
+Heine Exclusive Bait is really great! It must be a gift from the fishing gods!
+There are some items that can only be caught with Heine Exclusive Bait. Isn't that amazing?
+No doubt the fishing gods heard about this place that gets filled with fishers and decided to grace us with this amazing bait.
+You should try it out!
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/default/34156.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/default/34156.htm
new file mode 100644
index 0000000000..09f6982054
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/default/34156.htm
@@ -0,0 +1,11 @@
+Fisher Peeves:
+Oh, nice to meet you! I'm Peeves, a fisher.
+When I was young, my parents didn't want me to fish since it's dangerous... But how could I stop doing something so fun?
+Are you interested in fishing? Have you heard of the Heine Exclusive Bait?
+If you have a Heine Exclusive Bait Coupon, I can exchange it for Heine Exclusive Bait.
+Oh yeah, I also got a special fishing rod. Bring me some Heine Fishing Coins and I'll give you a Fancy Fishing Rod.
+You can get them from the Exclusive Reward Chest that you can get when you fish with Heine Exclusive Bait.
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31563.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31563.htm
index 25b6b4b199..cfd0217738 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31563.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31563.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Perelin:
-Do you like fishing? I love it.
-Fishing is such a great hobby, don't you think? Sure, it's not very exerting, but...that's the point. I don't like to run around sweating, you know? You can just sit quietly and enjoy the silence.
-
-
-
-
-
-
-
-
-
+Fishing is such a great hobby, don't you think? Sure, it's not very exerting, but...that's the point. I don't like to run around sweating, you know? You can just sit quietly and enjoy silence.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31567.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31567.htm
index 70eb2e221b..9500514c8e 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31567.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31567.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Bleaker:
-Nice to meet you! They call me Bleaker.
-Besides teaching you how to fish, I also sell the fishing gear you'll need. Oh, and I'll buy any fish you catch. In other words, this is your one-stop fishing shop!
-
-
-
-
-
-
-
-
-
+Nice to meet you! They call me Bleaker. I am with the Fishing Guild. If it has to do with fishing, I'm your man. Most of the time, anyway.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31568.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31568.htm
index 49f54d15d9..b2d1001145 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31568.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31568.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Pamfus:
-Do you like fishing? I love it.
-Fishing is such a great hobby, don't you think? Sure, it's not very exerting, but...that's the point. I don't like to run around sweating, you know? You can just sit quietly and enjoy the silence.
-
-
-
-
-
-
-
-
-
+There's no hobby other than fishing that lets you enjoy the nature around you so much. I really do love fishing.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31570.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31570.htm
index e6b7859e93..e92d40e6fb 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31570.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31570.htm
@@ -1,15 +1,13 @@
Fishing Guild Member Lanosco:
-Did you catch one?
-Heh, fishing is harder than it looks, right? You need to be prepared at all times.
-Which is why I'm here! Come see me whenever you need something, and I'll set you right up.
-
-
-
-
-
-
-
-
-
+Hi, I'm Fishing Guild Member Lanosco. Did you catch anything today? Fishing is not as easy as you might, you know. You need to prepare thoroughly.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31571.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31571.htm
index 0f55831347..ce281416f3 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31571.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31571.htm
@@ -1,14 +1,13 @@
Fishermen's Guild Member Huffs:
-Welcome! Are you here to fish?
-There's no better way to relax and decompress after a stressful day, week, or life! Haha!
-
-
-
-
-
-
-
-
-
+Hello, and welcome. Are you here to learn about fishing? There's no better way to relax and decompress after a stressful day, week, or life! Haha! It's quite the experience, wrestling huge fish along the coast or on the riverbanks, armed with little more than a rod and some string.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31572.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31572.htm
index b8434accc2..2d82c9fa59 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31572.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31572.htm
@@ -1,14 +1,13 @@
Fishing Guild Member O'Fulle:
-Everything is plentiful here in Giran, which is why so many people spend their leisure time fishing. It's a sign of abundance!
-Oh, pardon me -- I'm O'Fulle, the only officially licensed fishing gear merchant in this territory! See me if you need to buy bait or sell fish. Fish only -- no mermaids! Haha!
-
-
-
-
-
-
-
-
-
+I'm Fishing Guild Member O'Fulle. Try your luck at fishing in Giran, the land of plenty! Watch out, catching mermaids might get you into trouble! Stick with the fish! Hahaha!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31573.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31573.htm
index 7a9d68571a..2903e2c1d0 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31573.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31573.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Monakan:
-Well, hello there. I'm Monakan.
-I can teach you about fishing items as well as how to fish. Oh, I'll also buy any fish you catch. In other words, this is your one-stop fishing shop!
-
-
-
-
-
-
-
-
-
+Well, hello there. I'm Monakan, a member of the Fishing Guild. I'm the one to come to when it comes to fishing, since I deal not only in fishing supplies but also the fish that are caught.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31574.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31574.htm
index 021707372b..fb24509ac6 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31574.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31574.htm
@@ -1,13 +1,13 @@
Fishing Guild Member Willie:
-Fishing has become all the rage in these parts! I think it's because of all the brainy people around here -- the Ivory Tower, for example! Lots of them just sit there thinking, and forget to actually catch the fish!
-
-
-
-
-
-
-
-
-
+Oren is a city of culture, to which many intelligent ones flock. That's why we have so many fishing enthusiasts!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31575.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31575.htm
index 5381af429a..58f12301c3 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31575.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31575.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Litulon:
-There's no better place for fishing than Innadril. Wet and warm all year round, beautiful scenery, the best place in the whole world.
-I mean, Goddess Eva watches over us after all. The City of Waters! Haha!
-
-
-
-
-
-
-
-
-
+The Innadril Territory is just the spot for fishing. I mean, Goddess Eva watches over us after all. The City of Waters! Haha!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31576.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31576.htm
index 40daf36a06..dc3fe17673 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31576.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31576.htm
@@ -1,14 +1,14 @@
Fishing Guild Member Berix:
-I'm quite happy to be holding the fishing contest in my native town. It's good to know I can do what I love, where I live.
-I think it's time we got to it, perfect weather for fishing!
-
-
-
-
-
-
-
-
-
+Pleased to meet you. I'm Berix, a member of the Fishing Guild. See, people tend to think that there are only hunters in the Hunter's Village, but we have a lot of great fishers as well! I'm one of them, you see. Hahahaha.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31577.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31577.htm
index 42e3023192..dcf0570a3a 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31577.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31577.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Linnaeus:
-Did you know that the king is an avid fisher himself? Haha!
-Aden is filled with prime fishing zones. How about spending this beautiful day on one of them?
-
-
-
-
-
-
-
-
-
+Did you know that the King is an avid fisher himself? Haha! We at the Fishing Guild are quite proud of this fact. He's actually quite the Master!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31578.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31578.htm
index 22424bd71f..9a39b5209d 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31578.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31578.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Hilgendorf:
-Welcome! Beautiful day for fishing, dontcha' think?
-My family has been in the Guild for generations, ever since my great-grandfather joined.
-
-
-
-
-
-
-
-
-
+Welcome, and good to see you! The weather's perfect for fishing, wouldn't you agree? My family has been in the Guild for generations, ever since my great-grandfather joined.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31579.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31579.htm
index 4905012750..d19e501e8e 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31579.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31579.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Klaus:
-Well, well, well! Another fisher, huh?
-You know how lucky you are to be here, right? With its many mountain streams and lakes, Goddard is a prime fishing land. People come from all over to test their skill and try their luck here.
-
-
-
-
-
-
-
-
-
+I am Klaus, one of Fishing Guild members. If you have anything you need related with fishing, fine me.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31696.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31696.htm
index afb7f7612b..10fc8d9b1e 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31696.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31696.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Platis:
-This area is a rare spot in Elmore where you can catch actual saltwater fish. It used to be a famous fishing site in the Elmoreden years, and now that things have slowed down, the fish population is back.
-Care to give it a try? Let me know if you need any equipment!
-
-
-
-
-
-
-
-
-
+This has been a very popular fishing dock since the age of the Elmoreden. This is the tranquil and beautiful fishing spot you've been searching high and low for, I tell you!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31697.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31697.htm
index b78f53e3e4..77ef12b6d8 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31697.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31697.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Eindarkner:
-Do you know about these hot springs? The effects of the nearby Forge of the Gods have created a whole network of them around here. There are special species of fish living in these hot springs! It's the opportunity of a lifetime.
-Let me know if you need anything!
-
-
-
-
-
-
-
-
-
+Have you heard about the Hot Springs in the area? There are natural hot springs everywhere, thanks to the Forge of the Gods. Before, there were fish to be caught in the hot springs as well, but they have all disappeared now. What a pity.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31989.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31989.htm
index f8b1a88ccd..c032d201fa 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31989.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/31989.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Batidae:
-You came here to fish, right? Who am I kidding, of course you did!
-No better way to spend an afternoon than casting the line!
-
-
-
-
-
-
-
-
-
+Welcome. Want to learn how to fish, do you? You must have really been running out of things to learn to come all the way here to learn about fishing, of all things. Frankly, you'd be doing yourself more good by learning how to mine ore in the mines over there. Anyways, since you're here, really, there's no better way to spend an afternoon than casting the line!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/32007.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/32007.htm
index 939f2f8362..f65b882bdc 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/32007.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/32007.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Galba:
-Rainbow Springs -- ahh, heaven!
-You should try fishing around here. The fish here are huge. Let me know if you need any fishing items or want to sell something.
-
-
-
-
-
-
-
-
-
+Since you've come to find me, I reckon you know that the Rainbow Springs are a veritable heaven on earth for us fishing enthusiasts. That's right, this is some of the best fishing you'll find anywhere.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fish_appearance_exchange.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fish_appearance_exchange.htm
new file mode 100644
index 0000000000..8d25e5d848
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fish_appearance_exchange.htm
@@ -0,0 +1,11 @@
+
+
+ Exchange for appearance items:
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual001.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual001.htm
index dc66dd577c..d7badfef10 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual001.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual001.htm
@@ -1,10 +1,8 @@
Fishing Manual:
-
-
+
-
-
-
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual002.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual002.htm
index 3c1bb703da..a37c28a0da 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual002.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual002.htm
@@ -1,6 +1,5 @@
Fishing Manual:
-In order to fish, you need to find a fishing area. Once you arrive at the right spot, you'll see the button on the right side of your screen that alerts you that you can fish.
+In order to fish, you need to find a fishing area. Once you arrive at the right spot, you'll see the button on the right side of your screen that alerts you that you can fish.
Then check if you can actually fish. Check that you have a Fishing Rod and Bait equipped. You can set the Fishing Shots to be used automatically when you fish.
-
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual003.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual003.htm
index da8ab5942b..910782fc81 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual003.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual003.htm
@@ -1,6 +1,4 @@
-Fishing Manual:
-A fishing zone refers to a place with enough fish to be caught.
-The places that are good for fishing are the following: around Lake Iris, Narsell Lake where the Coliseum is, Giran Harbor's coast, around the Plains of the Lizardmen, waterside in the Town of Gludio, the Neutral Zone, Heine, Fellmere Lake, and the bridge near the Town of Giran.
+Fishing Manual:
+In order to fish, you need to find a fishing area. Once you arrive at the right spot, you'll see the button on the right side of your screen that alerts you that you can fish. Then check if you can actually fish. Check that you have a Fishing Rod and Bait equipped. You can set the Fishing Shots to be used automatically when you fish.
-
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual004.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual004.htm
index 7d4dbce9a9..a45c766c9a 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual004.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual004.htm
@@ -1,7 +1,7 @@
-Fishing Manual:
-There are two types of bait.
-The Normal Bait, you can buy from me.
-If you want to catch more expensive fish, I recommend you use the Special Bait. I have never seen Special Bait, but I heard that you can get it from the boxes you get from fishing.
+Fishing Manual:
+There are three types of bait.
+These are the basic bait, the R99 bait which can be used by characters of Lv. 99 and above and he PC Cafe bait, which can be purchased using PC Cafe Points.
+Of these, the Fishing Guild sells the basic bait and the R99 bait.
+With each type of bait, you can catch different types of fish. The conditions for purchasing and use vary among bait types as well. The Powerful Fish, which is the most expensive fish you can catch, can be caught using the R99 bait or the PC Cafe bait.
-
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual008.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual008.htm
index 4a56fdac27..5063653e3a 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual008.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual008.htm
@@ -1,7 +1,6 @@
-Fishing Manual:
+Fishing Manual:
Created by the Black Anvil Guild at the request of Ampitri, the founder of the Fishing Guild, Fishing Shots are variations of Soulshots made for fishing.
But while Soulshots amplify a hit, Fishing Shots increase the fisher's chances of catching a fish.
It's an item that will help you catch fish more efficiently.
-
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual009.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual009.htm
index 3094aa089d..29fe921d82 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual009.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual009.htm
@@ -1,7 +1,7 @@
-Fishing Manual:
-You can sell the fish whole, take it apart to sell a portion, or use it to craft items. You can also exchange it for Elcyum Powder through our Fishing Guild.
-Keep in mind that you might lose everything when cutting up your fish though! It depends on your luck.
-You can also bring Elcyum Powder to our guild to learn some legendary fishing skills. You decide what to do with your fish.
+Fishing Manual:
+Bring the fish you catch to us to exchange for various items that the Fishing Guild deals in.
+The Ugly Fish and Nimble Fish can be exchanged for Fish Stew, Appearance Stones, Hair Accessories, Transformation Scrolls, and Weapon Appearance Stones.
+If you have caught a Powerful Fish, it may be exchanged for a Stardust item or Elcyum Powder which is needed when exchanging for a Zodiac Agathion Treasure Chest. You may also sell the fish to the shop.
+If you bring us Elcyum Powder, we can let you in on a few secret techniques that have been handed down in our guild through the generation. Please think carefully about what you want to do with the fish that you catch.
-
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual010.htm b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual010.htm
index 4769d79268..21fb4dec2d 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual010.htm
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/html/fisherman/fishing_manual010.htm
@@ -1,6 +1,38 @@
-Fishing Manual:
-You can buy Normal Bait from the Fishing Guild.
-As for the Special Bait, you can get it from the wooden boxes that you get from fishing. Use the Special Bait to catch shiny fish.
-
+Fishing Manual:
+The time required for fishing, and the rate of success vary according to the type of bait, the type of rod, and whether or not Fishing Shot is used.
+
+
+
+
Bait - Fishing Time and Standby Time
+
+
+
+For each bait, the time required until fish bite is preset.
+As for the basic bait sold in the shop,Fishing Time is 105 seconds, and Standby Time is 15 seconds.This means catching a single fish takes a total of 120 seconds.
+
+
+
+
+
Fishing Rod - Fishing Time reduced
+
+
+
+
+A better fishing rod will reduce Fishing Time.
+The Normal Fishing Rod and Sturdy Fishing Rodwill not reduce Fishing Time.When you obtain Master Fishing Rod Stage 1,your Fishing Time will begin to decrease.
+
+
+
+
+
Fishing Shot - Fishing Probability increased
+
+
+
+
+
+Fishing Shot increases your odds of catching a fish.
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2144.xml b/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2144.xml
new file mode 100644
index 0000000000..b763fcb01e
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2144.xml
@@ -0,0 +1,39 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+ 34156
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2194.xml b/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2194.xml
new file mode 100644
index 0000000000..52d33e59e4
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2194.xml
@@ -0,0 +1,70 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2195.xml b/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2195.xml
new file mode 100644
index 0000000000..e73c2546f1
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2195.xml
@@ -0,0 +1,138 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2203.xml b/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2203.xml
new file mode 100644
index 0000000000..82d49aba41
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2203.xml
@@ -0,0 +1,62 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2207.xml b/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2207.xml
new file mode 100644
index 0000000000..a0521b646d
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2207.xml
@@ -0,0 +1,62 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2208.xml b/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2208.xml
new file mode 100644
index 0000000000..0c8953f318
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/2208.xml
@@ -0,0 +1,94 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/3034.xml b/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/3034.xml
new file mode 100644
index 0000000000..6bd81e7b08
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/multisell/3034.xml
@@ -0,0 +1,22 @@
+
+
+
+ 34156
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/spawns/Innadril/Heine.xml b/L2J_Mobius_5.0_Salvation/dist/game/data/spawns/Innadril/Heine.xml
index 7a35b26c4e..8a89d9a86e 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/spawns/Innadril/Heine.xml
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/spawns/Innadril/Heine.xml
@@ -75,6 +75,7 @@
+
-
\ No newline at end of file
+
diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/xsd/Fishing.xsd b/L2J_Mobius_5.0_Salvation/dist/game/data/xsd/Fishing.xsd
index 16e5ed9699..1078ed7f77 100644
--- a/L2J_Mobius_5.0_Salvation/dist/game/data/xsd/Fishing.xsd
+++ b/L2J_Mobius_5.0_Salvation/dist/game/data/xsd/Fishing.xsd
@@ -9,13 +9,13 @@
-
+
-
+
@@ -30,17 +30,35 @@
+
+
-
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/Config.java b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/Config.java
index 3ace6d94a3..0658b8c8ec 100644
--- a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/Config.java
+++ b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/Config.java
@@ -1133,11 +1133,12 @@ public final class Config
public static float PREMIUM_RATE_DROP_AMOUNT;
public static float PREMIUM_RATE_SPOIL_CHANCE;
public static float PREMIUM_RATE_SPOIL_AMOUNT;
+ public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
+ public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
public static boolean PREMIUM_HENNA_SLOT_ENABLED;
public static boolean PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL;
public static boolean PREMIUM_HENNA_SLOT_ALL_DYES;
- public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
- public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
+ public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
public static int PC_CAFE_MAX_POINTS;
@@ -2632,9 +2633,6 @@ public final class Config
PREMIUM_RATE_DROP_AMOUNT = PremiumSystem.getFloat("PremiumRateDropAmount", 1);
PREMIUM_RATE_SPOIL_CHANCE = PremiumSystem.getFloat("PremiumRateSpoilChance", 2);
PREMIUM_RATE_SPOIL_AMOUNT = PremiumSystem.getFloat("PremiumRateSpoilAmount", 1);
- PREMIUM_HENNA_SLOT_ENABLED = PremiumSystem.getBoolean("EnablePremiumHennaSlot", true);
- PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL = PremiumSystem.getBoolean("EnablePremiumHennaSlotforNonPremium", true);
- PREMIUM_HENNA_SLOT_ALL_DYES = PremiumSystem.getBoolean("EnableAnyHennaAtPremiumSlot", false);
final String[] premiumDropChanceMultiplier = PremiumSystem.getString("PremiumRateDropChanceByItemId", "").split(";");
PREMIUM_RATE_DROP_CHANCE_BY_ID = new HashMap<>(premiumDropChanceMultiplier.length);
if (!premiumDropChanceMultiplier[0].isEmpty())
@@ -2689,6 +2687,10 @@ public final class Config
}
}
}
+ PREMIUM_HENNA_SLOT_ENABLED = PremiumSystem.getBoolean("EnablePremiumHennaSlot", true);
+ PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL = PremiumSystem.getBoolean("EnablePremiumHennaSlotforNonPremium", true);
+ PREMIUM_HENNA_SLOT_ALL_DYES = PremiumSystem.getBoolean("EnableAnyHennaAtPremiumSlot", false);
+ PREMIUM_ONLY_FISHING = PremiumSystem.getBoolean("PremiumOnlyFishing", true);
// Load PrivateStoreRange config file (if exists)
final PropertiesParser PrivateStoreRange = new PropertiesParser(CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE);
diff --git a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
index 91b5f9c43e..bacf1ed08c 100644
--- a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
+++ b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
@@ -25,8 +25,12 @@ import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
+import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
-import com.l2jmobius.gameserver.model.FishingBaitData;
+import com.l2jmobius.gameserver.datatables.ItemTable;
+import com.l2jmobius.gameserver.model.fishing.FishingBait;
+import com.l2jmobius.gameserver.model.fishing.FishingCatch;
+import com.l2jmobius.gameserver.model.fishing.FishingRod;
/**
* This class holds the Fishing information.
@@ -35,7 +39,8 @@ import com.l2jmobius.gameserver.model.FishingBaitData;
public final class FishingData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(FishingData.class.getName());
- private final Map _baitData = new HashMap<>();
+ private final Map _baitData = new HashMap<>();
+ private final Map _rodData = new HashMap<>();
private int _baitDistanceMin;
private int _baitDistanceMax;
private double _expRateMin;
@@ -56,7 +61,7 @@ public final class FishingData implements IGameXmlReader
{
_baitData.clear();
parseDatapackFile("data/Fishing.xml");
- LOGGER.info(getClass().getSimpleName() + ": Loaded Fishing Data.");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _baitData.size() + " bait and " + _rodData.size() + " rod data.");
}
@Override
@@ -76,13 +81,13 @@ public final class FishingData implements IGameXmlReader
_baitDistanceMax = parseInteger(listItem.getAttributes(), "max");
break;
}
- case "experienceRate":
+ case "xpRate":
{
_expRateMin = parseDouble(listItem.getAttributes(), "min");
_expRateMax = parseDouble(listItem.getAttributes(), "max");
break;
}
- case "skillPointsRate":
+ case "spRate":
{
_spRateMin = parseDouble(listItem.getAttributes(), "min");
_spRateMax = parseDouble(listItem.getAttributes(), "max");
@@ -96,20 +101,39 @@ public final class FishingData implements IGameXmlReader
{
final NamedNodeMap attrs = bait.getAttributes();
final int itemId = parseInteger(attrs, "itemId");
- final int level = parseInteger(attrs, "level");
- final int minPlayerLevel = parseInteger(attrs, "minPlayerLevel");
+ final byte level = parseByte(attrs, "level", (byte) 1);
+ final byte minPlayerLevel = parseByte(attrs, "minPlayerLevel");
+ final byte maxPlayerLevel = parseByte(attrs, "minPlayerLevel", Config.PLAYER_MAXIMUM_LEVEL);
final double chance = parseDouble(attrs, "chance");
final int timeMin = parseInteger(attrs, "timeMin");
- final int timeMax = parseInteger(attrs, "timeMax");
+ final int timeMax = parseInteger(attrs, "timeMax", timeMin);
final int waitMin = parseInteger(attrs, "waitMin");
- final int waitMax = parseInteger(attrs, "waitMax");
- final FishingBaitData baitData = new FishingBaitData(itemId, level, minPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax);
+ final int waitMax = parseInteger(attrs, "waitMax", waitMin);
+ final boolean isPremiumOnly = parseBoolean(attrs, "isPremiumOnly", false);
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ final FishingBait baitData = new FishingBait(itemId, level, minPlayerLevel, maxPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax, isPremiumOnly);
for (Node c = bait.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("catch".equalsIgnoreCase(c.getNodeName()))
{
- baitData.addReward(parseInteger(c.getAttributes(), "itemId"));
+ final NamedNodeMap cAttrs = c.getAttributes();
+ final int cId = parseInteger(cAttrs, "itemId");
+ final float cChance = parseFloat(cAttrs, "chance");
+ final float cMultiplier = parseFloat(cAttrs, "multiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(cId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ baitData.addReward(new FishingCatch(cId, cChance, cMultiplier));
}
}
_baitData.put(baitData.getItemId(), baitData);
@@ -117,22 +141,44 @@ public final class FishingData implements IGameXmlReader
}
break;
}
+ case "rods":
+ {
+ for (Node rod = listItem.getFirstChild(); rod != null; rod = rod.getNextSibling())
+ {
+ if ("rod".equalsIgnoreCase(rod.getNodeName()))
+ {
+ final NamedNodeMap attrs = rod.getAttributes();
+ final int itemId = parseInteger(attrs, "itemId");
+ final int reduceFishingTime = parseInteger(attrs, "reduceFishingTime", 0);
+ final float xpMultiplier = parseFloat(attrs, "xpMultiplier", 1f);
+ final float spMultiplier = parseFloat(attrs, "spMultiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ _rodData.put(itemId, new FishingRod(itemId, reduceFishingTime, xpMultiplier, spMultiplier));
+ }
+ }
+ }
}
}
}
}
}
- /**
- * Gets the fishing rod.
- * @param baitItemId the item id
- * @return A list of reward item ids
- */
- public FishingBaitData getBaitData(int baitItemId)
+ public FishingBait getBaitData(int baitItemId)
{
return _baitData.get(baitItemId);
}
+ public FishingRod getRodData(int rodItemId)
+ {
+ return _rodData.get(rodItemId);
+ }
+
public int getBaitDistanceMin()
{
return _baitDistanceMin;
diff --git a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/FishingBaitData.java b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/FishingBaitData.java
deleted file mode 100644
index 9cf4893d66..0000000000
--- a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/FishingBaitData.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author bit
- */
-public class FishingBaitData
-{
- private final int _itemId;
- private final int _level;
- private final int _minPlayerLevel;
- private final double _chance;
- private final int _timeMin;
- private final int _timeMax;
- private final int _waitMin;
- private final int _waitMax;
- private final List _rewards = new ArrayList<>();
-
- public FishingBaitData(int itemId, int level, int minPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax)
- {
- _itemId = itemId;
- _level = level;
- _minPlayerLevel = minPlayerLevel;
- _chance = chance;
- _timeMin = timeMin;
- _timeMax = timeMax;
- _waitMin = waitMin;
- _waitMax = waitMax;
- }
-
- public int getItemId()
- {
- return _itemId;
- }
-
- public int getLevel()
- {
- return _level;
- }
-
- public int getMinPlayerLevel()
- {
- return _minPlayerLevel;
- }
-
- public double getChance()
- {
- return _chance;
- }
-
- public int getTimeMin()
- {
- return _timeMin;
- }
-
- public int getTimeMax()
- {
- return _timeMax;
- }
-
- public int getWaitMin()
- {
- return _waitMin;
- }
-
- public int getWaitMax()
- {
- return _waitMax;
- }
-
- public List getRewards()
- {
- return _rewards;
- }
-
- public void addReward(int itemId)
- {
- _rewards.add(itemId);
- }
-}
diff --git a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
index 2ddd4d237f..c9a6cc3df6 100644
--- a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
+++ b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
@@ -125,7 +125,6 @@ import com.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import com.l2jmobius.gameserver.model.BlockList;
import com.l2jmobius.gameserver.model.ClanPrivilege;
import com.l2jmobius.gameserver.model.ClanWar;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.L2AccessLevel;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
@@ -209,6 +208,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPCh
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPKill;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerReputationChanged;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerSubChange;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.MonsterBookCardHolder;
diff --git a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/Fishing.java b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
similarity index 80%
rename from L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/Fishing.java
rename to L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
index 17746b3e77..4421a1a3c0 100644
--- a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/Fishing.java
+++ b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
@@ -1,443 +1,471 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.concurrent.ScheduledFuture;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.commons.util.Rnd;
-import com.l2jmobius.gameserver.data.xml.impl.FishingData;
-import com.l2jmobius.gameserver.enums.ShotType;
-import com.l2jmobius.gameserver.geoengine.GeoEngine;
-import com.l2jmobius.gameserver.instancemanager.ZoneManager;
-import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jmobius.gameserver.model.events.EventDispatcher;
-import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
-import com.l2jmobius.gameserver.model.interfaces.ILocational;
-import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
-import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
-import com.l2jmobius.gameserver.model.items.type.WeaponType;
-import com.l2jmobius.gameserver.model.zone.L2ZoneType;
-import com.l2jmobius.gameserver.model.zone.ZoneId;
-import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
-import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
-import com.l2jmobius.gameserver.network.SystemMessageId;
-import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
-import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
-import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
-import com.l2jmobius.gameserver.util.Util;
-
-/**
- * @author bit
- */
-public class Fishing
-{
- protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
- private volatile ILocational _baitLocation = new Location(0, 0, 0);
-
- private final L2PcInstance _player;
- private ScheduledFuture> _reelInTask;
- private ScheduledFuture> _startFishingTask;
- private boolean _isFishing = false;
-
- public Fishing(L2PcInstance player)
- {
- _player = player;
- }
-
- public synchronized boolean isFishing()
- {
- return _isFishing;
- }
-
- public boolean isAtValidLocation()
- {
- // TODO: implement checking direction
- // if (calculateBaitLocation() == null)
- // {
- // return false;
- // }
- return _player.isInsideZone(ZoneId.FISHING);
- }
-
- public boolean canFish()
- {
- return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
- }
-
- private FishingBaitData getCurrentBaitData()
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
- }
-
- private void cancelTasks()
- {
- if (_reelInTask != null)
- {
- _reelInTask.cancel(false);
- _reelInTask = null;
- }
-
- if (_startFishingTask != null)
- {
- _startFishingTask.cancel(false);
- _startFishingTask = null;
- }
- }
-
- public synchronized void startFishing()
- {
- if (_isFishing)
- {
- return;
- }
- _isFishing = true;
- castLine();
- }
-
- private void castLine()
- {
- if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
- {
- _player.sendMessage("Fishing is disabled.");
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- cancelTasks();
-
- if (!canFish())
- {
- if (_isFishing)
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final FishingBaitData baitData = getCurrentBaitData();
- final int minPlayerLevel = baitData == null ? 85 : baitData.getMinPlayerLevel();
- if (_player.getLevel() < minPlayerLevel)
- {
- if (minPlayerLevel == 85)
- {
- _player.sendPacket(SystemMessageId.FISHING_IS_AVAILABLE_TO_PREMIUM_USERS_ONLY);
- }
- else // In case of custom fishing level.
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
- }
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final L2ItemInstance rod = _player.getActiveWeaponInstance();
- if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (baitData == null)
- {
- _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isTransformed() || _player.isInBoat())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHEN_TRANSFORMED_OR_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_IT_S_AGAINST_THE_RULES);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isCrafting() || _player.isInStoreMode())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- _baitLocation = calculateBaitLocation();
- if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
- {
- if (_isFishing)
- {
- // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- else
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- _player.rechargeShots(false, false, true);
- }
-
- _reelInTask = ThreadPool.schedule(() ->
- {
- _player.getFishing().reelInWithReward();
- _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), Rnd.get(baitData.getWaitMin(), baitData.getWaitMax()));
- }, Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()));
- _player.stopMove(null);
- _player.broadcastPacket(new ExFishingStart(_player, -1, baitData.getLevel(), _baitLocation));
- _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
- _player.sendPacket(new PlaySound("SF_P_01"));
- _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
- }
-
- public void reelInWithReward()
- {
- // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
- // Then player may or may not catch the fish. Using fishing shots increases chance to win.
- final FishingBaitData baitData = getCurrentBaitData();
- if (baitData == null)
- {
- reelIn(FishingEndReason.LOSE, false);
- LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
- return;
- }
-
- double chance = baitData.getChance();
- if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- chance *= 1.5; // +50 % chance to win
- }
-
- if (Rnd.get(0, 100) <= chance)
- {
- reelIn(FishingEndReason.WIN, true);
- }
- else
- {
- reelIn(FishingEndReason.LOSE, true);
- }
- }
-
- private void reelIn(FishingEndReason reason, boolean consumeBait)
- {
- if (!_isFishing)
- {
- return;
- }
-
- cancelTasks();
-
- try
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- if (consumeBait)
- {
- if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
- {
- reason = FishingEndReason.LOSE; // no bait - no reward
- return;
- }
- }
-
- if ((reason == FishingEndReason.WIN) && (bait != null))
- {
- final FishingBaitData baitData = FishingData.getInstance().getBaitData(bait.getId());
- final int numRewards = baitData.getRewards().size();
- if (numRewards > 0)
- {
- final FishingData fishingData = FishingData.getInstance();
- final int lvlModifier = _player.getLevel() * _player.getLevel();
- _player.addExpAndSp(Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier, Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier, true);
- final int fishId = baitData.getRewards().get(Rnd.get(0, numRewards - 1));
- _player.getInventory().addItem("Fishing Reward", fishId, 1, _player, null);
- final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
- msg.addItemName(fishId);
- _player.sendPacket(msg);
- _player.unchargeShot(ShotType.FISH_SOULSHOTS);
- _player.rechargeShots(false, false, true);
- }
- else
- {
- LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
- }
- }
- else if (reason == FishingEndReason.LOSE)
- {
- _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
- }
-
- if (consumeBait)
- {
- EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
- }
- }
- finally
- {
- _player.broadcastPacket(new ExFishingEnd(_player, reason));
- _player.sendPacket(new ExUserInfoFishing(_player, false));
- }
- }
-
- public void stopFishing()
- {
- stopFishing(FishingEndType.PLAYER_STOP);
- }
-
- public synchronized void stopFishing(FishingEndType endType)
- {
- if (_isFishing)
- {
- reelIn(FishingEndReason.STOP, false);
- _isFishing = false;
- switch (endType)
- {
- case PLAYER_STOP:
- {
- _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
- break;
- }
- case PLAYER_CANCEL:
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- break;
- }
- }
- }
- }
-
- public ILocational getBaitLocation()
- {
- return _baitLocation;
- }
-
- private Location calculateBaitLocation()
- {
- // calculate a position in front of the player with a random distance
- final int distMin = FishingData.getInstance().getBaitDistanceMin();
- final int distMax = FishingData.getInstance().getBaitDistanceMax();
- int distance = Rnd.get(distMin, distMax);
- final double angle = Util.convertHeadingToDegree(_player.getHeading());
- final double radian = Math.toRadians(angle);
- final double sin = Math.sin(radian);
- final double cos = Math.cos(radian);
- int baitX = (int) (_player.getX() + (cos * distance));
- int baitY = (int) (_player.getY() + (sin * distance));
-
- // search for fishing zone
- L2FishingZone fishingZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
- {
- if (zone instanceof L2FishingZone)
- {
- fishingZone = (L2FishingZone) zone;
- break;
- }
- }
- // search for water zone
- L2WaterZone waterZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
- {
- if (zone instanceof L2WaterZone)
- {
- waterZone = (L2WaterZone) zone;
- break;
- }
- }
-
- int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
- if (baitZ == Integer.MIN_VALUE)
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
- return null;
- }
-
- return new Location(baitX, baitY, baitZ);
- }
-
- /**
- * Computes the Z of the bait.
- * @param player the player
- * @param baitX the bait x
- * @param baitY the bait y
- * @param fishingZone the fishing zone
- * @param waterZone the water zone
- * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
- */
- private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
- {
- if ((fishingZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- if ((waterZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- // always use water zone, fishing zone high z is high in the air...
- final int baitZ = waterZone.getWaterZ();
-
- // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
- //
- // return Integer.MIN_VALUE;
- // }
-
- if (GeoEngine.getInstance().hasGeo(baitX, baitY))
- {
- if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
-
- if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
- }
-
- return baitZ;
- }
-}
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.commons.util.Rnd;
+import com.l2jmobius.gameserver.data.xml.impl.FishingData;
+import com.l2jmobius.gameserver.enums.ShotType;
+import com.l2jmobius.gameserver.geoengine.GeoEngine;
+import com.l2jmobius.gameserver.instancemanager.ZoneManager;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.PcCondOverride;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.events.EventDispatcher;
+import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
+import com.l2jmobius.gameserver.model.interfaces.ILocational;
+import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.model.items.type.WeaponType;
+import com.l2jmobius.gameserver.model.zone.L2ZoneType;
+import com.l2jmobius.gameserver.model.zone.ZoneId;
+import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
+import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
+import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author bit
+ */
+public class Fishing
+{
+ protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
+ private volatile ILocational _baitLocation = new Location(0, 0, 0);
+
+ private final L2PcInstance _player;
+ private ScheduledFuture> _reelInTask;
+ private ScheduledFuture> _startFishingTask;
+ private boolean _isFishing = false;
+
+ public Fishing(L2PcInstance player)
+ {
+ _player = player;
+ }
+
+ public synchronized boolean isFishing()
+ {
+ return _isFishing;
+ }
+
+ public boolean isAtValidLocation()
+ {
+ // TODO: implement checking direction
+ // if (calculateBaitLocation() == null)
+ // {
+ // return false;
+ // }
+ return _player.isInsideZone(ZoneId.FISHING);
+ }
+
+ public boolean canFish()
+ {
+ return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
+ }
+
+ private FishingBait getCurrentBaitData()
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
+ }
+
+ private void cancelTasks()
+ {
+ if (_reelInTask != null)
+ {
+ _reelInTask.cancel(false);
+ _reelInTask = null;
+ }
+
+ if (_startFishingTask != null)
+ {
+ _startFishingTask.cancel(false);
+ _startFishingTask = null;
+ }
+ }
+
+ public synchronized void startFishing()
+ {
+ if (_isFishing)
+ {
+ return;
+ }
+ _isFishing = true;
+ castLine();
+ }
+
+ private void castLine()
+ {
+ if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
+ {
+ _player.sendMessage("Fishing is disabled.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ cancelTasks();
+
+ if (!canFish())
+ {
+ if (_isFishing)
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (Config.PREMIUM_SYSTEM_ENABLED)
+ {
+ if (Config.PREMIUM_ONLY_FISHING && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.FISHING_IS_AVAILABLE_TO_PREMIUM_USERS_ONLY);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (baitData.isPremiumOnly() && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.FAILED_PLEASE_TRY_AGAIN_USING_THE_CORRECT_BAIT);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+ }
+
+ final int minPlayerLevel = baitData.getMinPlayerLevel();
+ final int maxPLayerLevel = baitData.getMaxPlayerLevel();
+ if ((_player.getLevel() < minPlayerLevel) && (_player.getLevel() > maxPLayerLevel))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final L2ItemInstance rod = _player.getActiveWeaponInstance();
+ if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingRod rodData = FishingData.getInstance().getRodData(rod.getId());
+ if (rodData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isTransformed() || _player.isInBoat())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHEN_TRANSFORMED_OR_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_IT_S_AGAINST_THE_RULES);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isCrafting() || _player.isInStoreMode())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ _baitLocation = calculateBaitLocation();
+ if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
+ {
+ if (_isFishing)
+ {
+ // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ else
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ _player.rechargeShots(false, false, true);
+ }
+
+ final long fishingTime = Math.max(Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()) - rodData.getReduceFishingTime(), 1000);
+ final long fishingWaitTime = Rnd.get(baitData.getWaitMin(), baitData.getWaitMax());
+
+ _reelInTask = ThreadPool.schedule(() ->
+ {
+ _player.getFishing().reelInWithReward();
+ _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), fishingWaitTime);
+ }, fishingTime);
+ _player.stopMove(null);
+ _player.broadcastPacket(new ExFishingStart(_player, -1, _baitLocation));
+ _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
+ _player.sendPacket(new PlaySound("SF_P_01"));
+ _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
+ }
+
+ public void reelInWithReward()
+ {
+ // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
+ // Then player may or may not catch the fish. Using fishing shots increases chance to win.
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ reelIn(FishingEndReason.LOSE, false);
+ LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
+ return;
+ }
+
+ double chance = baitData.getChance();
+ if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ chance *= 2;
+ }
+
+ if (Rnd.get(100) <= chance)
+ {
+ reelIn(FishingEndReason.WIN, true);
+ }
+ else
+ {
+ reelIn(FishingEndReason.LOSE, true);
+ }
+ }
+
+ private void reelIn(FishingEndReason reason, boolean consumeBait)
+ {
+ if (!_isFishing)
+ {
+ return;
+ }
+
+ cancelTasks();
+
+ try
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ if (consumeBait)
+ {
+ if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
+ {
+ reason = FishingEndReason.LOSE; // no bait - no reward
+ return;
+ }
+ }
+
+ if ((reason == FishingEndReason.WIN) && (bait != null))
+ {
+ final FishingBait baitData = FishingData.getInstance().getBaitData(bait.getId());
+ final FishingCatch fishingCatchData = baitData.getRandom();
+ if (fishingCatchData != null)
+ {
+ final FishingData fishingData = FishingData.getInstance();
+ final double lvlModifier = (Math.pow(_player.getLevel(), 2.2) * fishingCatchData.getMultiplier());
+ final long xp = (long) (Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier);
+ final long sp = (long) (Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier);
+ _player.addExpAndSp(xp, sp, true);
+ _player.getInventory().addItem("Fishing Reward", fishingCatchData.getItemId(), 1, _player, null);
+ final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
+ msg.addItemName(fishingCatchData.getItemId());
+ _player.sendPacket(msg);
+ _player.unchargeShot(ShotType.FISH_SOULSHOTS);
+ _player.rechargeShots(false, false, true);
+ }
+ else
+ {
+ LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
+ }
+ }
+ else if (reason == FishingEndReason.LOSE)
+ {
+ _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
+ }
+
+ if (consumeBait)
+ {
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
+ }
+ }
+ finally
+ {
+ _player.broadcastPacket(new ExFishingEnd(_player, reason));
+ _player.sendPacket(new ExUserInfoFishing(_player, false));
+ }
+ }
+
+ public void stopFishing()
+ {
+ stopFishing(FishingEndType.PLAYER_STOP);
+ }
+
+ public synchronized void stopFishing(FishingEndType endType)
+ {
+ if (_isFishing)
+ {
+ reelIn(FishingEndReason.STOP, false);
+ _isFishing = false;
+ switch (endType)
+ {
+ case PLAYER_STOP:
+ {
+ _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
+ break;
+ }
+ case PLAYER_CANCEL:
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ break;
+ }
+ }
+ }
+ }
+
+ public ILocational getBaitLocation()
+ {
+ return _baitLocation;
+ }
+
+ private Location calculateBaitLocation()
+ {
+ // calculate a position in front of the player with a random distance
+ final int distMin = FishingData.getInstance().getBaitDistanceMin();
+ final int distMax = FishingData.getInstance().getBaitDistanceMax();
+ int distance = Rnd.get(distMin, distMax);
+ final double angle = Util.convertHeadingToDegree(_player.getHeading());
+ final double radian = Math.toRadians(angle);
+ final double sin = Math.sin(radian);
+ final double cos = Math.cos(radian);
+ int baitX = (int) (_player.getX() + (cos * distance));
+ int baitY = (int) (_player.getY() + (sin * distance));
+
+ // search for fishing zone
+ L2FishingZone fishingZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
+ {
+ if (zone instanceof L2FishingZone)
+ {
+ fishingZone = (L2FishingZone) zone;
+ break;
+ }
+ }
+ // search for water zone
+ L2WaterZone waterZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
+ {
+ if (zone instanceof L2WaterZone)
+ {
+ waterZone = (L2WaterZone) zone;
+ break;
+ }
+ }
+
+ int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
+ if (baitZ == Integer.MIN_VALUE)
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
+ return null;
+ }
+
+ return new Location(baitX, baitY, baitZ);
+ }
+
+ /**
+ * Computes the Z of the bait.
+ * @param player the player
+ * @param baitX the bait x
+ * @param baitY the bait y
+ * @param fishingZone the fishing zone
+ * @param waterZone the water zone
+ * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
+ */
+ private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
+ {
+ if ((fishingZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if ((waterZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ // always use water zone, fishing zone high z is high in the air...
+ final int baitZ = waterZone.getWaterZ();
+
+ // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
+ //
+ // return Integer.MIN_VALUE;
+ // }
+
+ if (GeoEngine.getInstance().hasGeo(baitX, baitY))
+ {
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+ }
+
+ return baitZ;
+ }
+}
diff --git a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
new file mode 100644
index 0000000000..f5a5764254
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
@@ -0,0 +1,128 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.l2jmobius.commons.util.Rnd;
+
+/**
+ * @author bit
+ */
+public class FishingBait
+{
+ private final int _itemId;
+ private final byte _level;
+ private final byte _minPlayerLevel;
+ private final byte _maxPlayerLevel;
+ private final double _chance;
+ private final int _timeMin;
+ private final int _timeMax;
+ private final int _waitMin;
+ private final int _waitMax;
+ private final boolean _isPremiumOnly;
+ private final List _rewards = new ArrayList<>();
+
+ public FishingBait(int itemId, byte level, byte minPlayerLevel, byte maxPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax, boolean isPremiumOnly)
+ {
+ _itemId = itemId;
+ _level = level;
+ _minPlayerLevel = minPlayerLevel;
+ _maxPlayerLevel = maxPlayerLevel;
+ _chance = chance;
+ _timeMin = timeMin;
+ _timeMax = timeMax;
+ _waitMin = waitMin;
+ _waitMax = waitMax;
+ _isPremiumOnly = isPremiumOnly;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public byte getLevel()
+ {
+ return _level;
+ }
+
+ public byte getMinPlayerLevel()
+ {
+ return _minPlayerLevel;
+ }
+
+ public byte getMaxPlayerLevel()
+ {
+ return _maxPlayerLevel;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public int getTimeMin()
+ {
+ return _timeMin;
+ }
+
+ public int getTimeMax()
+ {
+ return _timeMax;
+ }
+
+ public int getWaitMin()
+ {
+ return _waitMin;
+ }
+
+ public int getWaitMax()
+ {
+ return _waitMax;
+ }
+
+ public boolean isPremiumOnly()
+ {
+ return _isPremiumOnly;
+ }
+
+ public List getRewards()
+ {
+ return _rewards;
+ }
+
+ public void addReward(FishingCatch catchData)
+ {
+ _rewards.add(catchData);
+ }
+
+ public FishingCatch getRandom()
+ {
+ float random = Rnd.get(100);
+ for (FishingCatch fishingCatchData : _rewards)
+ {
+ if (fishingCatchData.getChance() > random)
+ {
+ return fishingCatchData;
+ }
+ random -= fishingCatchData.getChance();
+ }
+ return null;
+ }
+}
diff --git a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
new file mode 100644
index 0000000000..85c2e42e5a
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
@@ -0,0 +1,49 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingCatch
+{
+ private final int _itemId;
+ private final float _chance;
+ private final float _multiplier;
+
+ public FishingCatch(int itemId, float chance, float multiplier)
+ {
+ _itemId = itemId;
+ _chance = chance;
+ _multiplier = multiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public float getChance()
+ {
+ return _chance;
+ }
+
+ public float getMultiplier()
+ {
+ return _multiplier;
+ }
+}
diff --git a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
new file mode 100644
index 0000000000..93b5fb9b8e
--- /dev/null
+++ b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingRod
+{
+ private final int _itemId;
+ private final int _reduceFishingTime;
+ private final float _xpMultiplier;
+ private final float _spMultiplier;
+
+ public FishingRod(int itemId, int reduceFishingTime, float xpMultiplier, float spMultiplier)
+ {
+ _itemId = itemId;
+ _reduceFishingTime = reduceFishingTime;
+ _xpMultiplier = xpMultiplier;
+ _spMultiplier = spMultiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public int getReduceFishingTime()
+ {
+ return _reduceFishingTime;
+ }
+
+ public float getXpMultiplier()
+ {
+ return _xpMultiplier;
+ }
+
+ public float getSpMultiplier()
+ {
+ return _spMultiplier;
+ }
+}
diff --git a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
index 71d8f10b3e..dfcf4d7f56 100644
--- a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
+++ b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
@@ -20,10 +20,10 @@ import java.lang.ref.WeakReference;
import com.l2jmobius.Config;
import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.PcCondOverride;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.serverpackets.fishing.ExAutoFishAvailable;
diff --git a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
index dea11bad61..cebaa3c7a5 100644
--- a/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
+++ b/L2J_Mobius_5.0_Salvation/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
@@ -29,20 +29,17 @@ public class ExFishingStart implements IClientOutgoingPacket
{
private final L2PcInstance _player;
private final int _fishType;
- private final int _baitType;
private final ILocational _baitLocation;
/**
* @param player
* @param fishType
- * @param baitType - 0 = newbie, 1 = normal, 2 = night
* @param baitLocation
*/
- public ExFishingStart(L2PcInstance player, int fishType, int baitType, ILocational baitLocation)
+ public ExFishingStart(L2PcInstance player, int fishType, ILocational baitLocation)
{
_player = player;
_fishType = fishType;
- _baitType = baitType;
_baitLocation = baitLocation;
}
@@ -55,7 +52,7 @@ public class ExFishingStart implements IClientOutgoingPacket
packet.writeD(_baitLocation.getX());
packet.writeD(_baitLocation.getY());
packet.writeD(_baitLocation.getZ());
- packet.writeC(_baitType);
+ packet.writeC(0x01); // 0 = newbie, 1 = normal, 2 = night
return true;
}
}
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/config/Custom/PremiumSystem.ini b/L2J_Mobius_5.5_EtinasFate/dist/game/config/Custom/PremiumSystem.ini
index 8b5d1f1f06..7b0874c29d 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/config/Custom/PremiumSystem.ini
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/config/Custom/PremiumSystem.ini
@@ -45,3 +45,7 @@ EnablePremiumHennaSlotforNonPremium = True
# Also premium henna drawn at normal slots.
# Retail: False
EnableAnyHennaAtPremiumSlot = False
+
+# Enable Fishing only for premium players.
+# Retail: True
+PremiumOnlyFishing = False
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/Fishing.xml b/L2J_Mobius_5.5_EtinasFate/dist/game/data/Fishing.xml
index 42f6633d60..0152888ab6 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/Fishing.xml
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/Fishing.xml
@@ -1,44 +1,41 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/default/34156-1.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/default/34156-1.htm
new file mode 100644
index 0000000000..44a2ea74ad
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/default/34156-1.htm
@@ -0,0 +1,7 @@
+Fisher Peeves:
+Heine Exclusive Bait is really great! It must be a gift from the fishing gods!
+There are some items that can only be caught with Heine Exclusive Bait. Isn't that amazing?
+No doubt the fishing gods heard about this place that gets filled with fishers and decided to grace us with this amazing bait.
+You should try it out!
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/default/34156.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/default/34156.htm
new file mode 100644
index 0000000000..09f6982054
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/default/34156.htm
@@ -0,0 +1,11 @@
+Fisher Peeves:
+Oh, nice to meet you! I'm Peeves, a fisher.
+When I was young, my parents didn't want me to fish since it's dangerous... But how could I stop doing something so fun?
+Are you interested in fishing? Have you heard of the Heine Exclusive Bait?
+If you have a Heine Exclusive Bait Coupon, I can exchange it for Heine Exclusive Bait.
+Oh yeah, I also got a special fishing rod. Bring me some Heine Fishing Coins and I'll give you a Fancy Fishing Rod.
+You can get them from the Exclusive Reward Chest that you can get when you fish with Heine Exclusive Bait.
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31563.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31563.htm
index 25b6b4b199..cfd0217738 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31563.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31563.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Perelin:
-Do you like fishing? I love it.
-Fishing is such a great hobby, don't you think? Sure, it's not very exerting, but...that's the point. I don't like to run around sweating, you know? You can just sit quietly and enjoy the silence.
-
-
-
-
-
-
-
-
-
+Fishing is such a great hobby, don't you think? Sure, it's not very exerting, but...that's the point. I don't like to run around sweating, you know? You can just sit quietly and enjoy silence.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31567.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31567.htm
index 70eb2e221b..9500514c8e 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31567.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31567.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Bleaker:
-Nice to meet you! They call me Bleaker.
-Besides teaching you how to fish, I also sell the fishing gear you'll need. Oh, and I'll buy any fish you catch. In other words, this is your one-stop fishing shop!
-
-
-
-
-
-
-
-
-
+Nice to meet you! They call me Bleaker. I am with the Fishing Guild. If it has to do with fishing, I'm your man. Most of the time, anyway.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31568.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31568.htm
index 49f54d15d9..b2d1001145 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31568.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31568.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Pamfus:
-Do you like fishing? I love it.
-Fishing is such a great hobby, don't you think? Sure, it's not very exerting, but...that's the point. I don't like to run around sweating, you know? You can just sit quietly and enjoy the silence.
-
-
-
-
-
-
-
-
-
+There's no hobby other than fishing that lets you enjoy the nature around you so much. I really do love fishing.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31570.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31570.htm
index e6b7859e93..e92d40e6fb 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31570.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31570.htm
@@ -1,15 +1,13 @@
Fishing Guild Member Lanosco:
-Did you catch one?
-Heh, fishing is harder than it looks, right? You need to be prepared at all times.
-Which is why I'm here! Come see me whenever you need something, and I'll set you right up.
-
-
-
-
-
-
-
-
-
+Hi, I'm Fishing Guild Member Lanosco. Did you catch anything today? Fishing is not as easy as you might, you know. You need to prepare thoroughly.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31571.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31571.htm
index 0f55831347..ce281416f3 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31571.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31571.htm
@@ -1,14 +1,13 @@
Fishermen's Guild Member Huffs:
-Welcome! Are you here to fish?
-There's no better way to relax and decompress after a stressful day, week, or life! Haha!
-
-
-
-
-
-
-
-
-
+Hello, and welcome. Are you here to learn about fishing? There's no better way to relax and decompress after a stressful day, week, or life! Haha! It's quite the experience, wrestling huge fish along the coast or on the riverbanks, armed with little more than a rod and some string.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31572.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31572.htm
index b8434accc2..2d82c9fa59 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31572.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31572.htm
@@ -1,14 +1,13 @@
Fishing Guild Member O'Fulle:
-Everything is plentiful here in Giran, which is why so many people spend their leisure time fishing. It's a sign of abundance!
-Oh, pardon me -- I'm O'Fulle, the only officially licensed fishing gear merchant in this territory! See me if you need to buy bait or sell fish. Fish only -- no mermaids! Haha!
-
-
-
-
-
-
-
-
-
+I'm Fishing Guild Member O'Fulle. Try your luck at fishing in Giran, the land of plenty! Watch out, catching mermaids might get you into trouble! Stick with the fish! Hahaha!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31573.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31573.htm
index 7a9d68571a..2903e2c1d0 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31573.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31573.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Monakan:
-Well, hello there. I'm Monakan.
-I can teach you about fishing items as well as how to fish. Oh, I'll also buy any fish you catch. In other words, this is your one-stop fishing shop!
-
-
-
-
-
-
-
-
-
+Well, hello there. I'm Monakan, a member of the Fishing Guild. I'm the one to come to when it comes to fishing, since I deal not only in fishing supplies but also the fish that are caught.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31574.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31574.htm
index 021707372b..fb24509ac6 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31574.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31574.htm
@@ -1,13 +1,13 @@
Fishing Guild Member Willie:
-Fishing has become all the rage in these parts! I think it's because of all the brainy people around here -- the Ivory Tower, for example! Lots of them just sit there thinking, and forget to actually catch the fish!
-
-
-
-
-
-
-
-
-
+Oren is a city of culture, to which many intelligent ones flock. That's why we have so many fishing enthusiasts!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31575.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31575.htm
index 5381af429a..58f12301c3 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31575.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31575.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Litulon:
-There's no better place for fishing than Innadril. Wet and warm all year round, beautiful scenery, the best place in the whole world.
-I mean, Goddess Eva watches over us after all. The City of Waters! Haha!
-
-
-
-
-
-
-
-
-
+The Innadril Territory is just the spot for fishing. I mean, Goddess Eva watches over us after all. The City of Waters! Haha!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31576.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31576.htm
index 40daf36a06..dc3fe17673 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31576.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31576.htm
@@ -1,14 +1,14 @@
Fishing Guild Member Berix:
-I'm quite happy to be holding the fishing contest in my native town. It's good to know I can do what I love, where I live.
-I think it's time we got to it, perfect weather for fishing!
-
-
-
-
-
-
-
-
-
+Pleased to meet you. I'm Berix, a member of the Fishing Guild. See, people tend to think that there are only hunters in the Hunter's Village, but we have a lot of great fishers as well! I'm one of them, you see. Hahahaha.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31577.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31577.htm
index 42e3023192..dcf0570a3a 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31577.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31577.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Linnaeus:
-Did you know that the king is an avid fisher himself? Haha!
-Aden is filled with prime fishing zones. How about spending this beautiful day on one of them?
-
-
-
-
-
-
-
-
-
+Did you know that the King is an avid fisher himself? Haha! We at the Fishing Guild are quite proud of this fact. He's actually quite the Master!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31578.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31578.htm
index 22424bd71f..9a39b5209d 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31578.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31578.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Hilgendorf:
-Welcome! Beautiful day for fishing, dontcha' think?
-My family has been in the Guild for generations, ever since my great-grandfather joined.
-
-
-
-
-
-
-
-
-
+Welcome, and good to see you! The weather's perfect for fishing, wouldn't you agree? My family has been in the Guild for generations, ever since my great-grandfather joined.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31579.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31579.htm
index 4905012750..d19e501e8e 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31579.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31579.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Klaus:
-Well, well, well! Another fisher, huh?
-You know how lucky you are to be here, right? With its many mountain streams and lakes, Goddard is a prime fishing land. People come from all over to test their skill and try their luck here.
-
-
-
-
-
-
-
-
-
+I am Klaus, one of Fishing Guild members. If you have anything you need related with fishing, fine me.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31696.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31696.htm
index afb7f7612b..10fc8d9b1e 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31696.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31696.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Platis:
-This area is a rare spot in Elmore where you can catch actual saltwater fish. It used to be a famous fishing site in the Elmoreden years, and now that things have slowed down, the fish population is back.
-Care to give it a try? Let me know if you need any equipment!
-
-
-
-
-
-
-
-
-
+This has been a very popular fishing dock since the age of the Elmoreden. This is the tranquil and beautiful fishing spot you've been searching high and low for, I tell you!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31697.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31697.htm
index b78f53e3e4..77ef12b6d8 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31697.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31697.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Eindarkner:
-Do you know about these hot springs? The effects of the nearby Forge of the Gods have created a whole network of them around here. There are special species of fish living in these hot springs! It's the opportunity of a lifetime.
-Let me know if you need anything!
-
-
-
-
-
-
-
-
-
+Have you heard about the Hot Springs in the area? There are natural hot springs everywhere, thanks to the Forge of the Gods. Before, there were fish to be caught in the hot springs as well, but they have all disappeared now. What a pity.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31989.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31989.htm
index f8b1a88ccd..c032d201fa 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31989.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/31989.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Batidae:
-You came here to fish, right? Who am I kidding, of course you did!
-No better way to spend an afternoon than casting the line!
-
-
-
-
-
-
-
-
-
+Welcome. Want to learn how to fish, do you? You must have really been running out of things to learn to come all the way here to learn about fishing, of all things. Frankly, you'd be doing yourself more good by learning how to mine ore in the mines over there. Anyways, since you're here, really, there's no better way to spend an afternoon than casting the line!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/32007.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/32007.htm
index 939f2f8362..f65b882bdc 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/32007.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/32007.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Galba:
-Rainbow Springs -- ahh, heaven!
-You should try fishing around here. The fish here are huge. Let me know if you need any fishing items or want to sell something.
-
-
-
-
-
-
-
-
-
+Since you've come to find me, I reckon you know that the Rainbow Springs are a veritable heaven on earth for us fishing enthusiasts. That's right, this is some of the best fishing you'll find anywhere.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fish_appearance_exchange.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fish_appearance_exchange.htm
new file mode 100644
index 0000000000..8d25e5d848
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fish_appearance_exchange.htm
@@ -0,0 +1,11 @@
+
+
+ Exchange for appearance items:
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual001.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual001.htm
index dc66dd577c..d7badfef10 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual001.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual001.htm
@@ -1,10 +1,8 @@
Fishing Manual:
-
-
+
-
-
-
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual002.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual002.htm
index 3c1bb703da..a37c28a0da 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual002.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual002.htm
@@ -1,6 +1,5 @@
Fishing Manual:
-In order to fish, you need to find a fishing area. Once you arrive at the right spot, you'll see the button on the right side of your screen that alerts you that you can fish.
+In order to fish, you need to find a fishing area. Once you arrive at the right spot, you'll see the button on the right side of your screen that alerts you that you can fish.
Then check if you can actually fish. Check that you have a Fishing Rod and Bait equipped. You can set the Fishing Shots to be used automatically when you fish.
-
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual003.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual003.htm
index da8ab5942b..910782fc81 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual003.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual003.htm
@@ -1,6 +1,4 @@
-Fishing Manual:
-A fishing zone refers to a place with enough fish to be caught.
-The places that are good for fishing are the following: around Lake Iris, Narsell Lake where the Coliseum is, Giran Harbor's coast, around the Plains of the Lizardmen, waterside in the Town of Gludio, the Neutral Zone, Heine, Fellmere Lake, and the bridge near the Town of Giran.
+Fishing Manual:
+In order to fish, you need to find a fishing area. Once you arrive at the right spot, you'll see the button on the right side of your screen that alerts you that you can fish. Then check if you can actually fish. Check that you have a Fishing Rod and Bait equipped. You can set the Fishing Shots to be used automatically when you fish.
-
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual004.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual004.htm
index 7d4dbce9a9..a45c766c9a 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual004.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual004.htm
@@ -1,7 +1,7 @@
-Fishing Manual:
-There are two types of bait.
-The Normal Bait, you can buy from me.
-If you want to catch more expensive fish, I recommend you use the Special Bait. I have never seen Special Bait, but I heard that you can get it from the boxes you get from fishing.
+Fishing Manual:
+There are three types of bait.
+These are the basic bait, the R99 bait which can be used by characters of Lv. 99 and above and he PC Cafe bait, which can be purchased using PC Cafe Points.
+Of these, the Fishing Guild sells the basic bait and the R99 bait.
+With each type of bait, you can catch different types of fish. The conditions for purchasing and use vary among bait types as well. The Powerful Fish, which is the most expensive fish you can catch, can be caught using the R99 bait or the PC Cafe bait.
-
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual008.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual008.htm
index 4a56fdac27..5063653e3a 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual008.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual008.htm
@@ -1,7 +1,6 @@
-Fishing Manual:
+Fishing Manual:
Created by the Black Anvil Guild at the request of Ampitri, the founder of the Fishing Guild, Fishing Shots are variations of Soulshots made for fishing.
But while Soulshots amplify a hit, Fishing Shots increase the fisher's chances of catching a fish.
It's an item that will help you catch fish more efficiently.
-
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual009.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual009.htm
index 3094aa089d..29fe921d82 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual009.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual009.htm
@@ -1,7 +1,7 @@
-Fishing Manual:
-You can sell the fish whole, take it apart to sell a portion, or use it to craft items. You can also exchange it for Elcyum Powder through our Fishing Guild.
-Keep in mind that you might lose everything when cutting up your fish though! It depends on your luck.
-You can also bring Elcyum Powder to our guild to learn some legendary fishing skills. You decide what to do with your fish.
+Fishing Manual:
+Bring the fish you catch to us to exchange for various items that the Fishing Guild deals in.
+The Ugly Fish and Nimble Fish can be exchanged for Fish Stew, Appearance Stones, Hair Accessories, Transformation Scrolls, and Weapon Appearance Stones.
+If you have caught a Powerful Fish, it may be exchanged for a Stardust item or Elcyum Powder which is needed when exchanging for a Zodiac Agathion Treasure Chest. You may also sell the fish to the shop.
+If you bring us Elcyum Powder, we can let you in on a few secret techniques that have been handed down in our guild through the generation. Please think carefully about what you want to do with the fish that you catch.
-
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual010.htm b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual010.htm
index 4769d79268..21fb4dec2d 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual010.htm
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/html/fisherman/fishing_manual010.htm
@@ -1,6 +1,38 @@
-Fishing Manual:
-You can buy Normal Bait from the Fishing Guild.
-As for the Special Bait, you can get it from the wooden boxes that you get from fishing. Use the Special Bait to catch shiny fish.
-
+Fishing Manual:
+The time required for fishing, and the rate of success vary according to the type of bait, the type of rod, and whether or not Fishing Shot is used.
+
+
+
+
Bait - Fishing Time and Standby Time
+
+
+
+For each bait, the time required until fish bite is preset.
+As for the basic bait sold in the shop,Fishing Time is 105 seconds, and Standby Time is 15 seconds.This means catching a single fish takes a total of 120 seconds.
+
+
+
+
+
Fishing Rod - Fishing Time reduced
+
+
+
+
+A better fishing rod will reduce Fishing Time.
+The Normal Fishing Rod and Sturdy Fishing Rodwill not reduce Fishing Time.When you obtain Master Fishing Rod Stage 1,your Fishing Time will begin to decrease.
+
+
+
+
+
Fishing Shot - Fishing Probability increased
+
+
+
+
+
+Fishing Shot increases your odds of catching a fish.
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2144.xml b/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2144.xml
new file mode 100644
index 0000000000..b763fcb01e
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2144.xml
@@ -0,0 +1,39 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+ 34156
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2194.xml b/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2194.xml
new file mode 100644
index 0000000000..52d33e59e4
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2194.xml
@@ -0,0 +1,70 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2195.xml b/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2195.xml
new file mode 100644
index 0000000000..e73c2546f1
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2195.xml
@@ -0,0 +1,138 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2203.xml b/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2203.xml
new file mode 100644
index 0000000000..82d49aba41
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2203.xml
@@ -0,0 +1,62 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2207.xml b/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2207.xml
new file mode 100644
index 0000000000..a0521b646d
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2207.xml
@@ -0,0 +1,62 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2208.xml b/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2208.xml
new file mode 100644
index 0000000000..0c8953f318
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/2208.xml
@@ -0,0 +1,94 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/3034.xml b/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/3034.xml
new file mode 100644
index 0000000000..6bd81e7b08
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/multisell/3034.xml
@@ -0,0 +1,22 @@
+
+
+
+ 34156
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/spawns/Innadril/Heine.xml b/L2J_Mobius_5.5_EtinasFate/dist/game/data/spawns/Innadril/Heine.xml
index 7a35b26c4e..8a89d9a86e 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/spawns/Innadril/Heine.xml
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/spawns/Innadril/Heine.xml
@@ -75,6 +75,7 @@
+
-
\ No newline at end of file
+
diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/xsd/Fishing.xsd b/L2J_Mobius_5.5_EtinasFate/dist/game/data/xsd/Fishing.xsd
index 16e5ed9699..1078ed7f77 100644
--- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/xsd/Fishing.xsd
+++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/xsd/Fishing.xsd
@@ -9,13 +9,13 @@
-
+
-
+
@@ -30,17 +30,35 @@
+
+
-
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/Config.java b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/Config.java
index 3ace6d94a3..0658b8c8ec 100644
--- a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/Config.java
+++ b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/Config.java
@@ -1133,11 +1133,12 @@ public final class Config
public static float PREMIUM_RATE_DROP_AMOUNT;
public static float PREMIUM_RATE_SPOIL_CHANCE;
public static float PREMIUM_RATE_SPOIL_AMOUNT;
+ public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
+ public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
public static boolean PREMIUM_HENNA_SLOT_ENABLED;
public static boolean PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL;
public static boolean PREMIUM_HENNA_SLOT_ALL_DYES;
- public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
- public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
+ public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
public static int PC_CAFE_MAX_POINTS;
@@ -2632,9 +2633,6 @@ public final class Config
PREMIUM_RATE_DROP_AMOUNT = PremiumSystem.getFloat("PremiumRateDropAmount", 1);
PREMIUM_RATE_SPOIL_CHANCE = PremiumSystem.getFloat("PremiumRateSpoilChance", 2);
PREMIUM_RATE_SPOIL_AMOUNT = PremiumSystem.getFloat("PremiumRateSpoilAmount", 1);
- PREMIUM_HENNA_SLOT_ENABLED = PremiumSystem.getBoolean("EnablePremiumHennaSlot", true);
- PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL = PremiumSystem.getBoolean("EnablePremiumHennaSlotforNonPremium", true);
- PREMIUM_HENNA_SLOT_ALL_DYES = PremiumSystem.getBoolean("EnableAnyHennaAtPremiumSlot", false);
final String[] premiumDropChanceMultiplier = PremiumSystem.getString("PremiumRateDropChanceByItemId", "").split(";");
PREMIUM_RATE_DROP_CHANCE_BY_ID = new HashMap<>(premiumDropChanceMultiplier.length);
if (!premiumDropChanceMultiplier[0].isEmpty())
@@ -2689,6 +2687,10 @@ public final class Config
}
}
}
+ PREMIUM_HENNA_SLOT_ENABLED = PremiumSystem.getBoolean("EnablePremiumHennaSlot", true);
+ PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL = PremiumSystem.getBoolean("EnablePremiumHennaSlotforNonPremium", true);
+ PREMIUM_HENNA_SLOT_ALL_DYES = PremiumSystem.getBoolean("EnableAnyHennaAtPremiumSlot", false);
+ PREMIUM_ONLY_FISHING = PremiumSystem.getBoolean("PremiumOnlyFishing", true);
// Load PrivateStoreRange config file (if exists)
final PropertiesParser PrivateStoreRange = new PropertiesParser(CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE);
diff --git a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
index 91b5f9c43e..bacf1ed08c 100644
--- a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
+++ b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
@@ -25,8 +25,12 @@ import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
+import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
-import com.l2jmobius.gameserver.model.FishingBaitData;
+import com.l2jmobius.gameserver.datatables.ItemTable;
+import com.l2jmobius.gameserver.model.fishing.FishingBait;
+import com.l2jmobius.gameserver.model.fishing.FishingCatch;
+import com.l2jmobius.gameserver.model.fishing.FishingRod;
/**
* This class holds the Fishing information.
@@ -35,7 +39,8 @@ import com.l2jmobius.gameserver.model.FishingBaitData;
public final class FishingData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(FishingData.class.getName());
- private final Map _baitData = new HashMap<>();
+ private final Map _baitData = new HashMap<>();
+ private final Map _rodData = new HashMap<>();
private int _baitDistanceMin;
private int _baitDistanceMax;
private double _expRateMin;
@@ -56,7 +61,7 @@ public final class FishingData implements IGameXmlReader
{
_baitData.clear();
parseDatapackFile("data/Fishing.xml");
- LOGGER.info(getClass().getSimpleName() + ": Loaded Fishing Data.");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _baitData.size() + " bait and " + _rodData.size() + " rod data.");
}
@Override
@@ -76,13 +81,13 @@ public final class FishingData implements IGameXmlReader
_baitDistanceMax = parseInteger(listItem.getAttributes(), "max");
break;
}
- case "experienceRate":
+ case "xpRate":
{
_expRateMin = parseDouble(listItem.getAttributes(), "min");
_expRateMax = parseDouble(listItem.getAttributes(), "max");
break;
}
- case "skillPointsRate":
+ case "spRate":
{
_spRateMin = parseDouble(listItem.getAttributes(), "min");
_spRateMax = parseDouble(listItem.getAttributes(), "max");
@@ -96,20 +101,39 @@ public final class FishingData implements IGameXmlReader
{
final NamedNodeMap attrs = bait.getAttributes();
final int itemId = parseInteger(attrs, "itemId");
- final int level = parseInteger(attrs, "level");
- final int minPlayerLevel = parseInteger(attrs, "minPlayerLevel");
+ final byte level = parseByte(attrs, "level", (byte) 1);
+ final byte minPlayerLevel = parseByte(attrs, "minPlayerLevel");
+ final byte maxPlayerLevel = parseByte(attrs, "minPlayerLevel", Config.PLAYER_MAXIMUM_LEVEL);
final double chance = parseDouble(attrs, "chance");
final int timeMin = parseInteger(attrs, "timeMin");
- final int timeMax = parseInteger(attrs, "timeMax");
+ final int timeMax = parseInteger(attrs, "timeMax", timeMin);
final int waitMin = parseInteger(attrs, "waitMin");
- final int waitMax = parseInteger(attrs, "waitMax");
- final FishingBaitData baitData = new FishingBaitData(itemId, level, minPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax);
+ final int waitMax = parseInteger(attrs, "waitMax", waitMin);
+ final boolean isPremiumOnly = parseBoolean(attrs, "isPremiumOnly", false);
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ final FishingBait baitData = new FishingBait(itemId, level, minPlayerLevel, maxPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax, isPremiumOnly);
for (Node c = bait.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("catch".equalsIgnoreCase(c.getNodeName()))
{
- baitData.addReward(parseInteger(c.getAttributes(), "itemId"));
+ final NamedNodeMap cAttrs = c.getAttributes();
+ final int cId = parseInteger(cAttrs, "itemId");
+ final float cChance = parseFloat(cAttrs, "chance");
+ final float cMultiplier = parseFloat(cAttrs, "multiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(cId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ baitData.addReward(new FishingCatch(cId, cChance, cMultiplier));
}
}
_baitData.put(baitData.getItemId(), baitData);
@@ -117,22 +141,44 @@ public final class FishingData implements IGameXmlReader
}
break;
}
+ case "rods":
+ {
+ for (Node rod = listItem.getFirstChild(); rod != null; rod = rod.getNextSibling())
+ {
+ if ("rod".equalsIgnoreCase(rod.getNodeName()))
+ {
+ final NamedNodeMap attrs = rod.getAttributes();
+ final int itemId = parseInteger(attrs, "itemId");
+ final int reduceFishingTime = parseInteger(attrs, "reduceFishingTime", 0);
+ final float xpMultiplier = parseFloat(attrs, "xpMultiplier", 1f);
+ final float spMultiplier = parseFloat(attrs, "spMultiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ _rodData.put(itemId, new FishingRod(itemId, reduceFishingTime, xpMultiplier, spMultiplier));
+ }
+ }
+ }
}
}
}
}
}
- /**
- * Gets the fishing rod.
- * @param baitItemId the item id
- * @return A list of reward item ids
- */
- public FishingBaitData getBaitData(int baitItemId)
+ public FishingBait getBaitData(int baitItemId)
{
return _baitData.get(baitItemId);
}
+ public FishingRod getRodData(int rodItemId)
+ {
+ return _rodData.get(rodItemId);
+ }
+
public int getBaitDistanceMin()
{
return _baitDistanceMin;
diff --git a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/FishingBaitData.java b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/FishingBaitData.java
deleted file mode 100644
index 9cf4893d66..0000000000
--- a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/FishingBaitData.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author bit
- */
-public class FishingBaitData
-{
- private final int _itemId;
- private final int _level;
- private final int _minPlayerLevel;
- private final double _chance;
- private final int _timeMin;
- private final int _timeMax;
- private final int _waitMin;
- private final int _waitMax;
- private final List _rewards = new ArrayList<>();
-
- public FishingBaitData(int itemId, int level, int minPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax)
- {
- _itemId = itemId;
- _level = level;
- _minPlayerLevel = minPlayerLevel;
- _chance = chance;
- _timeMin = timeMin;
- _timeMax = timeMax;
- _waitMin = waitMin;
- _waitMax = waitMax;
- }
-
- public int getItemId()
- {
- return _itemId;
- }
-
- public int getLevel()
- {
- return _level;
- }
-
- public int getMinPlayerLevel()
- {
- return _minPlayerLevel;
- }
-
- public double getChance()
- {
- return _chance;
- }
-
- public int getTimeMin()
- {
- return _timeMin;
- }
-
- public int getTimeMax()
- {
- return _timeMax;
- }
-
- public int getWaitMin()
- {
- return _waitMin;
- }
-
- public int getWaitMax()
- {
- return _waitMax;
- }
-
- public List getRewards()
- {
- return _rewards;
- }
-
- public void addReward(int itemId)
- {
- _rewards.add(itemId);
- }
-}
diff --git a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
index fd6244cfa0..23acc01567 100644
--- a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
+++ b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
@@ -125,7 +125,6 @@ import com.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import com.l2jmobius.gameserver.model.BlockList;
import com.l2jmobius.gameserver.model.ClanPrivilege;
import com.l2jmobius.gameserver.model.ClanWar;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.L2AccessLevel;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
@@ -209,6 +208,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPCh
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPKill;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerReputationChanged;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerSubChange;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.MonsterBookCardHolder;
diff --git a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/Fishing.java b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
similarity index 80%
rename from L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/Fishing.java
rename to L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
index 17746b3e77..4421a1a3c0 100644
--- a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/Fishing.java
+++ b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
@@ -1,443 +1,471 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.concurrent.ScheduledFuture;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.commons.util.Rnd;
-import com.l2jmobius.gameserver.data.xml.impl.FishingData;
-import com.l2jmobius.gameserver.enums.ShotType;
-import com.l2jmobius.gameserver.geoengine.GeoEngine;
-import com.l2jmobius.gameserver.instancemanager.ZoneManager;
-import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jmobius.gameserver.model.events.EventDispatcher;
-import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
-import com.l2jmobius.gameserver.model.interfaces.ILocational;
-import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
-import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
-import com.l2jmobius.gameserver.model.items.type.WeaponType;
-import com.l2jmobius.gameserver.model.zone.L2ZoneType;
-import com.l2jmobius.gameserver.model.zone.ZoneId;
-import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
-import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
-import com.l2jmobius.gameserver.network.SystemMessageId;
-import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
-import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
-import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
-import com.l2jmobius.gameserver.util.Util;
-
-/**
- * @author bit
- */
-public class Fishing
-{
- protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
- private volatile ILocational _baitLocation = new Location(0, 0, 0);
-
- private final L2PcInstance _player;
- private ScheduledFuture> _reelInTask;
- private ScheduledFuture> _startFishingTask;
- private boolean _isFishing = false;
-
- public Fishing(L2PcInstance player)
- {
- _player = player;
- }
-
- public synchronized boolean isFishing()
- {
- return _isFishing;
- }
-
- public boolean isAtValidLocation()
- {
- // TODO: implement checking direction
- // if (calculateBaitLocation() == null)
- // {
- // return false;
- // }
- return _player.isInsideZone(ZoneId.FISHING);
- }
-
- public boolean canFish()
- {
- return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
- }
-
- private FishingBaitData getCurrentBaitData()
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
- }
-
- private void cancelTasks()
- {
- if (_reelInTask != null)
- {
- _reelInTask.cancel(false);
- _reelInTask = null;
- }
-
- if (_startFishingTask != null)
- {
- _startFishingTask.cancel(false);
- _startFishingTask = null;
- }
- }
-
- public synchronized void startFishing()
- {
- if (_isFishing)
- {
- return;
- }
- _isFishing = true;
- castLine();
- }
-
- private void castLine()
- {
- if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
- {
- _player.sendMessage("Fishing is disabled.");
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- cancelTasks();
-
- if (!canFish())
- {
- if (_isFishing)
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final FishingBaitData baitData = getCurrentBaitData();
- final int minPlayerLevel = baitData == null ? 85 : baitData.getMinPlayerLevel();
- if (_player.getLevel() < minPlayerLevel)
- {
- if (minPlayerLevel == 85)
- {
- _player.sendPacket(SystemMessageId.FISHING_IS_AVAILABLE_TO_PREMIUM_USERS_ONLY);
- }
- else // In case of custom fishing level.
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
- }
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final L2ItemInstance rod = _player.getActiveWeaponInstance();
- if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (baitData == null)
- {
- _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isTransformed() || _player.isInBoat())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHEN_TRANSFORMED_OR_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_IT_S_AGAINST_THE_RULES);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isCrafting() || _player.isInStoreMode())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- _baitLocation = calculateBaitLocation();
- if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
- {
- if (_isFishing)
- {
- // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- else
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- _player.rechargeShots(false, false, true);
- }
-
- _reelInTask = ThreadPool.schedule(() ->
- {
- _player.getFishing().reelInWithReward();
- _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), Rnd.get(baitData.getWaitMin(), baitData.getWaitMax()));
- }, Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()));
- _player.stopMove(null);
- _player.broadcastPacket(new ExFishingStart(_player, -1, baitData.getLevel(), _baitLocation));
- _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
- _player.sendPacket(new PlaySound("SF_P_01"));
- _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
- }
-
- public void reelInWithReward()
- {
- // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
- // Then player may or may not catch the fish. Using fishing shots increases chance to win.
- final FishingBaitData baitData = getCurrentBaitData();
- if (baitData == null)
- {
- reelIn(FishingEndReason.LOSE, false);
- LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
- return;
- }
-
- double chance = baitData.getChance();
- if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- chance *= 1.5; // +50 % chance to win
- }
-
- if (Rnd.get(0, 100) <= chance)
- {
- reelIn(FishingEndReason.WIN, true);
- }
- else
- {
- reelIn(FishingEndReason.LOSE, true);
- }
- }
-
- private void reelIn(FishingEndReason reason, boolean consumeBait)
- {
- if (!_isFishing)
- {
- return;
- }
-
- cancelTasks();
-
- try
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- if (consumeBait)
- {
- if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
- {
- reason = FishingEndReason.LOSE; // no bait - no reward
- return;
- }
- }
-
- if ((reason == FishingEndReason.WIN) && (bait != null))
- {
- final FishingBaitData baitData = FishingData.getInstance().getBaitData(bait.getId());
- final int numRewards = baitData.getRewards().size();
- if (numRewards > 0)
- {
- final FishingData fishingData = FishingData.getInstance();
- final int lvlModifier = _player.getLevel() * _player.getLevel();
- _player.addExpAndSp(Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier, Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier, true);
- final int fishId = baitData.getRewards().get(Rnd.get(0, numRewards - 1));
- _player.getInventory().addItem("Fishing Reward", fishId, 1, _player, null);
- final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
- msg.addItemName(fishId);
- _player.sendPacket(msg);
- _player.unchargeShot(ShotType.FISH_SOULSHOTS);
- _player.rechargeShots(false, false, true);
- }
- else
- {
- LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
- }
- }
- else if (reason == FishingEndReason.LOSE)
- {
- _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
- }
-
- if (consumeBait)
- {
- EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
- }
- }
- finally
- {
- _player.broadcastPacket(new ExFishingEnd(_player, reason));
- _player.sendPacket(new ExUserInfoFishing(_player, false));
- }
- }
-
- public void stopFishing()
- {
- stopFishing(FishingEndType.PLAYER_STOP);
- }
-
- public synchronized void stopFishing(FishingEndType endType)
- {
- if (_isFishing)
- {
- reelIn(FishingEndReason.STOP, false);
- _isFishing = false;
- switch (endType)
- {
- case PLAYER_STOP:
- {
- _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
- break;
- }
- case PLAYER_CANCEL:
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- break;
- }
- }
- }
- }
-
- public ILocational getBaitLocation()
- {
- return _baitLocation;
- }
-
- private Location calculateBaitLocation()
- {
- // calculate a position in front of the player with a random distance
- final int distMin = FishingData.getInstance().getBaitDistanceMin();
- final int distMax = FishingData.getInstance().getBaitDistanceMax();
- int distance = Rnd.get(distMin, distMax);
- final double angle = Util.convertHeadingToDegree(_player.getHeading());
- final double radian = Math.toRadians(angle);
- final double sin = Math.sin(radian);
- final double cos = Math.cos(radian);
- int baitX = (int) (_player.getX() + (cos * distance));
- int baitY = (int) (_player.getY() + (sin * distance));
-
- // search for fishing zone
- L2FishingZone fishingZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
- {
- if (zone instanceof L2FishingZone)
- {
- fishingZone = (L2FishingZone) zone;
- break;
- }
- }
- // search for water zone
- L2WaterZone waterZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
- {
- if (zone instanceof L2WaterZone)
- {
- waterZone = (L2WaterZone) zone;
- break;
- }
- }
-
- int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
- if (baitZ == Integer.MIN_VALUE)
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
- return null;
- }
-
- return new Location(baitX, baitY, baitZ);
- }
-
- /**
- * Computes the Z of the bait.
- * @param player the player
- * @param baitX the bait x
- * @param baitY the bait y
- * @param fishingZone the fishing zone
- * @param waterZone the water zone
- * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
- */
- private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
- {
- if ((fishingZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- if ((waterZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- // always use water zone, fishing zone high z is high in the air...
- final int baitZ = waterZone.getWaterZ();
-
- // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
- //
- // return Integer.MIN_VALUE;
- // }
-
- if (GeoEngine.getInstance().hasGeo(baitX, baitY))
- {
- if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
-
- if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
- }
-
- return baitZ;
- }
-}
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.commons.util.Rnd;
+import com.l2jmobius.gameserver.data.xml.impl.FishingData;
+import com.l2jmobius.gameserver.enums.ShotType;
+import com.l2jmobius.gameserver.geoengine.GeoEngine;
+import com.l2jmobius.gameserver.instancemanager.ZoneManager;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.PcCondOverride;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.events.EventDispatcher;
+import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
+import com.l2jmobius.gameserver.model.interfaces.ILocational;
+import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.model.items.type.WeaponType;
+import com.l2jmobius.gameserver.model.zone.L2ZoneType;
+import com.l2jmobius.gameserver.model.zone.ZoneId;
+import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
+import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
+import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author bit
+ */
+public class Fishing
+{
+ protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
+ private volatile ILocational _baitLocation = new Location(0, 0, 0);
+
+ private final L2PcInstance _player;
+ private ScheduledFuture> _reelInTask;
+ private ScheduledFuture> _startFishingTask;
+ private boolean _isFishing = false;
+
+ public Fishing(L2PcInstance player)
+ {
+ _player = player;
+ }
+
+ public synchronized boolean isFishing()
+ {
+ return _isFishing;
+ }
+
+ public boolean isAtValidLocation()
+ {
+ // TODO: implement checking direction
+ // if (calculateBaitLocation() == null)
+ // {
+ // return false;
+ // }
+ return _player.isInsideZone(ZoneId.FISHING);
+ }
+
+ public boolean canFish()
+ {
+ return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
+ }
+
+ private FishingBait getCurrentBaitData()
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
+ }
+
+ private void cancelTasks()
+ {
+ if (_reelInTask != null)
+ {
+ _reelInTask.cancel(false);
+ _reelInTask = null;
+ }
+
+ if (_startFishingTask != null)
+ {
+ _startFishingTask.cancel(false);
+ _startFishingTask = null;
+ }
+ }
+
+ public synchronized void startFishing()
+ {
+ if (_isFishing)
+ {
+ return;
+ }
+ _isFishing = true;
+ castLine();
+ }
+
+ private void castLine()
+ {
+ if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
+ {
+ _player.sendMessage("Fishing is disabled.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ cancelTasks();
+
+ if (!canFish())
+ {
+ if (_isFishing)
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (Config.PREMIUM_SYSTEM_ENABLED)
+ {
+ if (Config.PREMIUM_ONLY_FISHING && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.FISHING_IS_AVAILABLE_TO_PREMIUM_USERS_ONLY);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (baitData.isPremiumOnly() && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.FAILED_PLEASE_TRY_AGAIN_USING_THE_CORRECT_BAIT);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+ }
+
+ final int minPlayerLevel = baitData.getMinPlayerLevel();
+ final int maxPLayerLevel = baitData.getMaxPlayerLevel();
+ if ((_player.getLevel() < minPlayerLevel) && (_player.getLevel() > maxPLayerLevel))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final L2ItemInstance rod = _player.getActiveWeaponInstance();
+ if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingRod rodData = FishingData.getInstance().getRodData(rod.getId());
+ if (rodData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isTransformed() || _player.isInBoat())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHEN_TRANSFORMED_OR_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_IT_S_AGAINST_THE_RULES);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isCrafting() || _player.isInStoreMode())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ _baitLocation = calculateBaitLocation();
+ if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
+ {
+ if (_isFishing)
+ {
+ // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ else
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ _player.rechargeShots(false, false, true);
+ }
+
+ final long fishingTime = Math.max(Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()) - rodData.getReduceFishingTime(), 1000);
+ final long fishingWaitTime = Rnd.get(baitData.getWaitMin(), baitData.getWaitMax());
+
+ _reelInTask = ThreadPool.schedule(() ->
+ {
+ _player.getFishing().reelInWithReward();
+ _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), fishingWaitTime);
+ }, fishingTime);
+ _player.stopMove(null);
+ _player.broadcastPacket(new ExFishingStart(_player, -1, _baitLocation));
+ _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
+ _player.sendPacket(new PlaySound("SF_P_01"));
+ _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
+ }
+
+ public void reelInWithReward()
+ {
+ // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
+ // Then player may or may not catch the fish. Using fishing shots increases chance to win.
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ reelIn(FishingEndReason.LOSE, false);
+ LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
+ return;
+ }
+
+ double chance = baitData.getChance();
+ if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ chance *= 2;
+ }
+
+ if (Rnd.get(100) <= chance)
+ {
+ reelIn(FishingEndReason.WIN, true);
+ }
+ else
+ {
+ reelIn(FishingEndReason.LOSE, true);
+ }
+ }
+
+ private void reelIn(FishingEndReason reason, boolean consumeBait)
+ {
+ if (!_isFishing)
+ {
+ return;
+ }
+
+ cancelTasks();
+
+ try
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ if (consumeBait)
+ {
+ if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
+ {
+ reason = FishingEndReason.LOSE; // no bait - no reward
+ return;
+ }
+ }
+
+ if ((reason == FishingEndReason.WIN) && (bait != null))
+ {
+ final FishingBait baitData = FishingData.getInstance().getBaitData(bait.getId());
+ final FishingCatch fishingCatchData = baitData.getRandom();
+ if (fishingCatchData != null)
+ {
+ final FishingData fishingData = FishingData.getInstance();
+ final double lvlModifier = (Math.pow(_player.getLevel(), 2.2) * fishingCatchData.getMultiplier());
+ final long xp = (long) (Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier);
+ final long sp = (long) (Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier);
+ _player.addExpAndSp(xp, sp, true);
+ _player.getInventory().addItem("Fishing Reward", fishingCatchData.getItemId(), 1, _player, null);
+ final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
+ msg.addItemName(fishingCatchData.getItemId());
+ _player.sendPacket(msg);
+ _player.unchargeShot(ShotType.FISH_SOULSHOTS);
+ _player.rechargeShots(false, false, true);
+ }
+ else
+ {
+ LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
+ }
+ }
+ else if (reason == FishingEndReason.LOSE)
+ {
+ _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
+ }
+
+ if (consumeBait)
+ {
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
+ }
+ }
+ finally
+ {
+ _player.broadcastPacket(new ExFishingEnd(_player, reason));
+ _player.sendPacket(new ExUserInfoFishing(_player, false));
+ }
+ }
+
+ public void stopFishing()
+ {
+ stopFishing(FishingEndType.PLAYER_STOP);
+ }
+
+ public synchronized void stopFishing(FishingEndType endType)
+ {
+ if (_isFishing)
+ {
+ reelIn(FishingEndReason.STOP, false);
+ _isFishing = false;
+ switch (endType)
+ {
+ case PLAYER_STOP:
+ {
+ _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
+ break;
+ }
+ case PLAYER_CANCEL:
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ break;
+ }
+ }
+ }
+ }
+
+ public ILocational getBaitLocation()
+ {
+ return _baitLocation;
+ }
+
+ private Location calculateBaitLocation()
+ {
+ // calculate a position in front of the player with a random distance
+ final int distMin = FishingData.getInstance().getBaitDistanceMin();
+ final int distMax = FishingData.getInstance().getBaitDistanceMax();
+ int distance = Rnd.get(distMin, distMax);
+ final double angle = Util.convertHeadingToDegree(_player.getHeading());
+ final double radian = Math.toRadians(angle);
+ final double sin = Math.sin(radian);
+ final double cos = Math.cos(radian);
+ int baitX = (int) (_player.getX() + (cos * distance));
+ int baitY = (int) (_player.getY() + (sin * distance));
+
+ // search for fishing zone
+ L2FishingZone fishingZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
+ {
+ if (zone instanceof L2FishingZone)
+ {
+ fishingZone = (L2FishingZone) zone;
+ break;
+ }
+ }
+ // search for water zone
+ L2WaterZone waterZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
+ {
+ if (zone instanceof L2WaterZone)
+ {
+ waterZone = (L2WaterZone) zone;
+ break;
+ }
+ }
+
+ int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
+ if (baitZ == Integer.MIN_VALUE)
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
+ return null;
+ }
+
+ return new Location(baitX, baitY, baitZ);
+ }
+
+ /**
+ * Computes the Z of the bait.
+ * @param player the player
+ * @param baitX the bait x
+ * @param baitY the bait y
+ * @param fishingZone the fishing zone
+ * @param waterZone the water zone
+ * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
+ */
+ private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
+ {
+ if ((fishingZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if ((waterZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ // always use water zone, fishing zone high z is high in the air...
+ final int baitZ = waterZone.getWaterZ();
+
+ // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
+ //
+ // return Integer.MIN_VALUE;
+ // }
+
+ if (GeoEngine.getInstance().hasGeo(baitX, baitY))
+ {
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+ }
+
+ return baitZ;
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
new file mode 100644
index 0000000000..f5a5764254
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
@@ -0,0 +1,128 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.l2jmobius.commons.util.Rnd;
+
+/**
+ * @author bit
+ */
+public class FishingBait
+{
+ private final int _itemId;
+ private final byte _level;
+ private final byte _minPlayerLevel;
+ private final byte _maxPlayerLevel;
+ private final double _chance;
+ private final int _timeMin;
+ private final int _timeMax;
+ private final int _waitMin;
+ private final int _waitMax;
+ private final boolean _isPremiumOnly;
+ private final List _rewards = new ArrayList<>();
+
+ public FishingBait(int itemId, byte level, byte minPlayerLevel, byte maxPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax, boolean isPremiumOnly)
+ {
+ _itemId = itemId;
+ _level = level;
+ _minPlayerLevel = minPlayerLevel;
+ _maxPlayerLevel = maxPlayerLevel;
+ _chance = chance;
+ _timeMin = timeMin;
+ _timeMax = timeMax;
+ _waitMin = waitMin;
+ _waitMax = waitMax;
+ _isPremiumOnly = isPremiumOnly;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public byte getLevel()
+ {
+ return _level;
+ }
+
+ public byte getMinPlayerLevel()
+ {
+ return _minPlayerLevel;
+ }
+
+ public byte getMaxPlayerLevel()
+ {
+ return _maxPlayerLevel;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public int getTimeMin()
+ {
+ return _timeMin;
+ }
+
+ public int getTimeMax()
+ {
+ return _timeMax;
+ }
+
+ public int getWaitMin()
+ {
+ return _waitMin;
+ }
+
+ public int getWaitMax()
+ {
+ return _waitMax;
+ }
+
+ public boolean isPremiumOnly()
+ {
+ return _isPremiumOnly;
+ }
+
+ public List getRewards()
+ {
+ return _rewards;
+ }
+
+ public void addReward(FishingCatch catchData)
+ {
+ _rewards.add(catchData);
+ }
+
+ public FishingCatch getRandom()
+ {
+ float random = Rnd.get(100);
+ for (FishingCatch fishingCatchData : _rewards)
+ {
+ if (fishingCatchData.getChance() > random)
+ {
+ return fishingCatchData;
+ }
+ random -= fishingCatchData.getChance();
+ }
+ return null;
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
new file mode 100644
index 0000000000..85c2e42e5a
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
@@ -0,0 +1,49 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingCatch
+{
+ private final int _itemId;
+ private final float _chance;
+ private final float _multiplier;
+
+ public FishingCatch(int itemId, float chance, float multiplier)
+ {
+ _itemId = itemId;
+ _chance = chance;
+ _multiplier = multiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public float getChance()
+ {
+ return _chance;
+ }
+
+ public float getMultiplier()
+ {
+ return _multiplier;
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
new file mode 100644
index 0000000000..93b5fb9b8e
--- /dev/null
+++ b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingRod
+{
+ private final int _itemId;
+ private final int _reduceFishingTime;
+ private final float _xpMultiplier;
+ private final float _spMultiplier;
+
+ public FishingRod(int itemId, int reduceFishingTime, float xpMultiplier, float spMultiplier)
+ {
+ _itemId = itemId;
+ _reduceFishingTime = reduceFishingTime;
+ _xpMultiplier = xpMultiplier;
+ _spMultiplier = spMultiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public int getReduceFishingTime()
+ {
+ return _reduceFishingTime;
+ }
+
+ public float getXpMultiplier()
+ {
+ return _xpMultiplier;
+ }
+
+ public float getSpMultiplier()
+ {
+ return _spMultiplier;
+ }
+}
diff --git a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
index 71d8f10b3e..dfcf4d7f56 100644
--- a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
+++ b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
@@ -20,10 +20,10 @@ import java.lang.ref.WeakReference;
import com.l2jmobius.Config;
import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.PcCondOverride;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.serverpackets.fishing.ExAutoFishAvailable;
diff --git a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
index dea11bad61..cebaa3c7a5 100644
--- a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
+++ b/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
@@ -29,20 +29,17 @@ public class ExFishingStart implements IClientOutgoingPacket
{
private final L2PcInstance _player;
private final int _fishType;
- private final int _baitType;
private final ILocational _baitLocation;
/**
* @param player
* @param fishType
- * @param baitType - 0 = newbie, 1 = normal, 2 = night
* @param baitLocation
*/
- public ExFishingStart(L2PcInstance player, int fishType, int baitType, ILocational baitLocation)
+ public ExFishingStart(L2PcInstance player, int fishType, ILocational baitLocation)
{
_player = player;
_fishType = fishType;
- _baitType = baitType;
_baitLocation = baitLocation;
}
@@ -55,7 +52,7 @@ public class ExFishingStart implements IClientOutgoingPacket
packet.writeD(_baitLocation.getX());
packet.writeD(_baitLocation.getY());
packet.writeD(_baitLocation.getZ());
- packet.writeC(_baitType);
+ packet.writeC(0x01); // 0 = newbie, 1 = normal, 2 = night
return true;
}
}
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/config/Custom/PremiumSystem.ini b/L2J_Mobius_6.0_Fafurion/dist/game/config/Custom/PremiumSystem.ini
index 8b5d1f1f06..7b0874c29d 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/config/Custom/PremiumSystem.ini
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/config/Custom/PremiumSystem.ini
@@ -45,3 +45,7 @@ EnablePremiumHennaSlotforNonPremium = True
# Also premium henna drawn at normal slots.
# Retail: False
EnableAnyHennaAtPremiumSlot = False
+
+# Enable Fishing only for premium players.
+# Retail: True
+PremiumOnlyFishing = False
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/Fishing.xml b/L2J_Mobius_6.0_Fafurion/dist/game/data/Fishing.xml
index 42f6633d60..0152888ab6 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/Fishing.xml
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/Fishing.xml
@@ -1,44 +1,41 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/default/34156-1.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/default/34156-1.htm
new file mode 100644
index 0000000000..44a2ea74ad
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/default/34156-1.htm
@@ -0,0 +1,7 @@
+Fisher Peeves:
+Heine Exclusive Bait is really great! It must be a gift from the fishing gods!
+There are some items that can only be caught with Heine Exclusive Bait. Isn't that amazing?
+No doubt the fishing gods heard about this place that gets filled with fishers and decided to grace us with this amazing bait.
+You should try it out!
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/default/34156.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/default/34156.htm
new file mode 100644
index 0000000000..09f6982054
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/default/34156.htm
@@ -0,0 +1,11 @@
+Fisher Peeves:
+Oh, nice to meet you! I'm Peeves, a fisher.
+When I was young, my parents didn't want me to fish since it's dangerous... But how could I stop doing something so fun?
+Are you interested in fishing? Have you heard of the Heine Exclusive Bait?
+If you have a Heine Exclusive Bait Coupon, I can exchange it for Heine Exclusive Bait.
+Oh yeah, I also got a special fishing rod. Bring me some Heine Fishing Coins and I'll give you a Fancy Fishing Rod.
+You can get them from the Exclusive Reward Chest that you can get when you fish with Heine Exclusive Bait.
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31563.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31563.htm
index 25b6b4b199..cfd0217738 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31563.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31563.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Perelin:
-Do you like fishing? I love it.
-Fishing is such a great hobby, don't you think? Sure, it's not very exerting, but...that's the point. I don't like to run around sweating, you know? You can just sit quietly and enjoy the silence.
-
-
-
-
-
-
-
-
-
+Fishing is such a great hobby, don't you think? Sure, it's not very exerting, but...that's the point. I don't like to run around sweating, you know? You can just sit quietly and enjoy silence.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31567.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31567.htm
index 70eb2e221b..9500514c8e 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31567.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31567.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Bleaker:
-Nice to meet you! They call me Bleaker.
-Besides teaching you how to fish, I also sell the fishing gear you'll need. Oh, and I'll buy any fish you catch. In other words, this is your one-stop fishing shop!
-
-
-
-
-
-
-
-
-
+Nice to meet you! They call me Bleaker. I am with the Fishing Guild. If it has to do with fishing, I'm your man. Most of the time, anyway.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31568.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31568.htm
index 49f54d15d9..b2d1001145 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31568.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31568.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Pamfus:
-Do you like fishing? I love it.
-Fishing is such a great hobby, don't you think? Sure, it's not very exerting, but...that's the point. I don't like to run around sweating, you know? You can just sit quietly and enjoy the silence.
-
-
-
-
-
-
-
-
-
+There's no hobby other than fishing that lets you enjoy the nature around you so much. I really do love fishing.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31570.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31570.htm
index e6b7859e93..e92d40e6fb 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31570.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31570.htm
@@ -1,15 +1,13 @@
Fishing Guild Member Lanosco:
-Did you catch one?
-Heh, fishing is harder than it looks, right? You need to be prepared at all times.
-Which is why I'm here! Come see me whenever you need something, and I'll set you right up.
-
-
-
-
-
-
-
-
-
+Hi, I'm Fishing Guild Member Lanosco. Did you catch anything today? Fishing is not as easy as you might, you know. You need to prepare thoroughly.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31571.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31571.htm
index 0f55831347..ce281416f3 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31571.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31571.htm
@@ -1,14 +1,13 @@
Fishermen's Guild Member Huffs:
-Welcome! Are you here to fish?
-There's no better way to relax and decompress after a stressful day, week, or life! Haha!
-
-
-
-
-
-
-
-
-
+Hello, and welcome. Are you here to learn about fishing? There's no better way to relax and decompress after a stressful day, week, or life! Haha! It's quite the experience, wrestling huge fish along the coast or on the riverbanks, armed with little more than a rod and some string.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31572.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31572.htm
index b8434accc2..2d82c9fa59 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31572.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31572.htm
@@ -1,14 +1,13 @@
Fishing Guild Member O'Fulle:
-Everything is plentiful here in Giran, which is why so many people spend their leisure time fishing. It's a sign of abundance!
-Oh, pardon me -- I'm O'Fulle, the only officially licensed fishing gear merchant in this territory! See me if you need to buy bait or sell fish. Fish only -- no mermaids! Haha!
-
-
-
-
-
-
-
-
-
+I'm Fishing Guild Member O'Fulle. Try your luck at fishing in Giran, the land of plenty! Watch out, catching mermaids might get you into trouble! Stick with the fish! Hahaha!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31573.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31573.htm
index 7a9d68571a..2903e2c1d0 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31573.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31573.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Monakan:
-Well, hello there. I'm Monakan.
-I can teach you about fishing items as well as how to fish. Oh, I'll also buy any fish you catch. In other words, this is your one-stop fishing shop!
-
-
-
-
-
-
-
-
-
+Well, hello there. I'm Monakan, a member of the Fishing Guild. I'm the one to come to when it comes to fishing, since I deal not only in fishing supplies but also the fish that are caught.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31574.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31574.htm
index 021707372b..fb24509ac6 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31574.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31574.htm
@@ -1,13 +1,13 @@
Fishing Guild Member Willie:
-Fishing has become all the rage in these parts! I think it's because of all the brainy people around here -- the Ivory Tower, for example! Lots of them just sit there thinking, and forget to actually catch the fish!
-
-
-
-
-
-
-
-
-
+Oren is a city of culture, to which many intelligent ones flock. That's why we have so many fishing enthusiasts!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31575.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31575.htm
index 5381af429a..58f12301c3 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31575.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31575.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Litulon:
-There's no better place for fishing than Innadril. Wet and warm all year round, beautiful scenery, the best place in the whole world.
-I mean, Goddess Eva watches over us after all. The City of Waters! Haha!
-
-
-
-
-
-
-
-
-
+The Innadril Territory is just the spot for fishing. I mean, Goddess Eva watches over us after all. The City of Waters! Haha!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31576.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31576.htm
index 40daf36a06..dc3fe17673 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31576.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31576.htm
@@ -1,14 +1,14 @@
Fishing Guild Member Berix:
-I'm quite happy to be holding the fishing contest in my native town. It's good to know I can do what I love, where I live.
-I think it's time we got to it, perfect weather for fishing!
-
-
-
-
-
-
-
-
-
+Pleased to meet you. I'm Berix, a member of the Fishing Guild. See, people tend to think that there are only hunters in the Hunter's Village, but we have a lot of great fishers as well! I'm one of them, you see. Hahahaha.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31577.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31577.htm
index 42e3023192..dcf0570a3a 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31577.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31577.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Linnaeus:
-Did you know that the king is an avid fisher himself? Haha!
-Aden is filled with prime fishing zones. How about spending this beautiful day on one of them?
-
-
-
-
-
-
-
-
-
+Did you know that the King is an avid fisher himself? Haha! We at the Fishing Guild are quite proud of this fact. He's actually quite the Master!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31578.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31578.htm
index 22424bd71f..9a39b5209d 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31578.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31578.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Hilgendorf:
-Welcome! Beautiful day for fishing, dontcha' think?
-My family has been in the Guild for generations, ever since my great-grandfather joined.
-
-
-
-
-
-
-
-
-
+Welcome, and good to see you! The weather's perfect for fishing, wouldn't you agree? My family has been in the Guild for generations, ever since my great-grandfather joined.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31579.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31579.htm
index 4905012750..d19e501e8e 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31579.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31579.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Klaus:
-Well, well, well! Another fisher, huh?
-You know how lucky you are to be here, right? With its many mountain streams and lakes, Goddard is a prime fishing land. People come from all over to test their skill and try their luck here.
-
-
-
-
-
-
-
-
-
+I am Klaus, one of Fishing Guild members. If you have anything you need related with fishing, fine me.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31696.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31696.htm
index afb7f7612b..10fc8d9b1e 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31696.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31696.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Platis:
-This area is a rare spot in Elmore where you can catch actual saltwater fish. It used to be a famous fishing site in the Elmoreden years, and now that things have slowed down, the fish population is back.
-Care to give it a try? Let me know if you need any equipment!
-
-
-
-
-
-
-
-
-
+This has been a very popular fishing dock since the age of the Elmoreden. This is the tranquil and beautiful fishing spot you've been searching high and low for, I tell you!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31697.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31697.htm
index b78f53e3e4..77ef12b6d8 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31697.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31697.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Eindarkner:
-Do you know about these hot springs? The effects of the nearby Forge of the Gods have created a whole network of them around here. There are special species of fish living in these hot springs! It's the opportunity of a lifetime.
-Let me know if you need anything!
-
-
-
-
-
-
-
-
-
+Have you heard about the Hot Springs in the area? There are natural hot springs everywhere, thanks to the Forge of the Gods. Before, there were fish to be caught in the hot springs as well, but they have all disappeared now. What a pity.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31989.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31989.htm
index f8b1a88ccd..c032d201fa 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31989.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/31989.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Batidae:
-You came here to fish, right? Who am I kidding, of course you did!
-No better way to spend an afternoon than casting the line!
-
-
-
-
-
-
-
-
-
+Welcome. Want to learn how to fish, do you? You must have really been running out of things to learn to come all the way here to learn about fishing, of all things. Frankly, you'd be doing yourself more good by learning how to mine ore in the mines over there. Anyways, since you're here, really, there's no better way to spend an afternoon than casting the line!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/32007.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/32007.htm
index 939f2f8362..f65b882bdc 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/32007.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/32007.htm
@@ -1,14 +1,13 @@
Fishing Guild Member Galba:
-Rainbow Springs -- ahh, heaven!
-You should try fishing around here. The fish here are huge. Let me know if you need any fishing items or want to sell something.
-
-
-
-
-
-
-
-
-
+Since you've come to find me, I reckon you know that the Rainbow Springs are a veritable heaven on earth for us fishing enthusiasts. That's right, this is some of the best fishing you'll find anywhere.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fish_appearance_exchange.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fish_appearance_exchange.htm
new file mode 100644
index 0000000000..8d25e5d848
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fish_appearance_exchange.htm
@@ -0,0 +1,11 @@
+
+
+ Exchange for appearance items:
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual001.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual001.htm
index dc66dd577c..d7badfef10 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual001.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual001.htm
@@ -1,10 +1,8 @@
Fishing Manual:
-
-
+
-
-
-
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual002.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual002.htm
index 3c1bb703da..a37c28a0da 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual002.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual002.htm
@@ -1,6 +1,5 @@
Fishing Manual:
-In order to fish, you need to find a fishing area. Once you arrive at the right spot, you'll see the button on the right side of your screen that alerts you that you can fish.
+In order to fish, you need to find a fishing area. Once you arrive at the right spot, you'll see the button on the right side of your screen that alerts you that you can fish.
Then check if you can actually fish. Check that you have a Fishing Rod and Bait equipped. You can set the Fishing Shots to be used automatically when you fish.
-
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual003.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual003.htm
index da8ab5942b..910782fc81 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual003.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual003.htm
@@ -1,6 +1,4 @@
-Fishing Manual:
-A fishing zone refers to a place with enough fish to be caught.
-The places that are good for fishing are the following: around Lake Iris, Narsell Lake where the Coliseum is, Giran Harbor's coast, around the Plains of the Lizardmen, waterside in the Town of Gludio, the Neutral Zone, Heine, Fellmere Lake, and the bridge near the Town of Giran.
+Fishing Manual:
+In order to fish, you need to find a fishing area. Once you arrive at the right spot, you'll see the button on the right side of your screen that alerts you that you can fish. Then check if you can actually fish. Check that you have a Fishing Rod and Bait equipped. You can set the Fishing Shots to be used automatically when you fish.
-
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual004.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual004.htm
index 7d4dbce9a9..a45c766c9a 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual004.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual004.htm
@@ -1,7 +1,7 @@
-Fishing Manual:
-There are two types of bait.
-The Normal Bait, you can buy from me.
-If you want to catch more expensive fish, I recommend you use the Special Bait. I have never seen Special Bait, but I heard that you can get it from the boxes you get from fishing.
+Fishing Manual:
+There are three types of bait.
+These are the basic bait, the R99 bait which can be used by characters of Lv. 99 and above and he PC Cafe bait, which can be purchased using PC Cafe Points.
+Of these, the Fishing Guild sells the basic bait and the R99 bait.
+With each type of bait, you can catch different types of fish. The conditions for purchasing and use vary among bait types as well. The Powerful Fish, which is the most expensive fish you can catch, can be caught using the R99 bait or the PC Cafe bait.
-
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual008.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual008.htm
index 4a56fdac27..5063653e3a 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual008.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual008.htm
@@ -1,7 +1,6 @@
-Fishing Manual:
+Fishing Manual:
Created by the Black Anvil Guild at the request of Ampitri, the founder of the Fishing Guild, Fishing Shots are variations of Soulshots made for fishing.
But while Soulshots amplify a hit, Fishing Shots increase the fisher's chances of catching a fish.
It's an item that will help you catch fish more efficiently.
-
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual009.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual009.htm
index 3094aa089d..29fe921d82 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual009.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual009.htm
@@ -1,7 +1,7 @@
-Fishing Manual:
-You can sell the fish whole, take it apart to sell a portion, or use it to craft items. You can also exchange it for Elcyum Powder through our Fishing Guild.
-Keep in mind that you might lose everything when cutting up your fish though! It depends on your luck.
-You can also bring Elcyum Powder to our guild to learn some legendary fishing skills. You decide what to do with your fish.
+Fishing Manual:
+Bring the fish you catch to us to exchange for various items that the Fishing Guild deals in.
+The Ugly Fish and Nimble Fish can be exchanged for Fish Stew, Appearance Stones, Hair Accessories, Transformation Scrolls, and Weapon Appearance Stones.
+If you have caught a Powerful Fish, it may be exchanged for a Stardust item or Elcyum Powder which is needed when exchanging for a Zodiac Agathion Treasure Chest. You may also sell the fish to the shop.
+If you bring us Elcyum Powder, we can let you in on a few secret techniques that have been handed down in our guild through the generation. Please think carefully about what you want to do with the fish that you catch.
-
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual010.htm b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual010.htm
index 4769d79268..21fb4dec2d 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual010.htm
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/html/fisherman/fishing_manual010.htm
@@ -1,6 +1,38 @@
-Fishing Manual:
-You can buy Normal Bait from the Fishing Guild.
-As for the Special Bait, you can get it from the wooden boxes that you get from fishing. Use the Special Bait to catch shiny fish.
-
+Fishing Manual:
+The time required for fishing, and the rate of success vary according to the type of bait, the type of rod, and whether or not Fishing Shot is used.
+
+
+
+
Bait - Fishing Time and Standby Time
+
+
+
+For each bait, the time required until fish bite is preset.
+As for the basic bait sold in the shop,Fishing Time is 105 seconds, and Standby Time is 15 seconds.This means catching a single fish takes a total of 120 seconds.
+
+
+
+
+
Fishing Rod - Fishing Time reduced
+
+
+
+
+A better fishing rod will reduce Fishing Time.
+The Normal Fishing Rod and Sturdy Fishing Rodwill not reduce Fishing Time.When you obtain Master Fishing Rod Stage 1,your Fishing Time will begin to decrease.
+
+
+
+
+
Fishing Shot - Fishing Probability increased
+
+
+
+
+
+Fishing Shot increases your odds of catching a fish.
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2144.xml b/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2144.xml
new file mode 100644
index 0000000000..b763fcb01e
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2144.xml
@@ -0,0 +1,39 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+ 34156
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2194.xml b/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2194.xml
new file mode 100644
index 0000000000..52d33e59e4
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2194.xml
@@ -0,0 +1,70 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2195.xml b/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2195.xml
new file mode 100644
index 0000000000..e73c2546f1
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2195.xml
@@ -0,0 +1,138 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2203.xml b/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2203.xml
new file mode 100644
index 0000000000..82d49aba41
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2203.xml
@@ -0,0 +1,62 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2207.xml b/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2207.xml
new file mode 100644
index 0000000000..a0521b646d
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2207.xml
@@ -0,0 +1,62 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2208.xml b/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2208.xml
new file mode 100644
index 0000000000..0c8953f318
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/2208.xml
@@ -0,0 +1,94 @@
+
+
+
+ 31563
+ 31567
+ 31568
+ 31570
+ 31571
+ 31572
+ 31573
+ 31574
+ 31575
+ 31576
+ 31577
+ 31578
+ 31579
+ 31696
+ 31697
+ 31989
+ 32007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/3034.xml b/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/3034.xml
new file mode 100644
index 0000000000..6bd81e7b08
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/multisell/3034.xml
@@ -0,0 +1,22 @@
+
+
+
+ 34156
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/spawns/Innadril/Heine.xml b/L2J_Mobius_6.0_Fafurion/dist/game/data/spawns/Innadril/Heine.xml
index 7a35b26c4e..bad6d06183 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/spawns/Innadril/Heine.xml
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/spawns/Innadril/Heine.xml
@@ -1,80 +1,81 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/xsd/Fishing.xsd b/L2J_Mobius_6.0_Fafurion/dist/game/data/xsd/Fishing.xsd
index 16e5ed9699..1078ed7f77 100644
--- a/L2J_Mobius_6.0_Fafurion/dist/game/data/xsd/Fishing.xsd
+++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/xsd/Fishing.xsd
@@ -9,13 +9,13 @@
-
+
-
+
@@ -30,17 +30,35 @@
+
+
-
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/Config.java b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/Config.java
index 720dfbd7dc..2960be50cb 100644
--- a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/Config.java
+++ b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/Config.java
@@ -1140,11 +1140,12 @@ public final class Config
public static float PREMIUM_RATE_DROP_AMOUNT;
public static float PREMIUM_RATE_SPOIL_CHANCE;
public static float PREMIUM_RATE_SPOIL_AMOUNT;
+ public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
+ public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
public static boolean PREMIUM_HENNA_SLOT_ENABLED;
public static boolean PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL;
public static boolean PREMIUM_HENNA_SLOT_ALL_DYES;
- public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
- public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
+ public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
public static int PC_CAFE_MAX_POINTS;
@@ -2645,9 +2646,6 @@ public final class Config
PREMIUM_RATE_DROP_AMOUNT = PremiumSystem.getFloat("PremiumRateDropAmount", 1);
PREMIUM_RATE_SPOIL_CHANCE = PremiumSystem.getFloat("PremiumRateSpoilChance", 2);
PREMIUM_RATE_SPOIL_AMOUNT = PremiumSystem.getFloat("PremiumRateSpoilAmount", 1);
- PREMIUM_HENNA_SLOT_ENABLED = PremiumSystem.getBoolean("EnablePremiumHennaSlot", true);
- PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL = PremiumSystem.getBoolean("EnablePremiumHennaSlotforNonPremium", true);
- PREMIUM_HENNA_SLOT_ALL_DYES = PremiumSystem.getBoolean("EnableAnyHennaAtPremiumSlot", false);
final String[] premiumDropChanceMultiplier = PremiumSystem.getString("PremiumRateDropChanceByItemId", "").split(";");
PREMIUM_RATE_DROP_CHANCE_BY_ID = new HashMap<>(premiumDropChanceMultiplier.length);
if (!premiumDropChanceMultiplier[0].isEmpty())
@@ -2702,6 +2700,10 @@ public final class Config
}
}
}
+ PREMIUM_HENNA_SLOT_ENABLED = PremiumSystem.getBoolean("EnablePremiumHennaSlot", true);
+ PREMIUM_HENNA_SLOT_ENABLED_FOR_ALL = PremiumSystem.getBoolean("EnablePremiumHennaSlotforNonPremium", true);
+ PREMIUM_HENNA_SLOT_ALL_DYES = PremiumSystem.getBoolean("EnableAnyHennaAtPremiumSlot", false);
+ PREMIUM_ONLY_FISHING = PremiumSystem.getBoolean("PremiumOnlyFishing", true);
// Load PrivateStoreRange config file (if exists)
final PropertiesParser PrivateStoreRange = new PropertiesParser(CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE);
diff --git a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
index 91b5f9c43e..bacf1ed08c 100644
--- a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
+++ b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
@@ -25,8 +25,12 @@ import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
+import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
-import com.l2jmobius.gameserver.model.FishingBaitData;
+import com.l2jmobius.gameserver.datatables.ItemTable;
+import com.l2jmobius.gameserver.model.fishing.FishingBait;
+import com.l2jmobius.gameserver.model.fishing.FishingCatch;
+import com.l2jmobius.gameserver.model.fishing.FishingRod;
/**
* This class holds the Fishing information.
@@ -35,7 +39,8 @@ import com.l2jmobius.gameserver.model.FishingBaitData;
public final class FishingData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(FishingData.class.getName());
- private final Map _baitData = new HashMap<>();
+ private final Map _baitData = new HashMap<>();
+ private final Map _rodData = new HashMap<>();
private int _baitDistanceMin;
private int _baitDistanceMax;
private double _expRateMin;
@@ -56,7 +61,7 @@ public final class FishingData implements IGameXmlReader
{
_baitData.clear();
parseDatapackFile("data/Fishing.xml");
- LOGGER.info(getClass().getSimpleName() + ": Loaded Fishing Data.");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _baitData.size() + " bait and " + _rodData.size() + " rod data.");
}
@Override
@@ -76,13 +81,13 @@ public final class FishingData implements IGameXmlReader
_baitDistanceMax = parseInteger(listItem.getAttributes(), "max");
break;
}
- case "experienceRate":
+ case "xpRate":
{
_expRateMin = parseDouble(listItem.getAttributes(), "min");
_expRateMax = parseDouble(listItem.getAttributes(), "max");
break;
}
- case "skillPointsRate":
+ case "spRate":
{
_spRateMin = parseDouble(listItem.getAttributes(), "min");
_spRateMax = parseDouble(listItem.getAttributes(), "max");
@@ -96,20 +101,39 @@ public final class FishingData implements IGameXmlReader
{
final NamedNodeMap attrs = bait.getAttributes();
final int itemId = parseInteger(attrs, "itemId");
- final int level = parseInteger(attrs, "level");
- final int minPlayerLevel = parseInteger(attrs, "minPlayerLevel");
+ final byte level = parseByte(attrs, "level", (byte) 1);
+ final byte minPlayerLevel = parseByte(attrs, "minPlayerLevel");
+ final byte maxPlayerLevel = parseByte(attrs, "minPlayerLevel", Config.PLAYER_MAXIMUM_LEVEL);
final double chance = parseDouble(attrs, "chance");
final int timeMin = parseInteger(attrs, "timeMin");
- final int timeMax = parseInteger(attrs, "timeMax");
+ final int timeMax = parseInteger(attrs, "timeMax", timeMin);
final int waitMin = parseInteger(attrs, "waitMin");
- final int waitMax = parseInteger(attrs, "waitMax");
- final FishingBaitData baitData = new FishingBaitData(itemId, level, minPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax);
+ final int waitMax = parseInteger(attrs, "waitMax", waitMin);
+ final boolean isPremiumOnly = parseBoolean(attrs, "isPremiumOnly", false);
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ final FishingBait baitData = new FishingBait(itemId, level, minPlayerLevel, maxPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax, isPremiumOnly);
for (Node c = bait.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("catch".equalsIgnoreCase(c.getNodeName()))
{
- baitData.addReward(parseInteger(c.getAttributes(), "itemId"));
+ final NamedNodeMap cAttrs = c.getAttributes();
+ final int cId = parseInteger(cAttrs, "itemId");
+ final float cChance = parseFloat(cAttrs, "chance");
+ final float cMultiplier = parseFloat(cAttrs, "multiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(cId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ baitData.addReward(new FishingCatch(cId, cChance, cMultiplier));
}
}
_baitData.put(baitData.getItemId(), baitData);
@@ -117,22 +141,44 @@ public final class FishingData implements IGameXmlReader
}
break;
}
+ case "rods":
+ {
+ for (Node rod = listItem.getFirstChild(); rod != null; rod = rod.getNextSibling())
+ {
+ if ("rod".equalsIgnoreCase(rod.getNodeName()))
+ {
+ final NamedNodeMap attrs = rod.getAttributes();
+ final int itemId = parseInteger(attrs, "itemId");
+ final int reduceFishingTime = parseInteger(attrs, "reduceFishingTime", 0);
+ final float xpMultiplier = parseFloat(attrs, "xpMultiplier", 1f);
+ final float spMultiplier = parseFloat(attrs, "spMultiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ _rodData.put(itemId, new FishingRod(itemId, reduceFishingTime, xpMultiplier, spMultiplier));
+ }
+ }
+ }
}
}
}
}
}
- /**
- * Gets the fishing rod.
- * @param baitItemId the item id
- * @return A list of reward item ids
- */
- public FishingBaitData getBaitData(int baitItemId)
+ public FishingBait getBaitData(int baitItemId)
{
return _baitData.get(baitItemId);
}
+ public FishingRod getRodData(int rodItemId)
+ {
+ return _rodData.get(rodItemId);
+ }
+
public int getBaitDistanceMin()
{
return _baitDistanceMin;
diff --git a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/FishingBaitData.java b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/FishingBaitData.java
deleted file mode 100644
index 9cf4893d66..0000000000
--- a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/FishingBaitData.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author bit
- */
-public class FishingBaitData
-{
- private final int _itemId;
- private final int _level;
- private final int _minPlayerLevel;
- private final double _chance;
- private final int _timeMin;
- private final int _timeMax;
- private final int _waitMin;
- private final int _waitMax;
- private final List _rewards = new ArrayList<>();
-
- public FishingBaitData(int itemId, int level, int minPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax)
- {
- _itemId = itemId;
- _level = level;
- _minPlayerLevel = minPlayerLevel;
- _chance = chance;
- _timeMin = timeMin;
- _timeMax = timeMax;
- _waitMin = waitMin;
- _waitMax = waitMax;
- }
-
- public int getItemId()
- {
- return _itemId;
- }
-
- public int getLevel()
- {
- return _level;
- }
-
- public int getMinPlayerLevel()
- {
- return _minPlayerLevel;
- }
-
- public double getChance()
- {
- return _chance;
- }
-
- public int getTimeMin()
- {
- return _timeMin;
- }
-
- public int getTimeMax()
- {
- return _timeMax;
- }
-
- public int getWaitMin()
- {
- return _waitMin;
- }
-
- public int getWaitMax()
- {
- return _waitMax;
- }
-
- public List getRewards()
- {
- return _rewards;
- }
-
- public void addReward(int itemId)
- {
- _rewards.add(itemId);
- }
-}
diff --git a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
index 65dc23cefd..f67eadcf6c 100644
--- a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
+++ b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
@@ -125,7 +125,6 @@ import com.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import com.l2jmobius.gameserver.model.BlockList;
import com.l2jmobius.gameserver.model.ClanPrivilege;
import com.l2jmobius.gameserver.model.ClanWar;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.L2AccessLevel;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
@@ -209,6 +208,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPCh
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPKill;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerReputationChanged;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerSubChange;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.MonsterBookCardHolder;
diff --git a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/Fishing.java b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
similarity index 80%
rename from L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/Fishing.java
rename to L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
index 17746b3e77..4421a1a3c0 100644
--- a/L2J_Mobius_5.5_EtinasFate/java/com/l2jmobius/gameserver/model/Fishing.java
+++ b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
@@ -1,443 +1,471 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.concurrent.ScheduledFuture;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.commons.util.Rnd;
-import com.l2jmobius.gameserver.data.xml.impl.FishingData;
-import com.l2jmobius.gameserver.enums.ShotType;
-import com.l2jmobius.gameserver.geoengine.GeoEngine;
-import com.l2jmobius.gameserver.instancemanager.ZoneManager;
-import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jmobius.gameserver.model.events.EventDispatcher;
-import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
-import com.l2jmobius.gameserver.model.interfaces.ILocational;
-import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
-import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
-import com.l2jmobius.gameserver.model.items.type.WeaponType;
-import com.l2jmobius.gameserver.model.zone.L2ZoneType;
-import com.l2jmobius.gameserver.model.zone.ZoneId;
-import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
-import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
-import com.l2jmobius.gameserver.network.SystemMessageId;
-import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
-import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
-import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
-import com.l2jmobius.gameserver.util.Util;
-
-/**
- * @author bit
- */
-public class Fishing
-{
- protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
- private volatile ILocational _baitLocation = new Location(0, 0, 0);
-
- private final L2PcInstance _player;
- private ScheduledFuture> _reelInTask;
- private ScheduledFuture> _startFishingTask;
- private boolean _isFishing = false;
-
- public Fishing(L2PcInstance player)
- {
- _player = player;
- }
-
- public synchronized boolean isFishing()
- {
- return _isFishing;
- }
-
- public boolean isAtValidLocation()
- {
- // TODO: implement checking direction
- // if (calculateBaitLocation() == null)
- // {
- // return false;
- // }
- return _player.isInsideZone(ZoneId.FISHING);
- }
-
- public boolean canFish()
- {
- return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
- }
-
- private FishingBaitData getCurrentBaitData()
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
- }
-
- private void cancelTasks()
- {
- if (_reelInTask != null)
- {
- _reelInTask.cancel(false);
- _reelInTask = null;
- }
-
- if (_startFishingTask != null)
- {
- _startFishingTask.cancel(false);
- _startFishingTask = null;
- }
- }
-
- public synchronized void startFishing()
- {
- if (_isFishing)
- {
- return;
- }
- _isFishing = true;
- castLine();
- }
-
- private void castLine()
- {
- if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
- {
- _player.sendMessage("Fishing is disabled.");
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- cancelTasks();
-
- if (!canFish())
- {
- if (_isFishing)
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final FishingBaitData baitData = getCurrentBaitData();
- final int minPlayerLevel = baitData == null ? 85 : baitData.getMinPlayerLevel();
- if (_player.getLevel() < minPlayerLevel)
- {
- if (minPlayerLevel == 85)
- {
- _player.sendPacket(SystemMessageId.FISHING_IS_AVAILABLE_TO_PREMIUM_USERS_ONLY);
- }
- else // In case of custom fishing level.
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
- }
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final L2ItemInstance rod = _player.getActiveWeaponInstance();
- if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (baitData == null)
- {
- _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isTransformed() || _player.isInBoat())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHEN_TRANSFORMED_OR_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_IT_S_AGAINST_THE_RULES);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isCrafting() || _player.isInStoreMode())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- _baitLocation = calculateBaitLocation();
- if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
- {
- if (_isFishing)
- {
- // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- else
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- _player.rechargeShots(false, false, true);
- }
-
- _reelInTask = ThreadPool.schedule(() ->
- {
- _player.getFishing().reelInWithReward();
- _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), Rnd.get(baitData.getWaitMin(), baitData.getWaitMax()));
- }, Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()));
- _player.stopMove(null);
- _player.broadcastPacket(new ExFishingStart(_player, -1, baitData.getLevel(), _baitLocation));
- _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
- _player.sendPacket(new PlaySound("SF_P_01"));
- _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
- }
-
- public void reelInWithReward()
- {
- // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
- // Then player may or may not catch the fish. Using fishing shots increases chance to win.
- final FishingBaitData baitData = getCurrentBaitData();
- if (baitData == null)
- {
- reelIn(FishingEndReason.LOSE, false);
- LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
- return;
- }
-
- double chance = baitData.getChance();
- if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- chance *= 1.5; // +50 % chance to win
- }
-
- if (Rnd.get(0, 100) <= chance)
- {
- reelIn(FishingEndReason.WIN, true);
- }
- else
- {
- reelIn(FishingEndReason.LOSE, true);
- }
- }
-
- private void reelIn(FishingEndReason reason, boolean consumeBait)
- {
- if (!_isFishing)
- {
- return;
- }
-
- cancelTasks();
-
- try
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- if (consumeBait)
- {
- if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
- {
- reason = FishingEndReason.LOSE; // no bait - no reward
- return;
- }
- }
-
- if ((reason == FishingEndReason.WIN) && (bait != null))
- {
- final FishingBaitData baitData = FishingData.getInstance().getBaitData(bait.getId());
- final int numRewards = baitData.getRewards().size();
- if (numRewards > 0)
- {
- final FishingData fishingData = FishingData.getInstance();
- final int lvlModifier = _player.getLevel() * _player.getLevel();
- _player.addExpAndSp(Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier, Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier, true);
- final int fishId = baitData.getRewards().get(Rnd.get(0, numRewards - 1));
- _player.getInventory().addItem("Fishing Reward", fishId, 1, _player, null);
- final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
- msg.addItemName(fishId);
- _player.sendPacket(msg);
- _player.unchargeShot(ShotType.FISH_SOULSHOTS);
- _player.rechargeShots(false, false, true);
- }
- else
- {
- LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
- }
- }
- else if (reason == FishingEndReason.LOSE)
- {
- _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
- }
-
- if (consumeBait)
- {
- EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
- }
- }
- finally
- {
- _player.broadcastPacket(new ExFishingEnd(_player, reason));
- _player.sendPacket(new ExUserInfoFishing(_player, false));
- }
- }
-
- public void stopFishing()
- {
- stopFishing(FishingEndType.PLAYER_STOP);
- }
-
- public synchronized void stopFishing(FishingEndType endType)
- {
- if (_isFishing)
- {
- reelIn(FishingEndReason.STOP, false);
- _isFishing = false;
- switch (endType)
- {
- case PLAYER_STOP:
- {
- _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
- break;
- }
- case PLAYER_CANCEL:
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- break;
- }
- }
- }
- }
-
- public ILocational getBaitLocation()
- {
- return _baitLocation;
- }
-
- private Location calculateBaitLocation()
- {
- // calculate a position in front of the player with a random distance
- final int distMin = FishingData.getInstance().getBaitDistanceMin();
- final int distMax = FishingData.getInstance().getBaitDistanceMax();
- int distance = Rnd.get(distMin, distMax);
- final double angle = Util.convertHeadingToDegree(_player.getHeading());
- final double radian = Math.toRadians(angle);
- final double sin = Math.sin(radian);
- final double cos = Math.cos(radian);
- int baitX = (int) (_player.getX() + (cos * distance));
- int baitY = (int) (_player.getY() + (sin * distance));
-
- // search for fishing zone
- L2FishingZone fishingZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
- {
- if (zone instanceof L2FishingZone)
- {
- fishingZone = (L2FishingZone) zone;
- break;
- }
- }
- // search for water zone
- L2WaterZone waterZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
- {
- if (zone instanceof L2WaterZone)
- {
- waterZone = (L2WaterZone) zone;
- break;
- }
- }
-
- int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
- if (baitZ == Integer.MIN_VALUE)
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
- return null;
- }
-
- return new Location(baitX, baitY, baitZ);
- }
-
- /**
- * Computes the Z of the bait.
- * @param player the player
- * @param baitX the bait x
- * @param baitY the bait y
- * @param fishingZone the fishing zone
- * @param waterZone the water zone
- * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
- */
- private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
- {
- if ((fishingZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- if ((waterZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- // always use water zone, fishing zone high z is high in the air...
- final int baitZ = waterZone.getWaterZ();
-
- // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
- //
- // return Integer.MIN_VALUE;
- // }
-
- if (GeoEngine.getInstance().hasGeo(baitX, baitY))
- {
- if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
-
- if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
- }
-
- return baitZ;
- }
-}
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.commons.util.Rnd;
+import com.l2jmobius.gameserver.data.xml.impl.FishingData;
+import com.l2jmobius.gameserver.enums.ShotType;
+import com.l2jmobius.gameserver.geoengine.GeoEngine;
+import com.l2jmobius.gameserver.instancemanager.ZoneManager;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.PcCondOverride;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.events.EventDispatcher;
+import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
+import com.l2jmobius.gameserver.model.interfaces.ILocational;
+import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.model.items.type.WeaponType;
+import com.l2jmobius.gameserver.model.zone.L2ZoneType;
+import com.l2jmobius.gameserver.model.zone.ZoneId;
+import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
+import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
+import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author bit
+ */
+public class Fishing
+{
+ protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
+ private volatile ILocational _baitLocation = new Location(0, 0, 0);
+
+ private final L2PcInstance _player;
+ private ScheduledFuture> _reelInTask;
+ private ScheduledFuture> _startFishingTask;
+ private boolean _isFishing = false;
+
+ public Fishing(L2PcInstance player)
+ {
+ _player = player;
+ }
+
+ public synchronized boolean isFishing()
+ {
+ return _isFishing;
+ }
+
+ public boolean isAtValidLocation()
+ {
+ // TODO: implement checking direction
+ // if (calculateBaitLocation() == null)
+ // {
+ // return false;
+ // }
+ return _player.isInsideZone(ZoneId.FISHING);
+ }
+
+ public boolean canFish()
+ {
+ return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
+ }
+
+ private FishingBait getCurrentBaitData()
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
+ }
+
+ private void cancelTasks()
+ {
+ if (_reelInTask != null)
+ {
+ _reelInTask.cancel(false);
+ _reelInTask = null;
+ }
+
+ if (_startFishingTask != null)
+ {
+ _startFishingTask.cancel(false);
+ _startFishingTask = null;
+ }
+ }
+
+ public synchronized void startFishing()
+ {
+ if (_isFishing)
+ {
+ return;
+ }
+ _isFishing = true;
+ castLine();
+ }
+
+ private void castLine()
+ {
+ if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
+ {
+ _player.sendMessage("Fishing is disabled.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ cancelTasks();
+
+ if (!canFish())
+ {
+ if (_isFishing)
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (Config.PREMIUM_SYSTEM_ENABLED)
+ {
+ if (Config.PREMIUM_ONLY_FISHING && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.FISHING_IS_AVAILABLE_TO_PREMIUM_USERS_ONLY);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (baitData.isPremiumOnly() && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.FAILED_PLEASE_TRY_AGAIN_USING_THE_CORRECT_BAIT);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+ }
+
+ final int minPlayerLevel = baitData.getMinPlayerLevel();
+ final int maxPLayerLevel = baitData.getMaxPlayerLevel();
+ if ((_player.getLevel() < minPlayerLevel) && (_player.getLevel() > maxPLayerLevel))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final L2ItemInstance rod = _player.getActiveWeaponInstance();
+ if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingRod rodData = FishingData.getInstance().getRodData(rod.getId());
+ if (rodData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isTransformed() || _player.isInBoat())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHEN_TRANSFORMED_OR_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_IT_S_AGAINST_THE_RULES);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isCrafting() || _player.isInStoreMode())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ _baitLocation = calculateBaitLocation();
+ if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
+ {
+ if (_isFishing)
+ {
+ // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ else
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ _player.rechargeShots(false, false, true);
+ }
+
+ final long fishingTime = Math.max(Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()) - rodData.getReduceFishingTime(), 1000);
+ final long fishingWaitTime = Rnd.get(baitData.getWaitMin(), baitData.getWaitMax());
+
+ _reelInTask = ThreadPool.schedule(() ->
+ {
+ _player.getFishing().reelInWithReward();
+ _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), fishingWaitTime);
+ }, fishingTime);
+ _player.stopMove(null);
+ _player.broadcastPacket(new ExFishingStart(_player, -1, _baitLocation));
+ _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
+ _player.sendPacket(new PlaySound("SF_P_01"));
+ _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
+ }
+
+ public void reelInWithReward()
+ {
+ // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
+ // Then player may or may not catch the fish. Using fishing shots increases chance to win.
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ reelIn(FishingEndReason.LOSE, false);
+ LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
+ return;
+ }
+
+ double chance = baitData.getChance();
+ if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ chance *= 2;
+ }
+
+ if (Rnd.get(100) <= chance)
+ {
+ reelIn(FishingEndReason.WIN, true);
+ }
+ else
+ {
+ reelIn(FishingEndReason.LOSE, true);
+ }
+ }
+
+ private void reelIn(FishingEndReason reason, boolean consumeBait)
+ {
+ if (!_isFishing)
+ {
+ return;
+ }
+
+ cancelTasks();
+
+ try
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ if (consumeBait)
+ {
+ if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
+ {
+ reason = FishingEndReason.LOSE; // no bait - no reward
+ return;
+ }
+ }
+
+ if ((reason == FishingEndReason.WIN) && (bait != null))
+ {
+ final FishingBait baitData = FishingData.getInstance().getBaitData(bait.getId());
+ final FishingCatch fishingCatchData = baitData.getRandom();
+ if (fishingCatchData != null)
+ {
+ final FishingData fishingData = FishingData.getInstance();
+ final double lvlModifier = (Math.pow(_player.getLevel(), 2.2) * fishingCatchData.getMultiplier());
+ final long xp = (long) (Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier);
+ final long sp = (long) (Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier);
+ _player.addExpAndSp(xp, sp, true);
+ _player.getInventory().addItem("Fishing Reward", fishingCatchData.getItemId(), 1, _player, null);
+ final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
+ msg.addItemName(fishingCatchData.getItemId());
+ _player.sendPacket(msg);
+ _player.unchargeShot(ShotType.FISH_SOULSHOTS);
+ _player.rechargeShots(false, false, true);
+ }
+ else
+ {
+ LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
+ }
+ }
+ else if (reason == FishingEndReason.LOSE)
+ {
+ _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
+ }
+
+ if (consumeBait)
+ {
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
+ }
+ }
+ finally
+ {
+ _player.broadcastPacket(new ExFishingEnd(_player, reason));
+ _player.sendPacket(new ExUserInfoFishing(_player, false));
+ }
+ }
+
+ public void stopFishing()
+ {
+ stopFishing(FishingEndType.PLAYER_STOP);
+ }
+
+ public synchronized void stopFishing(FishingEndType endType)
+ {
+ if (_isFishing)
+ {
+ reelIn(FishingEndReason.STOP, false);
+ _isFishing = false;
+ switch (endType)
+ {
+ case PLAYER_STOP:
+ {
+ _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
+ break;
+ }
+ case PLAYER_CANCEL:
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ break;
+ }
+ }
+ }
+ }
+
+ public ILocational getBaitLocation()
+ {
+ return _baitLocation;
+ }
+
+ private Location calculateBaitLocation()
+ {
+ // calculate a position in front of the player with a random distance
+ final int distMin = FishingData.getInstance().getBaitDistanceMin();
+ final int distMax = FishingData.getInstance().getBaitDistanceMax();
+ int distance = Rnd.get(distMin, distMax);
+ final double angle = Util.convertHeadingToDegree(_player.getHeading());
+ final double radian = Math.toRadians(angle);
+ final double sin = Math.sin(radian);
+ final double cos = Math.cos(radian);
+ int baitX = (int) (_player.getX() + (cos * distance));
+ int baitY = (int) (_player.getY() + (sin * distance));
+
+ // search for fishing zone
+ L2FishingZone fishingZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
+ {
+ if (zone instanceof L2FishingZone)
+ {
+ fishingZone = (L2FishingZone) zone;
+ break;
+ }
+ }
+ // search for water zone
+ L2WaterZone waterZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
+ {
+ if (zone instanceof L2WaterZone)
+ {
+ waterZone = (L2WaterZone) zone;
+ break;
+ }
+ }
+
+ int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
+ if (baitZ == Integer.MIN_VALUE)
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE_YOUR_CHARACTER_IS_NOT_FACING_WATER_OR_YOU_ARE_NOT_IN_A_FISHING_GROUND);
+ return null;
+ }
+
+ return new Location(baitX, baitY, baitZ);
+ }
+
+ /**
+ * Computes the Z of the bait.
+ * @param player the player
+ * @param baitX the bait x
+ * @param baitY the bait y
+ * @param fishingZone the fishing zone
+ * @param waterZone the water zone
+ * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
+ */
+ private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
+ {
+ if ((fishingZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if ((waterZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ // always use water zone, fishing zone high z is high in the air...
+ final int baitZ = waterZone.getWaterZ();
+
+ // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
+ //
+ // return Integer.MIN_VALUE;
+ // }
+
+ if (GeoEngine.getInstance().hasGeo(baitX, baitY))
+ {
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+ }
+
+ return baitZ;
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
new file mode 100644
index 0000000000..f5a5764254
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
@@ -0,0 +1,128 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.l2jmobius.commons.util.Rnd;
+
+/**
+ * @author bit
+ */
+public class FishingBait
+{
+ private final int _itemId;
+ private final byte _level;
+ private final byte _minPlayerLevel;
+ private final byte _maxPlayerLevel;
+ private final double _chance;
+ private final int _timeMin;
+ private final int _timeMax;
+ private final int _waitMin;
+ private final int _waitMax;
+ private final boolean _isPremiumOnly;
+ private final List _rewards = new ArrayList<>();
+
+ public FishingBait(int itemId, byte level, byte minPlayerLevel, byte maxPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax, boolean isPremiumOnly)
+ {
+ _itemId = itemId;
+ _level = level;
+ _minPlayerLevel = minPlayerLevel;
+ _maxPlayerLevel = maxPlayerLevel;
+ _chance = chance;
+ _timeMin = timeMin;
+ _timeMax = timeMax;
+ _waitMin = waitMin;
+ _waitMax = waitMax;
+ _isPremiumOnly = isPremiumOnly;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public byte getLevel()
+ {
+ return _level;
+ }
+
+ public byte getMinPlayerLevel()
+ {
+ return _minPlayerLevel;
+ }
+
+ public byte getMaxPlayerLevel()
+ {
+ return _maxPlayerLevel;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public int getTimeMin()
+ {
+ return _timeMin;
+ }
+
+ public int getTimeMax()
+ {
+ return _timeMax;
+ }
+
+ public int getWaitMin()
+ {
+ return _waitMin;
+ }
+
+ public int getWaitMax()
+ {
+ return _waitMax;
+ }
+
+ public boolean isPremiumOnly()
+ {
+ return _isPremiumOnly;
+ }
+
+ public List getRewards()
+ {
+ return _rewards;
+ }
+
+ public void addReward(FishingCatch catchData)
+ {
+ _rewards.add(catchData);
+ }
+
+ public FishingCatch getRandom()
+ {
+ float random = Rnd.get(100);
+ for (FishingCatch fishingCatchData : _rewards)
+ {
+ if (fishingCatchData.getChance() > random)
+ {
+ return fishingCatchData;
+ }
+ random -= fishingCatchData.getChance();
+ }
+ return null;
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
new file mode 100644
index 0000000000..85c2e42e5a
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
@@ -0,0 +1,49 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingCatch
+{
+ private final int _itemId;
+ private final float _chance;
+ private final float _multiplier;
+
+ public FishingCatch(int itemId, float chance, float multiplier)
+ {
+ _itemId = itemId;
+ _chance = chance;
+ _multiplier = multiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public float getChance()
+ {
+ return _chance;
+ }
+
+ public float getMultiplier()
+ {
+ return _multiplier;
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
new file mode 100644
index 0000000000..93b5fb9b8e
--- /dev/null
+++ b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingRod
+{
+ private final int _itemId;
+ private final int _reduceFishingTime;
+ private final float _xpMultiplier;
+ private final float _spMultiplier;
+
+ public FishingRod(int itemId, int reduceFishingTime, float xpMultiplier, float spMultiplier)
+ {
+ _itemId = itemId;
+ _reduceFishingTime = reduceFishingTime;
+ _xpMultiplier = xpMultiplier;
+ _spMultiplier = spMultiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public int getReduceFishingTime()
+ {
+ return _reduceFishingTime;
+ }
+
+ public float getXpMultiplier()
+ {
+ return _xpMultiplier;
+ }
+
+ public float getSpMultiplier()
+ {
+ return _spMultiplier;
+ }
+}
diff --git a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
index 71d8f10b3e..dfcf4d7f56 100644
--- a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
+++ b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
@@ -20,10 +20,10 @@ import java.lang.ref.WeakReference;
import com.l2jmobius.Config;
import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.PcCondOverride;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.serverpackets.fishing.ExAutoFishAvailable;
diff --git a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
index dea11bad61..cebaa3c7a5 100644
--- a/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
+++ b/L2J_Mobius_6.0_Fafurion/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
@@ -29,20 +29,17 @@ public class ExFishingStart implements IClientOutgoingPacket
{
private final L2PcInstance _player;
private final int _fishType;
- private final int _baitType;
private final ILocational _baitLocation;
/**
* @param player
* @param fishType
- * @param baitType - 0 = newbie, 1 = normal, 2 = night
* @param baitLocation
*/
- public ExFishingStart(L2PcInstance player, int fishType, int baitType, ILocational baitLocation)
+ public ExFishingStart(L2PcInstance player, int fishType, ILocational baitLocation)
{
_player = player;
_fishType = fishType;
- _baitType = baitType;
_baitLocation = baitLocation;
}
@@ -55,7 +52,7 @@ public class ExFishingStart implements IClientOutgoingPacket
packet.writeD(_baitLocation.getX());
packet.writeD(_baitLocation.getY());
packet.writeD(_baitLocation.getZ());
- packet.writeC(_baitType);
+ packet.writeC(0x01); // 0 = newbie, 1 = normal, 2 = night
return true;
}
}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/config/Custom/PremiumSystem.ini b/L2J_Mobius_Classic_2.0_Saviors/dist/game/config/Custom/PremiumSystem.ini
index ea1796cc7f..1f9a98a879 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/config/Custom/PremiumSystem.ini
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/config/Custom/PremiumSystem.ini
@@ -32,3 +32,7 @@ PremiumRateSpoilAmount = 2
# Usage: itemId1,multiplier1;itemId2,multiplier2;...
PremiumRateDropChanceByItemId = 57,2;6656,1;6657,1;6658,1;6659,1;6660,1;6661,1;6662,1;8191,1;10170,1;10314,1
PremiumRateDropAmountByItemId = 57,2;6656,1;6657,1;6658,1;6659,1;6660,1;6661,1;6662,1;8191,1;10170,1;10314,1
+
+# Enable Fishing only for premium players.
+# Retail: True
+PremiumOnlyFishing = True
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/Fishing.xml b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/Fishing.xml
index a4d243bc44..cfd7153244 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/Fishing.xml
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/Fishing.xml
@@ -1,12 +1,24 @@
-
-
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/xsd/Fishing.xsd b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/xsd/Fishing.xsd
index 16e5ed9699..1078ed7f77 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/xsd/Fishing.xsd
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/xsd/Fishing.xsd
@@ -9,13 +9,13 @@
-
+
-
+
@@ -30,17 +30,35 @@
+
+
-
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/Config.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/Config.java
index 3d5aee77da..f1d79f1a34 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/Config.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/Config.java
@@ -1082,6 +1082,7 @@ public final class Config
public static float PREMIUM_RATE_SPOIL_AMOUNT;
public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
+ public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
public static int PC_CAFE_MAX_POINTS;
@@ -2557,6 +2558,7 @@ public final class Config
}
}
}
+ PREMIUM_ONLY_FISHING = PremiumSystem.getBoolean("PremiumOnlyFishing", true);
// Load PrivateStoreRange config file (if exists)
final PropertiesParser PrivateStoreRange = new PropertiesParser(CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE);
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
index 91b5f9c43e..bacf1ed08c 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
@@ -25,8 +25,12 @@ import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
+import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
-import com.l2jmobius.gameserver.model.FishingBaitData;
+import com.l2jmobius.gameserver.datatables.ItemTable;
+import com.l2jmobius.gameserver.model.fishing.FishingBait;
+import com.l2jmobius.gameserver.model.fishing.FishingCatch;
+import com.l2jmobius.gameserver.model.fishing.FishingRod;
/**
* This class holds the Fishing information.
@@ -35,7 +39,8 @@ import com.l2jmobius.gameserver.model.FishingBaitData;
public final class FishingData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(FishingData.class.getName());
- private final Map _baitData = new HashMap<>();
+ private final Map _baitData = new HashMap<>();
+ private final Map _rodData = new HashMap<>();
private int _baitDistanceMin;
private int _baitDistanceMax;
private double _expRateMin;
@@ -56,7 +61,7 @@ public final class FishingData implements IGameXmlReader
{
_baitData.clear();
parseDatapackFile("data/Fishing.xml");
- LOGGER.info(getClass().getSimpleName() + ": Loaded Fishing Data.");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _baitData.size() + " bait and " + _rodData.size() + " rod data.");
}
@Override
@@ -76,13 +81,13 @@ public final class FishingData implements IGameXmlReader
_baitDistanceMax = parseInteger(listItem.getAttributes(), "max");
break;
}
- case "experienceRate":
+ case "xpRate":
{
_expRateMin = parseDouble(listItem.getAttributes(), "min");
_expRateMax = parseDouble(listItem.getAttributes(), "max");
break;
}
- case "skillPointsRate":
+ case "spRate":
{
_spRateMin = parseDouble(listItem.getAttributes(), "min");
_spRateMax = parseDouble(listItem.getAttributes(), "max");
@@ -96,20 +101,39 @@ public final class FishingData implements IGameXmlReader
{
final NamedNodeMap attrs = bait.getAttributes();
final int itemId = parseInteger(attrs, "itemId");
- final int level = parseInteger(attrs, "level");
- final int minPlayerLevel = parseInteger(attrs, "minPlayerLevel");
+ final byte level = parseByte(attrs, "level", (byte) 1);
+ final byte minPlayerLevel = parseByte(attrs, "minPlayerLevel");
+ final byte maxPlayerLevel = parseByte(attrs, "minPlayerLevel", Config.PLAYER_MAXIMUM_LEVEL);
final double chance = parseDouble(attrs, "chance");
final int timeMin = parseInteger(attrs, "timeMin");
- final int timeMax = parseInteger(attrs, "timeMax");
+ final int timeMax = parseInteger(attrs, "timeMax", timeMin);
final int waitMin = parseInteger(attrs, "waitMin");
- final int waitMax = parseInteger(attrs, "waitMax");
- final FishingBaitData baitData = new FishingBaitData(itemId, level, minPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax);
+ final int waitMax = parseInteger(attrs, "waitMax", waitMin);
+ final boolean isPremiumOnly = parseBoolean(attrs, "isPremiumOnly", false);
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ final FishingBait baitData = new FishingBait(itemId, level, minPlayerLevel, maxPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax, isPremiumOnly);
for (Node c = bait.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("catch".equalsIgnoreCase(c.getNodeName()))
{
- baitData.addReward(parseInteger(c.getAttributes(), "itemId"));
+ final NamedNodeMap cAttrs = c.getAttributes();
+ final int cId = parseInteger(cAttrs, "itemId");
+ final float cChance = parseFloat(cAttrs, "chance");
+ final float cMultiplier = parseFloat(cAttrs, "multiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(cId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ baitData.addReward(new FishingCatch(cId, cChance, cMultiplier));
}
}
_baitData.put(baitData.getItemId(), baitData);
@@ -117,22 +141,44 @@ public final class FishingData implements IGameXmlReader
}
break;
}
+ case "rods":
+ {
+ for (Node rod = listItem.getFirstChild(); rod != null; rod = rod.getNextSibling())
+ {
+ if ("rod".equalsIgnoreCase(rod.getNodeName()))
+ {
+ final NamedNodeMap attrs = rod.getAttributes();
+ final int itemId = parseInteger(attrs, "itemId");
+ final int reduceFishingTime = parseInteger(attrs, "reduceFishingTime", 0);
+ final float xpMultiplier = parseFloat(attrs, "xpMultiplier", 1f);
+ final float spMultiplier = parseFloat(attrs, "spMultiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ _rodData.put(itemId, new FishingRod(itemId, reduceFishingTime, xpMultiplier, spMultiplier));
+ }
+ }
+ }
}
}
}
}
}
- /**
- * Gets the fishing rod.
- * @param baitItemId the item id
- * @return A list of reward item ids
- */
- public FishingBaitData getBaitData(int baitItemId)
+ public FishingBait getBaitData(int baitItemId)
{
return _baitData.get(baitItemId);
}
+ public FishingRod getRodData(int rodItemId)
+ {
+ return _rodData.get(rodItemId);
+ }
+
public int getBaitDistanceMin()
{
return _baitDistanceMin;
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/FishingBaitData.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/FishingBaitData.java
deleted file mode 100644
index 9cf4893d66..0000000000
--- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/FishingBaitData.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author bit
- */
-public class FishingBaitData
-{
- private final int _itemId;
- private final int _level;
- private final int _minPlayerLevel;
- private final double _chance;
- private final int _timeMin;
- private final int _timeMax;
- private final int _waitMin;
- private final int _waitMax;
- private final List _rewards = new ArrayList<>();
-
- public FishingBaitData(int itemId, int level, int minPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax)
- {
- _itemId = itemId;
- _level = level;
- _minPlayerLevel = minPlayerLevel;
- _chance = chance;
- _timeMin = timeMin;
- _timeMax = timeMax;
- _waitMin = waitMin;
- _waitMax = waitMax;
- }
-
- public int getItemId()
- {
- return _itemId;
- }
-
- public int getLevel()
- {
- return _level;
- }
-
- public int getMinPlayerLevel()
- {
- return _minPlayerLevel;
- }
-
- public double getChance()
- {
- return _chance;
- }
-
- public int getTimeMin()
- {
- return _timeMin;
- }
-
- public int getTimeMax()
- {
- return _timeMax;
- }
-
- public int getWaitMin()
- {
- return _waitMin;
- }
-
- public int getWaitMax()
- {
- return _waitMax;
- }
-
- public List getRewards()
- {
- return _rewards;
- }
-
- public void addReward(int itemId)
- {
- _rewards.add(itemId);
- }
-}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
index 07b40a0afa..da8948ba42 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
@@ -121,7 +121,6 @@ import com.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import com.l2jmobius.gameserver.model.BlockList;
import com.l2jmobius.gameserver.model.ClanPrivilege;
import com.l2jmobius.gameserver.model.ClanWar;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.L2AccessLevel;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
@@ -209,6 +208,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPCh
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPKill;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerReputationChanged;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerSubChange;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.MovieHolder;
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/Fishing.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
similarity index 79%
rename from L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/Fishing.java
rename to L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
index 4d757ab046..9083a43c4b 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/Fishing.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
@@ -1,443 +1,471 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.concurrent.ScheduledFuture;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.commons.util.Rnd;
-import com.l2jmobius.gameserver.data.xml.impl.FishingData;
-import com.l2jmobius.gameserver.enums.ShotType;
-import com.l2jmobius.gameserver.geoengine.GeoEngine;
-import com.l2jmobius.gameserver.instancemanager.ZoneManager;
-import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jmobius.gameserver.model.events.EventDispatcher;
-import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
-import com.l2jmobius.gameserver.model.interfaces.ILocational;
-import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
-import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
-import com.l2jmobius.gameserver.model.items.type.WeaponType;
-import com.l2jmobius.gameserver.model.zone.L2ZoneType;
-import com.l2jmobius.gameserver.model.zone.ZoneId;
-import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
-import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
-import com.l2jmobius.gameserver.network.SystemMessageId;
-import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
-import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
-import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
-import com.l2jmobius.gameserver.util.Util;
-
-/**
- * @author bit
- */
-public class Fishing
-{
- protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
- private volatile ILocational _baitLocation = new Location(0, 0, 0);
-
- private final L2PcInstance _player;
- private ScheduledFuture> _reelInTask;
- private ScheduledFuture> _startFishingTask;
- private boolean _isFishing = false;
-
- public Fishing(L2PcInstance player)
- {
- _player = player;
- }
-
- public synchronized boolean isFishing()
- {
- return _isFishing;
- }
-
- public boolean isAtValidLocation()
- {
- // TODO: implement checking direction
- // if (calculateBaitLocation() == null)
- // {
- // return false;
- // }
- return _player.isInsideZone(ZoneId.FISHING);
- }
-
- public boolean canFish()
- {
- return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
- }
-
- private FishingBaitData getCurrentBaitData()
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
- }
-
- private void cancelTasks()
- {
- if (_reelInTask != null)
- {
- _reelInTask.cancel(false);
- _reelInTask = null;
- }
-
- if (_startFishingTask != null)
- {
- _startFishingTask.cancel(false);
- _startFishingTask = null;
- }
- }
-
- public synchronized void startFishing()
- {
- if (_isFishing)
- {
- return;
- }
- _isFishing = true;
- castLine();
- }
-
- private void castLine()
- {
- if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
- {
- _player.sendMessage("Fishing is disabled.");
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- cancelTasks();
-
- if (!canFish())
- {
- if (_isFishing)
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final FishingBaitData baitData = getCurrentBaitData();
- final int minPlayerLevel = baitData == null ? 20 : baitData.getMinPlayerLevel();
- if (_player.getLevel() < minPlayerLevel)
- {
- if (minPlayerLevel == 20)
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_AS_YOU_DO_NOT_MEET_THE_REQUIREMENTS);
- }
- else // In case of custom fishing level.
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
- }
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final L2ItemInstance rod = _player.getActiveWeaponInstance();
- if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (baitData == null)
- {
- _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isTransformed() || _player.isInBoat())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_OR_TRANSFORMED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isCrafting() || _player.isInStoreMode())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- _baitLocation = calculateBaitLocation();
- if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
- {
- if (_isFishing)
- {
- // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- else
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- _player.rechargeShots(false, false, true);
- }
-
- _reelInTask = ThreadPool.schedule(() ->
- {
- _player.getFishing().reelInWithReward();
- _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), Rnd.get(baitData.getWaitMin(), baitData.getWaitMax()));
- }, Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()));
- _player.stopMove(null);
- _player.broadcastPacket(new ExFishingStart(_player, -1, baitData.getLevel(), _baitLocation));
- _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
- _player.sendPacket(new PlaySound("SF_P_01"));
- _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
- }
-
- public void reelInWithReward()
- {
- // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
- // Then player may or may not catch the fish. Using fishing shots increases chance to win.
- final FishingBaitData baitData = getCurrentBaitData();
- if (baitData == null)
- {
- reelIn(FishingEndReason.LOSE, false);
- LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
- return;
- }
-
- double chance = baitData.getChance();
- if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- chance *= 1.5; // +50 % chance to win
- }
-
- if (Rnd.get(0, 100) <= chance)
- {
- reelIn(FishingEndReason.WIN, true);
- }
- else
- {
- reelIn(FishingEndReason.LOSE, true);
- }
- }
-
- private void reelIn(FishingEndReason reason, boolean consumeBait)
- {
- if (!_isFishing)
- {
- return;
- }
-
- cancelTasks();
-
- try
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- if (consumeBait)
- {
- if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
- {
- reason = FishingEndReason.LOSE; // no bait - no reward
- return;
- }
- }
-
- if ((reason == FishingEndReason.WIN) && (bait != null))
- {
- final FishingBaitData baitData = FishingData.getInstance().getBaitData(bait.getId());
- final int numRewards = baitData.getRewards().size();
- if (numRewards > 0)
- {
- final FishingData fishingData = FishingData.getInstance();
- final int lvlModifier = _player.getLevel() * _player.getLevel();
- _player.addExpAndSp(Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier, Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier, true);
- final int fishId = baitData.getRewards().get(Rnd.get(0, numRewards - 1));
- _player.getInventory().addItem("Fishing Reward", fishId, 1, _player, null);
- final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
- msg.addItemName(fishId);
- _player.sendPacket(msg);
- _player.unchargeShot(ShotType.FISH_SOULSHOTS);
- _player.rechargeShots(false, false, true);
- }
- else
- {
- LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
- }
- }
- else if (reason == FishingEndReason.LOSE)
- {
- _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
- }
-
- if (consumeBait)
- {
- EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
- }
- }
- finally
- {
- _player.broadcastPacket(new ExFishingEnd(_player, reason));
- _player.sendPacket(new ExUserInfoFishing(_player, false));
- }
- }
-
- public void stopFishing()
- {
- stopFishing(FishingEndType.PLAYER_STOP);
- }
-
- public synchronized void stopFishing(FishingEndType endType)
- {
- if (_isFishing)
- {
- reelIn(FishingEndReason.STOP, false);
- _isFishing = false;
- switch (endType)
- {
- case PLAYER_STOP:
- {
- _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
- break;
- }
- case PLAYER_CANCEL:
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- break;
- }
- }
- }
- }
-
- public ILocational getBaitLocation()
- {
- return _baitLocation;
- }
-
- private Location calculateBaitLocation()
- {
- // calculate a position in front of the player with a random distance
- final int distMin = FishingData.getInstance().getBaitDistanceMin();
- final int distMax = FishingData.getInstance().getBaitDistanceMax();
- int distance = Rnd.get(distMin, distMax);
- final double angle = Util.convertHeadingToDegree(_player.getHeading());
- final double radian = Math.toRadians(angle);
- final double sin = Math.sin(radian);
- final double cos = Math.cos(radian);
- int baitX = (int) (_player.getX() + (cos * distance));
- int baitY = (int) (_player.getY() + (sin * distance));
-
- // search for fishing zone
- L2FishingZone fishingZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
- {
- if (zone instanceof L2FishingZone)
- {
- fishingZone = (L2FishingZone) zone;
- break;
- }
- }
- // search for water zone
- L2WaterZone waterZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
- {
- if (zone instanceof L2WaterZone)
- {
- waterZone = (L2WaterZone) zone;
- break;
- }
- }
-
- int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
- if (baitZ == Integer.MIN_VALUE)
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
- return null;
- }
-
- return new Location(baitX, baitY, baitZ);
- }
-
- /**
- * Computes the Z of the bait.
- * @param player the player
- * @param baitX the bait x
- * @param baitY the bait y
- * @param fishingZone the fishing zone
- * @param waterZone the water zone
- * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
- */
- private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
- {
- if ((fishingZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- if ((waterZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- // always use water zone, fishing zone high z is high in the air...
- final int baitZ = waterZone.getWaterZ();
-
- // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
- //
- // return Integer.MIN_VALUE;
- // }
-
- if (GeoEngine.getInstance().hasGeo(baitX, baitY))
- {
- if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
-
- if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
- }
-
- return baitZ;
- }
-}
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.commons.util.Rnd;
+import com.l2jmobius.gameserver.data.xml.impl.FishingData;
+import com.l2jmobius.gameserver.enums.ShotType;
+import com.l2jmobius.gameserver.geoengine.GeoEngine;
+import com.l2jmobius.gameserver.instancemanager.ZoneManager;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.PcCondOverride;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.events.EventDispatcher;
+import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
+import com.l2jmobius.gameserver.model.interfaces.ILocational;
+import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.model.items.type.WeaponType;
+import com.l2jmobius.gameserver.model.zone.L2ZoneType;
+import com.l2jmobius.gameserver.model.zone.ZoneId;
+import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
+import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
+import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author bit
+ */
+public class Fishing
+{
+ protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
+ private volatile ILocational _baitLocation = new Location(0, 0, 0);
+
+ private final L2PcInstance _player;
+ private ScheduledFuture> _reelInTask;
+ private ScheduledFuture> _startFishingTask;
+ private boolean _isFishing = false;
+
+ public Fishing(L2PcInstance player)
+ {
+ _player = player;
+ }
+
+ public synchronized boolean isFishing()
+ {
+ return _isFishing;
+ }
+
+ public boolean isAtValidLocation()
+ {
+ // TODO: implement checking direction
+ // if (calculateBaitLocation() == null)
+ // {
+ // return false;
+ // }
+ return _player.isInsideZone(ZoneId.FISHING);
+ }
+
+ public boolean canFish()
+ {
+ return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
+ }
+
+ private FishingBait getCurrentBaitData()
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
+ }
+
+ private void cancelTasks()
+ {
+ if (_reelInTask != null)
+ {
+ _reelInTask.cancel(false);
+ _reelInTask = null;
+ }
+
+ if (_startFishingTask != null)
+ {
+ _startFishingTask.cancel(false);
+ _startFishingTask = null;
+ }
+ }
+
+ public synchronized void startFishing()
+ {
+ if (_isFishing)
+ {
+ return;
+ }
+ _isFishing = true;
+ castLine();
+ }
+
+ private void castLine()
+ {
+ if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
+ {
+ _player.sendMessage("Fishing is disabled.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ cancelTasks();
+
+ if (!canFish())
+ {
+ if (_isFishing)
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (Config.PREMIUM_SYSTEM_ENABLED)
+ {
+ if (Config.PREMIUM_ONLY_FISHING && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.C1_CANNOT_DUEL_BECAUSE_C1_IS_CURRENTLY_FISHING);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (baitData.isPremiumOnly() && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.FAILED_PLEASE_TRY_AGAIN_USING_THE_CORRECT_BAIT);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+ }
+
+ final int minPlayerLevel = baitData.getMinPlayerLevel();
+ final int maxPLayerLevel = baitData.getMaxPlayerLevel();
+ if ((_player.getLevel() < minPlayerLevel) && (_player.getLevel() > maxPLayerLevel))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final L2ItemInstance rod = _player.getActiveWeaponInstance();
+ if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingRod rodData = FishingData.getInstance().getRodData(rod.getId());
+ if (rodData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isTransformed() || _player.isInBoat())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_OR_TRANSFORMED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isCrafting() || _player.isInStoreMode())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ _baitLocation = calculateBaitLocation();
+ if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
+ {
+ if (_isFishing)
+ {
+ // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ else
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ _player.rechargeShots(false, false, true);
+ }
+
+ final long fishingTime = Math.max(Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()) - rodData.getReduceFishingTime(), 1000);
+ final long fishingWaitTime = Rnd.get(baitData.getWaitMin(), baitData.getWaitMax());
+
+ _reelInTask = ThreadPool.schedule(() ->
+ {
+ _player.getFishing().reelInWithReward();
+ _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), fishingWaitTime);
+ }, fishingTime);
+ _player.stopMove(null);
+ _player.broadcastPacket(new ExFishingStart(_player, -1, _baitLocation));
+ _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
+ _player.sendPacket(new PlaySound("SF_P_01"));
+ _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
+ }
+
+ public void reelInWithReward()
+ {
+ // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
+ // Then player may or may not catch the fish. Using fishing shots increases chance to win.
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ reelIn(FishingEndReason.LOSE, false);
+ LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
+ return;
+ }
+
+ double chance = baitData.getChance();
+ if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ chance *= 2;
+ }
+
+ if (Rnd.get(100) <= chance)
+ {
+ reelIn(FishingEndReason.WIN, true);
+ }
+ else
+ {
+ reelIn(FishingEndReason.LOSE, true);
+ }
+ }
+
+ private void reelIn(FishingEndReason reason, boolean consumeBait)
+ {
+ if (!_isFishing)
+ {
+ return;
+ }
+
+ cancelTasks();
+
+ try
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ if (consumeBait)
+ {
+ if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
+ {
+ reason = FishingEndReason.LOSE; // no bait - no reward
+ return;
+ }
+ }
+
+ if ((reason == FishingEndReason.WIN) && (bait != null))
+ {
+ final FishingBait baitData = FishingData.getInstance().getBaitData(bait.getId());
+ final FishingCatch fishingCatchData = baitData.getRandom();
+ if (fishingCatchData != null)
+ {
+ final FishingData fishingData = FishingData.getInstance();
+ final double lvlModifier = (Math.pow(_player.getLevel(), 2.2) * fishingCatchData.getMultiplier());
+ final long xp = (long) (Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier);
+ final long sp = (long) (Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier);
+ _player.addExpAndSp(xp, sp, true);
+ _player.getInventory().addItem("Fishing Reward", fishingCatchData.getItemId(), 1, _player, null);
+ final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
+ msg.addItemName(fishingCatchData.getItemId());
+ _player.sendPacket(msg);
+ _player.unchargeShot(ShotType.FISH_SOULSHOTS);
+ _player.rechargeShots(false, false, true);
+ }
+ else
+ {
+ LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
+ }
+ }
+ else if (reason == FishingEndReason.LOSE)
+ {
+ _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
+ }
+
+ if (consumeBait)
+ {
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
+ }
+ }
+ finally
+ {
+ _player.broadcastPacket(new ExFishingEnd(_player, reason));
+ _player.sendPacket(new ExUserInfoFishing(_player, false));
+ }
+ }
+
+ public void stopFishing()
+ {
+ stopFishing(FishingEndType.PLAYER_STOP);
+ }
+
+ public synchronized void stopFishing(FishingEndType endType)
+ {
+ if (_isFishing)
+ {
+ reelIn(FishingEndReason.STOP, false);
+ _isFishing = false;
+ switch (endType)
+ {
+ case PLAYER_STOP:
+ {
+ _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
+ break;
+ }
+ case PLAYER_CANCEL:
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ break;
+ }
+ }
+ }
+ }
+
+ public ILocational getBaitLocation()
+ {
+ return _baitLocation;
+ }
+
+ private Location calculateBaitLocation()
+ {
+ // calculate a position in front of the player with a random distance
+ final int distMin = FishingData.getInstance().getBaitDistanceMin();
+ final int distMax = FishingData.getInstance().getBaitDistanceMax();
+ int distance = Rnd.get(distMin, distMax);
+ final double angle = Util.convertHeadingToDegree(_player.getHeading());
+ final double radian = Math.toRadians(angle);
+ final double sin = Math.sin(radian);
+ final double cos = Math.cos(radian);
+ int baitX = (int) (_player.getX() + (cos * distance));
+ int baitY = (int) (_player.getY() + (sin * distance));
+
+ // search for fishing zone
+ L2FishingZone fishingZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
+ {
+ if (zone instanceof L2FishingZone)
+ {
+ fishingZone = (L2FishingZone) zone;
+ break;
+ }
+ }
+ // search for water zone
+ L2WaterZone waterZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
+ {
+ if (zone instanceof L2WaterZone)
+ {
+ waterZone = (L2WaterZone) zone;
+ break;
+ }
+ }
+
+ int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
+ if (baitZ == Integer.MIN_VALUE)
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
+ return null;
+ }
+
+ return new Location(baitX, baitY, baitZ);
+ }
+
+ /**
+ * Computes the Z of the bait.
+ * @param player the player
+ * @param baitX the bait x
+ * @param baitY the bait y
+ * @param fishingZone the fishing zone
+ * @param waterZone the water zone
+ * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
+ */
+ private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
+ {
+ if ((fishingZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if ((waterZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ // always use water zone, fishing zone high z is high in the air...
+ final int baitZ = waterZone.getWaterZ();
+
+ // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
+ //
+ // return Integer.MIN_VALUE;
+ // }
+
+ if (GeoEngine.getInstance().hasGeo(baitX, baitY))
+ {
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+ }
+
+ return baitZ;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
new file mode 100644
index 0000000000..f5a5764254
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
@@ -0,0 +1,128 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.l2jmobius.commons.util.Rnd;
+
+/**
+ * @author bit
+ */
+public class FishingBait
+{
+ private final int _itemId;
+ private final byte _level;
+ private final byte _minPlayerLevel;
+ private final byte _maxPlayerLevel;
+ private final double _chance;
+ private final int _timeMin;
+ private final int _timeMax;
+ private final int _waitMin;
+ private final int _waitMax;
+ private final boolean _isPremiumOnly;
+ private final List _rewards = new ArrayList<>();
+
+ public FishingBait(int itemId, byte level, byte minPlayerLevel, byte maxPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax, boolean isPremiumOnly)
+ {
+ _itemId = itemId;
+ _level = level;
+ _minPlayerLevel = minPlayerLevel;
+ _maxPlayerLevel = maxPlayerLevel;
+ _chance = chance;
+ _timeMin = timeMin;
+ _timeMax = timeMax;
+ _waitMin = waitMin;
+ _waitMax = waitMax;
+ _isPremiumOnly = isPremiumOnly;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public byte getLevel()
+ {
+ return _level;
+ }
+
+ public byte getMinPlayerLevel()
+ {
+ return _minPlayerLevel;
+ }
+
+ public byte getMaxPlayerLevel()
+ {
+ return _maxPlayerLevel;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public int getTimeMin()
+ {
+ return _timeMin;
+ }
+
+ public int getTimeMax()
+ {
+ return _timeMax;
+ }
+
+ public int getWaitMin()
+ {
+ return _waitMin;
+ }
+
+ public int getWaitMax()
+ {
+ return _waitMax;
+ }
+
+ public boolean isPremiumOnly()
+ {
+ return _isPremiumOnly;
+ }
+
+ public List getRewards()
+ {
+ return _rewards;
+ }
+
+ public void addReward(FishingCatch catchData)
+ {
+ _rewards.add(catchData);
+ }
+
+ public FishingCatch getRandom()
+ {
+ float random = Rnd.get(100);
+ for (FishingCatch fishingCatchData : _rewards)
+ {
+ if (fishingCatchData.getChance() > random)
+ {
+ return fishingCatchData;
+ }
+ random -= fishingCatchData.getChance();
+ }
+ return null;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
new file mode 100644
index 0000000000..85c2e42e5a
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
@@ -0,0 +1,49 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingCatch
+{
+ private final int _itemId;
+ private final float _chance;
+ private final float _multiplier;
+
+ public FishingCatch(int itemId, float chance, float multiplier)
+ {
+ _itemId = itemId;
+ _chance = chance;
+ _multiplier = multiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public float getChance()
+ {
+ return _chance;
+ }
+
+ public float getMultiplier()
+ {
+ return _multiplier;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
new file mode 100644
index 0000000000..93b5fb9b8e
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingRod
+{
+ private final int _itemId;
+ private final int _reduceFishingTime;
+ private final float _xpMultiplier;
+ private final float _spMultiplier;
+
+ public FishingRod(int itemId, int reduceFishingTime, float xpMultiplier, float spMultiplier)
+ {
+ _itemId = itemId;
+ _reduceFishingTime = reduceFishingTime;
+ _xpMultiplier = xpMultiplier;
+ _spMultiplier = spMultiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public int getReduceFishingTime()
+ {
+ return _reduceFishingTime;
+ }
+
+ public float getXpMultiplier()
+ {
+ return _xpMultiplier;
+ }
+
+ public float getSpMultiplier()
+ {
+ return _spMultiplier;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
index 71d8f10b3e..dfcf4d7f56 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
@@ -20,10 +20,10 @@ import java.lang.ref.WeakReference;
import com.l2jmobius.Config;
import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.PcCondOverride;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.serverpackets.fishing.ExAutoFishAvailable;
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
index dea11bad61..cebaa3c7a5 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
@@ -29,20 +29,17 @@ public class ExFishingStart implements IClientOutgoingPacket
{
private final L2PcInstance _player;
private final int _fishType;
- private final int _baitType;
private final ILocational _baitLocation;
/**
* @param player
* @param fishType
- * @param baitType - 0 = newbie, 1 = normal, 2 = night
* @param baitLocation
*/
- public ExFishingStart(L2PcInstance player, int fishType, int baitType, ILocational baitLocation)
+ public ExFishingStart(L2PcInstance player, int fishType, ILocational baitLocation)
{
_player = player;
_fishType = fishType;
- _baitType = baitType;
_baitLocation = baitLocation;
}
@@ -55,7 +52,7 @@ public class ExFishingStart implements IClientOutgoingPacket
packet.writeD(_baitLocation.getX());
packet.writeD(_baitLocation.getY());
packet.writeD(_baitLocation.getZ());
- packet.writeC(_baitType);
+ packet.writeC(0x01); // 0 = newbie, 1 = normal, 2 = night
return true;
}
}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/config/Custom/PremiumSystem.ini b/L2J_Mobius_Classic_2.1_Zaken/dist/game/config/Custom/PremiumSystem.ini
index ea1796cc7f..1f9a98a879 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/dist/game/config/Custom/PremiumSystem.ini
+++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/config/Custom/PremiumSystem.ini
@@ -32,3 +32,7 @@ PremiumRateSpoilAmount = 2
# Usage: itemId1,multiplier1;itemId2,multiplier2;...
PremiumRateDropChanceByItemId = 57,2;6656,1;6657,1;6658,1;6659,1;6660,1;6661,1;6662,1;8191,1;10170,1;10314,1
PremiumRateDropAmountByItemId = 57,2;6656,1;6657,1;6658,1;6659,1;6660,1;6661,1;6662,1;8191,1;10170,1;10314,1
+
+# Enable Fishing only for premium players.
+# Retail: True
+PremiumOnlyFishing = True
diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/Fishing.xml b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/Fishing.xml
index a4d243bc44..cfd7153244 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/Fishing.xml
+++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/Fishing.xml
@@ -1,12 +1,24 @@
-
-
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/xsd/Fishing.xsd b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/xsd/Fishing.xsd
index 16e5ed9699..1078ed7f77 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/xsd/Fishing.xsd
+++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/xsd/Fishing.xsd
@@ -9,13 +9,13 @@
-
+
-
+
@@ -30,17 +30,35 @@
+
+
-
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/Config.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/Config.java
index 6fbb7f47f5..b9fb99aa27 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/Config.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/Config.java
@@ -1086,6 +1086,7 @@ public final class Config
public static float PREMIUM_RATE_SPOIL_AMOUNT;
public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
+ public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
public static int PC_CAFE_MAX_POINTS;
@@ -2564,6 +2565,7 @@ public final class Config
}
}
}
+ PREMIUM_ONLY_FISHING = PremiumSystem.getBoolean("PremiumOnlyFishing", true);
// Load PrivateStoreRange config file (if exists)
final PropertiesParser PrivateStoreRange = new PropertiesParser(CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE);
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
index 91b5f9c43e..bacf1ed08c 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
@@ -25,8 +25,12 @@ import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
+import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
-import com.l2jmobius.gameserver.model.FishingBaitData;
+import com.l2jmobius.gameserver.datatables.ItemTable;
+import com.l2jmobius.gameserver.model.fishing.FishingBait;
+import com.l2jmobius.gameserver.model.fishing.FishingCatch;
+import com.l2jmobius.gameserver.model.fishing.FishingRod;
/**
* This class holds the Fishing information.
@@ -35,7 +39,8 @@ import com.l2jmobius.gameserver.model.FishingBaitData;
public final class FishingData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(FishingData.class.getName());
- private final Map _baitData = new HashMap<>();
+ private final Map _baitData = new HashMap<>();
+ private final Map _rodData = new HashMap<>();
private int _baitDistanceMin;
private int _baitDistanceMax;
private double _expRateMin;
@@ -56,7 +61,7 @@ public final class FishingData implements IGameXmlReader
{
_baitData.clear();
parseDatapackFile("data/Fishing.xml");
- LOGGER.info(getClass().getSimpleName() + ": Loaded Fishing Data.");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _baitData.size() + " bait and " + _rodData.size() + " rod data.");
}
@Override
@@ -76,13 +81,13 @@ public final class FishingData implements IGameXmlReader
_baitDistanceMax = parseInteger(listItem.getAttributes(), "max");
break;
}
- case "experienceRate":
+ case "xpRate":
{
_expRateMin = parseDouble(listItem.getAttributes(), "min");
_expRateMax = parseDouble(listItem.getAttributes(), "max");
break;
}
- case "skillPointsRate":
+ case "spRate":
{
_spRateMin = parseDouble(listItem.getAttributes(), "min");
_spRateMax = parseDouble(listItem.getAttributes(), "max");
@@ -96,20 +101,39 @@ public final class FishingData implements IGameXmlReader
{
final NamedNodeMap attrs = bait.getAttributes();
final int itemId = parseInteger(attrs, "itemId");
- final int level = parseInteger(attrs, "level");
- final int minPlayerLevel = parseInteger(attrs, "minPlayerLevel");
+ final byte level = parseByte(attrs, "level", (byte) 1);
+ final byte minPlayerLevel = parseByte(attrs, "minPlayerLevel");
+ final byte maxPlayerLevel = parseByte(attrs, "minPlayerLevel", Config.PLAYER_MAXIMUM_LEVEL);
final double chance = parseDouble(attrs, "chance");
final int timeMin = parseInteger(attrs, "timeMin");
- final int timeMax = parseInteger(attrs, "timeMax");
+ final int timeMax = parseInteger(attrs, "timeMax", timeMin);
final int waitMin = parseInteger(attrs, "waitMin");
- final int waitMax = parseInteger(attrs, "waitMax");
- final FishingBaitData baitData = new FishingBaitData(itemId, level, minPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax);
+ final int waitMax = parseInteger(attrs, "waitMax", waitMin);
+ final boolean isPremiumOnly = parseBoolean(attrs, "isPremiumOnly", false);
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ final FishingBait baitData = new FishingBait(itemId, level, minPlayerLevel, maxPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax, isPremiumOnly);
for (Node c = bait.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("catch".equalsIgnoreCase(c.getNodeName()))
{
- baitData.addReward(parseInteger(c.getAttributes(), "itemId"));
+ final NamedNodeMap cAttrs = c.getAttributes();
+ final int cId = parseInteger(cAttrs, "itemId");
+ final float cChance = parseFloat(cAttrs, "chance");
+ final float cMultiplier = parseFloat(cAttrs, "multiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(cId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ baitData.addReward(new FishingCatch(cId, cChance, cMultiplier));
}
}
_baitData.put(baitData.getItemId(), baitData);
@@ -117,22 +141,44 @@ public final class FishingData implements IGameXmlReader
}
break;
}
+ case "rods":
+ {
+ for (Node rod = listItem.getFirstChild(); rod != null; rod = rod.getNextSibling())
+ {
+ if ("rod".equalsIgnoreCase(rod.getNodeName()))
+ {
+ final NamedNodeMap attrs = rod.getAttributes();
+ final int itemId = parseInteger(attrs, "itemId");
+ final int reduceFishingTime = parseInteger(attrs, "reduceFishingTime", 0);
+ final float xpMultiplier = parseFloat(attrs, "xpMultiplier", 1f);
+ final float spMultiplier = parseFloat(attrs, "spMultiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ _rodData.put(itemId, new FishingRod(itemId, reduceFishingTime, xpMultiplier, spMultiplier));
+ }
+ }
+ }
}
}
}
}
}
- /**
- * Gets the fishing rod.
- * @param baitItemId the item id
- * @return A list of reward item ids
- */
- public FishingBaitData getBaitData(int baitItemId)
+ public FishingBait getBaitData(int baitItemId)
{
return _baitData.get(baitItemId);
}
+ public FishingRod getRodData(int rodItemId)
+ {
+ return _rodData.get(rodItemId);
+ }
+
public int getBaitDistanceMin()
{
return _baitDistanceMin;
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/FishingBaitData.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/FishingBaitData.java
deleted file mode 100644
index 9cf4893d66..0000000000
--- a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/FishingBaitData.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author bit
- */
-public class FishingBaitData
-{
- private final int _itemId;
- private final int _level;
- private final int _minPlayerLevel;
- private final double _chance;
- private final int _timeMin;
- private final int _timeMax;
- private final int _waitMin;
- private final int _waitMax;
- private final List _rewards = new ArrayList<>();
-
- public FishingBaitData(int itemId, int level, int minPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax)
- {
- _itemId = itemId;
- _level = level;
- _minPlayerLevel = minPlayerLevel;
- _chance = chance;
- _timeMin = timeMin;
- _timeMax = timeMax;
- _waitMin = waitMin;
- _waitMax = waitMax;
- }
-
- public int getItemId()
- {
- return _itemId;
- }
-
- public int getLevel()
- {
- return _level;
- }
-
- public int getMinPlayerLevel()
- {
- return _minPlayerLevel;
- }
-
- public double getChance()
- {
- return _chance;
- }
-
- public int getTimeMin()
- {
- return _timeMin;
- }
-
- public int getTimeMax()
- {
- return _timeMax;
- }
-
- public int getWaitMin()
- {
- return _waitMin;
- }
-
- public int getWaitMax()
- {
- return _waitMax;
- }
-
- public List getRewards()
- {
- return _rewards;
- }
-
- public void addReward(int itemId)
- {
- _rewards.add(itemId);
- }
-}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
index dcc81f6a9f..c94e2c886a 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
@@ -121,7 +121,6 @@ import com.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import com.l2jmobius.gameserver.model.BlockList;
import com.l2jmobius.gameserver.model.ClanPrivilege;
import com.l2jmobius.gameserver.model.ClanWar;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.L2AccessLevel;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
@@ -209,6 +208,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPCh
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPKill;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerReputationChanged;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerSubChange;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.MovieHolder;
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/Fishing.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
similarity index 79%
rename from L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/Fishing.java
rename to L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
index 4d757ab046..9083a43c4b 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/Fishing.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
@@ -1,443 +1,471 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.concurrent.ScheduledFuture;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.commons.util.Rnd;
-import com.l2jmobius.gameserver.data.xml.impl.FishingData;
-import com.l2jmobius.gameserver.enums.ShotType;
-import com.l2jmobius.gameserver.geoengine.GeoEngine;
-import com.l2jmobius.gameserver.instancemanager.ZoneManager;
-import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jmobius.gameserver.model.events.EventDispatcher;
-import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
-import com.l2jmobius.gameserver.model.interfaces.ILocational;
-import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
-import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
-import com.l2jmobius.gameserver.model.items.type.WeaponType;
-import com.l2jmobius.gameserver.model.zone.L2ZoneType;
-import com.l2jmobius.gameserver.model.zone.ZoneId;
-import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
-import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
-import com.l2jmobius.gameserver.network.SystemMessageId;
-import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
-import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
-import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
-import com.l2jmobius.gameserver.util.Util;
-
-/**
- * @author bit
- */
-public class Fishing
-{
- protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
- private volatile ILocational _baitLocation = new Location(0, 0, 0);
-
- private final L2PcInstance _player;
- private ScheduledFuture> _reelInTask;
- private ScheduledFuture> _startFishingTask;
- private boolean _isFishing = false;
-
- public Fishing(L2PcInstance player)
- {
- _player = player;
- }
-
- public synchronized boolean isFishing()
- {
- return _isFishing;
- }
-
- public boolean isAtValidLocation()
- {
- // TODO: implement checking direction
- // if (calculateBaitLocation() == null)
- // {
- // return false;
- // }
- return _player.isInsideZone(ZoneId.FISHING);
- }
-
- public boolean canFish()
- {
- return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
- }
-
- private FishingBaitData getCurrentBaitData()
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
- }
-
- private void cancelTasks()
- {
- if (_reelInTask != null)
- {
- _reelInTask.cancel(false);
- _reelInTask = null;
- }
-
- if (_startFishingTask != null)
- {
- _startFishingTask.cancel(false);
- _startFishingTask = null;
- }
- }
-
- public synchronized void startFishing()
- {
- if (_isFishing)
- {
- return;
- }
- _isFishing = true;
- castLine();
- }
-
- private void castLine()
- {
- if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
- {
- _player.sendMessage("Fishing is disabled.");
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- cancelTasks();
-
- if (!canFish())
- {
- if (_isFishing)
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final FishingBaitData baitData = getCurrentBaitData();
- final int minPlayerLevel = baitData == null ? 20 : baitData.getMinPlayerLevel();
- if (_player.getLevel() < minPlayerLevel)
- {
- if (minPlayerLevel == 20)
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_AS_YOU_DO_NOT_MEET_THE_REQUIREMENTS);
- }
- else // In case of custom fishing level.
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
- }
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final L2ItemInstance rod = _player.getActiveWeaponInstance();
- if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (baitData == null)
- {
- _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isTransformed() || _player.isInBoat())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_OR_TRANSFORMED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isCrafting() || _player.isInStoreMode())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- _baitLocation = calculateBaitLocation();
- if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
- {
- if (_isFishing)
- {
- // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- else
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- _player.rechargeShots(false, false, true);
- }
-
- _reelInTask = ThreadPool.schedule(() ->
- {
- _player.getFishing().reelInWithReward();
- _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), Rnd.get(baitData.getWaitMin(), baitData.getWaitMax()));
- }, Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()));
- _player.stopMove(null);
- _player.broadcastPacket(new ExFishingStart(_player, -1, baitData.getLevel(), _baitLocation));
- _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
- _player.sendPacket(new PlaySound("SF_P_01"));
- _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
- }
-
- public void reelInWithReward()
- {
- // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
- // Then player may or may not catch the fish. Using fishing shots increases chance to win.
- final FishingBaitData baitData = getCurrentBaitData();
- if (baitData == null)
- {
- reelIn(FishingEndReason.LOSE, false);
- LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
- return;
- }
-
- double chance = baitData.getChance();
- if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- chance *= 1.5; // +50 % chance to win
- }
-
- if (Rnd.get(0, 100) <= chance)
- {
- reelIn(FishingEndReason.WIN, true);
- }
- else
- {
- reelIn(FishingEndReason.LOSE, true);
- }
- }
-
- private void reelIn(FishingEndReason reason, boolean consumeBait)
- {
- if (!_isFishing)
- {
- return;
- }
-
- cancelTasks();
-
- try
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- if (consumeBait)
- {
- if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
- {
- reason = FishingEndReason.LOSE; // no bait - no reward
- return;
- }
- }
-
- if ((reason == FishingEndReason.WIN) && (bait != null))
- {
- final FishingBaitData baitData = FishingData.getInstance().getBaitData(bait.getId());
- final int numRewards = baitData.getRewards().size();
- if (numRewards > 0)
- {
- final FishingData fishingData = FishingData.getInstance();
- final int lvlModifier = _player.getLevel() * _player.getLevel();
- _player.addExpAndSp(Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier, Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier, true);
- final int fishId = baitData.getRewards().get(Rnd.get(0, numRewards - 1));
- _player.getInventory().addItem("Fishing Reward", fishId, 1, _player, null);
- final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
- msg.addItemName(fishId);
- _player.sendPacket(msg);
- _player.unchargeShot(ShotType.FISH_SOULSHOTS);
- _player.rechargeShots(false, false, true);
- }
- else
- {
- LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
- }
- }
- else if (reason == FishingEndReason.LOSE)
- {
- _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
- }
-
- if (consumeBait)
- {
- EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
- }
- }
- finally
- {
- _player.broadcastPacket(new ExFishingEnd(_player, reason));
- _player.sendPacket(new ExUserInfoFishing(_player, false));
- }
- }
-
- public void stopFishing()
- {
- stopFishing(FishingEndType.PLAYER_STOP);
- }
-
- public synchronized void stopFishing(FishingEndType endType)
- {
- if (_isFishing)
- {
- reelIn(FishingEndReason.STOP, false);
- _isFishing = false;
- switch (endType)
- {
- case PLAYER_STOP:
- {
- _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
- break;
- }
- case PLAYER_CANCEL:
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- break;
- }
- }
- }
- }
-
- public ILocational getBaitLocation()
- {
- return _baitLocation;
- }
-
- private Location calculateBaitLocation()
- {
- // calculate a position in front of the player with a random distance
- final int distMin = FishingData.getInstance().getBaitDistanceMin();
- final int distMax = FishingData.getInstance().getBaitDistanceMax();
- int distance = Rnd.get(distMin, distMax);
- final double angle = Util.convertHeadingToDegree(_player.getHeading());
- final double radian = Math.toRadians(angle);
- final double sin = Math.sin(radian);
- final double cos = Math.cos(radian);
- int baitX = (int) (_player.getX() + (cos * distance));
- int baitY = (int) (_player.getY() + (sin * distance));
-
- // search for fishing zone
- L2FishingZone fishingZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
- {
- if (zone instanceof L2FishingZone)
- {
- fishingZone = (L2FishingZone) zone;
- break;
- }
- }
- // search for water zone
- L2WaterZone waterZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
- {
- if (zone instanceof L2WaterZone)
- {
- waterZone = (L2WaterZone) zone;
- break;
- }
- }
-
- int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
- if (baitZ == Integer.MIN_VALUE)
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
- return null;
- }
-
- return new Location(baitX, baitY, baitZ);
- }
-
- /**
- * Computes the Z of the bait.
- * @param player the player
- * @param baitX the bait x
- * @param baitY the bait y
- * @param fishingZone the fishing zone
- * @param waterZone the water zone
- * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
- */
- private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
- {
- if ((fishingZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- if ((waterZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- // always use water zone, fishing zone high z is high in the air...
- final int baitZ = waterZone.getWaterZ();
-
- // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
- //
- // return Integer.MIN_VALUE;
- // }
-
- if (GeoEngine.getInstance().hasGeo(baitX, baitY))
- {
- if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
-
- if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
- }
-
- return baitZ;
- }
-}
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.commons.util.Rnd;
+import com.l2jmobius.gameserver.data.xml.impl.FishingData;
+import com.l2jmobius.gameserver.enums.ShotType;
+import com.l2jmobius.gameserver.geoengine.GeoEngine;
+import com.l2jmobius.gameserver.instancemanager.ZoneManager;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.PcCondOverride;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.events.EventDispatcher;
+import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
+import com.l2jmobius.gameserver.model.interfaces.ILocational;
+import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.model.items.type.WeaponType;
+import com.l2jmobius.gameserver.model.zone.L2ZoneType;
+import com.l2jmobius.gameserver.model.zone.ZoneId;
+import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
+import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
+import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author bit
+ */
+public class Fishing
+{
+ protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
+ private volatile ILocational _baitLocation = new Location(0, 0, 0);
+
+ private final L2PcInstance _player;
+ private ScheduledFuture> _reelInTask;
+ private ScheduledFuture> _startFishingTask;
+ private boolean _isFishing = false;
+
+ public Fishing(L2PcInstance player)
+ {
+ _player = player;
+ }
+
+ public synchronized boolean isFishing()
+ {
+ return _isFishing;
+ }
+
+ public boolean isAtValidLocation()
+ {
+ // TODO: implement checking direction
+ // if (calculateBaitLocation() == null)
+ // {
+ // return false;
+ // }
+ return _player.isInsideZone(ZoneId.FISHING);
+ }
+
+ public boolean canFish()
+ {
+ return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
+ }
+
+ private FishingBait getCurrentBaitData()
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
+ }
+
+ private void cancelTasks()
+ {
+ if (_reelInTask != null)
+ {
+ _reelInTask.cancel(false);
+ _reelInTask = null;
+ }
+
+ if (_startFishingTask != null)
+ {
+ _startFishingTask.cancel(false);
+ _startFishingTask = null;
+ }
+ }
+
+ public synchronized void startFishing()
+ {
+ if (_isFishing)
+ {
+ return;
+ }
+ _isFishing = true;
+ castLine();
+ }
+
+ private void castLine()
+ {
+ if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
+ {
+ _player.sendMessage("Fishing is disabled.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ cancelTasks();
+
+ if (!canFish())
+ {
+ if (_isFishing)
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (Config.PREMIUM_SYSTEM_ENABLED)
+ {
+ if (Config.PREMIUM_ONLY_FISHING && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.C1_CANNOT_DUEL_BECAUSE_C1_IS_CURRENTLY_FISHING);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (baitData.isPremiumOnly() && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.FAILED_PLEASE_TRY_AGAIN_USING_THE_CORRECT_BAIT);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+ }
+
+ final int minPlayerLevel = baitData.getMinPlayerLevel();
+ final int maxPLayerLevel = baitData.getMaxPlayerLevel();
+ if ((_player.getLevel() < minPlayerLevel) && (_player.getLevel() > maxPLayerLevel))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final L2ItemInstance rod = _player.getActiveWeaponInstance();
+ if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingRod rodData = FishingData.getInstance().getRodData(rod.getId());
+ if (rodData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isTransformed() || _player.isInBoat())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_OR_TRANSFORMED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isCrafting() || _player.isInStoreMode())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ _baitLocation = calculateBaitLocation();
+ if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
+ {
+ if (_isFishing)
+ {
+ // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ else
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ _player.rechargeShots(false, false, true);
+ }
+
+ final long fishingTime = Math.max(Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()) - rodData.getReduceFishingTime(), 1000);
+ final long fishingWaitTime = Rnd.get(baitData.getWaitMin(), baitData.getWaitMax());
+
+ _reelInTask = ThreadPool.schedule(() ->
+ {
+ _player.getFishing().reelInWithReward();
+ _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), fishingWaitTime);
+ }, fishingTime);
+ _player.stopMove(null);
+ _player.broadcastPacket(new ExFishingStart(_player, -1, _baitLocation));
+ _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
+ _player.sendPacket(new PlaySound("SF_P_01"));
+ _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
+ }
+
+ public void reelInWithReward()
+ {
+ // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
+ // Then player may or may not catch the fish. Using fishing shots increases chance to win.
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ reelIn(FishingEndReason.LOSE, false);
+ LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
+ return;
+ }
+
+ double chance = baitData.getChance();
+ if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ chance *= 2;
+ }
+
+ if (Rnd.get(100) <= chance)
+ {
+ reelIn(FishingEndReason.WIN, true);
+ }
+ else
+ {
+ reelIn(FishingEndReason.LOSE, true);
+ }
+ }
+
+ private void reelIn(FishingEndReason reason, boolean consumeBait)
+ {
+ if (!_isFishing)
+ {
+ return;
+ }
+
+ cancelTasks();
+
+ try
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ if (consumeBait)
+ {
+ if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
+ {
+ reason = FishingEndReason.LOSE; // no bait - no reward
+ return;
+ }
+ }
+
+ if ((reason == FishingEndReason.WIN) && (bait != null))
+ {
+ final FishingBait baitData = FishingData.getInstance().getBaitData(bait.getId());
+ final FishingCatch fishingCatchData = baitData.getRandom();
+ if (fishingCatchData != null)
+ {
+ final FishingData fishingData = FishingData.getInstance();
+ final double lvlModifier = (Math.pow(_player.getLevel(), 2.2) * fishingCatchData.getMultiplier());
+ final long xp = (long) (Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier);
+ final long sp = (long) (Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier);
+ _player.addExpAndSp(xp, sp, true);
+ _player.getInventory().addItem("Fishing Reward", fishingCatchData.getItemId(), 1, _player, null);
+ final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
+ msg.addItemName(fishingCatchData.getItemId());
+ _player.sendPacket(msg);
+ _player.unchargeShot(ShotType.FISH_SOULSHOTS);
+ _player.rechargeShots(false, false, true);
+ }
+ else
+ {
+ LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
+ }
+ }
+ else if (reason == FishingEndReason.LOSE)
+ {
+ _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
+ }
+
+ if (consumeBait)
+ {
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
+ }
+ }
+ finally
+ {
+ _player.broadcastPacket(new ExFishingEnd(_player, reason));
+ _player.sendPacket(new ExUserInfoFishing(_player, false));
+ }
+ }
+
+ public void stopFishing()
+ {
+ stopFishing(FishingEndType.PLAYER_STOP);
+ }
+
+ public synchronized void stopFishing(FishingEndType endType)
+ {
+ if (_isFishing)
+ {
+ reelIn(FishingEndReason.STOP, false);
+ _isFishing = false;
+ switch (endType)
+ {
+ case PLAYER_STOP:
+ {
+ _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
+ break;
+ }
+ case PLAYER_CANCEL:
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ break;
+ }
+ }
+ }
+ }
+
+ public ILocational getBaitLocation()
+ {
+ return _baitLocation;
+ }
+
+ private Location calculateBaitLocation()
+ {
+ // calculate a position in front of the player with a random distance
+ final int distMin = FishingData.getInstance().getBaitDistanceMin();
+ final int distMax = FishingData.getInstance().getBaitDistanceMax();
+ int distance = Rnd.get(distMin, distMax);
+ final double angle = Util.convertHeadingToDegree(_player.getHeading());
+ final double radian = Math.toRadians(angle);
+ final double sin = Math.sin(radian);
+ final double cos = Math.cos(radian);
+ int baitX = (int) (_player.getX() + (cos * distance));
+ int baitY = (int) (_player.getY() + (sin * distance));
+
+ // search for fishing zone
+ L2FishingZone fishingZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
+ {
+ if (zone instanceof L2FishingZone)
+ {
+ fishingZone = (L2FishingZone) zone;
+ break;
+ }
+ }
+ // search for water zone
+ L2WaterZone waterZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
+ {
+ if (zone instanceof L2WaterZone)
+ {
+ waterZone = (L2WaterZone) zone;
+ break;
+ }
+ }
+
+ int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
+ if (baitZ == Integer.MIN_VALUE)
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
+ return null;
+ }
+
+ return new Location(baitX, baitY, baitZ);
+ }
+
+ /**
+ * Computes the Z of the bait.
+ * @param player the player
+ * @param baitX the bait x
+ * @param baitY the bait y
+ * @param fishingZone the fishing zone
+ * @param waterZone the water zone
+ * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
+ */
+ private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
+ {
+ if ((fishingZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if ((waterZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ // always use water zone, fishing zone high z is high in the air...
+ final int baitZ = waterZone.getWaterZ();
+
+ // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
+ //
+ // return Integer.MIN_VALUE;
+ // }
+
+ if (GeoEngine.getInstance().hasGeo(baitX, baitY))
+ {
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+ }
+
+ return baitZ;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
new file mode 100644
index 0000000000..f5a5764254
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
@@ -0,0 +1,128 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.l2jmobius.commons.util.Rnd;
+
+/**
+ * @author bit
+ */
+public class FishingBait
+{
+ private final int _itemId;
+ private final byte _level;
+ private final byte _minPlayerLevel;
+ private final byte _maxPlayerLevel;
+ private final double _chance;
+ private final int _timeMin;
+ private final int _timeMax;
+ private final int _waitMin;
+ private final int _waitMax;
+ private final boolean _isPremiumOnly;
+ private final List _rewards = new ArrayList<>();
+
+ public FishingBait(int itemId, byte level, byte minPlayerLevel, byte maxPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax, boolean isPremiumOnly)
+ {
+ _itemId = itemId;
+ _level = level;
+ _minPlayerLevel = minPlayerLevel;
+ _maxPlayerLevel = maxPlayerLevel;
+ _chance = chance;
+ _timeMin = timeMin;
+ _timeMax = timeMax;
+ _waitMin = waitMin;
+ _waitMax = waitMax;
+ _isPremiumOnly = isPremiumOnly;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public byte getLevel()
+ {
+ return _level;
+ }
+
+ public byte getMinPlayerLevel()
+ {
+ return _minPlayerLevel;
+ }
+
+ public byte getMaxPlayerLevel()
+ {
+ return _maxPlayerLevel;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public int getTimeMin()
+ {
+ return _timeMin;
+ }
+
+ public int getTimeMax()
+ {
+ return _timeMax;
+ }
+
+ public int getWaitMin()
+ {
+ return _waitMin;
+ }
+
+ public int getWaitMax()
+ {
+ return _waitMax;
+ }
+
+ public boolean isPremiumOnly()
+ {
+ return _isPremiumOnly;
+ }
+
+ public List getRewards()
+ {
+ return _rewards;
+ }
+
+ public void addReward(FishingCatch catchData)
+ {
+ _rewards.add(catchData);
+ }
+
+ public FishingCatch getRandom()
+ {
+ float random = Rnd.get(100);
+ for (FishingCatch fishingCatchData : _rewards)
+ {
+ if (fishingCatchData.getChance() > random)
+ {
+ return fishingCatchData;
+ }
+ random -= fishingCatchData.getChance();
+ }
+ return null;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
new file mode 100644
index 0000000000..85c2e42e5a
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
@@ -0,0 +1,49 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingCatch
+{
+ private final int _itemId;
+ private final float _chance;
+ private final float _multiplier;
+
+ public FishingCatch(int itemId, float chance, float multiplier)
+ {
+ _itemId = itemId;
+ _chance = chance;
+ _multiplier = multiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public float getChance()
+ {
+ return _chance;
+ }
+
+ public float getMultiplier()
+ {
+ return _multiplier;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
new file mode 100644
index 0000000000..93b5fb9b8e
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingRod
+{
+ private final int _itemId;
+ private final int _reduceFishingTime;
+ private final float _xpMultiplier;
+ private final float _spMultiplier;
+
+ public FishingRod(int itemId, int reduceFishingTime, float xpMultiplier, float spMultiplier)
+ {
+ _itemId = itemId;
+ _reduceFishingTime = reduceFishingTime;
+ _xpMultiplier = xpMultiplier;
+ _spMultiplier = spMultiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public int getReduceFishingTime()
+ {
+ return _reduceFishingTime;
+ }
+
+ public float getXpMultiplier()
+ {
+ return _xpMultiplier;
+ }
+
+ public float getSpMultiplier()
+ {
+ return _spMultiplier;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
index 71d8f10b3e..dfcf4d7f56 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
@@ -20,10 +20,10 @@ import java.lang.ref.WeakReference;
import com.l2jmobius.Config;
import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.PcCondOverride;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.serverpackets.fishing.ExAutoFishAvailable;
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
index dea11bad61..cebaa3c7a5 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
@@ -29,20 +29,17 @@ public class ExFishingStart implements IClientOutgoingPacket
{
private final L2PcInstance _player;
private final int _fishType;
- private final int _baitType;
private final ILocational _baitLocation;
/**
* @param player
* @param fishType
- * @param baitType - 0 = newbie, 1 = normal, 2 = night
* @param baitLocation
*/
- public ExFishingStart(L2PcInstance player, int fishType, int baitType, ILocational baitLocation)
+ public ExFishingStart(L2PcInstance player, int fishType, ILocational baitLocation)
{
_player = player;
_fishType = fishType;
- _baitType = baitType;
_baitLocation = baitLocation;
}
@@ -55,7 +52,7 @@ public class ExFishingStart implements IClientOutgoingPacket
packet.writeD(_baitLocation.getX());
packet.writeD(_baitLocation.getY());
packet.writeD(_baitLocation.getZ());
- packet.writeC(_baitType);
+ packet.writeC(0x01); // 0 = newbie, 1 = normal, 2 = night
return true;
}
}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/config/Custom/PremiumSystem.ini b/L2J_Mobius_Classic_2.2_Antharas/dist/game/config/Custom/PremiumSystem.ini
index ea1796cc7f..1f9a98a879 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/dist/game/config/Custom/PremiumSystem.ini
+++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/config/Custom/PremiumSystem.ini
@@ -32,3 +32,7 @@ PremiumRateSpoilAmount = 2
# Usage: itemId1,multiplier1;itemId2,multiplier2;...
PremiumRateDropChanceByItemId = 57,2;6656,1;6657,1;6658,1;6659,1;6660,1;6661,1;6662,1;8191,1;10170,1;10314,1
PremiumRateDropAmountByItemId = 57,2;6656,1;6657,1;6658,1;6659,1;6660,1;6661,1;6662,1;8191,1;10170,1;10314,1
+
+# Enable Fishing only for premium players.
+# Retail: True
+PremiumOnlyFishing = True
diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/Fishing.xml b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/Fishing.xml
index a4d243bc44..cfd7153244 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/Fishing.xml
+++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/Fishing.xml
@@ -1,12 +1,24 @@
-
-
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/xsd/Fishing.xsd b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/xsd/Fishing.xsd
index 16e5ed9699..1078ed7f77 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/xsd/Fishing.xsd
+++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/xsd/Fishing.xsd
@@ -9,13 +9,13 @@
-
+
-
+
@@ -30,17 +30,35 @@
+
+
-
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/Config.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/Config.java
index 6fbb7f47f5..b9fb99aa27 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/Config.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/Config.java
@@ -1086,6 +1086,7 @@ public final class Config
public static float PREMIUM_RATE_SPOIL_AMOUNT;
public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
+ public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
public static int PC_CAFE_MAX_POINTS;
@@ -2564,6 +2565,7 @@ public final class Config
}
}
}
+ PREMIUM_ONLY_FISHING = PremiumSystem.getBoolean("PremiumOnlyFishing", true);
// Load PrivateStoreRange config file (if exists)
final PropertiesParser PrivateStoreRange = new PropertiesParser(CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE);
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
index 91b5f9c43e..bacf1ed08c 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
@@ -25,8 +25,12 @@ import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
+import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
-import com.l2jmobius.gameserver.model.FishingBaitData;
+import com.l2jmobius.gameserver.datatables.ItemTable;
+import com.l2jmobius.gameserver.model.fishing.FishingBait;
+import com.l2jmobius.gameserver.model.fishing.FishingCatch;
+import com.l2jmobius.gameserver.model.fishing.FishingRod;
/**
* This class holds the Fishing information.
@@ -35,7 +39,8 @@ import com.l2jmobius.gameserver.model.FishingBaitData;
public final class FishingData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(FishingData.class.getName());
- private final Map _baitData = new HashMap<>();
+ private final Map _baitData = new HashMap<>();
+ private final Map _rodData = new HashMap<>();
private int _baitDistanceMin;
private int _baitDistanceMax;
private double _expRateMin;
@@ -56,7 +61,7 @@ public final class FishingData implements IGameXmlReader
{
_baitData.clear();
parseDatapackFile("data/Fishing.xml");
- LOGGER.info(getClass().getSimpleName() + ": Loaded Fishing Data.");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _baitData.size() + " bait and " + _rodData.size() + " rod data.");
}
@Override
@@ -76,13 +81,13 @@ public final class FishingData implements IGameXmlReader
_baitDistanceMax = parseInteger(listItem.getAttributes(), "max");
break;
}
- case "experienceRate":
+ case "xpRate":
{
_expRateMin = parseDouble(listItem.getAttributes(), "min");
_expRateMax = parseDouble(listItem.getAttributes(), "max");
break;
}
- case "skillPointsRate":
+ case "spRate":
{
_spRateMin = parseDouble(listItem.getAttributes(), "min");
_spRateMax = parseDouble(listItem.getAttributes(), "max");
@@ -96,20 +101,39 @@ public final class FishingData implements IGameXmlReader
{
final NamedNodeMap attrs = bait.getAttributes();
final int itemId = parseInteger(attrs, "itemId");
- final int level = parseInteger(attrs, "level");
- final int minPlayerLevel = parseInteger(attrs, "minPlayerLevel");
+ final byte level = parseByte(attrs, "level", (byte) 1);
+ final byte minPlayerLevel = parseByte(attrs, "minPlayerLevel");
+ final byte maxPlayerLevel = parseByte(attrs, "minPlayerLevel", Config.PLAYER_MAXIMUM_LEVEL);
final double chance = parseDouble(attrs, "chance");
final int timeMin = parseInteger(attrs, "timeMin");
- final int timeMax = parseInteger(attrs, "timeMax");
+ final int timeMax = parseInteger(attrs, "timeMax", timeMin);
final int waitMin = parseInteger(attrs, "waitMin");
- final int waitMax = parseInteger(attrs, "waitMax");
- final FishingBaitData baitData = new FishingBaitData(itemId, level, minPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax);
+ final int waitMax = parseInteger(attrs, "waitMax", waitMin);
+ final boolean isPremiumOnly = parseBoolean(attrs, "isPremiumOnly", false);
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ final FishingBait baitData = new FishingBait(itemId, level, minPlayerLevel, maxPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax, isPremiumOnly);
for (Node c = bait.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("catch".equalsIgnoreCase(c.getNodeName()))
{
- baitData.addReward(parseInteger(c.getAttributes(), "itemId"));
+ final NamedNodeMap cAttrs = c.getAttributes();
+ final int cId = parseInteger(cAttrs, "itemId");
+ final float cChance = parseFloat(cAttrs, "chance");
+ final float cMultiplier = parseFloat(cAttrs, "multiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(cId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ baitData.addReward(new FishingCatch(cId, cChance, cMultiplier));
}
}
_baitData.put(baitData.getItemId(), baitData);
@@ -117,22 +141,44 @@ public final class FishingData implements IGameXmlReader
}
break;
}
+ case "rods":
+ {
+ for (Node rod = listItem.getFirstChild(); rod != null; rod = rod.getNextSibling())
+ {
+ if ("rod".equalsIgnoreCase(rod.getNodeName()))
+ {
+ final NamedNodeMap attrs = rod.getAttributes();
+ final int itemId = parseInteger(attrs, "itemId");
+ final int reduceFishingTime = parseInteger(attrs, "reduceFishingTime", 0);
+ final float xpMultiplier = parseFloat(attrs, "xpMultiplier", 1f);
+ final float spMultiplier = parseFloat(attrs, "spMultiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ _rodData.put(itemId, new FishingRod(itemId, reduceFishingTime, xpMultiplier, spMultiplier));
+ }
+ }
+ }
}
}
}
}
}
- /**
- * Gets the fishing rod.
- * @param baitItemId the item id
- * @return A list of reward item ids
- */
- public FishingBaitData getBaitData(int baitItemId)
+ public FishingBait getBaitData(int baitItemId)
{
return _baitData.get(baitItemId);
}
+ public FishingRod getRodData(int rodItemId)
+ {
+ return _rodData.get(rodItemId);
+ }
+
public int getBaitDistanceMin()
{
return _baitDistanceMin;
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/FishingBaitData.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/FishingBaitData.java
deleted file mode 100644
index 9cf4893d66..0000000000
--- a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/FishingBaitData.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author bit
- */
-public class FishingBaitData
-{
- private final int _itemId;
- private final int _level;
- private final int _minPlayerLevel;
- private final double _chance;
- private final int _timeMin;
- private final int _timeMax;
- private final int _waitMin;
- private final int _waitMax;
- private final List _rewards = new ArrayList<>();
-
- public FishingBaitData(int itemId, int level, int minPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax)
- {
- _itemId = itemId;
- _level = level;
- _minPlayerLevel = minPlayerLevel;
- _chance = chance;
- _timeMin = timeMin;
- _timeMax = timeMax;
- _waitMin = waitMin;
- _waitMax = waitMax;
- }
-
- public int getItemId()
- {
- return _itemId;
- }
-
- public int getLevel()
- {
- return _level;
- }
-
- public int getMinPlayerLevel()
- {
- return _minPlayerLevel;
- }
-
- public double getChance()
- {
- return _chance;
- }
-
- public int getTimeMin()
- {
- return _timeMin;
- }
-
- public int getTimeMax()
- {
- return _timeMax;
- }
-
- public int getWaitMin()
- {
- return _waitMin;
- }
-
- public int getWaitMax()
- {
- return _waitMax;
- }
-
- public List getRewards()
- {
- return _rewards;
- }
-
- public void addReward(int itemId)
- {
- _rewards.add(itemId);
- }
-}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
index e5678659ab..af65080411 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
@@ -121,7 +121,6 @@ import com.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import com.l2jmobius.gameserver.model.BlockList;
import com.l2jmobius.gameserver.model.ClanPrivilege;
import com.l2jmobius.gameserver.model.ClanWar;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.L2AccessLevel;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
@@ -209,6 +208,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPCh
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPKill;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerReputationChanged;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerSubChange;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.MovieHolder;
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/Fishing.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
similarity index 79%
rename from L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/Fishing.java
rename to L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
index 4d757ab046..9083a43c4b 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/Fishing.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
@@ -1,443 +1,471 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.concurrent.ScheduledFuture;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.commons.util.Rnd;
-import com.l2jmobius.gameserver.data.xml.impl.FishingData;
-import com.l2jmobius.gameserver.enums.ShotType;
-import com.l2jmobius.gameserver.geoengine.GeoEngine;
-import com.l2jmobius.gameserver.instancemanager.ZoneManager;
-import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jmobius.gameserver.model.events.EventDispatcher;
-import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
-import com.l2jmobius.gameserver.model.interfaces.ILocational;
-import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
-import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
-import com.l2jmobius.gameserver.model.items.type.WeaponType;
-import com.l2jmobius.gameserver.model.zone.L2ZoneType;
-import com.l2jmobius.gameserver.model.zone.ZoneId;
-import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
-import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
-import com.l2jmobius.gameserver.network.SystemMessageId;
-import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
-import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
-import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
-import com.l2jmobius.gameserver.util.Util;
-
-/**
- * @author bit
- */
-public class Fishing
-{
- protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
- private volatile ILocational _baitLocation = new Location(0, 0, 0);
-
- private final L2PcInstance _player;
- private ScheduledFuture> _reelInTask;
- private ScheduledFuture> _startFishingTask;
- private boolean _isFishing = false;
-
- public Fishing(L2PcInstance player)
- {
- _player = player;
- }
-
- public synchronized boolean isFishing()
- {
- return _isFishing;
- }
-
- public boolean isAtValidLocation()
- {
- // TODO: implement checking direction
- // if (calculateBaitLocation() == null)
- // {
- // return false;
- // }
- return _player.isInsideZone(ZoneId.FISHING);
- }
-
- public boolean canFish()
- {
- return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
- }
-
- private FishingBaitData getCurrentBaitData()
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
- }
-
- private void cancelTasks()
- {
- if (_reelInTask != null)
- {
- _reelInTask.cancel(false);
- _reelInTask = null;
- }
-
- if (_startFishingTask != null)
- {
- _startFishingTask.cancel(false);
- _startFishingTask = null;
- }
- }
-
- public synchronized void startFishing()
- {
- if (_isFishing)
- {
- return;
- }
- _isFishing = true;
- castLine();
- }
-
- private void castLine()
- {
- if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
- {
- _player.sendMessage("Fishing is disabled.");
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- cancelTasks();
-
- if (!canFish())
- {
- if (_isFishing)
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final FishingBaitData baitData = getCurrentBaitData();
- final int minPlayerLevel = baitData == null ? 20 : baitData.getMinPlayerLevel();
- if (_player.getLevel() < minPlayerLevel)
- {
- if (minPlayerLevel == 20)
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_AS_YOU_DO_NOT_MEET_THE_REQUIREMENTS);
- }
- else // In case of custom fishing level.
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
- }
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final L2ItemInstance rod = _player.getActiveWeaponInstance();
- if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (baitData == null)
- {
- _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isTransformed() || _player.isInBoat())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_OR_TRANSFORMED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isCrafting() || _player.isInStoreMode())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- _baitLocation = calculateBaitLocation();
- if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
- {
- if (_isFishing)
- {
- // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- else
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- _player.rechargeShots(false, false, true);
- }
-
- _reelInTask = ThreadPool.schedule(() ->
- {
- _player.getFishing().reelInWithReward();
- _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), Rnd.get(baitData.getWaitMin(), baitData.getWaitMax()));
- }, Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()));
- _player.stopMove(null);
- _player.broadcastPacket(new ExFishingStart(_player, -1, baitData.getLevel(), _baitLocation));
- _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
- _player.sendPacket(new PlaySound("SF_P_01"));
- _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
- }
-
- public void reelInWithReward()
- {
- // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
- // Then player may or may not catch the fish. Using fishing shots increases chance to win.
- final FishingBaitData baitData = getCurrentBaitData();
- if (baitData == null)
- {
- reelIn(FishingEndReason.LOSE, false);
- LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
- return;
- }
-
- double chance = baitData.getChance();
- if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- chance *= 1.5; // +50 % chance to win
- }
-
- if (Rnd.get(0, 100) <= chance)
- {
- reelIn(FishingEndReason.WIN, true);
- }
- else
- {
- reelIn(FishingEndReason.LOSE, true);
- }
- }
-
- private void reelIn(FishingEndReason reason, boolean consumeBait)
- {
- if (!_isFishing)
- {
- return;
- }
-
- cancelTasks();
-
- try
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- if (consumeBait)
- {
- if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
- {
- reason = FishingEndReason.LOSE; // no bait - no reward
- return;
- }
- }
-
- if ((reason == FishingEndReason.WIN) && (bait != null))
- {
- final FishingBaitData baitData = FishingData.getInstance().getBaitData(bait.getId());
- final int numRewards = baitData.getRewards().size();
- if (numRewards > 0)
- {
- final FishingData fishingData = FishingData.getInstance();
- final int lvlModifier = _player.getLevel() * _player.getLevel();
- _player.addExpAndSp(Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier, Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier, true);
- final int fishId = baitData.getRewards().get(Rnd.get(0, numRewards - 1));
- _player.getInventory().addItem("Fishing Reward", fishId, 1, _player, null);
- final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
- msg.addItemName(fishId);
- _player.sendPacket(msg);
- _player.unchargeShot(ShotType.FISH_SOULSHOTS);
- _player.rechargeShots(false, false, true);
- }
- else
- {
- LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
- }
- }
- else if (reason == FishingEndReason.LOSE)
- {
- _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
- }
-
- if (consumeBait)
- {
- EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
- }
- }
- finally
- {
- _player.broadcastPacket(new ExFishingEnd(_player, reason));
- _player.sendPacket(new ExUserInfoFishing(_player, false));
- }
- }
-
- public void stopFishing()
- {
- stopFishing(FishingEndType.PLAYER_STOP);
- }
-
- public synchronized void stopFishing(FishingEndType endType)
- {
- if (_isFishing)
- {
- reelIn(FishingEndReason.STOP, false);
- _isFishing = false;
- switch (endType)
- {
- case PLAYER_STOP:
- {
- _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
- break;
- }
- case PLAYER_CANCEL:
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- break;
- }
- }
- }
- }
-
- public ILocational getBaitLocation()
- {
- return _baitLocation;
- }
-
- private Location calculateBaitLocation()
- {
- // calculate a position in front of the player with a random distance
- final int distMin = FishingData.getInstance().getBaitDistanceMin();
- final int distMax = FishingData.getInstance().getBaitDistanceMax();
- int distance = Rnd.get(distMin, distMax);
- final double angle = Util.convertHeadingToDegree(_player.getHeading());
- final double radian = Math.toRadians(angle);
- final double sin = Math.sin(radian);
- final double cos = Math.cos(radian);
- int baitX = (int) (_player.getX() + (cos * distance));
- int baitY = (int) (_player.getY() + (sin * distance));
-
- // search for fishing zone
- L2FishingZone fishingZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
- {
- if (zone instanceof L2FishingZone)
- {
- fishingZone = (L2FishingZone) zone;
- break;
- }
- }
- // search for water zone
- L2WaterZone waterZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
- {
- if (zone instanceof L2WaterZone)
- {
- waterZone = (L2WaterZone) zone;
- break;
- }
- }
-
- int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
- if (baitZ == Integer.MIN_VALUE)
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
- return null;
- }
-
- return new Location(baitX, baitY, baitZ);
- }
-
- /**
- * Computes the Z of the bait.
- * @param player the player
- * @param baitX the bait x
- * @param baitY the bait y
- * @param fishingZone the fishing zone
- * @param waterZone the water zone
- * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
- */
- private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
- {
- if ((fishingZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- if ((waterZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- // always use water zone, fishing zone high z is high in the air...
- final int baitZ = waterZone.getWaterZ();
-
- // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
- //
- // return Integer.MIN_VALUE;
- // }
-
- if (GeoEngine.getInstance().hasGeo(baitX, baitY))
- {
- if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
-
- if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
- }
-
- return baitZ;
- }
-}
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.commons.util.Rnd;
+import com.l2jmobius.gameserver.data.xml.impl.FishingData;
+import com.l2jmobius.gameserver.enums.ShotType;
+import com.l2jmobius.gameserver.geoengine.GeoEngine;
+import com.l2jmobius.gameserver.instancemanager.ZoneManager;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.PcCondOverride;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.events.EventDispatcher;
+import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
+import com.l2jmobius.gameserver.model.interfaces.ILocational;
+import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.model.items.type.WeaponType;
+import com.l2jmobius.gameserver.model.zone.L2ZoneType;
+import com.l2jmobius.gameserver.model.zone.ZoneId;
+import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
+import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
+import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author bit
+ */
+public class Fishing
+{
+ protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
+ private volatile ILocational _baitLocation = new Location(0, 0, 0);
+
+ private final L2PcInstance _player;
+ private ScheduledFuture> _reelInTask;
+ private ScheduledFuture> _startFishingTask;
+ private boolean _isFishing = false;
+
+ public Fishing(L2PcInstance player)
+ {
+ _player = player;
+ }
+
+ public synchronized boolean isFishing()
+ {
+ return _isFishing;
+ }
+
+ public boolean isAtValidLocation()
+ {
+ // TODO: implement checking direction
+ // if (calculateBaitLocation() == null)
+ // {
+ // return false;
+ // }
+ return _player.isInsideZone(ZoneId.FISHING);
+ }
+
+ public boolean canFish()
+ {
+ return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
+ }
+
+ private FishingBait getCurrentBaitData()
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
+ }
+
+ private void cancelTasks()
+ {
+ if (_reelInTask != null)
+ {
+ _reelInTask.cancel(false);
+ _reelInTask = null;
+ }
+
+ if (_startFishingTask != null)
+ {
+ _startFishingTask.cancel(false);
+ _startFishingTask = null;
+ }
+ }
+
+ public synchronized void startFishing()
+ {
+ if (_isFishing)
+ {
+ return;
+ }
+ _isFishing = true;
+ castLine();
+ }
+
+ private void castLine()
+ {
+ if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
+ {
+ _player.sendMessage("Fishing is disabled.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ cancelTasks();
+
+ if (!canFish())
+ {
+ if (_isFishing)
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (Config.PREMIUM_SYSTEM_ENABLED)
+ {
+ if (Config.PREMIUM_ONLY_FISHING && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.C1_CANNOT_DUEL_BECAUSE_C1_IS_CURRENTLY_FISHING);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (baitData.isPremiumOnly() && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.FAILED_PLEASE_TRY_AGAIN_USING_THE_CORRECT_BAIT);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+ }
+
+ final int minPlayerLevel = baitData.getMinPlayerLevel();
+ final int maxPLayerLevel = baitData.getMaxPlayerLevel();
+ if ((_player.getLevel() < minPlayerLevel) && (_player.getLevel() > maxPLayerLevel))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final L2ItemInstance rod = _player.getActiveWeaponInstance();
+ if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingRod rodData = FishingData.getInstance().getRodData(rod.getId());
+ if (rodData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isTransformed() || _player.isInBoat())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_OR_TRANSFORMED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isCrafting() || _player.isInStoreMode())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ _baitLocation = calculateBaitLocation();
+ if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
+ {
+ if (_isFishing)
+ {
+ // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ else
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ _player.rechargeShots(false, false, true);
+ }
+
+ final long fishingTime = Math.max(Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()) - rodData.getReduceFishingTime(), 1000);
+ final long fishingWaitTime = Rnd.get(baitData.getWaitMin(), baitData.getWaitMax());
+
+ _reelInTask = ThreadPool.schedule(() ->
+ {
+ _player.getFishing().reelInWithReward();
+ _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), fishingWaitTime);
+ }, fishingTime);
+ _player.stopMove(null);
+ _player.broadcastPacket(new ExFishingStart(_player, -1, _baitLocation));
+ _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
+ _player.sendPacket(new PlaySound("SF_P_01"));
+ _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
+ }
+
+ public void reelInWithReward()
+ {
+ // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
+ // Then player may or may not catch the fish. Using fishing shots increases chance to win.
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ reelIn(FishingEndReason.LOSE, false);
+ LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
+ return;
+ }
+
+ double chance = baitData.getChance();
+ if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ chance *= 2;
+ }
+
+ if (Rnd.get(100) <= chance)
+ {
+ reelIn(FishingEndReason.WIN, true);
+ }
+ else
+ {
+ reelIn(FishingEndReason.LOSE, true);
+ }
+ }
+
+ private void reelIn(FishingEndReason reason, boolean consumeBait)
+ {
+ if (!_isFishing)
+ {
+ return;
+ }
+
+ cancelTasks();
+
+ try
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ if (consumeBait)
+ {
+ if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
+ {
+ reason = FishingEndReason.LOSE; // no bait - no reward
+ return;
+ }
+ }
+
+ if ((reason == FishingEndReason.WIN) && (bait != null))
+ {
+ final FishingBait baitData = FishingData.getInstance().getBaitData(bait.getId());
+ final FishingCatch fishingCatchData = baitData.getRandom();
+ if (fishingCatchData != null)
+ {
+ final FishingData fishingData = FishingData.getInstance();
+ final double lvlModifier = (Math.pow(_player.getLevel(), 2.2) * fishingCatchData.getMultiplier());
+ final long xp = (long) (Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier);
+ final long sp = (long) (Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier);
+ _player.addExpAndSp(xp, sp, true);
+ _player.getInventory().addItem("Fishing Reward", fishingCatchData.getItemId(), 1, _player, null);
+ final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
+ msg.addItemName(fishingCatchData.getItemId());
+ _player.sendPacket(msg);
+ _player.unchargeShot(ShotType.FISH_SOULSHOTS);
+ _player.rechargeShots(false, false, true);
+ }
+ else
+ {
+ LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
+ }
+ }
+ else if (reason == FishingEndReason.LOSE)
+ {
+ _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
+ }
+
+ if (consumeBait)
+ {
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
+ }
+ }
+ finally
+ {
+ _player.broadcastPacket(new ExFishingEnd(_player, reason));
+ _player.sendPacket(new ExUserInfoFishing(_player, false));
+ }
+ }
+
+ public void stopFishing()
+ {
+ stopFishing(FishingEndType.PLAYER_STOP);
+ }
+
+ public synchronized void stopFishing(FishingEndType endType)
+ {
+ if (_isFishing)
+ {
+ reelIn(FishingEndReason.STOP, false);
+ _isFishing = false;
+ switch (endType)
+ {
+ case PLAYER_STOP:
+ {
+ _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
+ break;
+ }
+ case PLAYER_CANCEL:
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ break;
+ }
+ }
+ }
+ }
+
+ public ILocational getBaitLocation()
+ {
+ return _baitLocation;
+ }
+
+ private Location calculateBaitLocation()
+ {
+ // calculate a position in front of the player with a random distance
+ final int distMin = FishingData.getInstance().getBaitDistanceMin();
+ final int distMax = FishingData.getInstance().getBaitDistanceMax();
+ int distance = Rnd.get(distMin, distMax);
+ final double angle = Util.convertHeadingToDegree(_player.getHeading());
+ final double radian = Math.toRadians(angle);
+ final double sin = Math.sin(radian);
+ final double cos = Math.cos(radian);
+ int baitX = (int) (_player.getX() + (cos * distance));
+ int baitY = (int) (_player.getY() + (sin * distance));
+
+ // search for fishing zone
+ L2FishingZone fishingZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
+ {
+ if (zone instanceof L2FishingZone)
+ {
+ fishingZone = (L2FishingZone) zone;
+ break;
+ }
+ }
+ // search for water zone
+ L2WaterZone waterZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
+ {
+ if (zone instanceof L2WaterZone)
+ {
+ waterZone = (L2WaterZone) zone;
+ break;
+ }
+ }
+
+ int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
+ if (baitZ == Integer.MIN_VALUE)
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
+ return null;
+ }
+
+ return new Location(baitX, baitY, baitZ);
+ }
+
+ /**
+ * Computes the Z of the bait.
+ * @param player the player
+ * @param baitX the bait x
+ * @param baitY the bait y
+ * @param fishingZone the fishing zone
+ * @param waterZone the water zone
+ * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
+ */
+ private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
+ {
+ if ((fishingZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if ((waterZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ // always use water zone, fishing zone high z is high in the air...
+ final int baitZ = waterZone.getWaterZ();
+
+ // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
+ //
+ // return Integer.MIN_VALUE;
+ // }
+
+ if (GeoEngine.getInstance().hasGeo(baitX, baitY))
+ {
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+ }
+
+ return baitZ;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
new file mode 100644
index 0000000000..f5a5764254
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
@@ -0,0 +1,128 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.l2jmobius.commons.util.Rnd;
+
+/**
+ * @author bit
+ */
+public class FishingBait
+{
+ private final int _itemId;
+ private final byte _level;
+ private final byte _minPlayerLevel;
+ private final byte _maxPlayerLevel;
+ private final double _chance;
+ private final int _timeMin;
+ private final int _timeMax;
+ private final int _waitMin;
+ private final int _waitMax;
+ private final boolean _isPremiumOnly;
+ private final List _rewards = new ArrayList<>();
+
+ public FishingBait(int itemId, byte level, byte minPlayerLevel, byte maxPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax, boolean isPremiumOnly)
+ {
+ _itemId = itemId;
+ _level = level;
+ _minPlayerLevel = minPlayerLevel;
+ _maxPlayerLevel = maxPlayerLevel;
+ _chance = chance;
+ _timeMin = timeMin;
+ _timeMax = timeMax;
+ _waitMin = waitMin;
+ _waitMax = waitMax;
+ _isPremiumOnly = isPremiumOnly;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public byte getLevel()
+ {
+ return _level;
+ }
+
+ public byte getMinPlayerLevel()
+ {
+ return _minPlayerLevel;
+ }
+
+ public byte getMaxPlayerLevel()
+ {
+ return _maxPlayerLevel;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public int getTimeMin()
+ {
+ return _timeMin;
+ }
+
+ public int getTimeMax()
+ {
+ return _timeMax;
+ }
+
+ public int getWaitMin()
+ {
+ return _waitMin;
+ }
+
+ public int getWaitMax()
+ {
+ return _waitMax;
+ }
+
+ public boolean isPremiumOnly()
+ {
+ return _isPremiumOnly;
+ }
+
+ public List getRewards()
+ {
+ return _rewards;
+ }
+
+ public void addReward(FishingCatch catchData)
+ {
+ _rewards.add(catchData);
+ }
+
+ public FishingCatch getRandom()
+ {
+ float random = Rnd.get(100);
+ for (FishingCatch fishingCatchData : _rewards)
+ {
+ if (fishingCatchData.getChance() > random)
+ {
+ return fishingCatchData;
+ }
+ random -= fishingCatchData.getChance();
+ }
+ return null;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
new file mode 100644
index 0000000000..85c2e42e5a
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
@@ -0,0 +1,49 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingCatch
+{
+ private final int _itemId;
+ private final float _chance;
+ private final float _multiplier;
+
+ public FishingCatch(int itemId, float chance, float multiplier)
+ {
+ _itemId = itemId;
+ _chance = chance;
+ _multiplier = multiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public float getChance()
+ {
+ return _chance;
+ }
+
+ public float getMultiplier()
+ {
+ return _multiplier;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
new file mode 100644
index 0000000000..93b5fb9b8e
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingRod
+{
+ private final int _itemId;
+ private final int _reduceFishingTime;
+ private final float _xpMultiplier;
+ private final float _spMultiplier;
+
+ public FishingRod(int itemId, int reduceFishingTime, float xpMultiplier, float spMultiplier)
+ {
+ _itemId = itemId;
+ _reduceFishingTime = reduceFishingTime;
+ _xpMultiplier = xpMultiplier;
+ _spMultiplier = spMultiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public int getReduceFishingTime()
+ {
+ return _reduceFishingTime;
+ }
+
+ public float getXpMultiplier()
+ {
+ return _xpMultiplier;
+ }
+
+ public float getSpMultiplier()
+ {
+ return _spMultiplier;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
index 71d8f10b3e..dfcf4d7f56 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
@@ -20,10 +20,10 @@ import java.lang.ref.WeakReference;
import com.l2jmobius.Config;
import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.PcCondOverride;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.serverpackets.fishing.ExAutoFishAvailable;
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
index dea11bad61..cebaa3c7a5 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
@@ -29,20 +29,17 @@ public class ExFishingStart implements IClientOutgoingPacket
{
private final L2PcInstance _player;
private final int _fishType;
- private final int _baitType;
private final ILocational _baitLocation;
/**
* @param player
* @param fishType
- * @param baitType - 0 = newbie, 1 = normal, 2 = night
* @param baitLocation
*/
- public ExFishingStart(L2PcInstance player, int fishType, int baitType, ILocational baitLocation)
+ public ExFishingStart(L2PcInstance player, int fishType, ILocational baitLocation)
{
_player = player;
_fishType = fishType;
- _baitType = baitType;
_baitLocation = baitLocation;
}
@@ -55,7 +52,7 @@ public class ExFishingStart implements IClientOutgoingPacket
packet.writeD(_baitLocation.getX());
packet.writeD(_baitLocation.getY());
packet.writeD(_baitLocation.getZ());
- packet.writeC(_baitType);
+ packet.writeC(0x01); // 0 = newbie, 1 = normal, 2 = night
return true;
}
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/config/Custom/PremiumSystem.ini b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/config/Custom/PremiumSystem.ini
index ea1796cc7f..1f9a98a879 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/config/Custom/PremiumSystem.ini
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/config/Custom/PremiumSystem.ini
@@ -32,3 +32,7 @@ PremiumRateSpoilAmount = 2
# Usage: itemId1,multiplier1;itemId2,multiplier2;...
PremiumRateDropChanceByItemId = 57,2;6656,1;6657,1;6658,1;6659,1;6660,1;6661,1;6662,1;8191,1;10170,1;10314,1
PremiumRateDropAmountByItemId = 57,2;6656,1;6657,1;6658,1;6659,1;6660,1;6661,1;6662,1;8191,1;10170,1;10314,1
+
+# Enable Fishing only for premium players.
+# Retail: True
+PremiumOnlyFishing = True
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/Fishing.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/Fishing.xml
index a4d243bc44..cfd7153244 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/Fishing.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/Fishing.xml
@@ -1,12 +1,24 @@
-
-
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/Fishing.xsd b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/Fishing.xsd
index 16e5ed9699..1078ed7f77 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/Fishing.xsd
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/Fishing.xsd
@@ -9,13 +9,13 @@
-
+
-
+
@@ -30,17 +30,35 @@
+
+
-
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/Config.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/Config.java
index 6fbb7f47f5..b9fb99aa27 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/Config.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/Config.java
@@ -1086,6 +1086,7 @@ public final class Config
public static float PREMIUM_RATE_SPOIL_AMOUNT;
public static Map PREMIUM_RATE_DROP_CHANCE_BY_ID;
public static Map PREMIUM_RATE_DROP_AMOUNT_BY_ID;
+ public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
public static int PC_CAFE_MAX_POINTS;
@@ -2564,6 +2565,7 @@ public final class Config
}
}
}
+ PREMIUM_ONLY_FISHING = PremiumSystem.getBoolean("PremiumOnlyFishing", true);
// Load PrivateStoreRange config file (if exists)
final PropertiesParser PrivateStoreRange = new PropertiesParser(CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE);
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
index 91b5f9c43e..bacf1ed08c 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/data/xml/impl/FishingData.java
@@ -25,8 +25,12 @@ import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
+import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
-import com.l2jmobius.gameserver.model.FishingBaitData;
+import com.l2jmobius.gameserver.datatables.ItemTable;
+import com.l2jmobius.gameserver.model.fishing.FishingBait;
+import com.l2jmobius.gameserver.model.fishing.FishingCatch;
+import com.l2jmobius.gameserver.model.fishing.FishingRod;
/**
* This class holds the Fishing information.
@@ -35,7 +39,8 @@ import com.l2jmobius.gameserver.model.FishingBaitData;
public final class FishingData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(FishingData.class.getName());
- private final Map _baitData = new HashMap<>();
+ private final Map _baitData = new HashMap<>();
+ private final Map _rodData = new HashMap<>();
private int _baitDistanceMin;
private int _baitDistanceMax;
private double _expRateMin;
@@ -56,7 +61,7 @@ public final class FishingData implements IGameXmlReader
{
_baitData.clear();
parseDatapackFile("data/Fishing.xml");
- LOGGER.info(getClass().getSimpleName() + ": Loaded Fishing Data.");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _baitData.size() + " bait and " + _rodData.size() + " rod data.");
}
@Override
@@ -76,13 +81,13 @@ public final class FishingData implements IGameXmlReader
_baitDistanceMax = parseInteger(listItem.getAttributes(), "max");
break;
}
- case "experienceRate":
+ case "xpRate":
{
_expRateMin = parseDouble(listItem.getAttributes(), "min");
_expRateMax = parseDouble(listItem.getAttributes(), "max");
break;
}
- case "skillPointsRate":
+ case "spRate":
{
_spRateMin = parseDouble(listItem.getAttributes(), "min");
_spRateMax = parseDouble(listItem.getAttributes(), "max");
@@ -96,20 +101,39 @@ public final class FishingData implements IGameXmlReader
{
final NamedNodeMap attrs = bait.getAttributes();
final int itemId = parseInteger(attrs, "itemId");
- final int level = parseInteger(attrs, "level");
- final int minPlayerLevel = parseInteger(attrs, "minPlayerLevel");
+ final byte level = parseByte(attrs, "level", (byte) 1);
+ final byte minPlayerLevel = parseByte(attrs, "minPlayerLevel");
+ final byte maxPlayerLevel = parseByte(attrs, "minPlayerLevel", Config.PLAYER_MAXIMUM_LEVEL);
final double chance = parseDouble(attrs, "chance");
final int timeMin = parseInteger(attrs, "timeMin");
- final int timeMax = parseInteger(attrs, "timeMax");
+ final int timeMax = parseInteger(attrs, "timeMax", timeMin);
final int waitMin = parseInteger(attrs, "waitMin");
- final int waitMax = parseInteger(attrs, "waitMax");
- final FishingBaitData baitData = new FishingBaitData(itemId, level, minPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax);
+ final int waitMax = parseInteger(attrs, "waitMax", waitMin);
+ final boolean isPremiumOnly = parseBoolean(attrs, "isPremiumOnly", false);
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ final FishingBait baitData = new FishingBait(itemId, level, minPlayerLevel, maxPlayerLevel, chance, timeMin, timeMax, waitMin, waitMax, isPremiumOnly);
for (Node c = bait.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("catch".equalsIgnoreCase(c.getNodeName()))
{
- baitData.addReward(parseInteger(c.getAttributes(), "itemId"));
+ final NamedNodeMap cAttrs = c.getAttributes();
+ final int cId = parseInteger(cAttrs, "itemId");
+ final float cChance = parseFloat(cAttrs, "chance");
+ final float cMultiplier = parseFloat(cAttrs, "multiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(cId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ baitData.addReward(new FishingCatch(cId, cChance, cMultiplier));
}
}
_baitData.put(baitData.getItemId(), baitData);
@@ -117,22 +141,44 @@ public final class FishingData implements IGameXmlReader
}
break;
}
+ case "rods":
+ {
+ for (Node rod = listItem.getFirstChild(); rod != null; rod = rod.getNextSibling())
+ {
+ if ("rod".equalsIgnoreCase(rod.getNodeName()))
+ {
+ final NamedNodeMap attrs = rod.getAttributes();
+ final int itemId = parseInteger(attrs, "itemId");
+ final int reduceFishingTime = parseInteger(attrs, "reduceFishingTime", 0);
+ final float xpMultiplier = parseFloat(attrs, "xpMultiplier", 1f);
+ final float spMultiplier = parseFloat(attrs, "spMultiplier", 1f);
+
+ if (ItemTable.getInstance().getTemplate(itemId) == null)
+ {
+ LOGGER.info(getClass().getSimpleName() + ": Could not find item with id " + itemId);
+ continue;
+ }
+
+ _rodData.put(itemId, new FishingRod(itemId, reduceFishingTime, xpMultiplier, spMultiplier));
+ }
+ }
+ }
}
}
}
}
}
- /**
- * Gets the fishing rod.
- * @param baitItemId the item id
- * @return A list of reward item ids
- */
- public FishingBaitData getBaitData(int baitItemId)
+ public FishingBait getBaitData(int baitItemId)
{
return _baitData.get(baitItemId);
}
+ public FishingRod getRodData(int rodItemId)
+ {
+ return _rodData.get(rodItemId);
+ }
+
public int getBaitDistanceMin()
{
return _baitDistanceMin;
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/FishingBaitData.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/FishingBaitData.java
deleted file mode 100644
index 9cf4893d66..0000000000
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/FishingBaitData.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author bit
- */
-public class FishingBaitData
-{
- private final int _itemId;
- private final int _level;
- private final int _minPlayerLevel;
- private final double _chance;
- private final int _timeMin;
- private final int _timeMax;
- private final int _waitMin;
- private final int _waitMax;
- private final List _rewards = new ArrayList<>();
-
- public FishingBaitData(int itemId, int level, int minPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax)
- {
- _itemId = itemId;
- _level = level;
- _minPlayerLevel = minPlayerLevel;
- _chance = chance;
- _timeMin = timeMin;
- _timeMax = timeMax;
- _waitMin = waitMin;
- _waitMax = waitMax;
- }
-
- public int getItemId()
- {
- return _itemId;
- }
-
- public int getLevel()
- {
- return _level;
- }
-
- public int getMinPlayerLevel()
- {
- return _minPlayerLevel;
- }
-
- public double getChance()
- {
- return _chance;
- }
-
- public int getTimeMin()
- {
- return _timeMin;
- }
-
- public int getTimeMax()
- {
- return _timeMax;
- }
-
- public int getWaitMin()
- {
- return _waitMin;
- }
-
- public int getWaitMax()
- {
- return _waitMax;
- }
-
- public List getRewards()
- {
- return _rewards;
- }
-
- public void addReward(int itemId)
- {
- _rewards.add(itemId);
- }
-}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
index 94bd437959..b9b8ed5eb2 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java
@@ -121,7 +121,6 @@ import com.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import com.l2jmobius.gameserver.model.BlockList;
import com.l2jmobius.gameserver.model.ClanPrivilege;
import com.l2jmobius.gameserver.model.ClanWar;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.L2AccessLevel;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
@@ -209,6 +208,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPCh
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerPvPKill;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerReputationChanged;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerSubChange;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.holders.AttendanceInfoHolder;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.MovieHolder;
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/Fishing.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
similarity index 79%
rename from L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/Fishing.java
rename to L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
index 4d757ab046..9083a43c4b 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/com/l2jmobius/gameserver/model/Fishing.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/fishing/Fishing.java
@@ -1,443 +1,471 @@
-/*
- * 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 com.l2jmobius.gameserver.model;
-
-import java.util.concurrent.ScheduledFuture;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.l2jmobius.Config;
-import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.commons.util.Rnd;
-import com.l2jmobius.gameserver.data.xml.impl.FishingData;
-import com.l2jmobius.gameserver.enums.ShotType;
-import com.l2jmobius.gameserver.geoengine.GeoEngine;
-import com.l2jmobius.gameserver.instancemanager.ZoneManager;
-import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jmobius.gameserver.model.events.EventDispatcher;
-import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
-import com.l2jmobius.gameserver.model.interfaces.ILocational;
-import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
-import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
-import com.l2jmobius.gameserver.model.items.type.WeaponType;
-import com.l2jmobius.gameserver.model.zone.L2ZoneType;
-import com.l2jmobius.gameserver.model.zone.ZoneId;
-import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
-import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
-import com.l2jmobius.gameserver.network.SystemMessageId;
-import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
-import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
-import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
-import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
-import com.l2jmobius.gameserver.util.Util;
-
-/**
- * @author bit
- */
-public class Fishing
-{
- protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
- private volatile ILocational _baitLocation = new Location(0, 0, 0);
-
- private final L2PcInstance _player;
- private ScheduledFuture> _reelInTask;
- private ScheduledFuture> _startFishingTask;
- private boolean _isFishing = false;
-
- public Fishing(L2PcInstance player)
- {
- _player = player;
- }
-
- public synchronized boolean isFishing()
- {
- return _isFishing;
- }
-
- public boolean isAtValidLocation()
- {
- // TODO: implement checking direction
- // if (calculateBaitLocation() == null)
- // {
- // return false;
- // }
- return _player.isInsideZone(ZoneId.FISHING);
- }
-
- public boolean canFish()
- {
- return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
- }
-
- private FishingBaitData getCurrentBaitData()
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
- }
-
- private void cancelTasks()
- {
- if (_reelInTask != null)
- {
- _reelInTask.cancel(false);
- _reelInTask = null;
- }
-
- if (_startFishingTask != null)
- {
- _startFishingTask.cancel(false);
- _startFishingTask = null;
- }
- }
-
- public synchronized void startFishing()
- {
- if (_isFishing)
- {
- return;
- }
- _isFishing = true;
- castLine();
- }
-
- private void castLine()
- {
- if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
- {
- _player.sendMessage("Fishing is disabled.");
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- cancelTasks();
-
- if (!canFish())
- {
- if (_isFishing)
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final FishingBaitData baitData = getCurrentBaitData();
- final int minPlayerLevel = baitData == null ? 20 : baitData.getMinPlayerLevel();
- if (_player.getLevel() < minPlayerLevel)
- {
- if (minPlayerLevel == 20)
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_AS_YOU_DO_NOT_MEET_THE_REQUIREMENTS);
- }
- else // In case of custom fishing level.
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
- }
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- final L2ItemInstance rod = _player.getActiveWeaponInstance();
- if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
- {
- _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (baitData == null)
- {
- _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isTransformed() || _player.isInBoat())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_OR_TRANSFORMED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isCrafting() || _player.isInStoreMode())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
- {
- _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- _baitLocation = calculateBaitLocation();
- if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
- {
- if (_isFishing)
- {
- // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- else
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
- _player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- stopFishing(FishingEndType.ERROR);
- return;
- }
-
- if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- _player.rechargeShots(false, false, true);
- }
-
- _reelInTask = ThreadPool.schedule(() ->
- {
- _player.getFishing().reelInWithReward();
- _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), Rnd.get(baitData.getWaitMin(), baitData.getWaitMax()));
- }, Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()));
- _player.stopMove(null);
- _player.broadcastPacket(new ExFishingStart(_player, -1, baitData.getLevel(), _baitLocation));
- _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
- _player.sendPacket(new PlaySound("SF_P_01"));
- _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
- }
-
- public void reelInWithReward()
- {
- // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
- // Then player may or may not catch the fish. Using fishing shots increases chance to win.
- final FishingBaitData baitData = getCurrentBaitData();
- if (baitData == null)
- {
- reelIn(FishingEndReason.LOSE, false);
- LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
- return;
- }
-
- double chance = baitData.getChance();
- if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
- {
- chance *= 1.5; // +50 % chance to win
- }
-
- if (Rnd.get(0, 100) <= chance)
- {
- reelIn(FishingEndReason.WIN, true);
- }
- else
- {
- reelIn(FishingEndReason.LOSE, true);
- }
- }
-
- private void reelIn(FishingEndReason reason, boolean consumeBait)
- {
- if (!_isFishing)
- {
- return;
- }
-
- cancelTasks();
-
- try
- {
- final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
- if (consumeBait)
- {
- if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
- {
- reason = FishingEndReason.LOSE; // no bait - no reward
- return;
- }
- }
-
- if ((reason == FishingEndReason.WIN) && (bait != null))
- {
- final FishingBaitData baitData = FishingData.getInstance().getBaitData(bait.getId());
- final int numRewards = baitData.getRewards().size();
- if (numRewards > 0)
- {
- final FishingData fishingData = FishingData.getInstance();
- final int lvlModifier = _player.getLevel() * _player.getLevel();
- _player.addExpAndSp(Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier, Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier, true);
- final int fishId = baitData.getRewards().get(Rnd.get(0, numRewards - 1));
- _player.getInventory().addItem("Fishing Reward", fishId, 1, _player, null);
- final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
- msg.addItemName(fishId);
- _player.sendPacket(msg);
- _player.unchargeShot(ShotType.FISH_SOULSHOTS);
- _player.rechargeShots(false, false, true);
- }
- else
- {
- LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
- }
- }
- else if (reason == FishingEndReason.LOSE)
- {
- _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
- }
-
- if (consumeBait)
- {
- EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
- }
- }
- finally
- {
- _player.broadcastPacket(new ExFishingEnd(_player, reason));
- _player.sendPacket(new ExUserInfoFishing(_player, false));
- }
- }
-
- public void stopFishing()
- {
- stopFishing(FishingEndType.PLAYER_STOP);
- }
-
- public synchronized void stopFishing(FishingEndType endType)
- {
- if (_isFishing)
- {
- reelIn(FishingEndReason.STOP, false);
- _isFishing = false;
- switch (endType)
- {
- case PLAYER_STOP:
- {
- _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
- break;
- }
- case PLAYER_CANCEL:
- {
- _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
- break;
- }
- }
- }
- }
-
- public ILocational getBaitLocation()
- {
- return _baitLocation;
- }
-
- private Location calculateBaitLocation()
- {
- // calculate a position in front of the player with a random distance
- final int distMin = FishingData.getInstance().getBaitDistanceMin();
- final int distMax = FishingData.getInstance().getBaitDistanceMax();
- int distance = Rnd.get(distMin, distMax);
- final double angle = Util.convertHeadingToDegree(_player.getHeading());
- final double radian = Math.toRadians(angle);
- final double sin = Math.sin(radian);
- final double cos = Math.cos(radian);
- int baitX = (int) (_player.getX() + (cos * distance));
- int baitY = (int) (_player.getY() + (sin * distance));
-
- // search for fishing zone
- L2FishingZone fishingZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
- {
- if (zone instanceof L2FishingZone)
- {
- fishingZone = (L2FishingZone) zone;
- break;
- }
- }
- // search for water zone
- L2WaterZone waterZone = null;
- for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
- {
- if (zone instanceof L2WaterZone)
- {
- waterZone = (L2WaterZone) zone;
- break;
- }
- }
-
- int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
- if (baitZ == Integer.MIN_VALUE)
- {
- _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
- return null;
- }
-
- return new Location(baitX, baitY, baitZ);
- }
-
- /**
- * Computes the Z of the bait.
- * @param player the player
- * @param baitX the bait x
- * @param baitY the bait y
- * @param fishingZone the fishing zone
- * @param waterZone the water zone
- * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
- */
- private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
- {
- if ((fishingZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- if ((waterZone == null))
- {
- return Integer.MIN_VALUE;
- }
-
- // always use water zone, fishing zone high z is high in the air...
- final int baitZ = waterZone.getWaterZ();
-
- // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
- //
- // return Integer.MIN_VALUE;
- // }
-
- if (GeoEngine.getInstance().hasGeo(baitX, baitY))
- {
- if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
-
- if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
- {
- return Integer.MIN_VALUE;
- }
- }
-
- return baitZ;
- }
-}
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.concurrent.ScheduledFuture;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.l2jmobius.Config;
+import com.l2jmobius.commons.concurrent.ThreadPool;
+import com.l2jmobius.commons.util.Rnd;
+import com.l2jmobius.gameserver.data.xml.impl.FishingData;
+import com.l2jmobius.gameserver.enums.ShotType;
+import com.l2jmobius.gameserver.geoengine.GeoEngine;
+import com.l2jmobius.gameserver.instancemanager.ZoneManager;
+import com.l2jmobius.gameserver.model.Location;
+import com.l2jmobius.gameserver.model.PcCondOverride;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.events.EventDispatcher;
+import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerFishing;
+import com.l2jmobius.gameserver.model.interfaces.ILocational;
+import com.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
+import com.l2jmobius.gameserver.model.items.type.WeaponType;
+import com.l2jmobius.gameserver.model.zone.L2ZoneType;
+import com.l2jmobius.gameserver.model.zone.ZoneId;
+import com.l2jmobius.gameserver.model.zone.type.L2FishingZone;
+import com.l2jmobius.gameserver.model.zone.type.L2WaterZone;
+import com.l2jmobius.gameserver.network.SystemMessageId;
+import com.l2jmobius.gameserver.network.serverpackets.ActionFailed;
+import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
+import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndReason;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingEnd.FishingEndType;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExFishingStart;
+import com.l2jmobius.gameserver.network.serverpackets.fishing.ExUserInfoFishing;
+import com.l2jmobius.gameserver.util.Util;
+
+/**
+ * @author bit
+ */
+public class Fishing
+{
+ protected static final Logger LOGGER = Logger.getLogger(Fishing.class.getName());
+ private volatile ILocational _baitLocation = new Location(0, 0, 0);
+
+ private final L2PcInstance _player;
+ private ScheduledFuture> _reelInTask;
+ private ScheduledFuture> _startFishingTask;
+ private boolean _isFishing = false;
+
+ public Fishing(L2PcInstance player)
+ {
+ _player = player;
+ }
+
+ public synchronized boolean isFishing()
+ {
+ return _isFishing;
+ }
+
+ public boolean isAtValidLocation()
+ {
+ // TODO: implement checking direction
+ // if (calculateBaitLocation() == null)
+ // {
+ // return false;
+ // }
+ return _player.isInsideZone(ZoneId.FISHING);
+ }
+
+ public boolean canFish()
+ {
+ return !_player.isDead() && !_player.isAlikeDead() && !_player.hasBlockActions() && !_player.isSitting();
+ }
+
+ private FishingBait getCurrentBaitData()
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ return bait != null ? FishingData.getInstance().getBaitData(bait.getId()) : null;
+ }
+
+ private void cancelTasks()
+ {
+ if (_reelInTask != null)
+ {
+ _reelInTask.cancel(false);
+ _reelInTask = null;
+ }
+
+ if (_startFishingTask != null)
+ {
+ _startFishingTask.cancel(false);
+ _startFishingTask = null;
+ }
+ }
+
+ public synchronized void startFishing()
+ {
+ if (_isFishing)
+ {
+ return;
+ }
+ _isFishing = true;
+ castLine();
+ }
+
+ private void castLine()
+ {
+ if (!Config.ALLOW_FISHING && !_player.canOverrideCond(PcCondOverride.ZONE_CONDITIONS))
+ {
+ _player.sendMessage("Fishing is disabled.");
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ cancelTasks();
+
+ if (!canFish())
+ {
+ if (_isFishing)
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_MUST_PUT_BAIT_ON_YOUR_HOOK_BEFORE_YOU_CAN_FISH);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (Config.PREMIUM_SYSTEM_ENABLED)
+ {
+ if (Config.PREMIUM_ONLY_FISHING && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.C1_CANNOT_DUEL_BECAUSE_C1_IS_CURRENTLY_FISHING);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (baitData.isPremiumOnly() && !_player.hasPremiumStatus())
+ {
+ _player.sendPacket(SystemMessageId.FAILED_PLEASE_TRY_AGAIN_USING_THE_CORRECT_BAIT);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+ }
+
+ final int minPlayerLevel = baitData.getMinPlayerLevel();
+ final int maxPLayerLevel = baitData.getMaxPlayerLevel();
+ if ((_player.getLevel() < minPlayerLevel) && (_player.getLevel() > maxPLayerLevel))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_FISHING_LEVEL_REQUIREMENTS);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final L2ItemInstance rod = _player.getActiveWeaponInstance();
+ if ((rod == null) || (rod.getItemType() != WeaponType.FISHINGROD))
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ final FishingRod rodData = FishingData.getInstance().getRodData(rod.getId());
+ if (rodData == null)
+ {
+ _player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_A_FISHING_POLE_EQUIPPED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isTransformed() || _player.isInBoat())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_RIDING_AS_A_PASSENGER_OF_A_BOAT_OR_TRANSFORMED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isCrafting() || _player.isInStoreMode())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_USING_A_RECIPE_BOOK_PRIVATE_WORKSHOP_OR_PRIVATE_STORE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (_player.isInsideZone(ZoneId.WATER) || _player.isInWater())
+ {
+ _player.sendPacket(SystemMessageId.YOU_CANNOT_FISH_WHILE_UNDER_WATER);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ _baitLocation = calculateBaitLocation();
+ if (!_player.isInsideZone(ZoneId.FISHING) || (_baitLocation == null))
+ {
+ if (_isFishing)
+ {
+ // _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ else
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
+ _player.sendPacket(ActionFailed.STATIC_PACKET);
+ }
+ stopFishing(FishingEndType.ERROR);
+ return;
+ }
+
+ if (!_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ _player.rechargeShots(false, false, true);
+ }
+
+ final long fishingTime = Math.max(Rnd.get(baitData.getTimeMin(), baitData.getTimeMax()) - rodData.getReduceFishingTime(), 1000);
+ final long fishingWaitTime = Rnd.get(baitData.getWaitMin(), baitData.getWaitMax());
+
+ _reelInTask = ThreadPool.schedule(() ->
+ {
+ _player.getFishing().reelInWithReward();
+ _startFishingTask = ThreadPool.schedule(() -> _player.getFishing().castLine(), fishingWaitTime);
+ }, fishingTime);
+ _player.stopMove(null);
+ _player.broadcastPacket(new ExFishingStart(_player, -1, _baitLocation));
+ _player.sendPacket(new ExUserInfoFishing(_player, true, _baitLocation));
+ _player.sendPacket(new PlaySound("SF_P_01"));
+ _player.sendPacket(SystemMessageId.YOU_CAST_YOUR_LINE_AND_START_TO_FISH);
+ }
+
+ public void reelInWithReward()
+ {
+ // Fish may or may not eat the hook. If it does - it consumes fishing bait and fishing shot.
+ // Then player may or may not catch the fish. Using fishing shots increases chance to win.
+ final FishingBait baitData = getCurrentBaitData();
+ if (baitData == null)
+ {
+ reelIn(FishingEndReason.LOSE, false);
+ LOGGER.warning("Player " + _player + " is fishing with unhandled bait: " + _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND));
+ return;
+ }
+
+ double chance = baitData.getChance();
+ if (_player.isChargedShot(ShotType.FISH_SOULSHOTS))
+ {
+ chance *= 2;
+ }
+
+ if (Rnd.get(100) <= chance)
+ {
+ reelIn(FishingEndReason.WIN, true);
+ }
+ else
+ {
+ reelIn(FishingEndReason.LOSE, true);
+ }
+ }
+
+ private void reelIn(FishingEndReason reason, boolean consumeBait)
+ {
+ if (!_isFishing)
+ {
+ return;
+ }
+
+ cancelTasks();
+
+ try
+ {
+ final L2ItemInstance bait = _player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LHAND);
+ if (consumeBait)
+ {
+ if ((bait == null) || !_player.getInventory().updateItemCount(null, bait, -1, _player, null))
+ {
+ reason = FishingEndReason.LOSE; // no bait - no reward
+ return;
+ }
+ }
+
+ if ((reason == FishingEndReason.WIN) && (bait != null))
+ {
+ final FishingBait baitData = FishingData.getInstance().getBaitData(bait.getId());
+ final FishingCatch fishingCatchData = baitData.getRandom();
+ if (fishingCatchData != null)
+ {
+ final FishingData fishingData = FishingData.getInstance();
+ final double lvlModifier = (Math.pow(_player.getLevel(), 2.2) * fishingCatchData.getMultiplier());
+ final long xp = (long) (Rnd.get(fishingData.getExpRateMin(), fishingData.getExpRateMax()) * lvlModifier);
+ final long sp = (long) (Rnd.get(fishingData.getSpRateMin(), fishingData.getSpRateMax()) * lvlModifier);
+ _player.addExpAndSp(xp, sp, true);
+ _player.getInventory().addItem("Fishing Reward", fishingCatchData.getItemId(), 1, _player, null);
+ final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S1);
+ msg.addItemName(fishingCatchData.getItemId());
+ _player.sendPacket(msg);
+ _player.unchargeShot(ShotType.FISH_SOULSHOTS);
+ _player.rechargeShots(false, false, true);
+ }
+ else
+ {
+ LOGGER.log(Level.WARNING, "Could not find fishing rewards for bait ", bait.getId());
+ }
+ }
+ else if (reason == FishingEndReason.LOSE)
+ {
+ _player.sendPacket(SystemMessageId.THE_BAIT_HAS_BEEN_LOST_BECAUSE_THE_FISH_GOT_AWAY);
+ }
+
+ if (consumeBait)
+ {
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerFishing(_player, reason), _player);
+ }
+ }
+ finally
+ {
+ _player.broadcastPacket(new ExFishingEnd(_player, reason));
+ _player.sendPacket(new ExUserInfoFishing(_player, false));
+ }
+ }
+
+ public void stopFishing()
+ {
+ stopFishing(FishingEndType.PLAYER_STOP);
+ }
+
+ public synchronized void stopFishing(FishingEndType endType)
+ {
+ if (_isFishing)
+ {
+ reelIn(FishingEndReason.STOP, false);
+ _isFishing = false;
+ switch (endType)
+ {
+ case PLAYER_STOP:
+ {
+ _player.sendPacket(SystemMessageId.YOU_REEL_YOUR_LINE_IN_AND_STOP_FISHING);
+ break;
+ }
+ case PLAYER_CANCEL:
+ {
+ _player.sendPacket(SystemMessageId.YOUR_ATTEMPT_AT_FISHING_HAS_BEEN_CANCELLED);
+ break;
+ }
+ }
+ }
+ }
+
+ public ILocational getBaitLocation()
+ {
+ return _baitLocation;
+ }
+
+ private Location calculateBaitLocation()
+ {
+ // calculate a position in front of the player with a random distance
+ final int distMin = FishingData.getInstance().getBaitDistanceMin();
+ final int distMax = FishingData.getInstance().getBaitDistanceMax();
+ int distance = Rnd.get(distMin, distMax);
+ final double angle = Util.convertHeadingToDegree(_player.getHeading());
+ final double radian = Math.toRadians(angle);
+ final double sin = Math.sin(radian);
+ final double cos = Math.cos(radian);
+ int baitX = (int) (_player.getX() + (cos * distance));
+ int baitY = (int) (_player.getY() + (sin * distance));
+
+ // search for fishing zone
+ L2FishingZone fishingZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(_player))
+ {
+ if (zone instanceof L2FishingZone)
+ {
+ fishingZone = (L2FishingZone) zone;
+ break;
+ }
+ }
+ // search for water zone
+ L2WaterZone waterZone = null;
+ for (L2ZoneType zone : ZoneManager.getInstance().getZones(baitX, baitY))
+ {
+ if (zone instanceof L2WaterZone)
+ {
+ waterZone = (L2WaterZone) zone;
+ break;
+ }
+ }
+
+ int baitZ = computeBaitZ(_player, baitX, baitY, fishingZone, waterZone);
+ if (baitZ == Integer.MIN_VALUE)
+ {
+ _player.sendPacket(SystemMessageId.YOU_CAN_T_FISH_HERE);
+ return null;
+ }
+
+ return new Location(baitX, baitY, baitZ);
+ }
+
+ /**
+ * Computes the Z of the bait.
+ * @param player the player
+ * @param baitX the bait x
+ * @param baitY the bait y
+ * @param fishingZone the fishing zone
+ * @param waterZone the water zone
+ * @return the bait z or {@link Integer#MIN_VALUE} when you cannot fish here
+ */
+ private static int computeBaitZ(L2PcInstance player, int baitX, int baitY, L2FishingZone fishingZone, L2WaterZone waterZone)
+ {
+ if ((fishingZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if ((waterZone == null))
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ // always use water zone, fishing zone high z is high in the air...
+ final int baitZ = waterZone.getWaterZ();
+
+ // if (!GeoEngine.getInstance().canSeeTarget(player.getX(), player.getY(), player.getZ(), baitX, baitY, baitZ))
+ //
+ // return Integer.MIN_VALUE;
+ // }
+
+ if (GeoEngine.getInstance().hasGeo(baitX, baitY))
+ {
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, baitZ) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+
+ if (GeoEngine.getInstance().getHeight(baitX, baitY, player.getZ()) > baitZ)
+ {
+ return Integer.MIN_VALUE;
+ }
+ }
+
+ return baitZ;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
new file mode 100644
index 0000000000..f5a5764254
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/fishing/FishingBait.java
@@ -0,0 +1,128 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.l2jmobius.commons.util.Rnd;
+
+/**
+ * @author bit
+ */
+public class FishingBait
+{
+ private final int _itemId;
+ private final byte _level;
+ private final byte _minPlayerLevel;
+ private final byte _maxPlayerLevel;
+ private final double _chance;
+ private final int _timeMin;
+ private final int _timeMax;
+ private final int _waitMin;
+ private final int _waitMax;
+ private final boolean _isPremiumOnly;
+ private final List _rewards = new ArrayList<>();
+
+ public FishingBait(int itemId, byte level, byte minPlayerLevel, byte maxPlayerLevel, double chance, int timeMin, int timeMax, int waitMin, int waitMax, boolean isPremiumOnly)
+ {
+ _itemId = itemId;
+ _level = level;
+ _minPlayerLevel = minPlayerLevel;
+ _maxPlayerLevel = maxPlayerLevel;
+ _chance = chance;
+ _timeMin = timeMin;
+ _timeMax = timeMax;
+ _waitMin = waitMin;
+ _waitMax = waitMax;
+ _isPremiumOnly = isPremiumOnly;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public byte getLevel()
+ {
+ return _level;
+ }
+
+ public byte getMinPlayerLevel()
+ {
+ return _minPlayerLevel;
+ }
+
+ public byte getMaxPlayerLevel()
+ {
+ return _maxPlayerLevel;
+ }
+
+ public double getChance()
+ {
+ return _chance;
+ }
+
+ public int getTimeMin()
+ {
+ return _timeMin;
+ }
+
+ public int getTimeMax()
+ {
+ return _timeMax;
+ }
+
+ public int getWaitMin()
+ {
+ return _waitMin;
+ }
+
+ public int getWaitMax()
+ {
+ return _waitMax;
+ }
+
+ public boolean isPremiumOnly()
+ {
+ return _isPremiumOnly;
+ }
+
+ public List getRewards()
+ {
+ return _rewards;
+ }
+
+ public void addReward(FishingCatch catchData)
+ {
+ _rewards.add(catchData);
+ }
+
+ public FishingCatch getRandom()
+ {
+ float random = Rnd.get(100);
+ for (FishingCatch fishingCatchData : _rewards)
+ {
+ if (fishingCatchData.getChance() > random)
+ {
+ return fishingCatchData;
+ }
+ random -= fishingCatchData.getChance();
+ }
+ return null;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
new file mode 100644
index 0000000000..85c2e42e5a
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/fishing/FishingCatch.java
@@ -0,0 +1,49 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingCatch
+{
+ private final int _itemId;
+ private final float _chance;
+ private final float _multiplier;
+
+ public FishingCatch(int itemId, float chance, float multiplier)
+ {
+ _itemId = itemId;
+ _chance = chance;
+ _multiplier = multiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public float getChance()
+ {
+ return _chance;
+ }
+
+ public float getMultiplier()
+ {
+ return _multiplier;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
new file mode 100644
index 0000000000..93b5fb9b8e
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/fishing/FishingRod.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.l2jmobius.gameserver.model.fishing;
+
+/**
+ * @author Zarcos
+ */
+public class FishingRod
+{
+ private final int _itemId;
+ private final int _reduceFishingTime;
+ private final float _xpMultiplier;
+ private final float _spMultiplier;
+
+ public FishingRod(int itemId, int reduceFishingTime, float xpMultiplier, float spMultiplier)
+ {
+ _itemId = itemId;
+ _reduceFishingTime = reduceFishingTime;
+ _xpMultiplier = xpMultiplier;
+ _spMultiplier = spMultiplier;
+ }
+
+ public int getItemId()
+ {
+ return _itemId;
+ }
+
+ public int getReduceFishingTime()
+ {
+ return _reduceFishingTime;
+ }
+
+ public float getXpMultiplier()
+ {
+ return _xpMultiplier;
+ }
+
+ public float getSpMultiplier()
+ {
+ return _spMultiplier;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
index 71d8f10b3e..dfcf4d7f56 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/model/zone/type/L2FishingZone.java
@@ -20,10 +20,10 @@ import java.lang.ref.WeakReference;
import com.l2jmobius.Config;
import com.l2jmobius.commons.concurrent.ThreadPool;
-import com.l2jmobius.gameserver.model.Fishing;
import com.l2jmobius.gameserver.model.PcCondOverride;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.model.fishing.Fishing;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.serverpackets.fishing.ExAutoFishAvailable;
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
index dea11bad61..cebaa3c7a5 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/com/l2jmobius/gameserver/network/serverpackets/fishing/ExFishingStart.java
@@ -29,20 +29,17 @@ public class ExFishingStart implements IClientOutgoingPacket
{
private final L2PcInstance _player;
private final int _fishType;
- private final int _baitType;
private final ILocational _baitLocation;
/**
* @param player
* @param fishType
- * @param baitType - 0 = newbie, 1 = normal, 2 = night
* @param baitLocation
*/
- public ExFishingStart(L2PcInstance player, int fishType, int baitType, ILocational baitLocation)
+ public ExFishingStart(L2PcInstance player, int fishType, ILocational baitLocation)
{
_player = player;
_fishType = fishType;
- _baitType = baitType;
_baitLocation = baitLocation;
}
@@ -55,7 +52,7 @@ public class ExFishingStart implements IClientOutgoingPacket
packet.writeD(_baitLocation.getX());
packet.writeD(_baitLocation.getY());
packet.writeD(_baitLocation.getZ());
- packet.writeC(_baitType);
+ packet.writeC(0x01); // 0 = newbie, 1 = normal, 2 = night
return true;
}
}