Skip to content

Commit

Permalink
plugins: readd quest list plugin
Browse files Browse the repository at this point in the history
This adds back the quest search functionality which is not included in vanilla now
  • Loading branch information
Adam- committed Mar 25, 2022
1 parent b640c22 commit eaf2f46
Show file tree
Hide file tree
Showing 7 changed files with 377 additions and 0 deletions.
1 change: 1 addition & 0 deletions runelite-api/src/main/java/net/runelite/api/ParamID.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public final class ParamID
* Long name for NPCs used in the HP hud
*/
public static final int NPC_HP_NAME = 510;
public static final int QUEST_NAME = 610;
/**
* @see SettingID
*/
Expand Down
18 changes: 18 additions & 0 deletions runelite-api/src/main/java/net/runelite/api/ScriptID.java
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,12 @@ public final class ScriptID
@ScriptArguments(integer = 3)
public static final int GE_ITEM_SEARCH = 752;

/**
* On load listener for building the quest list interface
*/
@ScriptArguments(integer = 8)
public static final int QUESTLIST_INIT = 1350;

/**
* Called when the friends list is updated
* <ul>
Expand Down Expand Up @@ -384,4 +390,16 @@ public final class ScriptID
*/
@ScriptArguments(integer = 1)
public static final int NOTIFICATION_DELAY = 3347;

/**
* Check if a quest should be filtered from the quest list
* <ul>
* <li> int (StructID) Quest struct </li>
* <li> int State filter </li>
* <li> int Requirement filter </li>
* <li> int Stats filter </li>
* </ul>
*/
@ScriptArguments(integer = 4)
public static final int QUEST_FILTER = 3238;
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ public final class WidgetID
public static final int SKOTIZO_GROUP_ID = 308;
public static final int ENTERING_HOUSE_GROUP_ID = 71;
public static final int FULLSCREEN_CONTAINER_TLI = 165;
public static final int QUESTLIST_GROUP_ID = 399;
public static final int SKILLS_GROUP_ID = 320;
public static final int MUSIC_GROUP_ID = 239;
public static final int BARROWS_PUZZLE_GROUP_ID = 25;
Expand Down Expand Up @@ -806,6 +807,12 @@ static class Skotizo
static final int CONTAINER = 2;
}

static class QuestList
{
static final int BOX = 0;
static final int CONTAINER = 2;
}

static class Music
{
static final int CONTAINER = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,9 @@ public enum WidgetInfo

SKOTIZO_CONTAINER(WidgetID.SKOTIZO_GROUP_ID, WidgetID.Skotizo.CONTAINER),

QUESTLIST_BOX(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.BOX),
QUESTLIST_CONTAINER(WidgetID.QUESTLIST_GROUP_ID, WidgetID.QuestList.CONTAINER),

SEED_VAULT_TITLE_CONTAINER(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.TITLE_CONTAINER),
SEED_VAULT_ITEM_CONTAINER(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.ITEM_CONTAINER),
SEED_VAULT_ITEM_TEXT(WidgetID.SEED_VAULT_GROUP_ID, WidgetID.SeedVault.ITEM_TEXT),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
/*
* Copyright (c) 2019 Spudjb <https://github.com/spudjb>
* Copyright (c) 2022 Adam <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.plugins.questlist;

import com.google.common.base.Strings;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.ParamID;
import net.runelite.api.ScriptID;
import net.runelite.api.SoundEffectID;
import net.runelite.api.SpriteID;
import net.runelite.api.VarClientInt;
import net.runelite.api.Varbits;
import net.runelite.api.events.ScriptCallbackEvent;
import net.runelite.api.events.ScriptPostFired;
import net.runelite.api.events.VarClientIntChanged;
import net.runelite.api.events.VarbitChanged;
import net.runelite.api.widgets.JavaScriptCallback;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.api.widgets.WidgetPositionMode;
import net.runelite.api.widgets.WidgetType;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.chatbox.ChatboxPanelManager;
import net.runelite.client.game.chatbox.ChatboxTextInput;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;

@PluginDescriptor(
name = "Quest List",
description = "Adds a search filter to the quest list"
)
public class QuestListPlugin extends Plugin
{
private static final String MENU_OPEN = "Open";
private static final String MENU_CLOSE = "Close";
private static final String MENU_SEARCH = "Search";

@Inject
private Client client;

@Inject
private ChatboxPanelManager chatboxPanelManager;

@Inject
private ClientThread clientThread;

private ChatboxTextInput searchInput;
private Widget questSearchButton;

@Override
protected void startUp()
{
clientThread.invoke(this::addQuestButtons);
}

@Override
protected void shutDown()
{
Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX);
if (header != null)
{
header.deleteAllChildren();
}
}

@Subscribe
public void onScriptPostFired(ScriptPostFired event)
{
if (event.getScriptId() == ScriptID.QUESTLIST_INIT)
{
addQuestButtons();
}
}

private void addQuestButtons()
{
Widget header = client.getWidget(WidgetInfo.QUESTLIST_BOX);
if (header != null)
{
header.deleteAllChildren();

questSearchButton = header.createChild(-1, WidgetType.GRAPHIC);
questSearchButton.setSpriteId(SpriteID.GE_SEARCH);
questSearchButton.setOriginalWidth(18);
questSearchButton.setOriginalHeight(17);
questSearchButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
questSearchButton.setOriginalX(5);
questSearchButton.setOriginalY(0);
questSearchButton.setHasListener(true);
questSearchButton.setAction(1, MENU_OPEN);
questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
questSearchButton.setName(MENU_SEARCH);
questSearchButton.revalidate();
}
}

@Subscribe
public void onVarbitChanged(VarbitChanged varbitChanged)
{
if (isChatboxOpen() && !isOnQuestTab())
{
chatboxPanelManager.close();
}
}

@Subscribe
public void onVarClientIntChanged(VarClientIntChanged varClientIntChanged)
{
if (varClientIntChanged.getIndex() == VarClientInt.INVENTORY_TAB.getIndex())
{
if (isChatboxOpen() && !isOnQuestTab())
{
chatboxPanelManager.close();
}
}
}

@Subscribe
public void onScriptCallbackEvent(ScriptCallbackEvent scriptCallbackEvent)
{
if (!"questFilter".equals(scriptCallbackEvent.getEventName()) || !isChatboxOpen())
{
return;
}

final String filter = searchInput.getValue();
if (Strings.isNullOrEmpty(filter))
{
return;
}

final int[] intStack = client.getIntStack();
final int intStackSize = client.getIntStackSize();

final int questStruct = intStack[intStackSize - 1];
final String questName = client.getStructComposition(questStruct)
.getStringValue(ParamID.QUEST_NAME);

intStack[intStackSize - 2] = questName.toLowerCase().contains(filter.toLowerCase()) ? 0 : 1;
}

private boolean isOnQuestTab()
{
return client.getVar(Varbits.QUEST_TAB) == 0 && client.getVar(VarClientInt.INVENTORY_TAB) == 2;
}

private boolean isChatboxOpen()
{
return searchInput != null && chatboxPanelManager.getCurrentInput() == searchInput;
}

private void closeSearch()
{
chatboxPanelManager.close();
redrawQuests();
client.playSoundEffect(SoundEffectID.UI_BOOP);
}

private void openSearch()
{
client.playSoundEffect(SoundEffectID.UI_BOOP);
questSearchButton.setAction(1, MENU_CLOSE);
questSearchButton.setOnOpListener((JavaScriptCallback) e -> closeSearch());
searchInput = chatboxPanelManager.openTextInput("Search quest list")
.onChanged(s -> redrawQuests())
.onDone(s -> false)
.onClose(() ->
{
redrawQuests();
questSearchButton.setOnOpListener((JavaScriptCallback) e -> openSearch());
questSearchButton.setAction(1, MENU_OPEN);
})
.build();
}

private void redrawQuests()
{
Widget w = client.getWidget(WidgetInfo.QUESTLIST_CONTAINER);
if (w == null)
{
return;
}

Object[] onVarTransmitListener = w.getOnVarTransmitListener();
if (onVarTransmitListener == null)
{
return;
}

clientThread.invokeLater(() ->
client.runScript(onVarTransmitListener));
}
}
1 change: 1 addition & 0 deletions runelite-client/src/main/scripts/QuestFilter.hash
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3FA5FFC8DB18A42971CED41A9BC7CEA407A0EC98061D56B2822F66CD910E4BAF
Loading

0 comments on commit eaf2f46

Please sign in to comment.