diff --git a/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/events/LetterCollector/LetterCollector.java b/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/events/LetterCollector/LetterCollector.java index 9343546f2b..a181a33a0f 100644 --- a/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/events/LetterCollector/LetterCollector.java +++ b/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/events/LetterCollector/LetterCollector.java @@ -16,22 +16,122 @@ */ package events.LetterCollector; +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import org.w3c.dom.Document; + +import org.l2jmobius.commons.util.IXmlReader; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; +import org.l2jmobius.gameserver.model.StatSet; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.events.EventType; import org.l2jmobius.gameserver.model.events.ListenerRegisterType; import org.l2jmobius.gameserver.model.events.annotations.RegisterEvent; import org.l2jmobius.gameserver.model.events.annotations.RegisterType; import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin; +import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.quest.LongTimeEvent; import org.l2jmobius.gameserver.network.serverpackets.ExLetterCollectorUI; /** * @author Mobius */ -public class LetterCollector extends LongTimeEvent +public class LetterCollector extends LongTimeEvent implements IXmlReader { private LetterCollector() { + if (isEventPeriod()) + { + load(); + LetterCollectorManager.getInstance().init(); + } + } + + public void reloadRewards() + { + LetterCollectorManager.getInstance().resetField(); + load(); + } + + @Override + public synchronized void load() + { + parseDatapackFile("data/scripts/events/LetterCollector/rewards.xml"); + } + + @Override + public void parseDocument(Document doc, File f) + { + final AtomicInteger minimumLevel = new AtomicInteger(); + final AtomicInteger maximumLevel = new AtomicInteger(); + final Map letters = new HashMap<>(); + forEach(doc, "list", listNode -> + { + forEach(listNode, "params", paramNode -> + { + forEach(paramNode, "minimum", minimumLevelNode -> minimumLevel.set(new StatSet(parseAttributes(minimumLevelNode)).getInt("level"))); + forEach(paramNode, "maximum", maximumLevelNode -> maximumLevel.set(new StatSet(parseAttributes(maximumLevelNode)).getInt("level"))); + }); + forEach(listNode, "letters", letterNode -> forEach(letterNode, "item", itemNode -> + { + StatSet letterSet = new StatSet(parseAttributes(itemNode)); + letters.put(letterSet.getString("name"), letterSet.getInt("id")); + })); + forEach(listNode, "reward", rewardNode -> + { + final int id = new StatSet(parseAttributes(rewardNode)).getInt("id"); + final AtomicReference> word = new AtomicReference<>(new ArrayList<>()); + final AtomicReference> rewards = new AtomicReference<>(new ArrayList<>()); + AtomicBoolean needToSumAllChance = new AtomicBoolean(false); + AtomicReference chanceSum = new AtomicReference<>(0.0); + forEach(rewardNode, "word", wordNode -> + { + String[] letter = wordNode.getTextContent().trim().split(";"); + for (String token : letter) + { + int count = 1; + for (ItemHolder check : word.get()) + { + if (check.getId() == letters.get(token)) + { + count = Math.toIntExact(check.getCount() + 1); + word.get().remove(check); + break; + } + } + word.get().add(new ItemHolder(letters.get(token), count)); + } + }); + forEach(rewardNode, "rewards", rewardsNode -> + { + needToSumAllChance.set(new StatSet(parseAttributes(rewardsNode)).getBoolean("sumChances")); + forEach(rewardsNode, "item", itemNode -> + { + StatSet itemSet = new StatSet(parseAttributes(itemNode)); + final double chance = itemSet.getDouble("chance"); + if (needToSumAllChance.get()) + { + chanceSum.set(chanceSum.get() + chance); + } + rewards.get().add(new ItemChanceHolder(itemSet.getInt("id"), chance, itemSet.getLong("count"), (byte) itemSet.getInt("enchantLevel", 0))); + }); + }); + LetterCollectorManager lcm = LetterCollectorManager.getInstance(); + lcm.addWords(id, word.get()); + lcm.addRewards(id, new LetterCollectorManager.LetterCollectorRewardHolder(rewards.get(), chanceSum.get() == 0d ? 100d : chanceSum.get())); + lcm.setLetters(letters); + lcm.setMinLevel(minimumLevel.get()); + lcm.setMaxLevel(maximumLevel.get()); + }); + }); } @RegisterEvent(EventType.ON_PLAYER_LOGIN) @@ -46,7 +146,7 @@ public class LetterCollector extends LongTimeEvent final Player player = event.getPlayer(); if (player != null) { - player.sendPacket(ExLetterCollectorUI.STATIC_PACKET); + player.sendPacket(new ExLetterCollectorUI(player)); } } diff --git a/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/events/LetterCollector/config.xml b/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/events/LetterCollector/config.xml index 44bb3fbde5..fb0bdb5a6b 100644 --- a/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/events/LetterCollector/config.xml +++ b/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/events/LetterCollector/config.xml @@ -1,7 +1,5 @@ - - diff --git a/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/events/LetterCollector/rewards.xml b/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/events/LetterCollector/rewards.xml new file mode 100644 index 0000000000..5069a9668e --- /dev/null +++ b/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/events/LetterCollector/rewards.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + L;I;N;E;A;G;E;II + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D;E;A;T;H + + + + + + + + + + + + + + + + + + + + + + + + + + + + + K;N;I;G;H;T + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/events/LetterCollector/rewards.xsd b/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/events/LetterCollector/rewards.xsd new file mode 100644 index 0000000000..5d9feae899 --- /dev/null +++ b/L2J_Mobius_10.1_MasterClass/dist/game/data/scripts/events/LetterCollector/rewards.xsd @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java new file mode 100644 index 0000000000..a90c9e0753 --- /dev/null +++ b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java @@ -0,0 +1,169 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.l2jmobius.gameserver.instancemanager.events; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import org.l2jmobius.Config; +import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; + +/** + * @author Index + */ +public class LetterCollectorManager +{ + protected static final Logger LOGGER = Logger.getLogger(LetterCollectorManager.class.getName()); + + private final Map _rewards = new HashMap<>(); + private final Map> _words = new HashMap<>(); + private final Map _letter = new HashMap<>(); + private final Map _needToSumAllChance = new HashMap<>(); + + private int _minLevel = 1; + private int _maxLevel = Config.PLAYER_MAXIMUM_LEVEL; + + protected LetterCollectorManager() + { + } + + public void init() + { + LOGGER.info(getClass().getSimpleName() + ": Loaded " + _rewards.size() + " words."); + LOGGER.info(getClass().getSimpleName() + ": Loaded " + _letter.size() + " letters."); + } + + public int getMinLevel() + { + return _minLevel; + } + + public void setMinLevel(int minLevel) + { + _minLevel = minLevel; + } + + public int getMaxLevel() + { + return _maxLevel; + } + + public void setMaxLevel(int maxLevel) + { + if (maxLevel < 1) + { + _maxLevel = Config.PLAYER_MAXIMUM_LEVEL; + } + else + { + _maxLevel = maxLevel; + } + } + + public LetterCollectorRewardHolder getRewards(int id) + { + return _rewards.get(id); + } + + public List getWord(int id) + { + return _words.get(id); + } + + public void setRewards(Map rewards) + { + _rewards.putAll(rewards); + } + + public void setWords(Map> words) + { + _words.putAll(words); + } + + public void addRewards(int id, LetterCollectorRewardHolder rewards) + { + _rewards.put(id, rewards); + } + + public void addWords(int id, List words) + { + _words.put(id, words); + } + + public void resetField() + { + _minLevel = 1; + _rewards.clear(); + _words.clear(); + _needToSumAllChance.clear(); + } + + public void setLetters(Map letters) + { + _letter.putAll(letters); + } + + public Map getLetters() + { + return _letter; + } + + public void setNeedToSumAllChance(int id, boolean needToSumAllChance) + { + _needToSumAllChance.put(id, needToSumAllChance); + } + + public boolean getNeedToSumAllChance(int id) + { + return _needToSumAllChance.get(id); + } + + public static class LetterCollectorRewardHolder + { + final List _rewards; + final double _chance; + + public LetterCollectorRewardHolder(List rewards, double chance) + { + _rewards = rewards; + _chance = chance; + } + + public List getRewards() + { + return _rewards; + } + + public double getChance() + { + return _chance; + } + } + + public static LetterCollectorManager getInstance() + { + return SingletonHolder.INSTANCE; + } + + private static class SingletonHolder + { + protected static final LetterCollectorManager INSTANCE = new LetterCollectorManager(); + } +} \ No newline at end of file diff --git a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java index 8d5d8a312e..b1e8c6b991 100644 --- a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java +++ b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java @@ -16,120 +16,24 @@ */ package org.l2jmobius.gameserver.network.clientpackets; +import java.util.List; + import org.l2jmobius.commons.network.PacketReader; import org.l2jmobius.commons.util.Rnd; -import org.l2jmobius.gameserver.data.ItemTable; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.itemcontainer.PlayerInventory; import org.l2jmobius.gameserver.network.GameClient; +import org.l2jmobius.gameserver.network.SystemMessageId; +import org.l2jmobius.gameserver.network.serverpackets.SystemMessage; /** * @author Index, Mobius */ public class ExLetterCollectorTakeReward implements IClientIncomingPacket { - // Items - private static final int A = 3875; - private static final int E = 3877; - private static final int G = 3879; - private static final int I = 3881; - private static final int L = 3882; - private static final int N = 3883; - private static final int O = 3884; - private static final int T = 3886; - private static final int H = 3880; - private static final int II = 3888; - private static final int W = 22894; - private static final int D = 29545; - private static final int P = 29825; - - // Rewards - private static final ItemChanceHolder[] LINEAGE_II_REWARDS = - { - new ItemChanceHolder(80333, 5, 1), // Dragon Necklace - new ItemChanceHolder(80334, 5, 1), // Dragon Earring - new ItemChanceHolder(80335, 5, 1), // Dragon Ring - new ItemChanceHolder(48296, 5, 1), // +10 Eternal Light Armor Capsule - new ItemChanceHolder(48297, 5, 1), // +10 Eternal Robe Capsule - new ItemChanceHolder(48295, 5, 1), // +10 Eternal Heavy Armor Capsule - new ItemChanceHolder(39573, 5, 1), // Sealed Talisman - Insanity - new ItemChanceHolder(37716, 5, 1), // Seven Signs' Energy - new ItemChanceHolder(80416, 5, 1), // Fortune Box of 10 Billion Adena - new ItemChanceHolder(36414, 5, 1), // Dragon Claw - new ItemChanceHolder(47705, 15, 1), // Blue Cat's Eye Lv. 3 Jewelry Box - new ItemChanceHolder(47627, 15, 1), // Sapphire Lv. 3 Jewelry Box - new ItemChanceHolder(47626, 15, 1), // Ruby Lv. 3 Jewelry Box - new ItemChanceHolder(47703, 15, 1), // Red Cat's Eye Lv. 3 Jewelry Box - new ItemChanceHolder(47629, 15, 1), // Opal Lv. 3 Jewelry Box - new ItemChanceHolder(28360, 15, 1), // Cat's Eye Lv. 3 Jewelry Box - new ItemChanceHolder(28362, 15, 1), // Amethyst Lv. 3 Jewelry Box - new ItemChanceHolder(47631, 15, 1), // Diamond Lv. 3 Jewelry Box - new ItemChanceHolder(47634, 15, 1), // Pearl Lv. 3 Jewelry Box - new ItemChanceHolder(47635, 15, 1), // Vital Stone Lv. 3 Jewelry Box - new ItemChanceHolder(47630, 15, 1), // Obsidian Lv. 3 Jewelry Box - new ItemChanceHolder(47633, 15, 1), // Aquamarine Lv. 3 Jewelry Box - new ItemChanceHolder(80423, 30, 1), // Balance Artifact Box - new ItemChanceHolder(80420, 30, 1), // Attack Artifact Box - new ItemChanceHolder(80421, 30, 1), // Protection Artifact Box - new ItemChanceHolder(80422, 30, 1), // Support Artifact Box - new ItemChanceHolder(39374, 30, 1), // Scroll: 5.000.000 SP - new ItemChanceHolder(46274, 30, 1), // Wind Vitality Tonic - new ItemChanceHolder(35563, 30, 1), // Giant's Energy - new ItemChanceHolder(38761, 30, 1), // Energy of Destruction 3-unit Pack - new ItemChanceHolder(36513, 30, 1), // Elcyum Powder - new ItemChanceHolder(27673, 30, 1), // Freya's Scroll of Storm - }; - private static final ItemChanceHolder[] DEATH_REWARDS = - { - new ItemChanceHolder(47821, 5, 1), // Sayha's Talisman Lv. 10 - new ItemChanceHolder(47820, 5, 1), // Sayha's Talisman Lv. 9 - new ItemChanceHolder(37717, 5, 1), // Talisman - Seven Signs - new ItemChanceHolder(39572, 5, 1), // Talisman - Insanity - new ItemChanceHolder(48032, 5, 1), // Sayha's Talisman Lv. 8 - new ItemChanceHolder(80416, 5, 1), // Fortune Box of 10 Billion Adena - new ItemChanceHolder(28448, 5, 1), // Sayha's Talisman Lv. 7 - new ItemChanceHolder(37715, 5, 1), // Talisman - Anakim - new ItemChanceHolder(35649, 15, 1), // Sealed Talisman - Longing - new ItemChanceHolder(29152, 15, 1), // High-grade Zodiac Agathion Pack - new ItemChanceHolder(29151, 15, 1), // Mid-grade Zodiac Agathion Pack - new ItemChanceHolder(28373, 15, 1), // Tanzenite Lv. 3 Jewelry Box - new ItemChanceHolder(47632, 15, 1), // Emerald Lv. 3 Jewelry Box - new ItemChanceHolder(47636, 15, 1), // Garnet Lv. 3 Jewelry Box - new ItemChanceHolder(80423, 30, 1), // Balance Artifact Box - new ItemChanceHolder(80420, 30, 1), // Attack Artifact Box - new ItemChanceHolder(80421, 30, 1), // Protection Artifact Box - new ItemChanceHolder(80422, 30, 1), // Support Artifact Box - new ItemChanceHolder(39374, 30, 1), // Scroll: 5.000.000 SP - new ItemChanceHolder(46274, 30, 1), // Wind Vitality Tonic - new ItemChanceHolder(35563, 30, 1), // Giant's Energy - new ItemChanceHolder(38761, 30, 1), // Energy of Destruction 3-unit Pack - new ItemChanceHolder(36513, 30, 1), // Elcyum Powder - new ItemChanceHolder(27673, 30, 1), // Freya's Scroll of Storm - }; - private static final ItemChanceHolder[] KNIGHT_REWARDS = - { - new ItemChanceHolder(80416, 5, 1), // Fortune Box of 10 Billion Adena - new ItemChanceHolder(28448, 5, 1), // Sayha's Talisman Lv. 7 - new ItemChanceHolder(26291, 5, 1), // Kaliel's Energy - Longing - new ItemChanceHolder(36731, 5, 1), // Life Stone: Giant's Power - new ItemChanceHolder(37714, 5, 1), // Talisman - Lilith - new ItemChanceHolder(29150, 15, 1), // Low-grade Zodiac Agathion Pack - new ItemChanceHolder(80423, 30, 1), // Balance Artifact Box - new ItemChanceHolder(80420, 30, 1), // Attack Artifact Box - new ItemChanceHolder(80421, 30, 1), // Protection Artifact Box - new ItemChanceHolder(80422, 30, 1), // Support Artifact Box - new ItemChanceHolder(36515, 15, 1), // Elcyum - new ItemChanceHolder(48215, 30, 1), // Circlet Spirit Stone - new ItemChanceHolder(28540, 30, 1), // Magnificent Brooch Spirit Stone - new ItemChanceHolder(36514, 30, 1), // Elcyum Crystal - new ItemChanceHolder(39374, 30, 1), // Scroll: 5.000.000 SP - new ItemChanceHolder(46274, 30, 1), // Wind Vitality Tonic - new ItemChanceHolder(35563, 30, 1), // Giant's Energy - new ItemChanceHolder(38761, 30, 1), // Energy of Destruction 3-unit Pack - new ItemChanceHolder(27673, 30, 1), // Freya's Scroll of Storm - }; - private int _wordId; @Override @@ -154,95 +58,53 @@ public class ExLetterCollectorTakeReward implements IClientIncomingPacket return; } - switch (_wordId) + final LetterCollectorManager.LetterCollectorRewardHolder lcrh = LetterCollectorManager.getInstance().getRewards(_wordId); + if (lcrh == null) { - case 0: + return; + } + + for (ItemHolder needLetter : LetterCollectorManager.getInstance().getWord(_wordId)) + { + if (inventory.getInventoryItemCount(needLetter.getId(), -1) < needLetter.getCount()) { - if ((inventory.getInventoryItemCount(L, -1) < 1) || // - (inventory.getInventoryItemCount(I, -1) < 1) || // - (inventory.getInventoryItemCount(N, -1) < 1) || // - (inventory.getInventoryItemCount(E, -1) < 2) || // - (inventory.getInventoryItemCount(A, -1) < 1) || // - (inventory.getInventoryItemCount(G, -1) < 1) || // - (inventory.getInventoryItemCount(II, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", L, 1, player, true); - player.destroyItemByItemId("LetterCollector", I, 1, player, true); - player.destroyItemByItemId("LetterCollector", N, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", A, 1, player, true); - player.destroyItemByItemId("LetterCollector", G, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", II, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(LINEAGE_II_REWARDS), player, true); - break; - } - case 1: - { - if ((inventory.getInventoryItemCount(N, -1) < 2) || // - (inventory.getInventoryItemCount(E, -1) < 3) || // - (inventory.getInventoryItemCount(W, -1) < 1) || // - (inventory.getInventoryItemCount(L, -1) < 1) || // - (inventory.getInventoryItemCount(G, -1) < 1) || // - (inventory.getInventoryItemCount(D, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", N, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", W, 1, player, true); - player.destroyItemByItemId("LetterCollector", L, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", G, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", N, 1, player, true); - player.destroyItemByItemId("LetterCollector", D, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(DEATH_REWARDS), player, true); - break; - } - case 2: - { - if ((inventory.getInventoryItemCount(T, -1) < 3) || // - (inventory.getInventoryItemCount(O, -1) < 2) || // - (inventory.getInventoryItemCount(H, -1) < 1) || // - (inventory.getInventoryItemCount(E, -1) < 1) || // - (inventory.getInventoryItemCount(P, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", T, 1, player, true); - player.destroyItemByItemId("LetterCollector", O, 1, player, true); - player.destroyItemByItemId("LetterCollector", T, 1, player, true); - player.destroyItemByItemId("LetterCollector", H, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", T, 1, player, true); - player.destroyItemByItemId("LetterCollector", O, 1, player, true); - player.destroyItemByItemId("LetterCollector", P, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(KNIGHT_REWARDS), player, true); - break; + return; } } + for (ItemHolder destroyLetter : LetterCollectorManager.getInstance().getWord(_wordId)) + { + if (!player.destroyItemByItemId("LetterCollector", destroyLetter.getId(), destroyLetter.getCount(), player, true)) + { + return; + } + } + + final ItemHolder rewardItem = getRandomReward(lcrh.getRewards(), lcrh.getChance()); + if (rewardItem == null) + { + player.sendPacket(new SystemMessage(SystemMessageId.NOTHING_HAPPENED)); + return; + } + + player.addItem("LetterCollector", rewardItem.getId(), rewardItem.getCount(), player, true); } - private ItemChanceHolder getRandomReward(ItemChanceHolder[] rewards) + private ItemHolder getRandomReward(List rewards, double holderChance) { - ItemChanceHolder reward = null; - while (reward == null) + final double chance = Rnd.get(holderChance); + double itemChance = 0; + for (ItemChanceHolder rewardItem : rewards) { - final ItemChanceHolder random = rewards[Rnd.get(rewards.length)]; - if ((Rnd.get(100) < random.getChance()) && (ItemTable.getInstance().getTemplate(random.getId()) != null)) + itemChance += rewardItem.getChance(); + if (chance <= itemChance) { - reward = random; + if (rewardItem.getId() == -1) + { + return null; + } + return rewardItem; } } - return reward; + return null; } } \ No newline at end of file diff --git a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java index 6a9f1e4eeb..991437e881 100644 --- a/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java +++ b/L2J_Mobius_10.1_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java @@ -16,7 +16,10 @@ */ package org.l2jmobius.gameserver.network.serverpackets; +import org.l2jmobius.Config; import org.l2jmobius.commons.network.PacketWriter; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; +import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.network.OutgoingPackets; /** @@ -24,12 +27,11 @@ import org.l2jmobius.gameserver.network.OutgoingPackets; */ public class ExLetterCollectorUI implements IClientOutgoingPacket { - public static final ExLetterCollectorUI STATIC_PACKET = new ExLetterCollectorUI(); + final int _minimumLevel; - private static final int LETTER_COLLECTOR_MIN_LEVEL = 95; - - private ExLetterCollectorUI() + public ExLetterCollectorUI(Player player) { + _minimumLevel = player.getLevel() <= LetterCollectorManager.getInstance().getMaxLevel() ? LetterCollectorManager.getInstance().getMinLevel() : Config.PLAYER_MAXIMUM_LEVEL; } @Override @@ -37,7 +39,7 @@ public class ExLetterCollectorUI implements IClientOutgoingPacket { OutgoingPackets.EX_LETTER_COLLECTOR_UI_LAUNCHER.writeId(packet); packet.writeC(1); // enabled (0x00 - no, 0x01 -yes) - packet.writeD(LETTER_COLLECTOR_MIN_LEVEL); // Minimum Level + packet.writeD(_minimumLevel); // Minimum Level return true; } } \ No newline at end of file diff --git a/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/events/LetterCollector/LetterCollector.java b/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/events/LetterCollector/LetterCollector.java index 9343546f2b..a181a33a0f 100644 --- a/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/events/LetterCollector/LetterCollector.java +++ b/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/events/LetterCollector/LetterCollector.java @@ -16,22 +16,122 @@ */ package events.LetterCollector; +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import org.w3c.dom.Document; + +import org.l2jmobius.commons.util.IXmlReader; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; +import org.l2jmobius.gameserver.model.StatSet; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.events.EventType; import org.l2jmobius.gameserver.model.events.ListenerRegisterType; import org.l2jmobius.gameserver.model.events.annotations.RegisterEvent; import org.l2jmobius.gameserver.model.events.annotations.RegisterType; import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin; +import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.quest.LongTimeEvent; import org.l2jmobius.gameserver.network.serverpackets.ExLetterCollectorUI; /** * @author Mobius */ -public class LetterCollector extends LongTimeEvent +public class LetterCollector extends LongTimeEvent implements IXmlReader { private LetterCollector() { + if (isEventPeriod()) + { + load(); + LetterCollectorManager.getInstance().init(); + } + } + + public void reloadRewards() + { + LetterCollectorManager.getInstance().resetField(); + load(); + } + + @Override + public synchronized void load() + { + parseDatapackFile("data/scripts/events/LetterCollector/rewards.xml"); + } + + @Override + public void parseDocument(Document doc, File f) + { + final AtomicInteger minimumLevel = new AtomicInteger(); + final AtomicInteger maximumLevel = new AtomicInteger(); + final Map letters = new HashMap<>(); + forEach(doc, "list", listNode -> + { + forEach(listNode, "params", paramNode -> + { + forEach(paramNode, "minimum", minimumLevelNode -> minimumLevel.set(new StatSet(parseAttributes(minimumLevelNode)).getInt("level"))); + forEach(paramNode, "maximum", maximumLevelNode -> maximumLevel.set(new StatSet(parseAttributes(maximumLevelNode)).getInt("level"))); + }); + forEach(listNode, "letters", letterNode -> forEach(letterNode, "item", itemNode -> + { + StatSet letterSet = new StatSet(parseAttributes(itemNode)); + letters.put(letterSet.getString("name"), letterSet.getInt("id")); + })); + forEach(listNode, "reward", rewardNode -> + { + final int id = new StatSet(parseAttributes(rewardNode)).getInt("id"); + final AtomicReference> word = new AtomicReference<>(new ArrayList<>()); + final AtomicReference> rewards = new AtomicReference<>(new ArrayList<>()); + AtomicBoolean needToSumAllChance = new AtomicBoolean(false); + AtomicReference chanceSum = new AtomicReference<>(0.0); + forEach(rewardNode, "word", wordNode -> + { + String[] letter = wordNode.getTextContent().trim().split(";"); + for (String token : letter) + { + int count = 1; + for (ItemHolder check : word.get()) + { + if (check.getId() == letters.get(token)) + { + count = Math.toIntExact(check.getCount() + 1); + word.get().remove(check); + break; + } + } + word.get().add(new ItemHolder(letters.get(token), count)); + } + }); + forEach(rewardNode, "rewards", rewardsNode -> + { + needToSumAllChance.set(new StatSet(parseAttributes(rewardsNode)).getBoolean("sumChances")); + forEach(rewardsNode, "item", itemNode -> + { + StatSet itemSet = new StatSet(parseAttributes(itemNode)); + final double chance = itemSet.getDouble("chance"); + if (needToSumAllChance.get()) + { + chanceSum.set(chanceSum.get() + chance); + } + rewards.get().add(new ItemChanceHolder(itemSet.getInt("id"), chance, itemSet.getLong("count"), (byte) itemSet.getInt("enchantLevel", 0))); + }); + }); + LetterCollectorManager lcm = LetterCollectorManager.getInstance(); + lcm.addWords(id, word.get()); + lcm.addRewards(id, new LetterCollectorManager.LetterCollectorRewardHolder(rewards.get(), chanceSum.get() == 0d ? 100d : chanceSum.get())); + lcm.setLetters(letters); + lcm.setMinLevel(minimumLevel.get()); + lcm.setMaxLevel(maximumLevel.get()); + }); + }); } @RegisterEvent(EventType.ON_PLAYER_LOGIN) @@ -46,7 +146,7 @@ public class LetterCollector extends LongTimeEvent final Player player = event.getPlayer(); if (player != null) { - player.sendPacket(ExLetterCollectorUI.STATIC_PACKET); + player.sendPacket(new ExLetterCollectorUI(player)); } } diff --git a/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/events/LetterCollector/config.xml b/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/events/LetterCollector/config.xml index 44bb3fbde5..fb0bdb5a6b 100644 --- a/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/events/LetterCollector/config.xml +++ b/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/events/LetterCollector/config.xml @@ -1,7 +1,5 @@ - - diff --git a/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/events/LetterCollector/rewards.xml b/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/events/LetterCollector/rewards.xml new file mode 100644 index 0000000000..becbe65c1c --- /dev/null +++ b/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/events/LetterCollector/rewards.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + L;I;N;E;A;G;E;II + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D;E;A;T;H + + + + + + + + + + + + + + + + + + + + + + + + + + + + + K;N;I;G;H;T + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/events/LetterCollector/rewards.xsd b/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/events/LetterCollector/rewards.xsd new file mode 100644 index 0000000000..10debf7a8b --- /dev/null +++ b/L2J_Mobius_10.2_MasterClass/dist/game/data/scripts/events/LetterCollector/rewards.xsd @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java new file mode 100644 index 0000000000..a90c9e0753 --- /dev/null +++ b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java @@ -0,0 +1,169 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.l2jmobius.gameserver.instancemanager.events; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import org.l2jmobius.Config; +import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; + +/** + * @author Index + */ +public class LetterCollectorManager +{ + protected static final Logger LOGGER = Logger.getLogger(LetterCollectorManager.class.getName()); + + private final Map _rewards = new HashMap<>(); + private final Map> _words = new HashMap<>(); + private final Map _letter = new HashMap<>(); + private final Map _needToSumAllChance = new HashMap<>(); + + private int _minLevel = 1; + private int _maxLevel = Config.PLAYER_MAXIMUM_LEVEL; + + protected LetterCollectorManager() + { + } + + public void init() + { + LOGGER.info(getClass().getSimpleName() + ": Loaded " + _rewards.size() + " words."); + LOGGER.info(getClass().getSimpleName() + ": Loaded " + _letter.size() + " letters."); + } + + public int getMinLevel() + { + return _minLevel; + } + + public void setMinLevel(int minLevel) + { + _minLevel = minLevel; + } + + public int getMaxLevel() + { + return _maxLevel; + } + + public void setMaxLevel(int maxLevel) + { + if (maxLevel < 1) + { + _maxLevel = Config.PLAYER_MAXIMUM_LEVEL; + } + else + { + _maxLevel = maxLevel; + } + } + + public LetterCollectorRewardHolder getRewards(int id) + { + return _rewards.get(id); + } + + public List getWord(int id) + { + return _words.get(id); + } + + public void setRewards(Map rewards) + { + _rewards.putAll(rewards); + } + + public void setWords(Map> words) + { + _words.putAll(words); + } + + public void addRewards(int id, LetterCollectorRewardHolder rewards) + { + _rewards.put(id, rewards); + } + + public void addWords(int id, List words) + { + _words.put(id, words); + } + + public void resetField() + { + _minLevel = 1; + _rewards.clear(); + _words.clear(); + _needToSumAllChance.clear(); + } + + public void setLetters(Map letters) + { + _letter.putAll(letters); + } + + public Map getLetters() + { + return _letter; + } + + public void setNeedToSumAllChance(int id, boolean needToSumAllChance) + { + _needToSumAllChance.put(id, needToSumAllChance); + } + + public boolean getNeedToSumAllChance(int id) + { + return _needToSumAllChance.get(id); + } + + public static class LetterCollectorRewardHolder + { + final List _rewards; + final double _chance; + + public LetterCollectorRewardHolder(List rewards, double chance) + { + _rewards = rewards; + _chance = chance; + } + + public List getRewards() + { + return _rewards; + } + + public double getChance() + { + return _chance; + } + } + + public static LetterCollectorManager getInstance() + { + return SingletonHolder.INSTANCE; + } + + private static class SingletonHolder + { + protected static final LetterCollectorManager INSTANCE = new LetterCollectorManager(); + } +} \ No newline at end of file diff --git a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java index 8d5d8a312e..8a05ba0b8d 100644 --- a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java +++ b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java @@ -16,120 +16,24 @@ */ package org.l2jmobius.gameserver.network.clientpackets; +import java.util.List; + import org.l2jmobius.commons.network.PacketReader; import org.l2jmobius.commons.util.Rnd; -import org.l2jmobius.gameserver.data.ItemTable; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.itemcontainer.PlayerInventory; import org.l2jmobius.gameserver.network.GameClient; +import org.l2jmobius.gameserver.network.SystemMessageId; +import org.l2jmobius.gameserver.network.serverpackets.SystemMessage; /** * @author Index, Mobius */ public class ExLetterCollectorTakeReward implements IClientIncomingPacket { - // Items - private static final int A = 3875; - private static final int E = 3877; - private static final int G = 3879; - private static final int I = 3881; - private static final int L = 3882; - private static final int N = 3883; - private static final int O = 3884; - private static final int T = 3886; - private static final int H = 3880; - private static final int II = 3888; - private static final int W = 22894; - private static final int D = 29545; - private static final int P = 29825; - - // Rewards - private static final ItemChanceHolder[] LINEAGE_II_REWARDS = - { - new ItemChanceHolder(80333, 5, 1), // Dragon Necklace - new ItemChanceHolder(80334, 5, 1), // Dragon Earring - new ItemChanceHolder(80335, 5, 1), // Dragon Ring - new ItemChanceHolder(48296, 5, 1), // +10 Eternal Light Armor Capsule - new ItemChanceHolder(48297, 5, 1), // +10 Eternal Robe Capsule - new ItemChanceHolder(48295, 5, 1), // +10 Eternal Heavy Armor Capsule - new ItemChanceHolder(39573, 5, 1), // Sealed Talisman - Insanity - new ItemChanceHolder(37716, 5, 1), // Seven Signs' Energy - new ItemChanceHolder(80416, 5, 1), // Fortune Box of 10 Billion Adena - new ItemChanceHolder(36414, 5, 1), // Dragon Claw - new ItemChanceHolder(47705, 15, 1), // Blue Cat's Eye Lv. 3 Jewelry Box - new ItemChanceHolder(47627, 15, 1), // Sapphire Lv. 3 Jewelry Box - new ItemChanceHolder(47626, 15, 1), // Ruby Lv. 3 Jewelry Box - new ItemChanceHolder(47703, 15, 1), // Red Cat's Eye Lv. 3 Jewelry Box - new ItemChanceHolder(47629, 15, 1), // Opal Lv. 3 Jewelry Box - new ItemChanceHolder(28360, 15, 1), // Cat's Eye Lv. 3 Jewelry Box - new ItemChanceHolder(28362, 15, 1), // Amethyst Lv. 3 Jewelry Box - new ItemChanceHolder(47631, 15, 1), // Diamond Lv. 3 Jewelry Box - new ItemChanceHolder(47634, 15, 1), // Pearl Lv. 3 Jewelry Box - new ItemChanceHolder(47635, 15, 1), // Vital Stone Lv. 3 Jewelry Box - new ItemChanceHolder(47630, 15, 1), // Obsidian Lv. 3 Jewelry Box - new ItemChanceHolder(47633, 15, 1), // Aquamarine Lv. 3 Jewelry Box - new ItemChanceHolder(80423, 30, 1), // Balance Artifact Box - new ItemChanceHolder(80420, 30, 1), // Attack Artifact Box - new ItemChanceHolder(80421, 30, 1), // Protection Artifact Box - new ItemChanceHolder(80422, 30, 1), // Support Artifact Box - new ItemChanceHolder(39374, 30, 1), // Scroll: 5.000.000 SP - new ItemChanceHolder(46274, 30, 1), // Wind Vitality Tonic - new ItemChanceHolder(35563, 30, 1), // Giant's Energy - new ItemChanceHolder(38761, 30, 1), // Energy of Destruction 3-unit Pack - new ItemChanceHolder(36513, 30, 1), // Elcyum Powder - new ItemChanceHolder(27673, 30, 1), // Freya's Scroll of Storm - }; - private static final ItemChanceHolder[] DEATH_REWARDS = - { - new ItemChanceHolder(47821, 5, 1), // Sayha's Talisman Lv. 10 - new ItemChanceHolder(47820, 5, 1), // Sayha's Talisman Lv. 9 - new ItemChanceHolder(37717, 5, 1), // Talisman - Seven Signs - new ItemChanceHolder(39572, 5, 1), // Talisman - Insanity - new ItemChanceHolder(48032, 5, 1), // Sayha's Talisman Lv. 8 - new ItemChanceHolder(80416, 5, 1), // Fortune Box of 10 Billion Adena - new ItemChanceHolder(28448, 5, 1), // Sayha's Talisman Lv. 7 - new ItemChanceHolder(37715, 5, 1), // Talisman - Anakim - new ItemChanceHolder(35649, 15, 1), // Sealed Talisman - Longing - new ItemChanceHolder(29152, 15, 1), // High-grade Zodiac Agathion Pack - new ItemChanceHolder(29151, 15, 1), // Mid-grade Zodiac Agathion Pack - new ItemChanceHolder(28373, 15, 1), // Tanzenite Lv. 3 Jewelry Box - new ItemChanceHolder(47632, 15, 1), // Emerald Lv. 3 Jewelry Box - new ItemChanceHolder(47636, 15, 1), // Garnet Lv. 3 Jewelry Box - new ItemChanceHolder(80423, 30, 1), // Balance Artifact Box - new ItemChanceHolder(80420, 30, 1), // Attack Artifact Box - new ItemChanceHolder(80421, 30, 1), // Protection Artifact Box - new ItemChanceHolder(80422, 30, 1), // Support Artifact Box - new ItemChanceHolder(39374, 30, 1), // Scroll: 5.000.000 SP - new ItemChanceHolder(46274, 30, 1), // Wind Vitality Tonic - new ItemChanceHolder(35563, 30, 1), // Giant's Energy - new ItemChanceHolder(38761, 30, 1), // Energy of Destruction 3-unit Pack - new ItemChanceHolder(36513, 30, 1), // Elcyum Powder - new ItemChanceHolder(27673, 30, 1), // Freya's Scroll of Storm - }; - private static final ItemChanceHolder[] KNIGHT_REWARDS = - { - new ItemChanceHolder(80416, 5, 1), // Fortune Box of 10 Billion Adena - new ItemChanceHolder(28448, 5, 1), // Sayha's Talisman Lv. 7 - new ItemChanceHolder(26291, 5, 1), // Kaliel's Energy - Longing - new ItemChanceHolder(36731, 5, 1), // Life Stone: Giant's Power - new ItemChanceHolder(37714, 5, 1), // Talisman - Lilith - new ItemChanceHolder(29150, 15, 1), // Low-grade Zodiac Agathion Pack - new ItemChanceHolder(80423, 30, 1), // Balance Artifact Box - new ItemChanceHolder(80420, 30, 1), // Attack Artifact Box - new ItemChanceHolder(80421, 30, 1), // Protection Artifact Box - new ItemChanceHolder(80422, 30, 1), // Support Artifact Box - new ItemChanceHolder(36515, 15, 1), // Elcyum - new ItemChanceHolder(48215, 30, 1), // Circlet Spirit Stone - new ItemChanceHolder(28540, 30, 1), // Magnificent Brooch Spirit Stone - new ItemChanceHolder(36514, 30, 1), // Elcyum Crystal - new ItemChanceHolder(39374, 30, 1), // Scroll: 5.000.000 SP - new ItemChanceHolder(46274, 30, 1), // Wind Vitality Tonic - new ItemChanceHolder(35563, 30, 1), // Giant's Energy - new ItemChanceHolder(38761, 30, 1), // Energy of Destruction 3-unit Pack - new ItemChanceHolder(27673, 30, 1), // Freya's Scroll of Storm - }; - private int _wordId; @Override @@ -154,95 +58,53 @@ public class ExLetterCollectorTakeReward implements IClientIncomingPacket return; } - switch (_wordId) + final LetterCollectorManager.LetterCollectorRewardHolder lcrh = LetterCollectorManager.getInstance().getRewards(_wordId); + if (lcrh == null) { - case 0: + return; + } + + for (ItemHolder needLetter : LetterCollectorManager.getInstance().getWord(_wordId)) + { + if (inventory.getInventoryItemCount(needLetter.getId(), -1) < needLetter.getCount()) { - if ((inventory.getInventoryItemCount(L, -1) < 1) || // - (inventory.getInventoryItemCount(I, -1) < 1) || // - (inventory.getInventoryItemCount(N, -1) < 1) || // - (inventory.getInventoryItemCount(E, -1) < 2) || // - (inventory.getInventoryItemCount(A, -1) < 1) || // - (inventory.getInventoryItemCount(G, -1) < 1) || // - (inventory.getInventoryItemCount(II, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", L, 1, player, true); - player.destroyItemByItemId("LetterCollector", I, 1, player, true); - player.destroyItemByItemId("LetterCollector", N, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", A, 1, player, true); - player.destroyItemByItemId("LetterCollector", G, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", II, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(LINEAGE_II_REWARDS), player, true); - break; - } - case 1: - { - if ((inventory.getInventoryItemCount(N, -1) < 2) || // - (inventory.getInventoryItemCount(E, -1) < 3) || // - (inventory.getInventoryItemCount(W, -1) < 1) || // - (inventory.getInventoryItemCount(L, -1) < 1) || // - (inventory.getInventoryItemCount(G, -1) < 1) || // - (inventory.getInventoryItemCount(D, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", N, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", W, 1, player, true); - player.destroyItemByItemId("LetterCollector", L, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", G, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", N, 1, player, true); - player.destroyItemByItemId("LetterCollector", D, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(DEATH_REWARDS), player, true); - break; - } - case 2: - { - if ((inventory.getInventoryItemCount(T, -1) < 3) || // - (inventory.getInventoryItemCount(O, -1) < 2) || // - (inventory.getInventoryItemCount(H, -1) < 1) || // - (inventory.getInventoryItemCount(E, -1) < 1) || // - (inventory.getInventoryItemCount(P, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", T, 1, player, true); - player.destroyItemByItemId("LetterCollector", O, 1, player, true); - player.destroyItemByItemId("LetterCollector", T, 1, player, true); - player.destroyItemByItemId("LetterCollector", H, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", T, 1, player, true); - player.destroyItemByItemId("LetterCollector", O, 1, player, true); - player.destroyItemByItemId("LetterCollector", P, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(KNIGHT_REWARDS), player, true); - break; + return; } } + for (ItemHolder destroyLetter : LetterCollectorManager.getInstance().getWord(_wordId)) + { + if (!player.destroyItemByItemId("LetterCollector", destroyLetter.getId(), destroyLetter.getCount(), player, true)) + { + return; + } + } + + final ItemChanceHolder rewardItem = getRandomReward(lcrh.getRewards(), lcrh.getChance()); + if (rewardItem == null) + { + player.sendPacket(new SystemMessage(SystemMessageId.NOTHING_HAPPENED)); + return; + } + + player.addItem("LetterCollector", rewardItem.getId(), rewardItem.getCount(), rewardItem.getEnchantmentLevel(), player, true); } - private ItemChanceHolder getRandomReward(ItemChanceHolder[] rewards) + private ItemChanceHolder getRandomReward(List rewards, double holderChance) { - ItemChanceHolder reward = null; - while (reward == null) + final double chance = Rnd.get(holderChance); + double itemChance = 0; + for (ItemChanceHolder rewardItem : rewards) { - final ItemChanceHolder random = rewards[Rnd.get(rewards.length)]; - if ((Rnd.get(100) < random.getChance()) && (ItemTable.getInstance().getTemplate(random.getId()) != null)) + itemChance += rewardItem.getChance(); + if (chance <= itemChance) { - reward = random; + if (rewardItem.getId() == -1) + { + return null; + } + return rewardItem; } } - return reward; + return null; } } \ No newline at end of file diff --git a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java index 6a9f1e4eeb..991437e881 100644 --- a/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java +++ b/L2J_Mobius_10.2_MasterClass/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java @@ -16,7 +16,10 @@ */ package org.l2jmobius.gameserver.network.serverpackets; +import org.l2jmobius.Config; import org.l2jmobius.commons.network.PacketWriter; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; +import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.network.OutgoingPackets; /** @@ -24,12 +27,11 @@ import org.l2jmobius.gameserver.network.OutgoingPackets; */ public class ExLetterCollectorUI implements IClientOutgoingPacket { - public static final ExLetterCollectorUI STATIC_PACKET = new ExLetterCollectorUI(); + final int _minimumLevel; - private static final int LETTER_COLLECTOR_MIN_LEVEL = 95; - - private ExLetterCollectorUI() + public ExLetterCollectorUI(Player player) { + _minimumLevel = player.getLevel() <= LetterCollectorManager.getInstance().getMaxLevel() ? LetterCollectorManager.getInstance().getMinLevel() : Config.PLAYER_MAXIMUM_LEVEL; } @Override @@ -37,7 +39,7 @@ public class ExLetterCollectorUI implements IClientOutgoingPacket { OutgoingPackets.EX_LETTER_COLLECTOR_UI_LAUNCHER.writeId(packet); packet.writeC(1); // enabled (0x00 - no, 0x01 -yes) - packet.writeD(LETTER_COLLECTOR_MIN_LEVEL); // Minimum Level + packet.writeD(_minimumLevel); // Minimum Level return true; } } \ No newline at end of file diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/events/LetterCollector/LetterCollector.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/events/LetterCollector/LetterCollector.java index 9343546f2b..a181a33a0f 100644 --- a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/events/LetterCollector/LetterCollector.java +++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/events/LetterCollector/LetterCollector.java @@ -16,22 +16,122 @@ */ package events.LetterCollector; +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import org.w3c.dom.Document; + +import org.l2jmobius.commons.util.IXmlReader; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; +import org.l2jmobius.gameserver.model.StatSet; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.events.EventType; import org.l2jmobius.gameserver.model.events.ListenerRegisterType; import org.l2jmobius.gameserver.model.events.annotations.RegisterEvent; import org.l2jmobius.gameserver.model.events.annotations.RegisterType; import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin; +import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.quest.LongTimeEvent; import org.l2jmobius.gameserver.network.serverpackets.ExLetterCollectorUI; /** * @author Mobius */ -public class LetterCollector extends LongTimeEvent +public class LetterCollector extends LongTimeEvent implements IXmlReader { private LetterCollector() { + if (isEventPeriod()) + { + load(); + LetterCollectorManager.getInstance().init(); + } + } + + public void reloadRewards() + { + LetterCollectorManager.getInstance().resetField(); + load(); + } + + @Override + public synchronized void load() + { + parseDatapackFile("data/scripts/events/LetterCollector/rewards.xml"); + } + + @Override + public void parseDocument(Document doc, File f) + { + final AtomicInteger minimumLevel = new AtomicInteger(); + final AtomicInteger maximumLevel = new AtomicInteger(); + final Map letters = new HashMap<>(); + forEach(doc, "list", listNode -> + { + forEach(listNode, "params", paramNode -> + { + forEach(paramNode, "minimum", minimumLevelNode -> minimumLevel.set(new StatSet(parseAttributes(minimumLevelNode)).getInt("level"))); + forEach(paramNode, "maximum", maximumLevelNode -> maximumLevel.set(new StatSet(parseAttributes(maximumLevelNode)).getInt("level"))); + }); + forEach(listNode, "letters", letterNode -> forEach(letterNode, "item", itemNode -> + { + StatSet letterSet = new StatSet(parseAttributes(itemNode)); + letters.put(letterSet.getString("name"), letterSet.getInt("id")); + })); + forEach(listNode, "reward", rewardNode -> + { + final int id = new StatSet(parseAttributes(rewardNode)).getInt("id"); + final AtomicReference> word = new AtomicReference<>(new ArrayList<>()); + final AtomicReference> rewards = new AtomicReference<>(new ArrayList<>()); + AtomicBoolean needToSumAllChance = new AtomicBoolean(false); + AtomicReference chanceSum = new AtomicReference<>(0.0); + forEach(rewardNode, "word", wordNode -> + { + String[] letter = wordNode.getTextContent().trim().split(";"); + for (String token : letter) + { + int count = 1; + for (ItemHolder check : word.get()) + { + if (check.getId() == letters.get(token)) + { + count = Math.toIntExact(check.getCount() + 1); + word.get().remove(check); + break; + } + } + word.get().add(new ItemHolder(letters.get(token), count)); + } + }); + forEach(rewardNode, "rewards", rewardsNode -> + { + needToSumAllChance.set(new StatSet(parseAttributes(rewardsNode)).getBoolean("sumChances")); + forEach(rewardsNode, "item", itemNode -> + { + StatSet itemSet = new StatSet(parseAttributes(itemNode)); + final double chance = itemSet.getDouble("chance"); + if (needToSumAllChance.get()) + { + chanceSum.set(chanceSum.get() + chance); + } + rewards.get().add(new ItemChanceHolder(itemSet.getInt("id"), chance, itemSet.getLong("count"), (byte) itemSet.getInt("enchantLevel", 0))); + }); + }); + LetterCollectorManager lcm = LetterCollectorManager.getInstance(); + lcm.addWords(id, word.get()); + lcm.addRewards(id, new LetterCollectorManager.LetterCollectorRewardHolder(rewards.get(), chanceSum.get() == 0d ? 100d : chanceSum.get())); + lcm.setLetters(letters); + lcm.setMinLevel(minimumLevel.get()); + lcm.setMaxLevel(maximumLevel.get()); + }); + }); } @RegisterEvent(EventType.ON_PLAYER_LOGIN) @@ -46,7 +146,7 @@ public class LetterCollector extends LongTimeEvent final Player player = event.getPlayer(); if (player != null) { - player.sendPacket(ExLetterCollectorUI.STATIC_PACKET); + player.sendPacket(new ExLetterCollectorUI(player)); } } diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/events/LetterCollector/config.xml b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/events/LetterCollector/config.xml index 9c4ce3483e..c4c5f44366 100644 --- a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/events/LetterCollector/config.xml +++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/events/LetterCollector/config.xml @@ -1,7 +1,5 @@ - - diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/events/LetterCollector/rewards.xml b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/events/LetterCollector/rewards.xml new file mode 100644 index 0000000000..602c12bf39 --- /dev/null +++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/events/LetterCollector/rewards.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + L;I;N;E;A;G;E;II + + + + + + + + + + + + + + + + + + + + + + + + D;E;A;T;H + + + + + + + + + + + + + + + + + + + + K;N;I;G;H;T + + + + + + + + + + + + + + + + + + + + S;U;M;M;E;R + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/events/LetterCollector/rewards.xsd b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/events/LetterCollector/rewards.xsd new file mode 100644 index 0000000000..5d9feae899 --- /dev/null +++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/dist/game/data/scripts/events/LetterCollector/rewards.xsd @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java new file mode 100644 index 0000000000..a90c9e0753 --- /dev/null +++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java @@ -0,0 +1,169 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.l2jmobius.gameserver.instancemanager.events; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import org.l2jmobius.Config; +import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; + +/** + * @author Index + */ +public class LetterCollectorManager +{ + protected static final Logger LOGGER = Logger.getLogger(LetterCollectorManager.class.getName()); + + private final Map _rewards = new HashMap<>(); + private final Map> _words = new HashMap<>(); + private final Map _letter = new HashMap<>(); + private final Map _needToSumAllChance = new HashMap<>(); + + private int _minLevel = 1; + private int _maxLevel = Config.PLAYER_MAXIMUM_LEVEL; + + protected LetterCollectorManager() + { + } + + public void init() + { + LOGGER.info(getClass().getSimpleName() + ": Loaded " + _rewards.size() + " words."); + LOGGER.info(getClass().getSimpleName() + ": Loaded " + _letter.size() + " letters."); + } + + public int getMinLevel() + { + return _minLevel; + } + + public void setMinLevel(int minLevel) + { + _minLevel = minLevel; + } + + public int getMaxLevel() + { + return _maxLevel; + } + + public void setMaxLevel(int maxLevel) + { + if (maxLevel < 1) + { + _maxLevel = Config.PLAYER_MAXIMUM_LEVEL; + } + else + { + _maxLevel = maxLevel; + } + } + + public LetterCollectorRewardHolder getRewards(int id) + { + return _rewards.get(id); + } + + public List getWord(int id) + { + return _words.get(id); + } + + public void setRewards(Map rewards) + { + _rewards.putAll(rewards); + } + + public void setWords(Map> words) + { + _words.putAll(words); + } + + public void addRewards(int id, LetterCollectorRewardHolder rewards) + { + _rewards.put(id, rewards); + } + + public void addWords(int id, List words) + { + _words.put(id, words); + } + + public void resetField() + { + _minLevel = 1; + _rewards.clear(); + _words.clear(); + _needToSumAllChance.clear(); + } + + public void setLetters(Map letters) + { + _letter.putAll(letters); + } + + public Map getLetters() + { + return _letter; + } + + public void setNeedToSumAllChance(int id, boolean needToSumAllChance) + { + _needToSumAllChance.put(id, needToSumAllChance); + } + + public boolean getNeedToSumAllChance(int id) + { + return _needToSumAllChance.get(id); + } + + public static class LetterCollectorRewardHolder + { + final List _rewards; + final double _chance; + + public LetterCollectorRewardHolder(List rewards, double chance) + { + _rewards = rewards; + _chance = chance; + } + + public List getRewards() + { + return _rewards; + } + + public double getChance() + { + return _chance; + } + } + + public static LetterCollectorManager getInstance() + { + return SingletonHolder.INSTANCE; + } + + private static class SingletonHolder + { + protected static final LetterCollectorManager INSTANCE = new LetterCollectorManager(); + } +} \ No newline at end of file diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java index bc986078ff..b1e8c6b991 100644 --- a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java +++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java @@ -16,114 +16,24 @@ */ package org.l2jmobius.gameserver.network.clientpackets; +import java.util.List; + import org.l2jmobius.commons.network.PacketReader; import org.l2jmobius.commons.util.Rnd; -import org.l2jmobius.gameserver.data.ItemTable; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.itemcontainer.PlayerInventory; import org.l2jmobius.gameserver.network.GameClient; +import org.l2jmobius.gameserver.network.SystemMessageId; +import org.l2jmobius.gameserver.network.serverpackets.SystemMessage; /** * @author Index, Mobius */ public class ExLetterCollectorTakeReward implements IClientIncomingPacket { - // Items - private static final int A = 3875; - private static final int E = 3877; - private static final int G = 3879; - private static final int I = 3881; - private static final int L = 3882; - private static final int N = 3883; - private static final int R = 3885; - private static final int M = 34956; - private static final int S = 3886; - private static final int T = 3886; - private static final int H = 3880; - private static final int II = 3888; - private static final int D = 92021; - private static final int K = 93412; - private static final int U = 93413; - - // Rewards - private static final ItemChanceHolder[] LINEAGE_II_REWARDS = - { - new ItemChanceHolder(49683, 5, 1), // Talisman of Baium - new ItemChanceHolder(91119, 5, 1), // Ignis' Necklace - new ItemChanceHolder(91117, 5, 1), // Nebula's Necklace - new ItemChanceHolder(91121, 5, 1), // Procella's Necklace - new ItemChanceHolder(91123, 5, 1), // Petram's Necklace - new ItemChanceHolder(91952, 5, 1), // Ring of Insolance - new ItemChanceHolder(91953, 5, 1), // Dragon Valley's Earring - new ItemChanceHolder(91035, 15, 1), // Water Spirit Ore - new ItemChanceHolder(91036, 15, 1), // Fire Spirit Ore - new ItemChanceHolder(91037, 15, 1), // Wind Spirit Ore - new ItemChanceHolder(91038, 15, 1), // Earth Spirit Ore - new ItemChanceHolder(91641, 30, 1), // Sayha's Blessing - new ItemChanceHolder(49674, 30, 1), // XP Growth Scroll - new ItemChanceHolder(90907, 30, 5), // Soulshot Ticket - new ItemChanceHolder(91757, 30, 1), // Magic Lamp Charging Potion - new ItemChanceHolder(91974, 30, 10), // HP Recovery Potion - new ItemChanceHolder(3031, 30, 10), // Spirit Ore - }; - private static final ItemChanceHolder[] DEATH_REWARDS = - { - new ItemChanceHolder(91012, 5, 1), // Top-grade A-grade Weapon Pack - new ItemChanceHolder(93459, 5, 1), // A-grade Armor Pack - Majestic Equipment - new ItemChanceHolder(93460, 5, 1), // A-grade Armor Pack - Equipment of Nightmare - new ItemChanceHolder(93461, 5, 1), // A-grade Armor Pack - Tallum Equipment - new ItemChanceHolder(93462, 5, 1), // A-grade Armor Pack - Dark Crystal Equipment - new ItemChanceHolder(90015, 15, 1), // Top-grade Life Stone - Weapon - new ItemChanceHolder(93100, 15, 1), // Mid-grade Life Stone Shield / Sigil - new ItemChanceHolder(91938, 15, 1), // Primeval Isle's Time Stone - new ItemChanceHolder(93699, 15, 1), // Charging Stone of Random Crafting - 1 charge - new ItemChanceHolder(91641, 30, 1), // Sayha's Blessing - new ItemChanceHolder(49674, 30, 1), // XP Growth Scroll - new ItemChanceHolder(90907, 30, 5), // Soulshot Ticket - new ItemChanceHolder(91757, 30, 1), // Magic Lamp Charging Potion - new ItemChanceHolder(91974, 30, 10), // HP Recovery Potion - new ItemChanceHolder(3031, 30, 10), // Spirit Ore - }; - private static final ItemChanceHolder[] KNIGHT_REWARDS = - { - new ItemChanceHolder(93103, 5, 1), // Spellbook: Divine Beam - new ItemChanceHolder(92401, 5, 1), // Spellbook: White Guardian - new ItemChanceHolder(91945, 5, 1), // Book of Shadows - new ItemChanceHolder(91944, 5, 1), // Book of Light - new ItemChanceHolder(91943, 15, 1), // Crystal of Shadows - new ItemChanceHolder(91942, 15, 1), // Crystal of Light - new ItemChanceHolder(8619, 15, 1), // Buff Expansion Book Lv. 2 - new ItemChanceHolder(8620, 15, 1), // Buff Expansion Book Lv. 3 - new ItemChanceHolder(90045, 15, 1), // Magical Tablet - new ItemChanceHolder(91641, 30, 1), // Sayha's Blessing - new ItemChanceHolder(49674, 30, 1), // XP Growth Scroll - new ItemChanceHolder(90907, 30, 5), // Soulshot Ticket - new ItemChanceHolder(91757, 30, 1), // Magic Lamp Charging Potion - new ItemChanceHolder(91974, 30, 10), // HP Recovery Potion - new ItemChanceHolder(3031, 30, 10), // Spirit Ore - }; - private static final ItemChanceHolder[] SUMMER_REWARDS = - { - new ItemChanceHolder(93976, 5, 1), // Blessed Scroll: Enchant A-grade Weapon - new ItemChanceHolder(93977, 5, 1), // Blessed Scroll: Enchant A-grade Armor - new ItemChanceHolder(729, 5, 1), // Scroll: Enchant A-grade Weapon - new ItemChanceHolder(730, 5, 1), // Scroll: Enchant A-grade Armor - new ItemChanceHolder(947, 15, 1), // Scroll: Enchant B-grade Weapon - new ItemChanceHolder(948, 15, 1), // Scroll: Enchant B-grade Armor - new ItemChanceHolder(91967, 15, 1), // Scroll: Enchant Dragon Valley's Earring - new ItemChanceHolder(91966, 15, 1), // Scroll: Enchant Ring of Insolance - new ItemChanceHolder(91641, 30, 1), // Sayha's Blessing - new ItemChanceHolder(91780, 30, 1), // Battle Scroll - new ItemChanceHolder(93486, 30, 1), // Combat Scroll - new ItemChanceHolder(49674, 30, 1), // XP Growth Scroll - new ItemChanceHolder(90907, 30, 5), // Soulshot Ticket - new ItemChanceHolder(1538, 30, 1), // Improved Scroll of Escape - new ItemChanceHolder(91757, 30, 1), // Magic Lamp Charging Potion - new ItemChanceHolder(91974, 30, 10), // HP Recovery Potion - new ItemChanceHolder(3031, 30, 10), // Spirit Ore - }; - private int _wordId; @Override @@ -148,110 +58,53 @@ public class ExLetterCollectorTakeReward implements IClientIncomingPacket return; } - switch (_wordId) + final LetterCollectorManager.LetterCollectorRewardHolder lcrh = LetterCollectorManager.getInstance().getRewards(_wordId); + if (lcrh == null) { - case 0: + return; + } + + for (ItemHolder needLetter : LetterCollectorManager.getInstance().getWord(_wordId)) + { + if (inventory.getInventoryItemCount(needLetter.getId(), -1) < needLetter.getCount()) { - if ((inventory.getInventoryItemCount(L, -1) < 1) || // - (inventory.getInventoryItemCount(I, -1) < 1) || // - (inventory.getInventoryItemCount(N, -1) < 1) || // - (inventory.getInventoryItemCount(E, -1) < 2) || // - (inventory.getInventoryItemCount(A, -1) < 1) || // - (inventory.getInventoryItemCount(G, -1) < 1) || // - (inventory.getInventoryItemCount(II, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", L, 1, player, true); - player.destroyItemByItemId("LetterCollector", I, 1, player, true); - player.destroyItemByItemId("LetterCollector", N, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", A, 1, player, true); - player.destroyItemByItemId("LetterCollector", G, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", II, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(LINEAGE_II_REWARDS), player, true); - break; - } - case 1: - { - if ((inventory.getInventoryItemCount(D, -1) < 1) || // - (inventory.getInventoryItemCount(E, -1) < 1) || // - (inventory.getInventoryItemCount(A, -1) < 1) || // - (inventory.getInventoryItemCount(T, -1) < 1) || // - (inventory.getInventoryItemCount(H, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", D, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", A, 1, player, true); - player.destroyItemByItemId("LetterCollector", T, 1, player, true); - player.destroyItemByItemId("LetterCollector", H, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(DEATH_REWARDS), player, true); - break; - } - case 2: - { - if ((inventory.getInventoryItemCount(K, -1) < 1) || // - (inventory.getInventoryItemCount(N, -1) < 1) || // - (inventory.getInventoryItemCount(I, -1) < 1) || // - (inventory.getInventoryItemCount(G, -1) < 1) || // - (inventory.getInventoryItemCount(H, -1) < 1) || // - (inventory.getInventoryItemCount(T, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", K, 1, player, true); - player.destroyItemByItemId("LetterCollector", N, 1, player, true); - player.destroyItemByItemId("LetterCollector", I, 1, player, true); - player.destroyItemByItemId("LetterCollector", G, 1, player, true); - player.destroyItemByItemId("LetterCollector", H, 1, player, true); - player.destroyItemByItemId("LetterCollector", T, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(KNIGHT_REWARDS), player, true); - break; - } - case 3: - { - if ((inventory.getInventoryItemCount(S, -1) < 1) || // - (inventory.getInventoryItemCount(U, -1) < 1) || // - (inventory.getInventoryItemCount(M, -1) < 2) || // - (inventory.getInventoryItemCount(E, -1) < 1) || // - (inventory.getInventoryItemCount(R, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", S, 1, player, true); - player.destroyItemByItemId("LetterCollector", U, 1, player, true); - player.destroyItemByItemId("LetterCollector", M, 1, player, true); - player.destroyItemByItemId("LetterCollector", M, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", R, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(SUMMER_REWARDS), player, true); - break; + return; } } + for (ItemHolder destroyLetter : LetterCollectorManager.getInstance().getWord(_wordId)) + { + if (!player.destroyItemByItemId("LetterCollector", destroyLetter.getId(), destroyLetter.getCount(), player, true)) + { + return; + } + } + + final ItemHolder rewardItem = getRandomReward(lcrh.getRewards(), lcrh.getChance()); + if (rewardItem == null) + { + player.sendPacket(new SystemMessage(SystemMessageId.NOTHING_HAPPENED)); + return; + } + + player.addItem("LetterCollector", rewardItem.getId(), rewardItem.getCount(), player, true); } - private ItemChanceHolder getRandomReward(ItemChanceHolder[] rewards) + private ItemHolder getRandomReward(List rewards, double holderChance) { - ItemChanceHolder reward = null; - while (reward == null) + final double chance = Rnd.get(holderChance); + double itemChance = 0; + for (ItemChanceHolder rewardItem : rewards) { - final ItemChanceHolder random = rewards[Rnd.get(rewards.length)]; - if ((Rnd.get(100) < random.getChance()) && (ItemTable.getInstance().getTemplate(random.getId()) != null)) + itemChance += rewardItem.getChance(); + if (chance <= itemChance) { - reward = random; + if (rewardItem.getId() == -1) + { + return null; + } + return rewardItem; } } - return reward; + return null; } } \ No newline at end of file diff --git a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java index ce54e4cf05..991437e881 100644 --- a/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java +++ b/L2J_Mobius_Essence_4.2_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java @@ -16,7 +16,10 @@ */ package org.l2jmobius.gameserver.network.serverpackets; +import org.l2jmobius.Config; import org.l2jmobius.commons.network.PacketWriter; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; +import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.network.OutgoingPackets; /** @@ -24,12 +27,11 @@ import org.l2jmobius.gameserver.network.OutgoingPackets; */ public class ExLetterCollectorUI implements IClientOutgoingPacket { - public static final ExLetterCollectorUI STATIC_PACKET = new ExLetterCollectorUI(); + final int _minimumLevel; - private static final int LETTER_COLLECTOR_MIN_LEVEL = 5; - - private ExLetterCollectorUI() + public ExLetterCollectorUI(Player player) { + _minimumLevel = player.getLevel() <= LetterCollectorManager.getInstance().getMaxLevel() ? LetterCollectorManager.getInstance().getMinLevel() : Config.PLAYER_MAXIMUM_LEVEL; } @Override @@ -37,7 +39,7 @@ public class ExLetterCollectorUI implements IClientOutgoingPacket { OutgoingPackets.EX_LETTER_COLLECTOR_UI_LAUNCHER.writeId(packet); packet.writeC(1); // enabled (0x00 - no, 0x01 -yes) - packet.writeD(LETTER_COLLECTOR_MIN_LEVEL); // Minimum Level + packet.writeD(_minimumLevel); // Minimum Level return true; } } \ No newline at end of file diff --git a/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/events/LetterCollector/LetterCollector.java b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/events/LetterCollector/LetterCollector.java index 9343546f2b..a181a33a0f 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/events/LetterCollector/LetterCollector.java +++ b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/events/LetterCollector/LetterCollector.java @@ -16,22 +16,122 @@ */ package events.LetterCollector; +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import org.w3c.dom.Document; + +import org.l2jmobius.commons.util.IXmlReader; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; +import org.l2jmobius.gameserver.model.StatSet; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.events.EventType; import org.l2jmobius.gameserver.model.events.ListenerRegisterType; import org.l2jmobius.gameserver.model.events.annotations.RegisterEvent; import org.l2jmobius.gameserver.model.events.annotations.RegisterType; import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin; +import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.quest.LongTimeEvent; import org.l2jmobius.gameserver.network.serverpackets.ExLetterCollectorUI; /** * @author Mobius */ -public class LetterCollector extends LongTimeEvent +public class LetterCollector extends LongTimeEvent implements IXmlReader { private LetterCollector() { + if (isEventPeriod()) + { + load(); + LetterCollectorManager.getInstance().init(); + } + } + + public void reloadRewards() + { + LetterCollectorManager.getInstance().resetField(); + load(); + } + + @Override + public synchronized void load() + { + parseDatapackFile("data/scripts/events/LetterCollector/rewards.xml"); + } + + @Override + public void parseDocument(Document doc, File f) + { + final AtomicInteger minimumLevel = new AtomicInteger(); + final AtomicInteger maximumLevel = new AtomicInteger(); + final Map letters = new HashMap<>(); + forEach(doc, "list", listNode -> + { + forEach(listNode, "params", paramNode -> + { + forEach(paramNode, "minimum", minimumLevelNode -> minimumLevel.set(new StatSet(parseAttributes(minimumLevelNode)).getInt("level"))); + forEach(paramNode, "maximum", maximumLevelNode -> maximumLevel.set(new StatSet(parseAttributes(maximumLevelNode)).getInt("level"))); + }); + forEach(listNode, "letters", letterNode -> forEach(letterNode, "item", itemNode -> + { + StatSet letterSet = new StatSet(parseAttributes(itemNode)); + letters.put(letterSet.getString("name"), letterSet.getInt("id")); + })); + forEach(listNode, "reward", rewardNode -> + { + final int id = new StatSet(parseAttributes(rewardNode)).getInt("id"); + final AtomicReference> word = new AtomicReference<>(new ArrayList<>()); + final AtomicReference> rewards = new AtomicReference<>(new ArrayList<>()); + AtomicBoolean needToSumAllChance = new AtomicBoolean(false); + AtomicReference chanceSum = new AtomicReference<>(0.0); + forEach(rewardNode, "word", wordNode -> + { + String[] letter = wordNode.getTextContent().trim().split(";"); + for (String token : letter) + { + int count = 1; + for (ItemHolder check : word.get()) + { + if (check.getId() == letters.get(token)) + { + count = Math.toIntExact(check.getCount() + 1); + word.get().remove(check); + break; + } + } + word.get().add(new ItemHolder(letters.get(token), count)); + } + }); + forEach(rewardNode, "rewards", rewardsNode -> + { + needToSumAllChance.set(new StatSet(parseAttributes(rewardsNode)).getBoolean("sumChances")); + forEach(rewardsNode, "item", itemNode -> + { + StatSet itemSet = new StatSet(parseAttributes(itemNode)); + final double chance = itemSet.getDouble("chance"); + if (needToSumAllChance.get()) + { + chanceSum.set(chanceSum.get() + chance); + } + rewards.get().add(new ItemChanceHolder(itemSet.getInt("id"), chance, itemSet.getLong("count"), (byte) itemSet.getInt("enchantLevel", 0))); + }); + }); + LetterCollectorManager lcm = LetterCollectorManager.getInstance(); + lcm.addWords(id, word.get()); + lcm.addRewards(id, new LetterCollectorManager.LetterCollectorRewardHolder(rewards.get(), chanceSum.get() == 0d ? 100d : chanceSum.get())); + lcm.setLetters(letters); + lcm.setMinLevel(minimumLevel.get()); + lcm.setMaxLevel(maximumLevel.get()); + }); + }); } @RegisterEvent(EventType.ON_PLAYER_LOGIN) @@ -46,7 +146,7 @@ public class LetterCollector extends LongTimeEvent final Player player = event.getPlayer(); if (player != null) { - player.sendPacket(ExLetterCollectorUI.STATIC_PACKET); + player.sendPacket(new ExLetterCollectorUI(player)); } } diff --git a/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/events/LetterCollector/config.xml b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/events/LetterCollector/config.xml index 03adf0460f..be41235de7 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/events/LetterCollector/config.xml +++ b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/events/LetterCollector/config.xml @@ -1,7 +1,5 @@ - - diff --git a/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/events/LetterCollector/rewards.xml b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/events/LetterCollector/rewards.xml new file mode 100644 index 0000000000..602c12bf39 --- /dev/null +++ b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/events/LetterCollector/rewards.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + L;I;N;E;A;G;E;II + + + + + + + + + + + + + + + + + + + + + + + + D;E;A;T;H + + + + + + + + + + + + + + + + + + + + K;N;I;G;H;T + + + + + + + + + + + + + + + + + + + + S;U;M;M;E;R + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/events/LetterCollector/rewards.xsd b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/events/LetterCollector/rewards.xsd new file mode 100644 index 0000000000..5d9feae899 --- /dev/null +++ b/L2J_Mobius_Essence_5.2_FrostLord/dist/game/data/scripts/events/LetterCollector/rewards.xsd @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java new file mode 100644 index 0000000000..a90c9e0753 --- /dev/null +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java @@ -0,0 +1,169 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.l2jmobius.gameserver.instancemanager.events; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import org.l2jmobius.Config; +import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; + +/** + * @author Index + */ +public class LetterCollectorManager +{ + protected static final Logger LOGGER = Logger.getLogger(LetterCollectorManager.class.getName()); + + private final Map _rewards = new HashMap<>(); + private final Map> _words = new HashMap<>(); + private final Map _letter = new HashMap<>(); + private final Map _needToSumAllChance = new HashMap<>(); + + private int _minLevel = 1; + private int _maxLevel = Config.PLAYER_MAXIMUM_LEVEL; + + protected LetterCollectorManager() + { + } + + public void init() + { + LOGGER.info(getClass().getSimpleName() + ": Loaded " + _rewards.size() + " words."); + LOGGER.info(getClass().getSimpleName() + ": Loaded " + _letter.size() + " letters."); + } + + public int getMinLevel() + { + return _minLevel; + } + + public void setMinLevel(int minLevel) + { + _minLevel = minLevel; + } + + public int getMaxLevel() + { + return _maxLevel; + } + + public void setMaxLevel(int maxLevel) + { + if (maxLevel < 1) + { + _maxLevel = Config.PLAYER_MAXIMUM_LEVEL; + } + else + { + _maxLevel = maxLevel; + } + } + + public LetterCollectorRewardHolder getRewards(int id) + { + return _rewards.get(id); + } + + public List getWord(int id) + { + return _words.get(id); + } + + public void setRewards(Map rewards) + { + _rewards.putAll(rewards); + } + + public void setWords(Map> words) + { + _words.putAll(words); + } + + public void addRewards(int id, LetterCollectorRewardHolder rewards) + { + _rewards.put(id, rewards); + } + + public void addWords(int id, List words) + { + _words.put(id, words); + } + + public void resetField() + { + _minLevel = 1; + _rewards.clear(); + _words.clear(); + _needToSumAllChance.clear(); + } + + public void setLetters(Map letters) + { + _letter.putAll(letters); + } + + public Map getLetters() + { + return _letter; + } + + public void setNeedToSumAllChance(int id, boolean needToSumAllChance) + { + _needToSumAllChance.put(id, needToSumAllChance); + } + + public boolean getNeedToSumAllChance(int id) + { + return _needToSumAllChance.get(id); + } + + public static class LetterCollectorRewardHolder + { + final List _rewards; + final double _chance; + + public LetterCollectorRewardHolder(List rewards, double chance) + { + _rewards = rewards; + _chance = chance; + } + + public List getRewards() + { + return _rewards; + } + + public double getChance() + { + return _chance; + } + } + + public static LetterCollectorManager getInstance() + { + return SingletonHolder.INSTANCE; + } + + private static class SingletonHolder + { + protected static final LetterCollectorManager INSTANCE = new LetterCollectorManager(); + } +} \ No newline at end of file diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java index bc986078ff..b1e8c6b991 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java @@ -16,114 +16,24 @@ */ package org.l2jmobius.gameserver.network.clientpackets; +import java.util.List; + import org.l2jmobius.commons.network.PacketReader; import org.l2jmobius.commons.util.Rnd; -import org.l2jmobius.gameserver.data.ItemTable; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.itemcontainer.PlayerInventory; import org.l2jmobius.gameserver.network.GameClient; +import org.l2jmobius.gameserver.network.SystemMessageId; +import org.l2jmobius.gameserver.network.serverpackets.SystemMessage; /** * @author Index, Mobius */ public class ExLetterCollectorTakeReward implements IClientIncomingPacket { - // Items - private static final int A = 3875; - private static final int E = 3877; - private static final int G = 3879; - private static final int I = 3881; - private static final int L = 3882; - private static final int N = 3883; - private static final int R = 3885; - private static final int M = 34956; - private static final int S = 3886; - private static final int T = 3886; - private static final int H = 3880; - private static final int II = 3888; - private static final int D = 92021; - private static final int K = 93412; - private static final int U = 93413; - - // Rewards - private static final ItemChanceHolder[] LINEAGE_II_REWARDS = - { - new ItemChanceHolder(49683, 5, 1), // Talisman of Baium - new ItemChanceHolder(91119, 5, 1), // Ignis' Necklace - new ItemChanceHolder(91117, 5, 1), // Nebula's Necklace - new ItemChanceHolder(91121, 5, 1), // Procella's Necklace - new ItemChanceHolder(91123, 5, 1), // Petram's Necklace - new ItemChanceHolder(91952, 5, 1), // Ring of Insolance - new ItemChanceHolder(91953, 5, 1), // Dragon Valley's Earring - new ItemChanceHolder(91035, 15, 1), // Water Spirit Ore - new ItemChanceHolder(91036, 15, 1), // Fire Spirit Ore - new ItemChanceHolder(91037, 15, 1), // Wind Spirit Ore - new ItemChanceHolder(91038, 15, 1), // Earth Spirit Ore - new ItemChanceHolder(91641, 30, 1), // Sayha's Blessing - new ItemChanceHolder(49674, 30, 1), // XP Growth Scroll - new ItemChanceHolder(90907, 30, 5), // Soulshot Ticket - new ItemChanceHolder(91757, 30, 1), // Magic Lamp Charging Potion - new ItemChanceHolder(91974, 30, 10), // HP Recovery Potion - new ItemChanceHolder(3031, 30, 10), // Spirit Ore - }; - private static final ItemChanceHolder[] DEATH_REWARDS = - { - new ItemChanceHolder(91012, 5, 1), // Top-grade A-grade Weapon Pack - new ItemChanceHolder(93459, 5, 1), // A-grade Armor Pack - Majestic Equipment - new ItemChanceHolder(93460, 5, 1), // A-grade Armor Pack - Equipment of Nightmare - new ItemChanceHolder(93461, 5, 1), // A-grade Armor Pack - Tallum Equipment - new ItemChanceHolder(93462, 5, 1), // A-grade Armor Pack - Dark Crystal Equipment - new ItemChanceHolder(90015, 15, 1), // Top-grade Life Stone - Weapon - new ItemChanceHolder(93100, 15, 1), // Mid-grade Life Stone Shield / Sigil - new ItemChanceHolder(91938, 15, 1), // Primeval Isle's Time Stone - new ItemChanceHolder(93699, 15, 1), // Charging Stone of Random Crafting - 1 charge - new ItemChanceHolder(91641, 30, 1), // Sayha's Blessing - new ItemChanceHolder(49674, 30, 1), // XP Growth Scroll - new ItemChanceHolder(90907, 30, 5), // Soulshot Ticket - new ItemChanceHolder(91757, 30, 1), // Magic Lamp Charging Potion - new ItemChanceHolder(91974, 30, 10), // HP Recovery Potion - new ItemChanceHolder(3031, 30, 10), // Spirit Ore - }; - private static final ItemChanceHolder[] KNIGHT_REWARDS = - { - new ItemChanceHolder(93103, 5, 1), // Spellbook: Divine Beam - new ItemChanceHolder(92401, 5, 1), // Spellbook: White Guardian - new ItemChanceHolder(91945, 5, 1), // Book of Shadows - new ItemChanceHolder(91944, 5, 1), // Book of Light - new ItemChanceHolder(91943, 15, 1), // Crystal of Shadows - new ItemChanceHolder(91942, 15, 1), // Crystal of Light - new ItemChanceHolder(8619, 15, 1), // Buff Expansion Book Lv. 2 - new ItemChanceHolder(8620, 15, 1), // Buff Expansion Book Lv. 3 - new ItemChanceHolder(90045, 15, 1), // Magical Tablet - new ItemChanceHolder(91641, 30, 1), // Sayha's Blessing - new ItemChanceHolder(49674, 30, 1), // XP Growth Scroll - new ItemChanceHolder(90907, 30, 5), // Soulshot Ticket - new ItemChanceHolder(91757, 30, 1), // Magic Lamp Charging Potion - new ItemChanceHolder(91974, 30, 10), // HP Recovery Potion - new ItemChanceHolder(3031, 30, 10), // Spirit Ore - }; - private static final ItemChanceHolder[] SUMMER_REWARDS = - { - new ItemChanceHolder(93976, 5, 1), // Blessed Scroll: Enchant A-grade Weapon - new ItemChanceHolder(93977, 5, 1), // Blessed Scroll: Enchant A-grade Armor - new ItemChanceHolder(729, 5, 1), // Scroll: Enchant A-grade Weapon - new ItemChanceHolder(730, 5, 1), // Scroll: Enchant A-grade Armor - new ItemChanceHolder(947, 15, 1), // Scroll: Enchant B-grade Weapon - new ItemChanceHolder(948, 15, 1), // Scroll: Enchant B-grade Armor - new ItemChanceHolder(91967, 15, 1), // Scroll: Enchant Dragon Valley's Earring - new ItemChanceHolder(91966, 15, 1), // Scroll: Enchant Ring of Insolance - new ItemChanceHolder(91641, 30, 1), // Sayha's Blessing - new ItemChanceHolder(91780, 30, 1), // Battle Scroll - new ItemChanceHolder(93486, 30, 1), // Combat Scroll - new ItemChanceHolder(49674, 30, 1), // XP Growth Scroll - new ItemChanceHolder(90907, 30, 5), // Soulshot Ticket - new ItemChanceHolder(1538, 30, 1), // Improved Scroll of Escape - new ItemChanceHolder(91757, 30, 1), // Magic Lamp Charging Potion - new ItemChanceHolder(91974, 30, 10), // HP Recovery Potion - new ItemChanceHolder(3031, 30, 10), // Spirit Ore - }; - private int _wordId; @Override @@ -148,110 +58,53 @@ public class ExLetterCollectorTakeReward implements IClientIncomingPacket return; } - switch (_wordId) + final LetterCollectorManager.LetterCollectorRewardHolder lcrh = LetterCollectorManager.getInstance().getRewards(_wordId); + if (lcrh == null) { - case 0: + return; + } + + for (ItemHolder needLetter : LetterCollectorManager.getInstance().getWord(_wordId)) + { + if (inventory.getInventoryItemCount(needLetter.getId(), -1) < needLetter.getCount()) { - if ((inventory.getInventoryItemCount(L, -1) < 1) || // - (inventory.getInventoryItemCount(I, -1) < 1) || // - (inventory.getInventoryItemCount(N, -1) < 1) || // - (inventory.getInventoryItemCount(E, -1) < 2) || // - (inventory.getInventoryItemCount(A, -1) < 1) || // - (inventory.getInventoryItemCount(G, -1) < 1) || // - (inventory.getInventoryItemCount(II, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", L, 1, player, true); - player.destroyItemByItemId("LetterCollector", I, 1, player, true); - player.destroyItemByItemId("LetterCollector", N, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", A, 1, player, true); - player.destroyItemByItemId("LetterCollector", G, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", II, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(LINEAGE_II_REWARDS), player, true); - break; - } - case 1: - { - if ((inventory.getInventoryItemCount(D, -1) < 1) || // - (inventory.getInventoryItemCount(E, -1) < 1) || // - (inventory.getInventoryItemCount(A, -1) < 1) || // - (inventory.getInventoryItemCount(T, -1) < 1) || // - (inventory.getInventoryItemCount(H, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", D, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", A, 1, player, true); - player.destroyItemByItemId("LetterCollector", T, 1, player, true); - player.destroyItemByItemId("LetterCollector", H, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(DEATH_REWARDS), player, true); - break; - } - case 2: - { - if ((inventory.getInventoryItemCount(K, -1) < 1) || // - (inventory.getInventoryItemCount(N, -1) < 1) || // - (inventory.getInventoryItemCount(I, -1) < 1) || // - (inventory.getInventoryItemCount(G, -1) < 1) || // - (inventory.getInventoryItemCount(H, -1) < 1) || // - (inventory.getInventoryItemCount(T, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", K, 1, player, true); - player.destroyItemByItemId("LetterCollector", N, 1, player, true); - player.destroyItemByItemId("LetterCollector", I, 1, player, true); - player.destroyItemByItemId("LetterCollector", G, 1, player, true); - player.destroyItemByItemId("LetterCollector", H, 1, player, true); - player.destroyItemByItemId("LetterCollector", T, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(KNIGHT_REWARDS), player, true); - break; - } - case 3: - { - if ((inventory.getInventoryItemCount(S, -1) < 1) || // - (inventory.getInventoryItemCount(U, -1) < 1) || // - (inventory.getInventoryItemCount(M, -1) < 2) || // - (inventory.getInventoryItemCount(E, -1) < 1) || // - (inventory.getInventoryItemCount(R, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", S, 1, player, true); - player.destroyItemByItemId("LetterCollector", U, 1, player, true); - player.destroyItemByItemId("LetterCollector", M, 1, player, true); - player.destroyItemByItemId("LetterCollector", M, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", R, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(SUMMER_REWARDS), player, true); - break; + return; } } + for (ItemHolder destroyLetter : LetterCollectorManager.getInstance().getWord(_wordId)) + { + if (!player.destroyItemByItemId("LetterCollector", destroyLetter.getId(), destroyLetter.getCount(), player, true)) + { + return; + } + } + + final ItemHolder rewardItem = getRandomReward(lcrh.getRewards(), lcrh.getChance()); + if (rewardItem == null) + { + player.sendPacket(new SystemMessage(SystemMessageId.NOTHING_HAPPENED)); + return; + } + + player.addItem("LetterCollector", rewardItem.getId(), rewardItem.getCount(), player, true); } - private ItemChanceHolder getRandomReward(ItemChanceHolder[] rewards) + private ItemHolder getRandomReward(List rewards, double holderChance) { - ItemChanceHolder reward = null; - while (reward == null) + final double chance = Rnd.get(holderChance); + double itemChance = 0; + for (ItemChanceHolder rewardItem : rewards) { - final ItemChanceHolder random = rewards[Rnd.get(rewards.length)]; - if ((Rnd.get(100) < random.getChance()) && (ItemTable.getInstance().getTemplate(random.getId()) != null)) + itemChance += rewardItem.getChance(); + if (chance <= itemChance) { - reward = random; + if (rewardItem.getId() == -1) + { + return null; + } + return rewardItem; } } - return reward; + return null; } } \ No newline at end of file diff --git a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java index ce54e4cf05..991437e881 100644 --- a/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java +++ b/L2J_Mobius_Essence_5.2_FrostLord/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java @@ -16,7 +16,10 @@ */ package org.l2jmobius.gameserver.network.serverpackets; +import org.l2jmobius.Config; import org.l2jmobius.commons.network.PacketWriter; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; +import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.network.OutgoingPackets; /** @@ -24,12 +27,11 @@ import org.l2jmobius.gameserver.network.OutgoingPackets; */ public class ExLetterCollectorUI implements IClientOutgoingPacket { - public static final ExLetterCollectorUI STATIC_PACKET = new ExLetterCollectorUI(); + final int _minimumLevel; - private static final int LETTER_COLLECTOR_MIN_LEVEL = 5; - - private ExLetterCollectorUI() + public ExLetterCollectorUI(Player player) { + _minimumLevel = player.getLevel() <= LetterCollectorManager.getInstance().getMaxLevel() ? LetterCollectorManager.getInstance().getMinLevel() : Config.PLAYER_MAXIMUM_LEVEL; } @Override @@ -37,7 +39,7 @@ public class ExLetterCollectorUI implements IClientOutgoingPacket { OutgoingPackets.EX_LETTER_COLLECTOR_UI_LAUNCHER.writeId(packet); packet.writeC(1); // enabled (0x00 - no, 0x01 -yes) - packet.writeD(LETTER_COLLECTOR_MIN_LEVEL); // Minimum Level + packet.writeD(_minimumLevel); // Minimum Level return true; } } \ No newline at end of file diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/events/LetterCollector/LetterCollector.java b/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/events/LetterCollector/LetterCollector.java index 9343546f2b..a181a33a0f 100644 --- a/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/events/LetterCollector/LetterCollector.java +++ b/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/events/LetterCollector/LetterCollector.java @@ -16,22 +16,122 @@ */ package events.LetterCollector; +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import org.w3c.dom.Document; + +import org.l2jmobius.commons.util.IXmlReader; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; +import org.l2jmobius.gameserver.model.StatSet; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.events.EventType; import org.l2jmobius.gameserver.model.events.ListenerRegisterType; import org.l2jmobius.gameserver.model.events.annotations.RegisterEvent; import org.l2jmobius.gameserver.model.events.annotations.RegisterType; import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin; +import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.quest.LongTimeEvent; import org.l2jmobius.gameserver.network.serverpackets.ExLetterCollectorUI; /** * @author Mobius */ -public class LetterCollector extends LongTimeEvent +public class LetterCollector extends LongTimeEvent implements IXmlReader { private LetterCollector() { + if (isEventPeriod()) + { + load(); + LetterCollectorManager.getInstance().init(); + } + } + + public void reloadRewards() + { + LetterCollectorManager.getInstance().resetField(); + load(); + } + + @Override + public synchronized void load() + { + parseDatapackFile("data/scripts/events/LetterCollector/rewards.xml"); + } + + @Override + public void parseDocument(Document doc, File f) + { + final AtomicInteger minimumLevel = new AtomicInteger(); + final AtomicInteger maximumLevel = new AtomicInteger(); + final Map letters = new HashMap<>(); + forEach(doc, "list", listNode -> + { + forEach(listNode, "params", paramNode -> + { + forEach(paramNode, "minimum", minimumLevelNode -> minimumLevel.set(new StatSet(parseAttributes(minimumLevelNode)).getInt("level"))); + forEach(paramNode, "maximum", maximumLevelNode -> maximumLevel.set(new StatSet(parseAttributes(maximumLevelNode)).getInt("level"))); + }); + forEach(listNode, "letters", letterNode -> forEach(letterNode, "item", itemNode -> + { + StatSet letterSet = new StatSet(parseAttributes(itemNode)); + letters.put(letterSet.getString("name"), letterSet.getInt("id")); + })); + forEach(listNode, "reward", rewardNode -> + { + final int id = new StatSet(parseAttributes(rewardNode)).getInt("id"); + final AtomicReference> word = new AtomicReference<>(new ArrayList<>()); + final AtomicReference> rewards = new AtomicReference<>(new ArrayList<>()); + AtomicBoolean needToSumAllChance = new AtomicBoolean(false); + AtomicReference chanceSum = new AtomicReference<>(0.0); + forEach(rewardNode, "word", wordNode -> + { + String[] letter = wordNode.getTextContent().trim().split(";"); + for (String token : letter) + { + int count = 1; + for (ItemHolder check : word.get()) + { + if (check.getId() == letters.get(token)) + { + count = Math.toIntExact(check.getCount() + 1); + word.get().remove(check); + break; + } + } + word.get().add(new ItemHolder(letters.get(token), count)); + } + }); + forEach(rewardNode, "rewards", rewardsNode -> + { + needToSumAllChance.set(new StatSet(parseAttributes(rewardsNode)).getBoolean("sumChances")); + forEach(rewardsNode, "item", itemNode -> + { + StatSet itemSet = new StatSet(parseAttributes(itemNode)); + final double chance = itemSet.getDouble("chance"); + if (needToSumAllChance.get()) + { + chanceSum.set(chanceSum.get() + chance); + } + rewards.get().add(new ItemChanceHolder(itemSet.getInt("id"), chance, itemSet.getLong("count"), (byte) itemSet.getInt("enchantLevel", 0))); + }); + }); + LetterCollectorManager lcm = LetterCollectorManager.getInstance(); + lcm.addWords(id, word.get()); + lcm.addRewards(id, new LetterCollectorManager.LetterCollectorRewardHolder(rewards.get(), chanceSum.get() == 0d ? 100d : chanceSum.get())); + lcm.setLetters(letters); + lcm.setMinLevel(minimumLevel.get()); + lcm.setMaxLevel(maximumLevel.get()); + }); + }); } @RegisterEvent(EventType.ON_PLAYER_LOGIN) @@ -46,7 +146,7 @@ public class LetterCollector extends LongTimeEvent final Player player = event.getPlayer(); if (player != null) { - player.sendPacket(ExLetterCollectorUI.STATIC_PACKET); + player.sendPacket(new ExLetterCollectorUI(player)); } } diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/events/LetterCollector/config.xml b/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/events/LetterCollector/config.xml index 03adf0460f..be41235de7 100644 --- a/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/events/LetterCollector/config.xml +++ b/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/events/LetterCollector/config.xml @@ -1,7 +1,5 @@ - - diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/events/LetterCollector/rewards.xml b/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/events/LetterCollector/rewards.xml new file mode 100644 index 0000000000..602c12bf39 --- /dev/null +++ b/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/events/LetterCollector/rewards.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + L;I;N;E;A;G;E;II + + + + + + + + + + + + + + + + + + + + + + + + D;E;A;T;H + + + + + + + + + + + + + + + + + + + + K;N;I;G;H;T + + + + + + + + + + + + + + + + + + + + S;U;M;M;E;R + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/events/LetterCollector/rewards.xsd b/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/events/LetterCollector/rewards.xsd new file mode 100644 index 0000000000..5d9feae899 --- /dev/null +++ b/L2J_Mobius_Essence_6.1_BattleChronicle/dist/game/data/scripts/events/LetterCollector/rewards.xsd @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java new file mode 100644 index 0000000000..a90c9e0753 --- /dev/null +++ b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java @@ -0,0 +1,169 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.l2jmobius.gameserver.instancemanager.events; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import org.l2jmobius.Config; +import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; + +/** + * @author Index + */ +public class LetterCollectorManager +{ + protected static final Logger LOGGER = Logger.getLogger(LetterCollectorManager.class.getName()); + + private final Map _rewards = new HashMap<>(); + private final Map> _words = new HashMap<>(); + private final Map _letter = new HashMap<>(); + private final Map _needToSumAllChance = new HashMap<>(); + + private int _minLevel = 1; + private int _maxLevel = Config.PLAYER_MAXIMUM_LEVEL; + + protected LetterCollectorManager() + { + } + + public void init() + { + LOGGER.info(getClass().getSimpleName() + ": Loaded " + _rewards.size() + " words."); + LOGGER.info(getClass().getSimpleName() + ": Loaded " + _letter.size() + " letters."); + } + + public int getMinLevel() + { + return _minLevel; + } + + public void setMinLevel(int minLevel) + { + _minLevel = minLevel; + } + + public int getMaxLevel() + { + return _maxLevel; + } + + public void setMaxLevel(int maxLevel) + { + if (maxLevel < 1) + { + _maxLevel = Config.PLAYER_MAXIMUM_LEVEL; + } + else + { + _maxLevel = maxLevel; + } + } + + public LetterCollectorRewardHolder getRewards(int id) + { + return _rewards.get(id); + } + + public List getWord(int id) + { + return _words.get(id); + } + + public void setRewards(Map rewards) + { + _rewards.putAll(rewards); + } + + public void setWords(Map> words) + { + _words.putAll(words); + } + + public void addRewards(int id, LetterCollectorRewardHolder rewards) + { + _rewards.put(id, rewards); + } + + public void addWords(int id, List words) + { + _words.put(id, words); + } + + public void resetField() + { + _minLevel = 1; + _rewards.clear(); + _words.clear(); + _needToSumAllChance.clear(); + } + + public void setLetters(Map letters) + { + _letter.putAll(letters); + } + + public Map getLetters() + { + return _letter; + } + + public void setNeedToSumAllChance(int id, boolean needToSumAllChance) + { + _needToSumAllChance.put(id, needToSumAllChance); + } + + public boolean getNeedToSumAllChance(int id) + { + return _needToSumAllChance.get(id); + } + + public static class LetterCollectorRewardHolder + { + final List _rewards; + final double _chance; + + public LetterCollectorRewardHolder(List rewards, double chance) + { + _rewards = rewards; + _chance = chance; + } + + public List getRewards() + { + return _rewards; + } + + public double getChance() + { + return _chance; + } + } + + public static LetterCollectorManager getInstance() + { + return SingletonHolder.INSTANCE; + } + + private static class SingletonHolder + { + protected static final LetterCollectorManager INSTANCE = new LetterCollectorManager(); + } +} \ No newline at end of file diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java index bc986078ff..b1e8c6b991 100644 --- a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java +++ b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java @@ -16,114 +16,24 @@ */ package org.l2jmobius.gameserver.network.clientpackets; +import java.util.List; + import org.l2jmobius.commons.network.PacketReader; import org.l2jmobius.commons.util.Rnd; -import org.l2jmobius.gameserver.data.ItemTable; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.itemcontainer.PlayerInventory; import org.l2jmobius.gameserver.network.GameClient; +import org.l2jmobius.gameserver.network.SystemMessageId; +import org.l2jmobius.gameserver.network.serverpackets.SystemMessage; /** * @author Index, Mobius */ public class ExLetterCollectorTakeReward implements IClientIncomingPacket { - // Items - private static final int A = 3875; - private static final int E = 3877; - private static final int G = 3879; - private static final int I = 3881; - private static final int L = 3882; - private static final int N = 3883; - private static final int R = 3885; - private static final int M = 34956; - private static final int S = 3886; - private static final int T = 3886; - private static final int H = 3880; - private static final int II = 3888; - private static final int D = 92021; - private static final int K = 93412; - private static final int U = 93413; - - // Rewards - private static final ItemChanceHolder[] LINEAGE_II_REWARDS = - { - new ItemChanceHolder(49683, 5, 1), // Talisman of Baium - new ItemChanceHolder(91119, 5, 1), // Ignis' Necklace - new ItemChanceHolder(91117, 5, 1), // Nebula's Necklace - new ItemChanceHolder(91121, 5, 1), // Procella's Necklace - new ItemChanceHolder(91123, 5, 1), // Petram's Necklace - new ItemChanceHolder(91952, 5, 1), // Ring of Insolance - new ItemChanceHolder(91953, 5, 1), // Dragon Valley's Earring - new ItemChanceHolder(91035, 15, 1), // Water Spirit Ore - new ItemChanceHolder(91036, 15, 1), // Fire Spirit Ore - new ItemChanceHolder(91037, 15, 1), // Wind Spirit Ore - new ItemChanceHolder(91038, 15, 1), // Earth Spirit Ore - new ItemChanceHolder(91641, 30, 1), // Sayha's Blessing - new ItemChanceHolder(49674, 30, 1), // XP Growth Scroll - new ItemChanceHolder(90907, 30, 5), // Soulshot Ticket - new ItemChanceHolder(91757, 30, 1), // Magic Lamp Charging Potion - new ItemChanceHolder(91974, 30, 10), // HP Recovery Potion - new ItemChanceHolder(3031, 30, 10), // Spirit Ore - }; - private static final ItemChanceHolder[] DEATH_REWARDS = - { - new ItemChanceHolder(91012, 5, 1), // Top-grade A-grade Weapon Pack - new ItemChanceHolder(93459, 5, 1), // A-grade Armor Pack - Majestic Equipment - new ItemChanceHolder(93460, 5, 1), // A-grade Armor Pack - Equipment of Nightmare - new ItemChanceHolder(93461, 5, 1), // A-grade Armor Pack - Tallum Equipment - new ItemChanceHolder(93462, 5, 1), // A-grade Armor Pack - Dark Crystal Equipment - new ItemChanceHolder(90015, 15, 1), // Top-grade Life Stone - Weapon - new ItemChanceHolder(93100, 15, 1), // Mid-grade Life Stone Shield / Sigil - new ItemChanceHolder(91938, 15, 1), // Primeval Isle's Time Stone - new ItemChanceHolder(93699, 15, 1), // Charging Stone of Random Crafting - 1 charge - new ItemChanceHolder(91641, 30, 1), // Sayha's Blessing - new ItemChanceHolder(49674, 30, 1), // XP Growth Scroll - new ItemChanceHolder(90907, 30, 5), // Soulshot Ticket - new ItemChanceHolder(91757, 30, 1), // Magic Lamp Charging Potion - new ItemChanceHolder(91974, 30, 10), // HP Recovery Potion - new ItemChanceHolder(3031, 30, 10), // Spirit Ore - }; - private static final ItemChanceHolder[] KNIGHT_REWARDS = - { - new ItemChanceHolder(93103, 5, 1), // Spellbook: Divine Beam - new ItemChanceHolder(92401, 5, 1), // Spellbook: White Guardian - new ItemChanceHolder(91945, 5, 1), // Book of Shadows - new ItemChanceHolder(91944, 5, 1), // Book of Light - new ItemChanceHolder(91943, 15, 1), // Crystal of Shadows - new ItemChanceHolder(91942, 15, 1), // Crystal of Light - new ItemChanceHolder(8619, 15, 1), // Buff Expansion Book Lv. 2 - new ItemChanceHolder(8620, 15, 1), // Buff Expansion Book Lv. 3 - new ItemChanceHolder(90045, 15, 1), // Magical Tablet - new ItemChanceHolder(91641, 30, 1), // Sayha's Blessing - new ItemChanceHolder(49674, 30, 1), // XP Growth Scroll - new ItemChanceHolder(90907, 30, 5), // Soulshot Ticket - new ItemChanceHolder(91757, 30, 1), // Magic Lamp Charging Potion - new ItemChanceHolder(91974, 30, 10), // HP Recovery Potion - new ItemChanceHolder(3031, 30, 10), // Spirit Ore - }; - private static final ItemChanceHolder[] SUMMER_REWARDS = - { - new ItemChanceHolder(93976, 5, 1), // Blessed Scroll: Enchant A-grade Weapon - new ItemChanceHolder(93977, 5, 1), // Blessed Scroll: Enchant A-grade Armor - new ItemChanceHolder(729, 5, 1), // Scroll: Enchant A-grade Weapon - new ItemChanceHolder(730, 5, 1), // Scroll: Enchant A-grade Armor - new ItemChanceHolder(947, 15, 1), // Scroll: Enchant B-grade Weapon - new ItemChanceHolder(948, 15, 1), // Scroll: Enchant B-grade Armor - new ItemChanceHolder(91967, 15, 1), // Scroll: Enchant Dragon Valley's Earring - new ItemChanceHolder(91966, 15, 1), // Scroll: Enchant Ring of Insolance - new ItemChanceHolder(91641, 30, 1), // Sayha's Blessing - new ItemChanceHolder(91780, 30, 1), // Battle Scroll - new ItemChanceHolder(93486, 30, 1), // Combat Scroll - new ItemChanceHolder(49674, 30, 1), // XP Growth Scroll - new ItemChanceHolder(90907, 30, 5), // Soulshot Ticket - new ItemChanceHolder(1538, 30, 1), // Improved Scroll of Escape - new ItemChanceHolder(91757, 30, 1), // Magic Lamp Charging Potion - new ItemChanceHolder(91974, 30, 10), // HP Recovery Potion - new ItemChanceHolder(3031, 30, 10), // Spirit Ore - }; - private int _wordId; @Override @@ -148,110 +58,53 @@ public class ExLetterCollectorTakeReward implements IClientIncomingPacket return; } - switch (_wordId) + final LetterCollectorManager.LetterCollectorRewardHolder lcrh = LetterCollectorManager.getInstance().getRewards(_wordId); + if (lcrh == null) { - case 0: + return; + } + + for (ItemHolder needLetter : LetterCollectorManager.getInstance().getWord(_wordId)) + { + if (inventory.getInventoryItemCount(needLetter.getId(), -1) < needLetter.getCount()) { - if ((inventory.getInventoryItemCount(L, -1) < 1) || // - (inventory.getInventoryItemCount(I, -1) < 1) || // - (inventory.getInventoryItemCount(N, -1) < 1) || // - (inventory.getInventoryItemCount(E, -1) < 2) || // - (inventory.getInventoryItemCount(A, -1) < 1) || // - (inventory.getInventoryItemCount(G, -1) < 1) || // - (inventory.getInventoryItemCount(II, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", L, 1, player, true); - player.destroyItemByItemId("LetterCollector", I, 1, player, true); - player.destroyItemByItemId("LetterCollector", N, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", A, 1, player, true); - player.destroyItemByItemId("LetterCollector", G, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", II, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(LINEAGE_II_REWARDS), player, true); - break; - } - case 1: - { - if ((inventory.getInventoryItemCount(D, -1) < 1) || // - (inventory.getInventoryItemCount(E, -1) < 1) || // - (inventory.getInventoryItemCount(A, -1) < 1) || // - (inventory.getInventoryItemCount(T, -1) < 1) || // - (inventory.getInventoryItemCount(H, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", D, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", A, 1, player, true); - player.destroyItemByItemId("LetterCollector", T, 1, player, true); - player.destroyItemByItemId("LetterCollector", H, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(DEATH_REWARDS), player, true); - break; - } - case 2: - { - if ((inventory.getInventoryItemCount(K, -1) < 1) || // - (inventory.getInventoryItemCount(N, -1) < 1) || // - (inventory.getInventoryItemCount(I, -1) < 1) || // - (inventory.getInventoryItemCount(G, -1) < 1) || // - (inventory.getInventoryItemCount(H, -1) < 1) || // - (inventory.getInventoryItemCount(T, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", K, 1, player, true); - player.destroyItemByItemId("LetterCollector", N, 1, player, true); - player.destroyItemByItemId("LetterCollector", I, 1, player, true); - player.destroyItemByItemId("LetterCollector", G, 1, player, true); - player.destroyItemByItemId("LetterCollector", H, 1, player, true); - player.destroyItemByItemId("LetterCollector", T, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(KNIGHT_REWARDS), player, true); - break; - } - case 3: - { - if ((inventory.getInventoryItemCount(S, -1) < 1) || // - (inventory.getInventoryItemCount(U, -1) < 1) || // - (inventory.getInventoryItemCount(M, -1) < 2) || // - (inventory.getInventoryItemCount(E, -1) < 1) || // - (inventory.getInventoryItemCount(R, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", S, 1, player, true); - player.destroyItemByItemId("LetterCollector", U, 1, player, true); - player.destroyItemByItemId("LetterCollector", M, 1, player, true); - player.destroyItemByItemId("LetterCollector", M, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", R, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(SUMMER_REWARDS), player, true); - break; + return; } } + for (ItemHolder destroyLetter : LetterCollectorManager.getInstance().getWord(_wordId)) + { + if (!player.destroyItemByItemId("LetterCollector", destroyLetter.getId(), destroyLetter.getCount(), player, true)) + { + return; + } + } + + final ItemHolder rewardItem = getRandomReward(lcrh.getRewards(), lcrh.getChance()); + if (rewardItem == null) + { + player.sendPacket(new SystemMessage(SystemMessageId.NOTHING_HAPPENED)); + return; + } + + player.addItem("LetterCollector", rewardItem.getId(), rewardItem.getCount(), player, true); } - private ItemChanceHolder getRandomReward(ItemChanceHolder[] rewards) + private ItemHolder getRandomReward(List rewards, double holderChance) { - ItemChanceHolder reward = null; - while (reward == null) + final double chance = Rnd.get(holderChance); + double itemChance = 0; + for (ItemChanceHolder rewardItem : rewards) { - final ItemChanceHolder random = rewards[Rnd.get(rewards.length)]; - if ((Rnd.get(100) < random.getChance()) && (ItemTable.getInstance().getTemplate(random.getId()) != null)) + itemChance += rewardItem.getChance(); + if (chance <= itemChance) { - reward = random; + if (rewardItem.getId() == -1) + { + return null; + } + return rewardItem; } } - return reward; + return null; } } \ No newline at end of file diff --git a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java index ce54e4cf05..991437e881 100644 --- a/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java +++ b/L2J_Mobius_Essence_6.1_BattleChronicle/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java @@ -16,7 +16,10 @@ */ package org.l2jmobius.gameserver.network.serverpackets; +import org.l2jmobius.Config; import org.l2jmobius.commons.network.PacketWriter; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; +import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.network.OutgoingPackets; /** @@ -24,12 +27,11 @@ import org.l2jmobius.gameserver.network.OutgoingPackets; */ public class ExLetterCollectorUI implements IClientOutgoingPacket { - public static final ExLetterCollectorUI STATIC_PACKET = new ExLetterCollectorUI(); + final int _minimumLevel; - private static final int LETTER_COLLECTOR_MIN_LEVEL = 5; - - private ExLetterCollectorUI() + public ExLetterCollectorUI(Player player) { + _minimumLevel = player.getLevel() <= LetterCollectorManager.getInstance().getMaxLevel() ? LetterCollectorManager.getInstance().getMinLevel() : Config.PLAYER_MAXIMUM_LEVEL; } @Override @@ -37,7 +39,7 @@ public class ExLetterCollectorUI implements IClientOutgoingPacket { OutgoingPackets.EX_LETTER_COLLECTOR_UI_LAUNCHER.writeId(packet); packet.writeC(1); // enabled (0x00 - no, 0x01 -yes) - packet.writeD(LETTER_COLLECTOR_MIN_LEVEL); // Minimum Level + packet.writeD(_minimumLevel); // Minimum Level return true; } } \ No newline at end of file diff --git a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/events/LetterCollector/LetterCollector.java b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/events/LetterCollector/LetterCollector.java index 9343546f2b..a181a33a0f 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/events/LetterCollector/LetterCollector.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/events/LetterCollector/LetterCollector.java @@ -16,22 +16,122 @@ */ package events.LetterCollector; +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import org.w3c.dom.Document; + +import org.l2jmobius.commons.util.IXmlReader; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; +import org.l2jmobius.gameserver.model.StatSet; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.events.EventType; import org.l2jmobius.gameserver.model.events.ListenerRegisterType; import org.l2jmobius.gameserver.model.events.annotations.RegisterEvent; import org.l2jmobius.gameserver.model.events.annotations.RegisterType; import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin; +import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.quest.LongTimeEvent; import org.l2jmobius.gameserver.network.serverpackets.ExLetterCollectorUI; /** * @author Mobius */ -public class LetterCollector extends LongTimeEvent +public class LetterCollector extends LongTimeEvent implements IXmlReader { private LetterCollector() { + if (isEventPeriod()) + { + load(); + LetterCollectorManager.getInstance().init(); + } + } + + public void reloadRewards() + { + LetterCollectorManager.getInstance().resetField(); + load(); + } + + @Override + public synchronized void load() + { + parseDatapackFile("data/scripts/events/LetterCollector/rewards.xml"); + } + + @Override + public void parseDocument(Document doc, File f) + { + final AtomicInteger minimumLevel = new AtomicInteger(); + final AtomicInteger maximumLevel = new AtomicInteger(); + final Map letters = new HashMap<>(); + forEach(doc, "list", listNode -> + { + forEach(listNode, "params", paramNode -> + { + forEach(paramNode, "minimum", minimumLevelNode -> minimumLevel.set(new StatSet(parseAttributes(minimumLevelNode)).getInt("level"))); + forEach(paramNode, "maximum", maximumLevelNode -> maximumLevel.set(new StatSet(parseAttributes(maximumLevelNode)).getInt("level"))); + }); + forEach(listNode, "letters", letterNode -> forEach(letterNode, "item", itemNode -> + { + StatSet letterSet = new StatSet(parseAttributes(itemNode)); + letters.put(letterSet.getString("name"), letterSet.getInt("id")); + })); + forEach(listNode, "reward", rewardNode -> + { + final int id = new StatSet(parseAttributes(rewardNode)).getInt("id"); + final AtomicReference> word = new AtomicReference<>(new ArrayList<>()); + final AtomicReference> rewards = new AtomicReference<>(new ArrayList<>()); + AtomicBoolean needToSumAllChance = new AtomicBoolean(false); + AtomicReference chanceSum = new AtomicReference<>(0.0); + forEach(rewardNode, "word", wordNode -> + { + String[] letter = wordNode.getTextContent().trim().split(";"); + for (String token : letter) + { + int count = 1; + for (ItemHolder check : word.get()) + { + if (check.getId() == letters.get(token)) + { + count = Math.toIntExact(check.getCount() + 1); + word.get().remove(check); + break; + } + } + word.get().add(new ItemHolder(letters.get(token), count)); + } + }); + forEach(rewardNode, "rewards", rewardsNode -> + { + needToSumAllChance.set(new StatSet(parseAttributes(rewardsNode)).getBoolean("sumChances")); + forEach(rewardsNode, "item", itemNode -> + { + StatSet itemSet = new StatSet(parseAttributes(itemNode)); + final double chance = itemSet.getDouble("chance"); + if (needToSumAllChance.get()) + { + chanceSum.set(chanceSum.get() + chance); + } + rewards.get().add(new ItemChanceHolder(itemSet.getInt("id"), chance, itemSet.getLong("count"), (byte) itemSet.getInt("enchantLevel", 0))); + }); + }); + LetterCollectorManager lcm = LetterCollectorManager.getInstance(); + lcm.addWords(id, word.get()); + lcm.addRewards(id, new LetterCollectorManager.LetterCollectorRewardHolder(rewards.get(), chanceSum.get() == 0d ? 100d : chanceSum.get())); + lcm.setLetters(letters); + lcm.setMinLevel(minimumLevel.get()); + lcm.setMaxLevel(maximumLevel.get()); + }); + }); } @RegisterEvent(EventType.ON_PLAYER_LOGIN) @@ -46,7 +146,7 @@ public class LetterCollector extends LongTimeEvent final Player player = event.getPlayer(); if (player != null) { - player.sendPacket(ExLetterCollectorUI.STATIC_PACKET); + player.sendPacket(new ExLetterCollectorUI(player)); } } diff --git a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/events/LetterCollector/config.xml b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/events/LetterCollector/config.xml index bef0cbd482..cac293677a 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/events/LetterCollector/config.xml +++ b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/events/LetterCollector/config.xml @@ -1,8 +1,5 @@ - - - diff --git a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/events/LetterCollector/rewards.xml b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/events/LetterCollector/rewards.xml new file mode 100644 index 0000000000..89b068669f --- /dev/null +++ b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/events/LetterCollector/rewards.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + N;C;J;A;P;A;N;XX;T;H + + + + + + + + + + + + + + + + + + + + + + + + L;I;N;E;A;G;E;II + + + + + + + + + + + + + + + + + + + + T;O;G;E;T;H;E;R + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/events/LetterCollector/rewards.xsd b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/events/LetterCollector/rewards.xsd new file mode 100644 index 0000000000..10debf7a8b --- /dev/null +++ b/L2J_Mobius_Essence_6.2_Vanguard/dist/game/data/scripts/events/LetterCollector/rewards.xsd @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java new file mode 100644 index 0000000000..a90c9e0753 --- /dev/null +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/instancemanager/events/LetterCollectorManager.java @@ -0,0 +1,169 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.l2jmobius.gameserver.instancemanager.events; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import org.l2jmobius.Config; +import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; + +/** + * @author Index + */ +public class LetterCollectorManager +{ + protected static final Logger LOGGER = Logger.getLogger(LetterCollectorManager.class.getName()); + + private final Map _rewards = new HashMap<>(); + private final Map> _words = new HashMap<>(); + private final Map _letter = new HashMap<>(); + private final Map _needToSumAllChance = new HashMap<>(); + + private int _minLevel = 1; + private int _maxLevel = Config.PLAYER_MAXIMUM_LEVEL; + + protected LetterCollectorManager() + { + } + + public void init() + { + LOGGER.info(getClass().getSimpleName() + ": Loaded " + _rewards.size() + " words."); + LOGGER.info(getClass().getSimpleName() + ": Loaded " + _letter.size() + " letters."); + } + + public int getMinLevel() + { + return _minLevel; + } + + public void setMinLevel(int minLevel) + { + _minLevel = minLevel; + } + + public int getMaxLevel() + { + return _maxLevel; + } + + public void setMaxLevel(int maxLevel) + { + if (maxLevel < 1) + { + _maxLevel = Config.PLAYER_MAXIMUM_LEVEL; + } + else + { + _maxLevel = maxLevel; + } + } + + public LetterCollectorRewardHolder getRewards(int id) + { + return _rewards.get(id); + } + + public List getWord(int id) + { + return _words.get(id); + } + + public void setRewards(Map rewards) + { + _rewards.putAll(rewards); + } + + public void setWords(Map> words) + { + _words.putAll(words); + } + + public void addRewards(int id, LetterCollectorRewardHolder rewards) + { + _rewards.put(id, rewards); + } + + public void addWords(int id, List words) + { + _words.put(id, words); + } + + public void resetField() + { + _minLevel = 1; + _rewards.clear(); + _words.clear(); + _needToSumAllChance.clear(); + } + + public void setLetters(Map letters) + { + _letter.putAll(letters); + } + + public Map getLetters() + { + return _letter; + } + + public void setNeedToSumAllChance(int id, boolean needToSumAllChance) + { + _needToSumAllChance.put(id, needToSumAllChance); + } + + public boolean getNeedToSumAllChance(int id) + { + return _needToSumAllChance.get(id); + } + + public static class LetterCollectorRewardHolder + { + final List _rewards; + final double _chance; + + public LetterCollectorRewardHolder(List rewards, double chance) + { + _rewards = rewards; + _chance = chance; + } + + public List getRewards() + { + return _rewards; + } + + public double getChance() + { + return _chance; + } + } + + public static LetterCollectorManager getInstance() + { + return SingletonHolder.INSTANCE; + } + + private static class SingletonHolder + { + protected static final LetterCollectorManager INSTANCE = new LetterCollectorManager(); + } +} \ No newline at end of file diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java index c742d6977b..8a05ba0b8d 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/clientpackets/ExLetterCollectorTakeReward.java @@ -16,104 +16,24 @@ */ package org.l2jmobius.gameserver.network.clientpackets; +import java.util.List; + import org.l2jmobius.commons.network.PacketReader; import org.l2jmobius.commons.util.Rnd; -import org.l2jmobius.gameserver.data.ItemTable; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.holders.ItemChanceHolder; +import org.l2jmobius.gameserver.model.holders.ItemHolder; import org.l2jmobius.gameserver.model.itemcontainer.PlayerInventory; import org.l2jmobius.gameserver.network.GameClient; +import org.l2jmobius.gameserver.network.SystemMessageId; +import org.l2jmobius.gameserver.network.serverpackets.SystemMessage; /** * @author Index, Mobius */ public class ExLetterCollectorTakeReward implements IClientIncomingPacket { - // Items - private static final int A = 3875; - private static final int C = 3876; - private static final int E = 3877; - // private static final int F = 3878; - private static final int G = 3879; - private static final int H = 3880; - private static final int I = 3881; - private static final int L = 3882; - private static final int N = 3883; - private static final int O = 3884; - private static final int R = 3885; - // private static final int S = 3886; - private static final int T = 3887; - private static final int II = 3888; - // private static final int Y = 13417; - // private static final int M = 34956; - private static final int J = 72343; - private static final int XX = 72344; - // private static final int D = 92021; - private static final int P = 92022; - // private static final int K = 93412; - // private static final int U = 93413; - // private static final int W = 93414; - - // Rewards - private static final ItemChanceHolder[] NCJAPAN_20TH_REWARDS = - { - new ItemChanceHolder(49683, 5, 1), // Talisman of Baium - new ItemChanceHolder(91119, 5, 1), // Ignis' Necklace - new ItemChanceHolder(91117, 5, 1), // Nebula's Necklace - new ItemChanceHolder(91121, 5, 1), // Procella's Necklace - new ItemChanceHolder(91123, 5, 1), // Petram's Necklace - new ItemChanceHolder(91952, 5, 1), // Ring of Insolance - new ItemChanceHolder(91953, 5, 1), // Dragon Valley's Earring - new ItemChanceHolder(91035, 15, 1), // Water Spirit Ore - new ItemChanceHolder(91036, 15, 1), // Fire Spirit Ore - new ItemChanceHolder(91037, 15, 1), // Wind Spirit Ore - new ItemChanceHolder(91038, 15, 1), // Earth Spirit Ore - new ItemChanceHolder(91641, 30, 1), // Sayha's Blessing - new ItemChanceHolder(49674, 30, 1), // XP Growth Scroll - new ItemChanceHolder(90907, 30, 5), // Soulshot Ticket - new ItemChanceHolder(91757, 30, 1), // Magic Lamp Charging Potion - new ItemChanceHolder(91974, 30, 10), // HP Recovery Potion - new ItemChanceHolder(3031, 30, 10), // Spirit Ore - }; - private static final ItemChanceHolder[] LINEAGE_II_REWARDS = - { - new ItemChanceHolder(91012, 5, 1), // Top-grade A-grade Weapon Pack - new ItemChanceHolder(93459, 5, 1), // A-grade Armor Pack - Majestic Equipment - new ItemChanceHolder(93460, 5, 1), // A-grade Armor Pack - Equipment of Nightmare - new ItemChanceHolder(93461, 5, 1), // A-grade Armor Pack - Tallum Equipment - new ItemChanceHolder(93462, 5, 1), // A-grade Armor Pack - Dark Crystal Equipment - new ItemChanceHolder(90015, 15, 1), // Top-grade Life Stone - Weapon - new ItemChanceHolder(93100, 15, 1), // Mid-grade Life Stone Shield / Sigil - new ItemChanceHolder(91938, 15, 1), // Primeval Isle's Time Stone - new ItemChanceHolder(93699, 15, 1), // Charging Stone of Random Crafting - 1 charge - new ItemChanceHolder(91641, 30, 1), // Sayha's Blessing - new ItemChanceHolder(49674, 30, 1), // XP Growth Scroll - new ItemChanceHolder(90907, 30, 5), // Soulshot Ticket - new ItemChanceHolder(91757, 30, 1), // Magic Lamp Charging Potion - new ItemChanceHolder(91974, 30, 10), // HP Recovery Potion - new ItemChanceHolder(3031, 30, 10), // Spirit Ore - }; - private static final ItemChanceHolder[] TOGETHER_REWARDS = - { - new ItemChanceHolder(93976, 5, 1), // Blessed Scroll: Enchant A-grade Weapon - new ItemChanceHolder(93977, 5, 1), // Blessed Scroll: Enchant A-grade Armor - new ItemChanceHolder(729, 5, 1), // Scroll: Enchant A-grade Weapon - new ItemChanceHolder(730, 5, 1), // Scroll: Enchant A-grade Armor - new ItemChanceHolder(947, 15, 1), // Scroll: Enchant B-grade Weapon - new ItemChanceHolder(948, 15, 1), // Scroll: Enchant B-grade Armor - new ItemChanceHolder(91967, 15, 1), // Scroll: Enchant Dragon Valley's Earring - new ItemChanceHolder(91966, 15, 1), // Scroll: Enchant Ring of Insolance - new ItemChanceHolder(91641, 30, 1), // Sayha's Blessing - new ItemChanceHolder(91780, 30, 1), // Battle Scroll - new ItemChanceHolder(93486, 30, 1), // Combat Scroll - new ItemChanceHolder(49674, 30, 1), // XP Growth Scroll - new ItemChanceHolder(90907, 30, 5), // Soulshot Ticket - new ItemChanceHolder(1538, 30, 1), // Improved Scroll of Escape - new ItemChanceHolder(91757, 30, 1), // Magic Lamp Charging Potion - new ItemChanceHolder(91974, 30, 10), // HP Recovery Potion - new ItemChanceHolder(3031, 30, 10), // Spirit Ore - }; - private int _wordId; @Override @@ -138,99 +58,53 @@ public class ExLetterCollectorTakeReward implements IClientIncomingPacket return; } - switch (_wordId) + final LetterCollectorManager.LetterCollectorRewardHolder lcrh = LetterCollectorManager.getInstance().getRewards(_wordId); + if (lcrh == null) { - case 0: + return; + } + + for (ItemHolder needLetter : LetterCollectorManager.getInstance().getWord(_wordId)) + { + if (inventory.getInventoryItemCount(needLetter.getId(), -1) < needLetter.getCount()) { - if ((inventory.getInventoryItemCount(N, -1) < 2) || // - (inventory.getInventoryItemCount(C, -1) < 1) || // - (inventory.getInventoryItemCount(J, -1) < 1) || // - (inventory.getInventoryItemCount(A, -1) < 2) || // - (inventory.getInventoryItemCount(P, -1) < 1) || // - (inventory.getInventoryItemCount(XX, -1) < 1) || // - (inventory.getInventoryItemCount(T, -1) < 1) || // - (inventory.getInventoryItemCount(H, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", N, 1, player, true); - player.destroyItemByItemId("LetterCollector", C, 1, player, true); - player.destroyItemByItemId("LetterCollector", J, 1, player, true); - player.destroyItemByItemId("LetterCollector", A, 1, player, true); - player.destroyItemByItemId("LetterCollector", P, 1, player, true); - player.destroyItemByItemId("LetterCollector", A, 1, player, true); - player.destroyItemByItemId("LetterCollector", N, 1, player, true); - player.destroyItemByItemId("LetterCollector", XX, 1, player, true); - player.destroyItemByItemId("LetterCollector", T, 1, player, true); - player.destroyItemByItemId("LetterCollector", H, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(NCJAPAN_20TH_REWARDS), player, true); - break; - } - case 1: - { - if ((inventory.getInventoryItemCount(L, -1) < 1) || // - (inventory.getInventoryItemCount(I, -1) < 1) || // - (inventory.getInventoryItemCount(N, -1) < 1) || // - (inventory.getInventoryItemCount(E, -1) < 2) || // - (inventory.getInventoryItemCount(A, -1) < 1) || // - (inventory.getInventoryItemCount(G, -1) < 1) || // - (inventory.getInventoryItemCount(II, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", L, 1, player, true); - player.destroyItemByItemId("LetterCollector", I, 1, player, true); - player.destroyItemByItemId("LetterCollector", N, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", A, 1, player, true); - player.destroyItemByItemId("LetterCollector", G, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", II, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(LINEAGE_II_REWARDS), player, true); - break; - } - case 2: - { - if ((inventory.getInventoryItemCount(T, -1) < 2) || // - (inventory.getInventoryItemCount(O, -1) < 1) || // - (inventory.getInventoryItemCount(G, -1) < 1) || // - (inventory.getInventoryItemCount(E, -1) < 2) || // - (inventory.getInventoryItemCount(H, -1) < 1) || // - (inventory.getInventoryItemCount(R, -1) < 1)) - { - return; - } - - player.destroyItemByItemId("LetterCollector", T, 1, player, true); - player.destroyItemByItemId("LetterCollector", O, 1, player, true); - player.destroyItemByItemId("LetterCollector", G, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", T, 1, player, true); - player.destroyItemByItemId("LetterCollector", H, 1, player, true); - player.destroyItemByItemId("LetterCollector", E, 1, player, true); - player.destroyItemByItemId("LetterCollector", R, 1, player, true); - - player.addItem("LetterCollector", getRandomReward(TOGETHER_REWARDS), player, true); - break; + return; } } + for (ItemHolder destroyLetter : LetterCollectorManager.getInstance().getWord(_wordId)) + { + if (!player.destroyItemByItemId("LetterCollector", destroyLetter.getId(), destroyLetter.getCount(), player, true)) + { + return; + } + } + + final ItemChanceHolder rewardItem = getRandomReward(lcrh.getRewards(), lcrh.getChance()); + if (rewardItem == null) + { + player.sendPacket(new SystemMessage(SystemMessageId.NOTHING_HAPPENED)); + return; + } + + player.addItem("LetterCollector", rewardItem.getId(), rewardItem.getCount(), rewardItem.getEnchantmentLevel(), player, true); } - private ItemChanceHolder getRandomReward(ItemChanceHolder[] rewards) + private ItemChanceHolder getRandomReward(List rewards, double holderChance) { - ItemChanceHolder reward = null; - while (reward == null) + final double chance = Rnd.get(holderChance); + double itemChance = 0; + for (ItemChanceHolder rewardItem : rewards) { - final ItemChanceHolder random = rewards[Rnd.get(rewards.length)]; - if ((Rnd.get(100) < random.getChance()) && (ItemTable.getInstance().getTemplate(random.getId()) != null)) + itemChance += rewardItem.getChance(); + if (chance <= itemChance) { - reward = random; + if (rewardItem.getId() == -1) + { + return null; + } + return rewardItem; } } - return reward; + return null; } } \ No newline at end of file diff --git a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java index ce54e4cf05..991437e881 100644 --- a/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java +++ b/L2J_Mobius_Essence_6.2_Vanguard/java/org/l2jmobius/gameserver/network/serverpackets/ExLetterCollectorUI.java @@ -16,7 +16,10 @@ */ package org.l2jmobius.gameserver.network.serverpackets; +import org.l2jmobius.Config; import org.l2jmobius.commons.network.PacketWriter; +import org.l2jmobius.gameserver.instancemanager.events.LetterCollectorManager; +import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.network.OutgoingPackets; /** @@ -24,12 +27,11 @@ import org.l2jmobius.gameserver.network.OutgoingPackets; */ public class ExLetterCollectorUI implements IClientOutgoingPacket { - public static final ExLetterCollectorUI STATIC_PACKET = new ExLetterCollectorUI(); + final int _minimumLevel; - private static final int LETTER_COLLECTOR_MIN_LEVEL = 5; - - private ExLetterCollectorUI() + public ExLetterCollectorUI(Player player) { + _minimumLevel = player.getLevel() <= LetterCollectorManager.getInstance().getMaxLevel() ? LetterCollectorManager.getInstance().getMinLevel() : Config.PLAYER_MAXIMUM_LEVEL; } @Override @@ -37,7 +39,7 @@ public class ExLetterCollectorUI implements IClientOutgoingPacket { OutgoingPackets.EX_LETTER_COLLECTOR_UI_LAUNCHER.writeId(packet); packet.writeC(1); // enabled (0x00 - no, 0x01 -yes) - packet.writeD(LETTER_COLLECTOR_MIN_LEVEL); // Minimum Level + packet.writeD(_minimumLevel); // Minimum Level return true; } } \ No newline at end of file