diff --git a/L2J_Mobius_Classic/dist/game/data/scripts/handlers/admincommandhandlers/AdminShowQuests.java b/L2J_Mobius_Classic/dist/game/data/scripts/handlers/admincommandhandlers/AdminShowQuests.java index 592bb7489e..a569d1fca6 100644 --- a/L2J_Mobius_Classic/dist/game/data/scripts/handlers/admincommandhandlers/AdminShowQuests.java +++ b/L2J_Mobius_Classic/dist/game/data/scripts/handlers/admincommandhandlers/AdminShowQuests.java @@ -321,6 +321,7 @@ public class AdminShowQuests implements IAdminCommandHandler { QuestState qs = target.getQuestState(val[0]); final String[] outval = new String[3]; + qs.setSimulated(false); if (val[1].equals("state")) { diff --git a/L2J_Mobius_Classic/dist/game/data/scripts/handlers/bypasshandlers/QuestLink.java b/L2J_Mobius_Classic/dist/game/data/scripts/handlers/bypasshandlers/QuestLink.java index 87d48e691d..599b59495d 100644 --- a/L2J_Mobius_Classic/dist/game/data/scripts/handlers/bypasshandlers/QuestLink.java +++ b/L2J_Mobius_Classic/dist/game/data/scripts/handlers/bypasshandlers/QuestLink.java @@ -87,9 +87,6 @@ public class QuestLink implements IBypassHandler final StringBuilder sbCanStart = new StringBuilder(128); final StringBuilder sbCantStart = new StringBuilder(128); final StringBuilder sbCompleted = new StringBuilder(128); - Quest lastSavedAvailableQuest = null; - Quest lastSavedProgressQuest = null; - int questCounter = 0; //@formatter:off final Set startingQuests = npc.getListeners(EventType.ON_NPC_QUEST_START).stream() @@ -126,8 +123,6 @@ public class QuestLink implements IBypassHandler sbCanStart.append(""); - lastSavedAvailableQuest = quest; - questCounter++; } else { @@ -135,17 +130,18 @@ public class QuestLink implements IBypassHandler sbCantStart.append(""); - questCounter++; } } + else if (Quest.getNoQuestMsg(player).equals(quest.onTalk(npc, player, true))) + { + continue; + } else if (qs.isStarted()) { sbStarted.append(""); sbStarted.append(""); - lastSavedProgressQuest = quest; - questCounter++; } else if (qs.isCompleted()) { @@ -153,21 +149,6 @@ public class QuestLink implements IBypassHandler sbCompleted.append(""); - questCounter++; - } - } - - if (questCounter == 1) - { - if (lastSavedProgressQuest != null) - { - showQuestWindow(player, npc, lastSavedProgressQuest.getName()); - return; - } - if (lastSavedAvailableQuest != null) - { - showQuestWindow(player, npc, lastSavedAvailableQuest.getName()); - return; } } @@ -268,6 +249,7 @@ public class QuestLink implements IBypassHandler .filter(Quest.class::isInstance) .map(Quest.class::cast) .filter(quest -> (quest.getId() > 0) && (quest.getId() < 20000) && (quest.getId() != 255)) + .filter(quest -> !Quest.getNoQuestMsg(player).equals(quest.onTalk(npc, player, true))) .distinct() .collect(Collectors.toSet()); //@formatter:on diff --git a/L2J_Mobius_Classic/dist/game/data/scripts/quests/Q00348_AnArrogantSearch/Q00348_AnArrogantSearch.java b/L2J_Mobius_Classic/dist/game/data/scripts/quests/Q00348_AnArrogantSearch/Q00348_AnArrogantSearch.java index b8fbd0bd82..7c8b70180a 100644 --- a/L2J_Mobius_Classic/dist/game/data/scripts/quests/Q00348_AnArrogantSearch/Q00348_AnArrogantSearch.java +++ b/L2J_Mobius_Classic/dist/game/data/scripts/quests/Q00348_AnArrogantSearch/Q00348_AnArrogantSearch.java @@ -357,8 +357,8 @@ public class Q00348_AnArrogantSearch extends Quest st.setMemoStateEx(1, st.getMemoStateEx(1) + 10); if ((st.getMemoStateEx(1) % 10) == 0) { - st.clearRadar(); - st.addRadar(-2908, 44128, -2712); + clearRadar(attacker); + addRadar(attacker, -2908, 44128, -2712); } else { @@ -1073,7 +1073,7 @@ public class Q00348_AnArrogantSearch extends Quest if (hasQuestItems(player, FIRST_KEY_OF_ARK)) { giveItems(player, BLOOD_OF_SAINT, 1); - st.clearRadar(); + clearRadar(player); if ((st.getMemoStateEx(1) % 10) == 0) { if (hasQuestItems(player, BOOK_OF_SAINT, BOUGH_OF_SAINT)) @@ -1119,7 +1119,7 @@ public class Q00348_AnArrogantSearch extends Quest { giveItems(player, BOOK_OF_SAINT, 1); takeItems(player, SECOND_KEY_OF_ARK, 1); - st.clearRadar(); + clearRadar(player); if ((st.getMemoStateEx(1) % 10) == 0) { if (hasQuestItems(player, BLOOD_OF_SAINT, BOUGH_OF_SAINT)) @@ -1172,7 +1172,7 @@ public class Q00348_AnArrogantSearch extends Quest { giveItems(player, BOUGH_OF_SAINT, 1); takeItems(player, THIRD_KEY_OF_ARK, 1); - st.clearRadar(); + clearRadar(player); if ((st.getMemoStateEx(1) % 10) == 0) { if (hasQuestItems(player, BLOOD_OF_SAINT, BOOK_OF_SAINT)) @@ -1224,7 +1224,7 @@ public class Q00348_AnArrogantSearch extends Quest if ((st.getMemoState() < 8) && (((st.getMemoStateEx(1) % 100) / 10) == 1) && !hasQuestItems(player, FIRST_KEY_OF_ARK) && !hasQuestItems(player, BLOOD_OF_SAINT)) { htmltext = "30980-02.html"; - st.clearRadar(); + clearRadar(player); if ((st.getMemoStateEx(1) % 10) != 0) { st.setCond(18, true); @@ -1237,7 +1237,7 @@ public class Q00348_AnArrogantSearch extends Quest else if ((st.getMemoState() < 8) && (((st.getMemoStateEx(1) % 100) / 10) == 2) && !hasQuestItems(player, FIRST_KEY_OF_ARK) && !hasQuestItems(player, BLOOD_OF_SAINT)) { giveItems(player, FIRST_KEY_OF_ARK, 1); - st.addRadar(-418, 44174, -3568); + addRadar(player, -418, 44174, -3568); htmltext = "30980-03.html"; } else if (hasAtLeastOneQuestItem(player, FIRST_KEY_OF_ARK, BLOOD_OF_SAINT)) @@ -1253,7 +1253,7 @@ public class Q00348_AnArrogantSearch extends Quest int i0 = st.getMemoStateEx(1) + 100; if ((i0 % 10) == 0) { - st.addRadar(181472, 7158, -2725); + addRadar(player, 181472, 7158, -2725); } else { @@ -1269,7 +1269,7 @@ public class Q00348_AnArrogantSearch extends Quest // retail typo if ((st.getMemoStateEx(1) % 10) == 0) { - st.addRadar(181472, 7158, -2725); + addRadar(player, 181472, 7158, -2725); } htmltext = "31001-03.html"; @@ -1278,7 +1278,7 @@ public class Q00348_AnArrogantSearch extends Quest { if ((st.getMemoStateEx(1) % 10) == 0) { - st.addRadar(181472, 7158, -2725); + addRadar(player, 181472, 7158, -2725); } htmltext = "31001-04.html"; @@ -1296,7 +1296,7 @@ public class Q00348_AnArrogantSearch extends Quest int i0 = st.getMemoStateEx(1) + 10; if ((i0 % 10) == 0) { - st.addRadar(2908, 44128, -2712); + addRadar(player, 2908, 44128, -2712); } else { @@ -1312,7 +1312,7 @@ public class Q00348_AnArrogantSearch extends Quest // retail typo if ((st.getMemoStateEx(1) % 10) == 0) { - st.addRadar(2908, 44128, -2712); + addRadar(player, 2908, 44128, -2712); } htmltext = "30144-03.html"; @@ -1321,7 +1321,7 @@ public class Q00348_AnArrogantSearch extends Quest { if ((st.getMemoStateEx(1) % 10) == 0) { - st.addRadar(2908, 44128, -2712); + addRadar(player, 2908, 44128, -2712); } htmltext = "30144-04.html"; @@ -1339,7 +1339,7 @@ public class Q00348_AnArrogantSearch extends Quest int i0 = st.getMemoStateEx(1) + 1000; if ((i0 % 10) == 0) { - st.addRadar(50693, 158674, 376); + addRadar(player, 50693, 158674, 376); } else { @@ -1355,7 +1355,7 @@ public class Q00348_AnArrogantSearch extends Quest // retail typo if ((st.getMemoStateEx(1) % 10) == 0) { - st.addRadar(50693, 158674, 376); + addRadar(player, 50693, 158674, 376); } htmltext = "30645-03.html"; @@ -1364,7 +1364,7 @@ public class Q00348_AnArrogantSearch extends Quest { if ((st.getMemoStateEx(1) % 10) == 0) { - st.addRadar(50693, 158674, 376); + addRadar(player, 50693, 158674, 376); } htmltext = "30645-04.html"; diff --git a/L2J_Mobius_Classic/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_Classic/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java index b34d09f34d..cada75c56c 100644 --- a/L2J_Mobius_Classic/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java +++ b/L2J_Mobius_Classic/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java @@ -579,6 +579,9 @@ public final class L2PcInstance extends L2Playable /** Last NPC Id talked on a quest */ private int _questNpcObject = 0; + /** Used for simulating Quest onTalk */ + private boolean _simulatedTalking = false; + /** The table containing all Quests began by the L2PcInstance */ private final Map _quests = new ConcurrentHashMap<>(); @@ -1372,6 +1375,16 @@ public final class L2PcInstance extends L2Playable _questNpcObject = npcId; } + public boolean isSimulatingTalking() + { + return _simulatedTalking; + } + + public void setSimulatedTalking(boolean value) + { + _simulatedTalking = value; + } + /** * @param quest The name of the quest * @return the QuestState object corresponding to the quest name. diff --git a/L2J_Mobius_Classic/java/com/l2jmobius/gameserver/model/events/AbstractScript.java b/L2J_Mobius_Classic/java/com/l2jmobius/gameserver/model/events/AbstractScript.java index a83373057d..4b3521c88c 100644 --- a/L2J_Mobius_Classic/java/com/l2jmobius/gameserver/model/events/AbstractScript.java +++ b/L2J_Mobius_Classic/java/com/l2jmobius/gameserver/model/events/AbstractScript.java @@ -1952,6 +1952,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void showOnScreenMsg(L2PcInstance player, String text, int time) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new ExShowScreenMessage(text, time)); } @@ -1965,6 +1969,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void showOnScreenMsg(L2PcInstance player, NpcStringId npcString, int position, int time, String... params) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new ExShowScreenMessage(npcString, position, time, params)); } @@ -1979,6 +1987,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void showOnScreenMsg(L2PcInstance player, NpcStringId npcString, int position, int time, boolean showEffect, String... params) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new ExShowScreenMessage(npcString, position, time, showEffect, params)); } @@ -1992,6 +2004,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void showOnScreenMsg(L2PcInstance player, SystemMessageId systemMsg, int position, int time, String... params) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new ExShowScreenMessage(systemMsg, position, time, params)); } @@ -2472,6 +2488,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void rewardItems(L2PcInstance player, int itemId, long count) { + if (player.isSimulatingTalking()) + { + return; + } + if (count <= 0) { return; @@ -2610,6 +2631,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void giveItems(L2PcInstance player, int itemId, long count, int enchantlevel, boolean playSound) { + if (player.isSimulatingTalking()) + { + return; + } + if (count <= 0) { return; @@ -2644,6 +2670,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void giveItems(L2PcInstance player, int itemId, long count, AttributeType attributeType, int attributeValue) { + if (player.isSimulatingTalking()) + { + return; + } + if (count <= 0) { return; @@ -2722,6 +2753,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static boolean giveItemRandomly(L2PcInstance player, L2Npc npc, int itemId, long minAmount, long maxAmount, long limit, double dropChance, boolean playSound) { + if (player.isSimulatingTalking()) + { + return false; + } + final long currentCount = getQuestItemsCount(player, itemId); if ((limit > 0) && (currentCount >= limit)) @@ -2794,6 +2830,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static boolean takeItems(L2PcInstance player, int itemId, long amount) { + if (player.isSimulatingTalking()) + { + return false; + } + // Get object item from player's inventory list final L2ItemInstance item = player.getInventory().getItemByItemId(itemId); if (item == null) @@ -2845,6 +2886,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ protected static boolean takeAllItems(L2PcInstance player, ItemHolder... itemList) { + if (player.isSimulatingTalking()) + { + return false; + } if ((itemList == null) || (itemList.length == 0)) { return false; @@ -2874,6 +2919,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static boolean takeItems(L2PcInstance player, int amount, int... itemIds) { + if (player.isSimulatingTalking()) + { + return false; + } + boolean check = true; if (itemIds != null) { @@ -2897,6 +2947,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void playSound(L2PcInstance player, String sound) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(QuestSound.getSound(sound)); } @@ -2907,6 +2961,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void playSound(L2PcInstance player, QuestSound sound) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(sound.getPacket()); } @@ -2918,6 +2976,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void addExpAndSp(L2PcInstance player, long exp, int sp) { + if (player.isSimulatingTalking()) + { + return; + } player.addExpAndSp((long) player.getStat().getValue(Stats.EXPSP_RATE, (exp * Config.RATE_QUEST_REWARD_XP)), (int) player.getStat().getValue(Stats.EXPSP_RATE, (sp * Config.RATE_QUEST_REWARD_SP))); PcCafePointsManager.getInstance().givePcCafePoint(player, (long) (exp * Config.RATE_QUEST_REWARD_XP)); } @@ -3005,6 +3067,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public final void executeForEachPlayer(L2PcInstance player, L2Npc npc, boolean isSummon, boolean includeParty, boolean includeCommandChannel) { + if (player.isSimulatingTalking()) + { + return; + } if ((includeParty || includeCommandChannel) && player.isInParty()) { if (includeCommandChannel && player.getParty().isInCommandChannel()) @@ -3219,6 +3285,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void specialCamera(L2PcInstance player, L2Character creature, int force, int angle1, int angle2, int time, int range, int duration, int relYaw, int relPitch, int isWide, int relAngle) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new SpecialCamera(creature, force, angle1, angle2, time, range, duration, relYaw, relPitch, isWide, relAngle)); } @@ -3238,6 +3308,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void specialCameraEx(L2PcInstance player, L2Character creature, int force, int angle1, int angle2, int time, int duration, int relYaw, int relPitch, int isWide, int relAngle) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new SpecialCamera(creature, player, force, angle1, angle2, time, duration, relYaw, relPitch, isWide, relAngle)); } @@ -3259,6 +3333,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void specialCamera3(L2PcInstance player, L2Character creature, int force, int angle1, int angle2, int time, int range, int duration, int relYaw, int relPitch, int isWide, int relAngle, int unk) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new SpecialCamera(creature, force, angle1, angle2, time, range, duration, relYaw, relPitch, isWide, relAngle, unk)); } @@ -3275,6 +3353,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void addRadar(L2PcInstance player, int x, int y, int z) { + if (player.isSimulatingTalking()) + { + return; + } player.getRadar().addMarker(x, y, z); } @@ -3286,6 +3368,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public void removeRadar(L2PcInstance player, int x, int y, int z) { + if (player.isSimulatingTalking()) + { + return; + } player.getRadar().removeMarker(x, y, z); } @@ -3294,6 +3380,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public void clearRadar(L2PcInstance player) { + if (player.isSimulatingTalking()) + { + return; + } player.getRadar().removeAllMarkers(); } @@ -3304,6 +3394,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public void playMovie(L2PcInstance player, Movie movie) { + if (player.isSimulatingTalking()) + { + return; + } new MovieHolder(Arrays.asList(player), movie); } diff --git a/L2J_Mobius_Classic/java/com/l2jmobius/gameserver/model/quest/Quest.java b/L2J_Mobius_Classic/java/com/l2jmobius/gameserver/model/quest/Quest.java index a9752be58e..a028478de6 100644 --- a/L2J_Mobius_Classic/java/com/l2jmobius/gameserver/model/quest/Quest.java +++ b/L2J_Mobius_Classic/java/com/l2jmobius/gameserver/model/quest/Quest.java @@ -635,7 +635,7 @@ public class Quest extends AbstractScript implements IIdentifiable } else { - res = onTalk(npc, player); + res = onTalk(npc, player, false); } } catch (Exception e) @@ -1113,6 +1113,24 @@ public class Quest extends AbstractScript implements IIdentifiable return null; } + /** + * This function is called whenever a player clicks to the "Quest" link of an NPC that is registered for the quest. + * @param npc this parameter contains a reference to the exact instance of the NPC that the player is talking with. + * @param talker this parameter contains a reference to the exact instance of the player who is talking to the NPC. + * @param simulated Used by QuestLink to determine state of quest. + * @return the text returned by the event (may be {@code null}, a filename or just text) + */ + public String onTalk(L2Npc npc, L2PcInstance talker, boolean simulated) + { + final QuestState qs = talker.getQuestState(getName()); + if (qs != null) + { + qs.setSimulated(simulated); + } + talker.setSimulatedTalking(simulated); + return onTalk(npc, talker); + } + /** * This function is called whenever a player clicks to the "Quest" link of an NPC that is registered for the quest. * @param npc this parameter contains a reference to the exact instance of the NPC that the player is talking with. diff --git a/L2J_Mobius_Classic/java/com/l2jmobius/gameserver/model/quest/QuestState.java b/L2J_Mobius_Classic/java/com/l2jmobius/gameserver/model/quest/QuestState.java index cb1ec04662..abf9825d8e 100644 --- a/L2J_Mobius_Classic/java/com/l2jmobius/gameserver/model/quest/QuestState.java +++ b/L2J_Mobius_Classic/java/com/l2jmobius/gameserver/model/quest/QuestState.java @@ -26,7 +26,6 @@ import com.l2jmobius.gameserver.enums.QuestSound; import com.l2jmobius.gameserver.enums.QuestType; import com.l2jmobius.gameserver.instancemanager.QuestManager; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.events.AbstractScript; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerQuestComplete; import com.l2jmobius.gameserver.network.serverpackets.ExShowQuestMark; @@ -50,6 +49,9 @@ public final class QuestState /** The current state of the quest */ private byte _state; + /** Used for simulating Quest onTalk */ + private boolean _simulated = false; + /** A map of key->value pairs containing the quest state variables and their values */ private Map _vars; @@ -153,6 +155,10 @@ public final class QuestState */ public boolean setState(byte state, boolean saveInDb) { + if (_simulated) + { + return false; + } if (_state == state) { return false; @@ -183,6 +189,11 @@ public final class QuestState */ public String setInternal(String var, String val) { + if (_simulated) + { + return null; + } + if (_vars == null) { _vars = new HashMap<>(); @@ -199,6 +210,10 @@ public final class QuestState public String set(String var, int val) { + if (_simulated) + { + return null; + } return set(var, Integer.toString(val)); } @@ -219,6 +234,11 @@ public final class QuestState */ public String set(String var, String val) { + if (_simulated) + { + return null; + } + if (_vars == null) { _vars = new HashMap<>(); @@ -279,6 +299,11 @@ public final class QuestState */ private void setCond(int cond, int old) { + if (_simulated) + { + return; + } + if (cond == old) { return; @@ -368,6 +393,11 @@ public final class QuestState */ public String unset(String var) { + if (_simulated) + { + return null; + } + if (_vars == null) { return null; @@ -445,6 +475,11 @@ public final class QuestState */ public QuestState setCond(int value) { + if (_simulated) + { + return null; + } + if (isStarted()) { set("cond", Integer.toString(value)); @@ -501,6 +536,11 @@ public final class QuestState */ public QuestState setCond(int value, boolean playQuestMiddle) { + if (_simulated) + { + return null; + } + if (!isStarted()) { return this; @@ -509,13 +549,17 @@ public final class QuestState if (playQuestMiddle) { - AbstractScript.playSound(_player, QuestSound.ITEMSOUND_QUEST_MIDDLE); + _player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket()); } return this; } public QuestState setMemoState(int value) { + if (_simulated) + { + return null; + } set("memoState", String.valueOf(value)); return this; } @@ -559,6 +603,10 @@ public final class QuestState */ public QuestState setMemoStateEx(int slot, int value) { + if (_simulated) + { + return null; + } set("memoStateEx" + slot, String.valueOf(value)); return this; } @@ -574,21 +622,6 @@ public final class QuestState return (getMemoStateEx(slot) == memoStateEx); } - public void addRadar(int x, int y, int z) - { - _player.getRadar().addMarker(x, y, z); - } - - public void removeRadar(int x, int y, int z) - { - _player.getRadar().removeMarker(x, y, z); - } - - public void clearRadar() - { - _player.getRadar().removeAllMarkers(); - } - /** * @return {@code true} if quest is to be exited on clean up by QuestStateManager, {@code false} otherwise */ @@ -602,6 +635,10 @@ public final class QuestState */ public void setIsExitQuestOnCleanUp(boolean isExitQuestOnCleanUp) { + if (_simulated) + { + return; + } _isExitQuestOnCleanUp = isExitQuestOnCleanUp; } @@ -612,11 +649,15 @@ public final class QuestState */ public QuestState startQuest() { + if (_simulated) + { + return null; + } if (isCreated() && !getQuest().isCustomQuest()) { set("cond", "1"); setState(State.STARTED); - AbstractScript.playSound(getPlayer(), QuestSound.ITEMSOUND_QUEST_ACCEPT); + _player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket()); getQuest().sendNpcLogList(getPlayer()); } return this; @@ -633,6 +674,11 @@ public final class QuestState */ public QuestState exitQuest(QuestType type) { + if (_simulated) + { + return null; + } + switch (type) { case DAILY: @@ -668,10 +714,14 @@ public final class QuestState */ public QuestState exitQuest(QuestType type, boolean playExitQuest) { + if (_simulated) + { + return null; + } exitQuest(type); if (playExitQuest) { - AbstractScript.playSound(getPlayer(), QuestSound.ITEMSOUND_QUEST_FINISH); + _player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket()); } return this; } @@ -687,6 +737,11 @@ public final class QuestState */ private QuestState exitQuest(boolean repeatable) { + if (_simulated) + { + return null; + } + _player.removeNotifyQuestOfDeath(this); if (!isStarted()) @@ -723,10 +778,15 @@ public final class QuestState */ public QuestState exitQuest(boolean repeatable, boolean playExitQuest) { + if (_simulated) + { + return null; + } + exitQuest(repeatable); if (playExitQuest) { - AbstractScript.playSound(getPlayer(), QuestSound.ITEMSOUND_QUEST_FINISH); + _player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket()); } // Notify to scripts @@ -741,6 +801,11 @@ public final class QuestState */ public void setRestartTime() { + if (_simulated) + { + return; + } + final Calendar reDo = Calendar.getInstance(); if (reDo.get(Calendar.HOUR_OF_DAY) >= getQuest().getResetHour()) { @@ -760,4 +825,9 @@ public final class QuestState final String val = get("restartTime"); return (val != null) && (!Util.isDigit(val) || (Long.parseLong(val) <= System.currentTimeMillis())); } + + public void setSimulated(boolean simulated) + { + _simulated = simulated; + } } \ No newline at end of file diff --git a/L2J_Mobius_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminShowQuests.java b/L2J_Mobius_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminShowQuests.java index 592bb7489e..a569d1fca6 100644 --- a/L2J_Mobius_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminShowQuests.java +++ b/L2J_Mobius_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminShowQuests.java @@ -321,6 +321,7 @@ public class AdminShowQuests implements IAdminCommandHandler { QuestState qs = target.getQuestState(val[0]); final String[] outval = new String[3]; + qs.setSimulated(false); if (val[1].equals("state")) { diff --git a/L2J_Mobius_Helios/dist/game/data/scripts/handlers/bypasshandlers/QuestLink.java b/L2J_Mobius_Helios/dist/game/data/scripts/handlers/bypasshandlers/QuestLink.java index c289fda3e7..599b59495d 100644 --- a/L2J_Mobius_Helios/dist/game/data/scripts/handlers/bypasshandlers/QuestLink.java +++ b/L2J_Mobius_Helios/dist/game/data/scripts/handlers/bypasshandlers/QuestLink.java @@ -87,9 +87,6 @@ public class QuestLink implements IBypassHandler final StringBuilder sbCanStart = new StringBuilder(128); final StringBuilder sbCantStart = new StringBuilder(128); final StringBuilder sbCompleted = new StringBuilder(128); - Quest lastSavedAvailableQuest = null; - Quest lastSavedProgressQuest = null; - int questCounter = 0; //@formatter:off final Set startingQuests = npc.getListeners(EventType.ON_NPC_QUEST_START).stream() @@ -126,8 +123,6 @@ public class QuestLink implements IBypassHandler sbCanStart.append(""); - lastSavedAvailableQuest = quest; - questCounter++; } else { @@ -135,17 +130,18 @@ public class QuestLink implements IBypassHandler sbCantStart.append(""); - questCounter++; } } + else if (Quest.getNoQuestMsg(player).equals(quest.onTalk(npc, player, true))) + { + continue; + } else if (qs.isStarted()) { sbStarted.append(""); sbStarted.append(""); - lastSavedProgressQuest = quest; - questCounter++; } else if (qs.isCompleted()) { @@ -153,21 +149,6 @@ public class QuestLink implements IBypassHandler sbCompleted.append(""); - questCounter++; - } - } - - if (questCounter == 1) - { - if (lastSavedProgressQuest != null) - { - showQuestWindow(player, npc, lastSavedProgressQuest.getName()); - return; - } - if (lastSavedAvailableQuest != null) - { - showQuestWindow(player, npc, lastSavedAvailableQuest.getName()); - return; } } @@ -267,7 +248,8 @@ public class QuestLink implements IBypassHandler .map(AbstractEventListener::getOwner) .filter(Quest.class::isInstance) .map(Quest.class::cast) - .filter(quest -> (quest.getId() > 0) && (quest.getId() < 20000)) + .filter(quest -> (quest.getId() > 0) && (quest.getId() < 20000) && (quest.getId() != 255)) + .filter(quest -> !Quest.getNoQuestMsg(player).equals(quest.onTalk(npc, player, true))) .distinct() .collect(Collectors.toSet()); //@formatter:on diff --git a/L2J_Mobius_Helios/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_Helios/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java index b34d09f34d..cada75c56c 100644 --- a/L2J_Mobius_Helios/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java +++ b/L2J_Mobius_Helios/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java @@ -579,6 +579,9 @@ public final class L2PcInstance extends L2Playable /** Last NPC Id talked on a quest */ private int _questNpcObject = 0; + /** Used for simulating Quest onTalk */ + private boolean _simulatedTalking = false; + /** The table containing all Quests began by the L2PcInstance */ private final Map _quests = new ConcurrentHashMap<>(); @@ -1372,6 +1375,16 @@ public final class L2PcInstance extends L2Playable _questNpcObject = npcId; } + public boolean isSimulatingTalking() + { + return _simulatedTalking; + } + + public void setSimulatedTalking(boolean value) + { + _simulatedTalking = value; + } + /** * @param quest The name of the quest * @return the QuestState object corresponding to the quest name. diff --git a/L2J_Mobius_Helios/java/com/l2jmobius/gameserver/model/events/AbstractScript.java b/L2J_Mobius_Helios/java/com/l2jmobius/gameserver/model/events/AbstractScript.java index a83373057d..4b3521c88c 100644 --- a/L2J_Mobius_Helios/java/com/l2jmobius/gameserver/model/events/AbstractScript.java +++ b/L2J_Mobius_Helios/java/com/l2jmobius/gameserver/model/events/AbstractScript.java @@ -1952,6 +1952,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void showOnScreenMsg(L2PcInstance player, String text, int time) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new ExShowScreenMessage(text, time)); } @@ -1965,6 +1969,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void showOnScreenMsg(L2PcInstance player, NpcStringId npcString, int position, int time, String... params) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new ExShowScreenMessage(npcString, position, time, params)); } @@ -1979,6 +1987,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void showOnScreenMsg(L2PcInstance player, NpcStringId npcString, int position, int time, boolean showEffect, String... params) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new ExShowScreenMessage(npcString, position, time, showEffect, params)); } @@ -1992,6 +2004,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void showOnScreenMsg(L2PcInstance player, SystemMessageId systemMsg, int position, int time, String... params) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new ExShowScreenMessage(systemMsg, position, time, params)); } @@ -2472,6 +2488,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void rewardItems(L2PcInstance player, int itemId, long count) { + if (player.isSimulatingTalking()) + { + return; + } + if (count <= 0) { return; @@ -2610,6 +2631,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void giveItems(L2PcInstance player, int itemId, long count, int enchantlevel, boolean playSound) { + if (player.isSimulatingTalking()) + { + return; + } + if (count <= 0) { return; @@ -2644,6 +2670,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void giveItems(L2PcInstance player, int itemId, long count, AttributeType attributeType, int attributeValue) { + if (player.isSimulatingTalking()) + { + return; + } + if (count <= 0) { return; @@ -2722,6 +2753,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static boolean giveItemRandomly(L2PcInstance player, L2Npc npc, int itemId, long minAmount, long maxAmount, long limit, double dropChance, boolean playSound) { + if (player.isSimulatingTalking()) + { + return false; + } + final long currentCount = getQuestItemsCount(player, itemId); if ((limit > 0) && (currentCount >= limit)) @@ -2794,6 +2830,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static boolean takeItems(L2PcInstance player, int itemId, long amount) { + if (player.isSimulatingTalking()) + { + return false; + } + // Get object item from player's inventory list final L2ItemInstance item = player.getInventory().getItemByItemId(itemId); if (item == null) @@ -2845,6 +2886,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ protected static boolean takeAllItems(L2PcInstance player, ItemHolder... itemList) { + if (player.isSimulatingTalking()) + { + return false; + } if ((itemList == null) || (itemList.length == 0)) { return false; @@ -2874,6 +2919,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static boolean takeItems(L2PcInstance player, int amount, int... itemIds) { + if (player.isSimulatingTalking()) + { + return false; + } + boolean check = true; if (itemIds != null) { @@ -2897,6 +2947,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void playSound(L2PcInstance player, String sound) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(QuestSound.getSound(sound)); } @@ -2907,6 +2961,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void playSound(L2PcInstance player, QuestSound sound) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(sound.getPacket()); } @@ -2918,6 +2976,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void addExpAndSp(L2PcInstance player, long exp, int sp) { + if (player.isSimulatingTalking()) + { + return; + } player.addExpAndSp((long) player.getStat().getValue(Stats.EXPSP_RATE, (exp * Config.RATE_QUEST_REWARD_XP)), (int) player.getStat().getValue(Stats.EXPSP_RATE, (sp * Config.RATE_QUEST_REWARD_SP))); PcCafePointsManager.getInstance().givePcCafePoint(player, (long) (exp * Config.RATE_QUEST_REWARD_XP)); } @@ -3005,6 +3067,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public final void executeForEachPlayer(L2PcInstance player, L2Npc npc, boolean isSummon, boolean includeParty, boolean includeCommandChannel) { + if (player.isSimulatingTalking()) + { + return; + } if ((includeParty || includeCommandChannel) && player.isInParty()) { if (includeCommandChannel && player.getParty().isInCommandChannel()) @@ -3219,6 +3285,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void specialCamera(L2PcInstance player, L2Character creature, int force, int angle1, int angle2, int time, int range, int duration, int relYaw, int relPitch, int isWide, int relAngle) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new SpecialCamera(creature, force, angle1, angle2, time, range, duration, relYaw, relPitch, isWide, relAngle)); } @@ -3238,6 +3308,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void specialCameraEx(L2PcInstance player, L2Character creature, int force, int angle1, int angle2, int time, int duration, int relYaw, int relPitch, int isWide, int relAngle) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new SpecialCamera(creature, player, force, angle1, angle2, time, duration, relYaw, relPitch, isWide, relAngle)); } @@ -3259,6 +3333,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void specialCamera3(L2PcInstance player, L2Character creature, int force, int angle1, int angle2, int time, int range, int duration, int relYaw, int relPitch, int isWide, int relAngle, int unk) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new SpecialCamera(creature, force, angle1, angle2, time, range, duration, relYaw, relPitch, isWide, relAngle, unk)); } @@ -3275,6 +3353,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void addRadar(L2PcInstance player, int x, int y, int z) { + if (player.isSimulatingTalking()) + { + return; + } player.getRadar().addMarker(x, y, z); } @@ -3286,6 +3368,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public void removeRadar(L2PcInstance player, int x, int y, int z) { + if (player.isSimulatingTalking()) + { + return; + } player.getRadar().removeMarker(x, y, z); } @@ -3294,6 +3380,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public void clearRadar(L2PcInstance player) { + if (player.isSimulatingTalking()) + { + return; + } player.getRadar().removeAllMarkers(); } @@ -3304,6 +3394,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public void playMovie(L2PcInstance player, Movie movie) { + if (player.isSimulatingTalking()) + { + return; + } new MovieHolder(Arrays.asList(player), movie); } diff --git a/L2J_Mobius_Helios/java/com/l2jmobius/gameserver/model/quest/Quest.java b/L2J_Mobius_Helios/java/com/l2jmobius/gameserver/model/quest/Quest.java index 77be2879c3..07d10a322a 100644 --- a/L2J_Mobius_Helios/java/com/l2jmobius/gameserver/model/quest/Quest.java +++ b/L2J_Mobius_Helios/java/com/l2jmobius/gameserver/model/quest/Quest.java @@ -635,7 +635,7 @@ public class Quest extends AbstractScript implements IIdentifiable } else { - res = onTalk(npc, player); + res = onTalk(npc, player, false); } } catch (Exception e) @@ -1113,6 +1113,24 @@ public class Quest extends AbstractScript implements IIdentifiable return null; } + /** + * This function is called whenever a player clicks to the "Quest" link of an NPC that is registered for the quest. + * @param npc this parameter contains a reference to the exact instance of the NPC that the player is talking with. + * @param talker this parameter contains a reference to the exact instance of the player who is talking to the NPC. + * @param simulated Used by QuestLink to determine state of quest. + * @return the text returned by the event (may be {@code null}, a filename or just text) + */ + public String onTalk(L2Npc npc, L2PcInstance talker, boolean simulated) + { + final QuestState qs = talker.getQuestState(getName()); + if (qs != null) + { + qs.setSimulated(simulated); + } + talker.setSimulatedTalking(simulated); + return onTalk(npc, talker); + } + /** * This function is called whenever a player clicks to the "Quest" link of an NPC that is registered for the quest. * @param npc this parameter contains a reference to the exact instance of the NPC that the player is talking with. diff --git a/L2J_Mobius_Helios/java/com/l2jmobius/gameserver/model/quest/QuestState.java b/L2J_Mobius_Helios/java/com/l2jmobius/gameserver/model/quest/QuestState.java index cb1ec04662..abf9825d8e 100644 --- a/L2J_Mobius_Helios/java/com/l2jmobius/gameserver/model/quest/QuestState.java +++ b/L2J_Mobius_Helios/java/com/l2jmobius/gameserver/model/quest/QuestState.java @@ -26,7 +26,6 @@ import com.l2jmobius.gameserver.enums.QuestSound; import com.l2jmobius.gameserver.enums.QuestType; import com.l2jmobius.gameserver.instancemanager.QuestManager; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.events.AbstractScript; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerQuestComplete; import com.l2jmobius.gameserver.network.serverpackets.ExShowQuestMark; @@ -50,6 +49,9 @@ public final class QuestState /** The current state of the quest */ private byte _state; + /** Used for simulating Quest onTalk */ + private boolean _simulated = false; + /** A map of key->value pairs containing the quest state variables and their values */ private Map _vars; @@ -153,6 +155,10 @@ public final class QuestState */ public boolean setState(byte state, boolean saveInDb) { + if (_simulated) + { + return false; + } if (_state == state) { return false; @@ -183,6 +189,11 @@ public final class QuestState */ public String setInternal(String var, String val) { + if (_simulated) + { + return null; + } + if (_vars == null) { _vars = new HashMap<>(); @@ -199,6 +210,10 @@ public final class QuestState public String set(String var, int val) { + if (_simulated) + { + return null; + } return set(var, Integer.toString(val)); } @@ -219,6 +234,11 @@ public final class QuestState */ public String set(String var, String val) { + if (_simulated) + { + return null; + } + if (_vars == null) { _vars = new HashMap<>(); @@ -279,6 +299,11 @@ public final class QuestState */ private void setCond(int cond, int old) { + if (_simulated) + { + return; + } + if (cond == old) { return; @@ -368,6 +393,11 @@ public final class QuestState */ public String unset(String var) { + if (_simulated) + { + return null; + } + if (_vars == null) { return null; @@ -445,6 +475,11 @@ public final class QuestState */ public QuestState setCond(int value) { + if (_simulated) + { + return null; + } + if (isStarted()) { set("cond", Integer.toString(value)); @@ -501,6 +536,11 @@ public final class QuestState */ public QuestState setCond(int value, boolean playQuestMiddle) { + if (_simulated) + { + return null; + } + if (!isStarted()) { return this; @@ -509,13 +549,17 @@ public final class QuestState if (playQuestMiddle) { - AbstractScript.playSound(_player, QuestSound.ITEMSOUND_QUEST_MIDDLE); + _player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket()); } return this; } public QuestState setMemoState(int value) { + if (_simulated) + { + return null; + } set("memoState", String.valueOf(value)); return this; } @@ -559,6 +603,10 @@ public final class QuestState */ public QuestState setMemoStateEx(int slot, int value) { + if (_simulated) + { + return null; + } set("memoStateEx" + slot, String.valueOf(value)); return this; } @@ -574,21 +622,6 @@ public final class QuestState return (getMemoStateEx(slot) == memoStateEx); } - public void addRadar(int x, int y, int z) - { - _player.getRadar().addMarker(x, y, z); - } - - public void removeRadar(int x, int y, int z) - { - _player.getRadar().removeMarker(x, y, z); - } - - public void clearRadar() - { - _player.getRadar().removeAllMarkers(); - } - /** * @return {@code true} if quest is to be exited on clean up by QuestStateManager, {@code false} otherwise */ @@ -602,6 +635,10 @@ public final class QuestState */ public void setIsExitQuestOnCleanUp(boolean isExitQuestOnCleanUp) { + if (_simulated) + { + return; + } _isExitQuestOnCleanUp = isExitQuestOnCleanUp; } @@ -612,11 +649,15 @@ public final class QuestState */ public QuestState startQuest() { + if (_simulated) + { + return null; + } if (isCreated() && !getQuest().isCustomQuest()) { set("cond", "1"); setState(State.STARTED); - AbstractScript.playSound(getPlayer(), QuestSound.ITEMSOUND_QUEST_ACCEPT); + _player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket()); getQuest().sendNpcLogList(getPlayer()); } return this; @@ -633,6 +674,11 @@ public final class QuestState */ public QuestState exitQuest(QuestType type) { + if (_simulated) + { + return null; + } + switch (type) { case DAILY: @@ -668,10 +714,14 @@ public final class QuestState */ public QuestState exitQuest(QuestType type, boolean playExitQuest) { + if (_simulated) + { + return null; + } exitQuest(type); if (playExitQuest) { - AbstractScript.playSound(getPlayer(), QuestSound.ITEMSOUND_QUEST_FINISH); + _player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket()); } return this; } @@ -687,6 +737,11 @@ public final class QuestState */ private QuestState exitQuest(boolean repeatable) { + if (_simulated) + { + return null; + } + _player.removeNotifyQuestOfDeath(this); if (!isStarted()) @@ -723,10 +778,15 @@ public final class QuestState */ public QuestState exitQuest(boolean repeatable, boolean playExitQuest) { + if (_simulated) + { + return null; + } + exitQuest(repeatable); if (playExitQuest) { - AbstractScript.playSound(getPlayer(), QuestSound.ITEMSOUND_QUEST_FINISH); + _player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket()); } // Notify to scripts @@ -741,6 +801,11 @@ public final class QuestState */ public void setRestartTime() { + if (_simulated) + { + return; + } + final Calendar reDo = Calendar.getInstance(); if (reDo.get(Calendar.HOUR_OF_DAY) >= getQuest().getResetHour()) { @@ -760,4 +825,9 @@ public final class QuestState final String val = get("restartTime"); return (val != null) && (!Util.isDigit(val) || (Long.parseLong(val) <= System.currentTimeMillis())); } + + public void setSimulated(boolean simulated) + { + _simulated = simulated; + } } \ No newline at end of file diff --git a/L2J_Mobius_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminShowQuests.java b/L2J_Mobius_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminShowQuests.java index 592bb7489e..a569d1fca6 100644 --- a/L2J_Mobius_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminShowQuests.java +++ b/L2J_Mobius_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminShowQuests.java @@ -321,6 +321,7 @@ public class AdminShowQuests implements IAdminCommandHandler { QuestState qs = target.getQuestState(val[0]); final String[] outval = new String[3]; + qs.setSimulated(false); if (val[1].equals("state")) { diff --git a/L2J_Mobius_Underground/dist/game/data/scripts/handlers/bypasshandlers/QuestLink.java b/L2J_Mobius_Underground/dist/game/data/scripts/handlers/bypasshandlers/QuestLink.java index c289fda3e7..599b59495d 100644 --- a/L2J_Mobius_Underground/dist/game/data/scripts/handlers/bypasshandlers/QuestLink.java +++ b/L2J_Mobius_Underground/dist/game/data/scripts/handlers/bypasshandlers/QuestLink.java @@ -87,9 +87,6 @@ public class QuestLink implements IBypassHandler final StringBuilder sbCanStart = new StringBuilder(128); final StringBuilder sbCantStart = new StringBuilder(128); final StringBuilder sbCompleted = new StringBuilder(128); - Quest lastSavedAvailableQuest = null; - Quest lastSavedProgressQuest = null; - int questCounter = 0; //@formatter:off final Set startingQuests = npc.getListeners(EventType.ON_NPC_QUEST_START).stream() @@ -126,8 +123,6 @@ public class QuestLink implements IBypassHandler sbCanStart.append(""); - lastSavedAvailableQuest = quest; - questCounter++; } else { @@ -135,17 +130,18 @@ public class QuestLink implements IBypassHandler sbCantStart.append(""); - questCounter++; } } + else if (Quest.getNoQuestMsg(player).equals(quest.onTalk(npc, player, true))) + { + continue; + } else if (qs.isStarted()) { sbStarted.append(""); sbStarted.append(""); - lastSavedProgressQuest = quest; - questCounter++; } else if (qs.isCompleted()) { @@ -153,21 +149,6 @@ public class QuestLink implements IBypassHandler sbCompleted.append(""); - questCounter++; - } - } - - if (questCounter == 1) - { - if (lastSavedProgressQuest != null) - { - showQuestWindow(player, npc, lastSavedProgressQuest.getName()); - return; - } - if (lastSavedAvailableQuest != null) - { - showQuestWindow(player, npc, lastSavedAvailableQuest.getName()); - return; } } @@ -267,7 +248,8 @@ public class QuestLink implements IBypassHandler .map(AbstractEventListener::getOwner) .filter(Quest.class::isInstance) .map(Quest.class::cast) - .filter(quest -> (quest.getId() > 0) && (quest.getId() < 20000)) + .filter(quest -> (quest.getId() > 0) && (quest.getId() < 20000) && (quest.getId() != 255)) + .filter(quest -> !Quest.getNoQuestMsg(player).equals(quest.onTalk(npc, player, true))) .distinct() .collect(Collectors.toSet()); //@formatter:on diff --git a/L2J_Mobius_Underground/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_Underground/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java index 59500f4667..fdc391c521 100644 --- a/L2J_Mobius_Underground/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java +++ b/L2J_Mobius_Underground/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java @@ -578,6 +578,9 @@ public final class L2PcInstance extends L2Playable /** Last NPC Id talked on a quest */ private int _questNpcObject = 0; + /** Used for simulating Quest onTalk */ + private boolean _simulatedTalking = false; + /** The table containing all Quests began by the L2PcInstance */ private final Map _quests = new ConcurrentHashMap<>(); @@ -1371,6 +1374,16 @@ public final class L2PcInstance extends L2Playable _questNpcObject = npcId; } + public boolean isSimulatingTalking() + { + return _simulatedTalking; + } + + public void setSimulatedTalking(boolean value) + { + _simulatedTalking = value; + } + /** * @param quest The name of the quest * @return the QuestState object corresponding to the quest name. diff --git a/L2J_Mobius_Underground/java/com/l2jmobius/gameserver/model/events/AbstractScript.java b/L2J_Mobius_Underground/java/com/l2jmobius/gameserver/model/events/AbstractScript.java index a83373057d..4b3521c88c 100644 --- a/L2J_Mobius_Underground/java/com/l2jmobius/gameserver/model/events/AbstractScript.java +++ b/L2J_Mobius_Underground/java/com/l2jmobius/gameserver/model/events/AbstractScript.java @@ -1952,6 +1952,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void showOnScreenMsg(L2PcInstance player, String text, int time) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new ExShowScreenMessage(text, time)); } @@ -1965,6 +1969,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void showOnScreenMsg(L2PcInstance player, NpcStringId npcString, int position, int time, String... params) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new ExShowScreenMessage(npcString, position, time, params)); } @@ -1979,6 +1987,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void showOnScreenMsg(L2PcInstance player, NpcStringId npcString, int position, int time, boolean showEffect, String... params) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new ExShowScreenMessage(npcString, position, time, showEffect, params)); } @@ -1992,6 +2004,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void showOnScreenMsg(L2PcInstance player, SystemMessageId systemMsg, int position, int time, String... params) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new ExShowScreenMessage(systemMsg, position, time, params)); } @@ -2472,6 +2488,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void rewardItems(L2PcInstance player, int itemId, long count) { + if (player.isSimulatingTalking()) + { + return; + } + if (count <= 0) { return; @@ -2610,6 +2631,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void giveItems(L2PcInstance player, int itemId, long count, int enchantlevel, boolean playSound) { + if (player.isSimulatingTalking()) + { + return; + } + if (count <= 0) { return; @@ -2644,6 +2670,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void giveItems(L2PcInstance player, int itemId, long count, AttributeType attributeType, int attributeValue) { + if (player.isSimulatingTalking()) + { + return; + } + if (count <= 0) { return; @@ -2722,6 +2753,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static boolean giveItemRandomly(L2PcInstance player, L2Npc npc, int itemId, long minAmount, long maxAmount, long limit, double dropChance, boolean playSound) { + if (player.isSimulatingTalking()) + { + return false; + } + final long currentCount = getQuestItemsCount(player, itemId); if ((limit > 0) && (currentCount >= limit)) @@ -2794,6 +2830,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static boolean takeItems(L2PcInstance player, int itemId, long amount) { + if (player.isSimulatingTalking()) + { + return false; + } + // Get object item from player's inventory list final L2ItemInstance item = player.getInventory().getItemByItemId(itemId); if (item == null) @@ -2845,6 +2886,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ protected static boolean takeAllItems(L2PcInstance player, ItemHolder... itemList) { + if (player.isSimulatingTalking()) + { + return false; + } if ((itemList == null) || (itemList.length == 0)) { return false; @@ -2874,6 +2919,11 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static boolean takeItems(L2PcInstance player, int amount, int... itemIds) { + if (player.isSimulatingTalking()) + { + return false; + } + boolean check = true; if (itemIds != null) { @@ -2897,6 +2947,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void playSound(L2PcInstance player, String sound) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(QuestSound.getSound(sound)); } @@ -2907,6 +2961,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void playSound(L2PcInstance player, QuestSound sound) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(sound.getPacket()); } @@ -2918,6 +2976,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void addExpAndSp(L2PcInstance player, long exp, int sp) { + if (player.isSimulatingTalking()) + { + return; + } player.addExpAndSp((long) player.getStat().getValue(Stats.EXPSP_RATE, (exp * Config.RATE_QUEST_REWARD_XP)), (int) player.getStat().getValue(Stats.EXPSP_RATE, (sp * Config.RATE_QUEST_REWARD_SP))); PcCafePointsManager.getInstance().givePcCafePoint(player, (long) (exp * Config.RATE_QUEST_REWARD_XP)); } @@ -3005,6 +3067,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public final void executeForEachPlayer(L2PcInstance player, L2Npc npc, boolean isSummon, boolean includeParty, boolean includeCommandChannel) { + if (player.isSimulatingTalking()) + { + return; + } if ((includeParty || includeCommandChannel) && player.isInParty()) { if (includeCommandChannel && player.getParty().isInCommandChannel()) @@ -3219,6 +3285,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void specialCamera(L2PcInstance player, L2Character creature, int force, int angle1, int angle2, int time, int range, int duration, int relYaw, int relPitch, int isWide, int relAngle) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new SpecialCamera(creature, force, angle1, angle2, time, range, duration, relYaw, relPitch, isWide, relAngle)); } @@ -3238,6 +3308,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void specialCameraEx(L2PcInstance player, L2Character creature, int force, int angle1, int angle2, int time, int duration, int relYaw, int relPitch, int isWide, int relAngle) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new SpecialCamera(creature, player, force, angle1, angle2, time, duration, relYaw, relPitch, isWide, relAngle)); } @@ -3259,6 +3333,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void specialCamera3(L2PcInstance player, L2Character creature, int force, int angle1, int angle2, int time, int range, int duration, int relYaw, int relPitch, int isWide, int relAngle, int unk) { + if (player.isSimulatingTalking()) + { + return; + } player.sendPacket(new SpecialCamera(creature, force, angle1, angle2, time, range, duration, relYaw, relPitch, isWide, relAngle, unk)); } @@ -3275,6 +3353,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public static void addRadar(L2PcInstance player, int x, int y, int z) { + if (player.isSimulatingTalking()) + { + return; + } player.getRadar().addMarker(x, y, z); } @@ -3286,6 +3368,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public void removeRadar(L2PcInstance player, int x, int y, int z) { + if (player.isSimulatingTalking()) + { + return; + } player.getRadar().removeMarker(x, y, z); } @@ -3294,6 +3380,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public void clearRadar(L2PcInstance player) { + if (player.isSimulatingTalking()) + { + return; + } player.getRadar().removeAllMarkers(); } @@ -3304,6 +3394,10 @@ public abstract class AbstractScript extends ManagedScript implements IEventTime */ public void playMovie(L2PcInstance player, Movie movie) { + if (player.isSimulatingTalking()) + { + return; + } new MovieHolder(Arrays.asList(player), movie); } diff --git a/L2J_Mobius_Underground/java/com/l2jmobius/gameserver/model/quest/Quest.java b/L2J_Mobius_Underground/java/com/l2jmobius/gameserver/model/quest/Quest.java index 77be2879c3..07d10a322a 100644 --- a/L2J_Mobius_Underground/java/com/l2jmobius/gameserver/model/quest/Quest.java +++ b/L2J_Mobius_Underground/java/com/l2jmobius/gameserver/model/quest/Quest.java @@ -635,7 +635,7 @@ public class Quest extends AbstractScript implements IIdentifiable } else { - res = onTalk(npc, player); + res = onTalk(npc, player, false); } } catch (Exception e) @@ -1113,6 +1113,24 @@ public class Quest extends AbstractScript implements IIdentifiable return null; } + /** + * This function is called whenever a player clicks to the "Quest" link of an NPC that is registered for the quest. + * @param npc this parameter contains a reference to the exact instance of the NPC that the player is talking with. + * @param talker this parameter contains a reference to the exact instance of the player who is talking to the NPC. + * @param simulated Used by QuestLink to determine state of quest. + * @return the text returned by the event (may be {@code null}, a filename or just text) + */ + public String onTalk(L2Npc npc, L2PcInstance talker, boolean simulated) + { + final QuestState qs = talker.getQuestState(getName()); + if (qs != null) + { + qs.setSimulated(simulated); + } + talker.setSimulatedTalking(simulated); + return onTalk(npc, talker); + } + /** * This function is called whenever a player clicks to the "Quest" link of an NPC that is registered for the quest. * @param npc this parameter contains a reference to the exact instance of the NPC that the player is talking with. diff --git a/L2J_Mobius_Underground/java/com/l2jmobius/gameserver/model/quest/QuestState.java b/L2J_Mobius_Underground/java/com/l2jmobius/gameserver/model/quest/QuestState.java index cb1ec04662..abf9825d8e 100644 --- a/L2J_Mobius_Underground/java/com/l2jmobius/gameserver/model/quest/QuestState.java +++ b/L2J_Mobius_Underground/java/com/l2jmobius/gameserver/model/quest/QuestState.java @@ -26,7 +26,6 @@ import com.l2jmobius.gameserver.enums.QuestSound; import com.l2jmobius.gameserver.enums.QuestType; import com.l2jmobius.gameserver.instancemanager.QuestManager; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.events.AbstractScript; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerQuestComplete; import com.l2jmobius.gameserver.network.serverpackets.ExShowQuestMark; @@ -50,6 +49,9 @@ public final class QuestState /** The current state of the quest */ private byte _state; + /** Used for simulating Quest onTalk */ + private boolean _simulated = false; + /** A map of key->value pairs containing the quest state variables and their values */ private Map _vars; @@ -153,6 +155,10 @@ public final class QuestState */ public boolean setState(byte state, boolean saveInDb) { + if (_simulated) + { + return false; + } if (_state == state) { return false; @@ -183,6 +189,11 @@ public final class QuestState */ public String setInternal(String var, String val) { + if (_simulated) + { + return null; + } + if (_vars == null) { _vars = new HashMap<>(); @@ -199,6 +210,10 @@ public final class QuestState public String set(String var, int val) { + if (_simulated) + { + return null; + } return set(var, Integer.toString(val)); } @@ -219,6 +234,11 @@ public final class QuestState */ public String set(String var, String val) { + if (_simulated) + { + return null; + } + if (_vars == null) { _vars = new HashMap<>(); @@ -279,6 +299,11 @@ public final class QuestState */ private void setCond(int cond, int old) { + if (_simulated) + { + return; + } + if (cond == old) { return; @@ -368,6 +393,11 @@ public final class QuestState */ public String unset(String var) { + if (_simulated) + { + return null; + } + if (_vars == null) { return null; @@ -445,6 +475,11 @@ public final class QuestState */ public QuestState setCond(int value) { + if (_simulated) + { + return null; + } + if (isStarted()) { set("cond", Integer.toString(value)); @@ -501,6 +536,11 @@ public final class QuestState */ public QuestState setCond(int value, boolean playQuestMiddle) { + if (_simulated) + { + return null; + } + if (!isStarted()) { return this; @@ -509,13 +549,17 @@ public final class QuestState if (playQuestMiddle) { - AbstractScript.playSound(_player, QuestSound.ITEMSOUND_QUEST_MIDDLE); + _player.sendPacket(QuestSound.ITEMSOUND_QUEST_MIDDLE.getPacket()); } return this; } public QuestState setMemoState(int value) { + if (_simulated) + { + return null; + } set("memoState", String.valueOf(value)); return this; } @@ -559,6 +603,10 @@ public final class QuestState */ public QuestState setMemoStateEx(int slot, int value) { + if (_simulated) + { + return null; + } set("memoStateEx" + slot, String.valueOf(value)); return this; } @@ -574,21 +622,6 @@ public final class QuestState return (getMemoStateEx(slot) == memoStateEx); } - public void addRadar(int x, int y, int z) - { - _player.getRadar().addMarker(x, y, z); - } - - public void removeRadar(int x, int y, int z) - { - _player.getRadar().removeMarker(x, y, z); - } - - public void clearRadar() - { - _player.getRadar().removeAllMarkers(); - } - /** * @return {@code true} if quest is to be exited on clean up by QuestStateManager, {@code false} otherwise */ @@ -602,6 +635,10 @@ public final class QuestState */ public void setIsExitQuestOnCleanUp(boolean isExitQuestOnCleanUp) { + if (_simulated) + { + return; + } _isExitQuestOnCleanUp = isExitQuestOnCleanUp; } @@ -612,11 +649,15 @@ public final class QuestState */ public QuestState startQuest() { + if (_simulated) + { + return null; + } if (isCreated() && !getQuest().isCustomQuest()) { set("cond", "1"); setState(State.STARTED); - AbstractScript.playSound(getPlayer(), QuestSound.ITEMSOUND_QUEST_ACCEPT); + _player.sendPacket(QuestSound.ITEMSOUND_QUEST_ACCEPT.getPacket()); getQuest().sendNpcLogList(getPlayer()); } return this; @@ -633,6 +674,11 @@ public final class QuestState */ public QuestState exitQuest(QuestType type) { + if (_simulated) + { + return null; + } + switch (type) { case DAILY: @@ -668,10 +714,14 @@ public final class QuestState */ public QuestState exitQuest(QuestType type, boolean playExitQuest) { + if (_simulated) + { + return null; + } exitQuest(type); if (playExitQuest) { - AbstractScript.playSound(getPlayer(), QuestSound.ITEMSOUND_QUEST_FINISH); + _player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket()); } return this; } @@ -687,6 +737,11 @@ public final class QuestState */ private QuestState exitQuest(boolean repeatable) { + if (_simulated) + { + return null; + } + _player.removeNotifyQuestOfDeath(this); if (!isStarted()) @@ -723,10 +778,15 @@ public final class QuestState */ public QuestState exitQuest(boolean repeatable, boolean playExitQuest) { + if (_simulated) + { + return null; + } + exitQuest(repeatable); if (playExitQuest) { - AbstractScript.playSound(getPlayer(), QuestSound.ITEMSOUND_QUEST_FINISH); + _player.sendPacket(QuestSound.ITEMSOUND_QUEST_FINISH.getPacket()); } // Notify to scripts @@ -741,6 +801,11 @@ public final class QuestState */ public void setRestartTime() { + if (_simulated) + { + return; + } + final Calendar reDo = Calendar.getInstance(); if (reDo.get(Calendar.HOUR_OF_DAY) >= getQuest().getResetHour()) { @@ -760,4 +825,9 @@ public final class QuestState final String val = get("restartTime"); return (val != null) && (!Util.isDigit(val) || (Long.parseLong(val) <= System.currentTimeMillis())); } + + public void setSimulated(boolean simulated) + { + _simulated = simulated; + } } \ No newline at end of file