Просмотр исходного кода

Adding support for start quest condition
Reviewed by: @NosBit, @UnAfraid, LoneRanger

Sdw- 10 лет назад
Родитель
Сommit
ac426d90c3

+ 11 - 129
L2J_Server/java/com/l2jserver/gameserver/model/actor/instance/L2PcInstance.java

@@ -64,7 +64,6 @@ import com.l2jserver.gameserver.ai.CtrlIntention;
 import com.l2jserver.gameserver.ai.L2CharacterAI;
 import com.l2jserver.gameserver.ai.L2PlayerAI;
 import com.l2jserver.gameserver.ai.L2SummonAI;
-import com.l2jserver.gameserver.cache.HtmCache;
 import com.l2jserver.gameserver.cache.WarehouseCacheManager;
 import com.l2jserver.gameserver.communitybbs.BB.Forum;
 import com.l2jserver.gameserver.communitybbs.Manager.ForumsBBSManager;
@@ -181,7 +180,6 @@ import com.l2jserver.gameserver.model.actor.tasks.player.TeleportWatchdogTask;
 import com.l2jserver.gameserver.model.actor.tasks.player.VitalityTask;
 import com.l2jserver.gameserver.model.actor.tasks.player.WarnUserTakeBreakTask;
 import com.l2jserver.gameserver.model.actor.tasks.player.WaterTask;
-import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
 import com.l2jserver.gameserver.model.actor.templates.L2PcTemplate;
 import com.l2jserver.gameserver.model.actor.transform.Transform;
 import com.l2jserver.gameserver.model.base.ClassId;
@@ -199,7 +197,6 @@ import com.l2jserver.gameserver.model.entity.L2Event;
 import com.l2jserver.gameserver.model.entity.Siege;
 import com.l2jserver.gameserver.model.entity.TvTEvent;
 import com.l2jserver.gameserver.model.events.EventDispatcher;
-import com.l2jserver.gameserver.model.events.EventType;
 import com.l2jserver.gameserver.model.events.impl.character.player.OnPlayerEquipItem;
 import com.l2jserver.gameserver.model.events.impl.character.player.OnPlayerFameChanged;
 import com.l2jserver.gameserver.model.events.impl.character.player.OnPlayerHennaRemove;
@@ -211,7 +208,6 @@ import com.l2jserver.gameserver.model.events.impl.character.player.OnPlayerProfe
 import com.l2jserver.gameserver.model.events.impl.character.player.OnPlayerPvPChanged;
 import com.l2jserver.gameserver.model.events.impl.character.player.OnPlayerPvPKill;
 import com.l2jserver.gameserver.model.events.impl.character.player.OnPlayerTransform;
-import com.l2jserver.gameserver.model.events.listeners.AbstractEventListener;
 import com.l2jserver.gameserver.model.fishing.L2Fish;
 import com.l2jserver.gameserver.model.fishing.L2Fishing;
 import com.l2jserver.gameserver.model.holders.ItemHolder;
@@ -244,7 +240,6 @@ import com.l2jserver.gameserver.model.punishment.PunishmentAffect;
 import com.l2jserver.gameserver.model.punishment.PunishmentType;
 import com.l2jserver.gameserver.model.quest.Quest;
 import com.l2jserver.gameserver.model.quest.QuestState;
-import com.l2jserver.gameserver.model.quest.State;
 import com.l2jserver.gameserver.model.skills.AbnormalType;
 import com.l2jserver.gameserver.model.skills.BuffInfo;
 import com.l2jserver.gameserver.model.skills.CommonSkill;
@@ -291,7 +286,6 @@ import com.l2jserver.gameserver.network.serverpackets.LeaveWorld;
 import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse;
 import com.l2jserver.gameserver.network.serverpackets.MyTargetSelected;
 import com.l2jserver.gameserver.network.serverpackets.NicknameChanged;
-import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
 import com.l2jserver.gameserver.network.serverpackets.ObservationMode;
 import com.l2jserver.gameserver.network.serverpackets.ObservationReturn;
 import com.l2jserver.gameserver.network.serverpackets.PartySmallWindowUpdate;
@@ -1395,10 +1389,7 @@ public final class L2PcInstance extends L2Playable
 		}
 		catch (SQLException e)
 		{
-			if (_log.isLoggable(Level.SEVERE))
-			{
-				_log.log(Level.SEVERE, "SQL exception while inserting recipe: " + recipeId + " from character " + getObjectId(), e);
-			}
+			_log.log(Level.WARNING, "SQL exception while inserting recipe: " + recipeId + " from character " + getObjectId(), e);
 		}
 	}
 	
@@ -1414,10 +1405,7 @@ public final class L2PcInstance extends L2Playable
 		}
 		catch (SQLException e)
 		{
-			if (_log.isLoggable(Level.SEVERE))
-			{
-				_log.log(Level.SEVERE, "SQL exception while deleting recipe: " + recipeId + " from character " + getObjectId(), e);
-			}
+			_log.log(Level.WARNING, "SQL exception while deleting recipe: " + recipeId + " from character " + getObjectId(), e);
 		}
 	}
 	
@@ -1471,15 +1459,6 @@ public final class L2PcInstance extends L2Playable
 		_quests.remove(quest);
 	}
 	
-	private QuestState[] addToQuestStateArray(QuestState[] questStateArray, QuestState state)
-	{
-		final int len = questStateArray.length;
-		QuestState[] tmp = new QuestState[len + 1];
-		System.arraycopy(questStateArray, 0, tmp, 0, len);
-		tmp[len] = state;
-		return tmp;
-	}
-	
 	/**
 	 * @return a table containing all Quest in progress from the table _quests.
 	 */
@@ -1503,120 +1482,23 @@ public final class L2PcInstance extends L2Playable
 		return quests.toArray(new Quest[quests.size()]);
 	}
 	
-	/**
-	 * @param npcId The Identifier of the NPC
-	 * @return a table containing all QuestState from the table _quests in which the L2PcInstance must talk to the NPC.
-	 */
-	public QuestState[] getQuestsForTalk(int npcId)
+	public void processQuestEvent(String questName, String event)
 	{
-		// Create a QuestState table that will contain all QuestState to modify
-		QuestState[] states = null;
-		
-		final L2NpcTemplate template = NpcData.getInstance().getTemplate(npcId);
-		if (template == null)
+		final Quest quest = QuestManager.getInstance().getQuest(questName);
+		if ((quest == null) || (event == null) || event.isEmpty())
 		{
-			_log.log(Level.WARNING, getClass().getSimpleName() + ": " + getName() + " requested quests for talk on non existing npc " + npcId);
-			return states;
+			return;
 		}
 		
-		// Go through the QuestState of the L2PcInstance quests
-		for (AbstractEventListener listener : template.getListeners(EventType.ON_NPC_TALK))
+		if (getLastQuestNpcObject() > 0)
 		{
-			if (listener.getOwner() instanceof Quest)
+			final L2Object object = L2World.getInstance().findObject(getLastQuestNpcObject());
+			if (object.isNpc() && isInsideRadius(object, L2Npc.INTERACTION_DISTANCE, false, false))
 			{
-				final Quest quest = (Quest) listener.getOwner();
-				
-				// Copy the current L2PcInstance QuestState in the QuestState table
-				if (getQuestState(quest.getName()) != null)
-				{
-					if (states == null)
-					{
-						states = new QuestState[]
-						{
-							getQuestState(quest.getName())
-						};
-					}
-					else
-					{
-						states = addToQuestStateArray(states, getQuestState(quest.getName()));
-					}
-				}
+				final L2Npc npc = (L2Npc) object;
+				quest.notifyEvent(event, npc, this);
 			}
 		}
-		
-		// Return a table containing all QuestState to modify
-		return states;
-	}
-	
-	public QuestState processQuestEvent(String quest, String event)
-	{
-		QuestState retval = null;
-		if (event == null)
-		{
-			event = "";
-		}
-		QuestState qs = getQuestState(quest);
-		if ((qs == null) && event.isEmpty())
-		{
-			return retval;
-		}
-		if (qs == null)
-		{
-			Quest q = QuestManager.getInstance().getQuest(quest);
-			if (q == null)
-			{
-				return retval;
-			}
-			qs = q.newQuestState(this);
-		}
-		if (qs != null)
-		{
-			/**
-			 * Allow quest events if there was a quest talk event before.<br>
-			 * Since this method is only called for quest bypasses from html,<br>
-			 * getLastHtmlActionOriginId() should be equals getLastQuestNpcObject().
-			 */
-			if ((getLastQuestNpcObject() > 0) && (getLastQuestNpcObject() == getLastHtmlActionOriginId()))
-			{
-				L2Object object = L2World.getInstance().findObject(getLastQuestNpcObject());
-				if ((object instanceof L2Npc) && isInsideRadius(object, L2Npc.INTERACTION_DISTANCE, false, false))
-				{
-					L2Npc npc = (L2Npc) object;
-					QuestState[] states = getQuestsForTalk(npc.getId());
-					
-					if (states != null)
-					{
-						for (QuestState state : states)
-						{
-							if (state.getQuest().getName().equals(qs.getQuest().getName()))
-							{
-								if (qs.getQuest().notifyEvent(event, npc, this))
-								{
-									showQuestWindow(quest, npc, State.getStateName(qs.getState()));
-								}
-								
-								retval = qs;
-							}
-						}
-					}
-				}
-			}
-		}
-		
-		return retval;
-	}
-	
-	private void showQuestWindow(String questId, L2Npc npc, String stateId)
-	{
-		String path = "data/scripts/quests/" + questId + "/" + stateId + ".htm";
-		String content = HtmCache.getInstance().getHtm(getHtmlPrefix(), path); // TODO path for quests html
-		
-		if (content != null)
-		{
-			sendPacket(new NpcHtmlMessage(npc != null ? npc.getObjectId() : 0, content));
-		}
-		
-		sendPacket(ActionFailed.STATIC_PACKET);
 	}
 	
 	/** List of all QuestState instance that needs to be notified of this L2PcInstance's or its pet's death */

+ 133 - 36
L2J_Server/java/com/l2jserver/gameserver/model/quest/Quest.java

@@ -23,18 +23,22 @@ import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
+import java.util.function.Predicate;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import com.l2jserver.Config;
 import com.l2jserver.L2DatabaseFactory;
 import com.l2jserver.gameserver.cache.HtmCache;
+import com.l2jserver.gameserver.enums.CategoryType;
+import com.l2jserver.gameserver.enums.Race;
 import com.l2jserver.gameserver.enums.TrapAction;
 import com.l2jserver.gameserver.instancemanager.QuestManager;
 import com.l2jserver.gameserver.model.L2Object;
@@ -46,6 +50,7 @@ import com.l2jserver.gameserver.model.actor.L2Summon;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
 import com.l2jserver.gameserver.model.actor.instance.L2TrapInstance;
 import com.l2jserver.gameserver.model.base.AcquireSkillType;
+import com.l2jserver.gameserver.model.base.ClassId;
 import com.l2jserver.gameserver.model.events.AbstractScript;
 import com.l2jserver.gameserver.model.events.EventType;
 import com.l2jserver.gameserver.model.events.listeners.AbstractEventListener;
@@ -77,6 +82,7 @@ public class Quest extends AbstractScript implements IIdentifiable
 	private final ReentrantReadWriteLock _rwLock = new ReentrantReadWriteLock();
 	private final WriteLock _writeLock = _rwLock.writeLock();
 	private final ReadLock _readLock = _rwLock.readLock();
+	private final Map<Predicate<L2PcInstance>, String> _startCondition = new LinkedHashMap<>();
 	
 	private final int _questId;
 	private final String _name;
@@ -407,6 +413,7 @@ public class Quest extends AbstractScript implements IIdentifiable
 		catch (Exception e)
 		{
 			showError(qs.getPlayer(), e);
+			return;
 		}
 		showResult(qs.getPlayer(), res);
 	}
@@ -425,6 +432,7 @@ public class Quest extends AbstractScript implements IIdentifiable
 		catch (Exception e)
 		{
 			showError(player, e);
+			return;
 		}
 		showResult(player, res);
 	}
@@ -444,6 +452,7 @@ public class Quest extends AbstractScript implements IIdentifiable
 		catch (Exception e)
 		{
 			showError(player, e);
+			return;
 		}
 		showResult(player, res);
 	}
@@ -510,9 +519,8 @@ public class Quest extends AbstractScript implements IIdentifiable
 	 * @param event
 	 * @param npc
 	 * @param player
-	 * @return {@code false} if there was an error or the message was sent, {@code true} otherwise
 	 */
-	public final boolean notifyEvent(String event, L2Npc npc, L2PcInstance player)
+	public final void notifyEvent(String event, L2Npc npc, L2PcInstance player)
 	{
 		String res = null;
 		try
@@ -521,9 +529,10 @@ public class Quest extends AbstractScript implements IIdentifiable
 		}
 		catch (Exception e)
 		{
-			return showError(player, e);
+			showError(player, e);
+			return;
 		}
-		return showResult(player, res, npc);
+		showResult(player, res);
 	}
 	
 	/**
@@ -539,6 +548,7 @@ public class Quest extends AbstractScript implements IIdentifiable
 		catch (Exception e)
 		{
 			showError(player, e);
+			return;
 		}
 		showResult(player, res);
 	}
@@ -558,28 +568,37 @@ public class Quest extends AbstractScript implements IIdentifiable
 		catch (Exception e)
 		{
 			showError(killer, e);
+			return;
 		}
 		showResult(killer, res);
 	}
 	
 	/**
 	 * @param npc
-	 * @param activeChar
-	 * @return {@code false} if there was an error or the message was sent, {@code true} otherwise
+	 * @param player
 	 */
-	public final boolean notifyTalk(L2Npc npc, L2PcInstance activeChar)
+	public final void notifyTalk(L2Npc npc, L2PcInstance player)
 	{
 		String res = null;
 		try
 		{
-			res = onTalk(npc, activeChar);
+			final String startConditionHtml = getStartConditionHtml(player);
+			if (!player.hasQuestState(_name) && (startConditionHtml != null))
+			{
+				res = startConditionHtml;
+			}
+			else
+			{
+				res = onTalk(npc, player);
+			}
 		}
 		catch (Exception e)
 		{
-			return showError(activeChar, e);
+			showError(player, e);
+			return;
 		}
-		activeChar.setLastQuestNpcObject(npc.getObjectId());
-		return showResult(activeChar, res, npc);
+		player.setLastQuestNpcObject(npc.getObjectId());
+		showResult(player, res);
 	}
 	
 	/**
@@ -598,6 +617,7 @@ public class Quest extends AbstractScript implements IIdentifiable
 		catch (Exception e)
 		{
 			showError(player, e);
+			return;
 		}
 		showResult(player, res, npc);
 	}
@@ -619,6 +639,7 @@ public class Quest extends AbstractScript implements IIdentifiable
 		catch (Exception e)
 		{
 			showError(player, e);
+			return;
 		}
 		showResult(player, res);
 	}
@@ -626,31 +647,20 @@ public class Quest extends AbstractScript implements IIdentifiable
 	/**
 	 * @param item
 	 * @param player
-	 * @return
 	 */
-	public final boolean notifyItemTalk(L2ItemInstance item, L2PcInstance player)
+	public final void notifyItemTalk(L2ItemInstance item, L2PcInstance player)
 	{
 		String res = null;
 		try
 		{
 			res = onItemTalk(item, player);
-			if (res != null)
-			{
-				if (res.equalsIgnoreCase("true"))
-				{
-					return true;
-				}
-				else if (res.equalsIgnoreCase("false"))
-				{
-					return false;
-				}
-			}
 		}
 		catch (Exception e)
 		{
-			return showError(player, e);
+			showError(player, e);
+			return;
 		}
-		return showResult(player, res);
+		showResult(player, res);
 	}
 	
 	/**
@@ -667,9 +677,8 @@ public class Quest extends AbstractScript implements IIdentifiable
 	 * @param item
 	 * @param player
 	 * @param event
-	 * @return
 	 */
-	public final boolean notifyItemEvent(L2ItemInstance item, L2PcInstance player, String event)
+	public final void notifyItemEvent(L2ItemInstance item, L2PcInstance player, String event)
 	{
 		String res = null;
 		try
@@ -677,21 +686,18 @@ public class Quest extends AbstractScript implements IIdentifiable
 			res = onItemEvent(item, player, event);
 			if (res != null)
 			{
-				if (res.equalsIgnoreCase("true"))
-				{
-					return true;
-				}
-				else if (res.equalsIgnoreCase("false"))
+				if (res.equalsIgnoreCase("true") || res.equalsIgnoreCase("false"))
 				{
-					return false;
+					return;
 				}
 			}
 		}
 		catch (Exception e)
 		{
-			return showError(player, e);
+			showError(player, e);
+			return;
 		}
-		return showResult(player, res);
+		showResult(player, res);
 	}
 	
 	/**
@@ -711,6 +717,7 @@ public class Quest extends AbstractScript implements IIdentifiable
 		catch (Exception e)
 		{
 			showError(caster, e);
+			return;
 		}
 		showResult(caster, res);
 	}
@@ -731,6 +738,7 @@ public class Quest extends AbstractScript implements IIdentifiable
 		catch (Exception e)
 		{
 			showError(attacker, e);
+			return;
 		}
 		showResult(attacker, res);
 	}
@@ -750,6 +758,7 @@ public class Quest extends AbstractScript implements IIdentifiable
 		catch (Exception e)
 		{
 			showError(player, e);
+			return;
 		}
 		showResult(player, res);
 	}
@@ -777,6 +786,7 @@ public class Quest extends AbstractScript implements IIdentifiable
 			{
 				showError(player, e);
 			}
+			return;
 		}
 		if (player != null)
 		{
@@ -820,6 +830,7 @@ public class Quest extends AbstractScript implements IIdentifiable
 			{
 				showError(player, e);
 			}
+			return;
 		}
 		if (player != null)
 		{
@@ -845,6 +856,7 @@ public class Quest extends AbstractScript implements IIdentifiable
 			{
 				showError(player, e);
 			}
+			return;
 		}
 		if (player != null)
 		{
@@ -2768,4 +2780,89 @@ public class Quest extends AbstractScript implements IIdentifiable
 	{
 		return _isCustom;
 	}
+	
+	public boolean canStartQuest(L2PcInstance player)
+	{
+		for (Predicate<L2PcInstance> cond : _startCondition.keySet())
+		{
+			if (!cond.test(player))
+			{
+				return false;
+			}
+		}
+		return true;
+	}
+	
+	public String getStartConditionHtml(L2PcInstance player)
+	{
+		for (Map.Entry<Predicate<L2PcInstance>, String> startRequirement : _startCondition.entrySet())
+		{
+			if (!startRequirement.getKey().test(player))
+			{
+				return startRequirement.getValue();
+			}
+		}
+		
+		return null;
+	}
+	
+	public void addStartCondition(Predicate<L2PcInstance> questStartRequirement, String html)
+	{
+		_startCondition.put(questStartRequirement, html);
+	}
+	
+	public void addLevelCondition(int minLevel, int maxLevel, String html)
+	{
+		_startCondition.put(p -> (p.getLevel() >= minLevel) && (p.getLevel() <= maxLevel), html);
+	}
+	
+	public void addMinLevelCondition(int minLevel, String html)
+	{
+		_startCondition.put(p -> p.getLevel() >= minLevel, html);
+	}
+	
+	public void addMaxLevelCondition(int maxLevel, String html)
+	{
+		_startCondition.put(p -> p.getLevel() <= maxLevel, html);
+	}
+	
+	public void addRaceCondition(Race race, String html)
+	{
+		_startCondition.put(p -> p.getRace() == race, html);
+	}
+	
+	public void addNotRaceCondition(Race race, String html)
+	{
+		_startCondition.put(p -> p.getRace() != race, html);
+	}
+	
+	public void addCompletedQuestCondition(String name, String html)
+	{
+		_startCondition.put(p -> p.hasQuestState(name) && p.getQuestState(name).isCompleted(), html);
+	}
+	
+	public void addClassIdCondition(ClassId classId, String html)
+	{
+		_startCondition.put(p -> p.getClassId() == classId, html);
+	}
+	
+	public void addNotClassIdCondition(ClassId classId, String html)
+	{
+		_startCondition.put(p -> p.getClassId() != classId, html);
+	}
+	
+	public void addIsSubClassActiveCondition(String html)
+	{
+		_startCondition.put(p -> p.isSubClassActive(), html);
+	}
+	
+	public void addIsNotSubClassActiveCondition(String html)
+	{
+		_startCondition.put(p -> !p.isSubClassActive(), html);
+	}
+	
+	public void addInCategoryCondition(CategoryType categoryType, String html)
+	{
+		_startCondition.put(p -> p.isInCategory(categoryType), html);
+	}
 }