Merge pull request #612 from Abextm/kourend-library
Add kourend library plugin
@@ -103,6 +103,7 @@ public final class AnimationID
|
||||
public static final int HERBLORE_POTIONMAKING = 363; //used for both herb and secondary
|
||||
public static final int MAGIC_CHARGING_ORBS = 726;
|
||||
public static final int BURYING_BONES = 827;
|
||||
public static final int LOOKING_INTO = 832;
|
||||
|
||||
// NPC animations
|
||||
public static final int TZTOK_JAD_MAGIC_ATTACK = 2656;
|
||||
|
||||
@@ -279,8 +279,8 @@ public class Perspective
|
||||
int baseX = client.getBaseX();
|
||||
int baseY = client.getBaseY();
|
||||
|
||||
int x = (point.getX() - baseX) << LOCAL_COORD_BITS;
|
||||
int y = (point.getY() - baseY) << LOCAL_COORD_BITS;
|
||||
int x = ((point.getX() - baseX) << LOCAL_COORD_BITS) + (1 << LOCAL_COORD_BITS - 1) - 1;
|
||||
int y = ((point.getY() - baseY) << LOCAL_COORD_BITS) + (1 << LOCAL_COORD_BITS - 1) - 1;
|
||||
|
||||
return new Point(x, y);
|
||||
}
|
||||
|
||||
39
runelite-api/src/main/java/net/runelite/api/Point3D.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* 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.api;
|
||||
|
||||
import lombok.Value;
|
||||
import net.runelite.api.Point;
|
||||
|
||||
@Value
|
||||
public class Point3D
|
||||
{
|
||||
private final int X, Y, Z;
|
||||
|
||||
public Point toPoint()
|
||||
{
|
||||
return new Point(X, Y);
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,7 @@ public class WidgetID
|
||||
public static final int BA_DEFENDER_GROUP_ID = 487;
|
||||
public static final int BA_HEALER_GROUP_ID = 488;
|
||||
public static final int LEVEL_UP_GROUP_ID = 233;
|
||||
public static final int HUNTER_LEVEL_UP_GROUP_ID = 193;
|
||||
public static final int DIALOG_SPRITE_GROUP_ID = 193;
|
||||
public static final int QUEST_COMPLETED_GROUP_ID = 277;
|
||||
public static final int CLUE_SCROLL_REWARD_GROUP_ID = 73;
|
||||
public static final int BARROWS_REWARD_GROUP_ID = 155;
|
||||
@@ -293,4 +293,10 @@ public class WidgetID
|
||||
{
|
||||
static final int VISIBLE_BOX = 4;
|
||||
}
|
||||
|
||||
static class DialogSprite
|
||||
{
|
||||
static final int SPRITE = 0;
|
||||
static final int TEXT = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +120,10 @@ public enum WidgetInfo
|
||||
COMBAT_SPELL_ICON(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.SPELL_ICON),
|
||||
COMBAT_SPELL_TEXT(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.SPELL_TEXT),
|
||||
|
||||
DIALOG_SPRITE(WidgetID.DIALOG_SPRITE_GROUP_ID, 0),
|
||||
DIALOG_SPRITE_SPRITE(WidgetID.DIALOG_SPRITE_GROUP_ID, WidgetID.DialogSprite.SPRITE),
|
||||
DIALOG_SPRITE_TEXT(WidgetID.DIALOG_SPRITE_GROUP_ID, WidgetID.DialogSprite.TEXT),
|
||||
|
||||
DIALOG_NPC_NAME(WidgetID.DIALOG_NPC_GROUP_ID, WidgetID.DialogNPC.NAME),
|
||||
DIALOG_NPC_TEXT(WidgetID.DIALOG_NPC_GROUP_ID, WidgetID.DialogNPC.TEXT),
|
||||
DIALOG_NPC_HEAD_MODEL(WidgetID.DIALOG_NPC_GROUP_ID, WidgetID.DialogNPC.HEAD_MODEL),
|
||||
@@ -162,10 +166,6 @@ public enum WidgetInfo
|
||||
LEVEL_UP_SKILL(WidgetID.LEVEL_UP_GROUP_ID, WidgetID.LevelUp.SKILL),
|
||||
LEVEL_UP_LEVEL(WidgetID.LEVEL_UP_GROUP_ID, WidgetID.LevelUp.LEVEL),
|
||||
|
||||
HUNTER_LEVEL_UP(WidgetID.HUNTER_LEVEL_UP_GROUP_ID, 0),
|
||||
HUNTER_LEVEL_UP_SKILL(WidgetID.HUNTER_LEVEL_UP_GROUP_ID, WidgetID.LevelUp.SKILL),
|
||||
HUNTER_LEVEL_UP_LEVEL(WidgetID.HUNTER_LEVEL_UP_GROUP_ID, WidgetID.LevelUp.LEVEL),
|
||||
|
||||
QUEST_COMPLETED(WidgetID.QUEST_COMPLETED_GROUP_ID, 0),
|
||||
QUEST_COMPLETED_NAME_TEXT(WidgetID.QUEST_COMPLETED_GROUP_ID, WidgetID.QuestCompleted.NAME_TEXT),
|
||||
|
||||
|
||||
@@ -178,9 +178,6 @@ public class Hooks
|
||||
menuAction -= 2000;
|
||||
}
|
||||
|
||||
log.debug("Menu action clicked: {} ({}) on {} ({} widget: {})",
|
||||
menuOption, menuAction, menuTarget.isEmpty() ? "<nothing>" : menuTarget, id, actionParam, widgetId);
|
||||
|
||||
MenuOptionClicked menuOptionClicked = new MenuOptionClicked();
|
||||
menuOptionClicked.setActionParam(actionParam);
|
||||
menuOptionClicked.setMenuOption(menuOption);
|
||||
@@ -189,6 +186,8 @@ public class Hooks
|
||||
menuOptionClicked.setId(id);
|
||||
menuOptionClicked.setWidgetId(widgetId);
|
||||
|
||||
log.debug("Menu action clicked: {}", menuOptionClicked);
|
||||
|
||||
eventBus.post(menuOptionClicked);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* 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.kourendlibrary;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.imageio.ImageIO;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.ItemID;
|
||||
|
||||
public enum Book
|
||||
{
|
||||
DARK_MANUSCRIPT_13514(ItemID.DARK_MANUSCRIPT),
|
||||
DARK_MANUSCRIPT_13515(ItemID.DARK_MANUSCRIPT_13515),
|
||||
DARK_MANUSCRIPT_13516(ItemID.DARK_MANUSCRIPT_13516),
|
||||
DARK_MANUSCRIPT_13517(ItemID.DARK_MANUSCRIPT_13517),
|
||||
DARK_MANUSCRIPT_13518(ItemID.DARK_MANUSCRIPT_13518),
|
||||
DARK_MANUSCRIPT_13519(ItemID.DARK_MANUSCRIPT_13519),
|
||||
DARK_MANUSCRIPT_13520(ItemID.DARK_MANUSCRIPT_13520),
|
||||
DARK_MANUSCRIPT_13521(ItemID.DARK_MANUSCRIPT_13521),
|
||||
DARK_MANUSCRIPT_13522(ItemID.DARK_MANUSCRIPT_13522),
|
||||
DARK_MANUSCRIPT_13523(ItemID.DARK_MANUSCRIPT_13523),
|
||||
|
||||
RADAS_CENSUS(ItemID.RADAS_CENSUS, "Rada's Census", "Census of King Rada III, by Matthias Vorseth."),
|
||||
RICKTORS_DIARY_7(ItemID.RICKTORS_DIARY_7, "Ricktor's Diary 7", "Diary of Steklan Ricktor, volume 7."),
|
||||
EATHRAM_RADA_EXTRACT(ItemID.EATHRAM__RADA_EXTRACT, "Eathram & Rada extract", "An extract from Eathram & Rada, by Anonymous."),
|
||||
KILLING_OF_A_KING(ItemID.KILLING_OF_A_KING, "Killing of a King", "Killing of a King, by Griselle."),
|
||||
HOSIDIUS_LETTER(ItemID.HOSIDIUS_LETTER, "Hosidius Letter", "A letter from Lord Hosidius to the Council of Elders."),
|
||||
WINTERTODT_PARABLE(ItemID.WINTERTODT_PARABLE, "Wintertodt Parable", "The Parable of the Wintertodt, by Anonymous."),
|
||||
TWILL_ACCORD(ItemID.TWILL_ACCORD, "Twill Accord", "The Royal Accord of Twill."),
|
||||
BYRNES_CORONATION_SPEECH(ItemID.BYRNES_CORONATION_SPEECH, "Byrnes Coronation Speech", "Speech of King Byrne I, on the occasion of his coronation."),
|
||||
IDEOLOGY_OF_DARKNESS(ItemID.IDEOLOGY_OF_DARKNESS, "The Ideology of Darkness", "The Ideology of Darkness, by Philophaire."),
|
||||
RADAS_JOURNEY(ItemID.RADAS_JOURNEY, "Rada's Journey", "The Journey of Rada, by Griselle."),
|
||||
TRANSVERGENCE_THEORY(ItemID.TRANSVERGENCE_THEORY, "Transvergence Theory", "The Theory of Transvergence, by Amon Ducot."),
|
||||
TRISTESSAS_TRAGEDY(ItemID.TRISTESSAS_TRAGEDY, "Tristessa's Tradgedy", "The Tragedy of Tristessa."),
|
||||
TREACHERY_OF_ROYALTY(ItemID.TREACHERY_OF_ROYALTY, "The Treachery of Royalty", "The Treachery of Royalty, by Professor Answith."),
|
||||
TRANSPORTATION_INCANTATIONS(ItemID.TRANSPORTATION_INCANTATIONS, "Transportation Incantations", "Transportation Incantations, by Amon Ducot."),
|
||||
SOUL_JORUNEY(ItemID.SOUL_JOURNEY, "Soul Journey", "The Journey of Souls, by Aretha."),
|
||||
VARLAMORE_ENVOY(ItemID.VARLAMORE_ENVOY, "Varlamore Envoy", "The Envoy to Varlamore, by Deryk Paulson.");
|
||||
|
||||
private static final Map<Integer, Book> BY_ID = buildById();
|
||||
|
||||
private static final Map<String, Book> BY_NAME = buildByName();
|
||||
|
||||
private static Map<Integer, Book> buildById()
|
||||
{
|
||||
HashMap<Integer, Book> byId = new HashMap<>();
|
||||
for (Book b : Book.values())
|
||||
{
|
||||
byId.put(b.item, b);
|
||||
}
|
||||
return Collections.unmodifiableMap(byId);
|
||||
}
|
||||
|
||||
private static final Map<String, Book> buildByName()
|
||||
{
|
||||
HashMap<String, Book> byName = new HashMap<>();
|
||||
for (Book b : Book.values())
|
||||
{
|
||||
if (!b.isDarkManuscript)
|
||||
{
|
||||
byName.put(b.name, b);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableMap(byName);
|
||||
}
|
||||
|
||||
public static Book byId(int id)
|
||||
{
|
||||
return BY_ID.get(id);
|
||||
}
|
||||
|
||||
public static Book byName(String name)
|
||||
{
|
||||
return BY_NAME.get(name);
|
||||
}
|
||||
|
||||
@Getter
|
||||
private final int item;
|
||||
|
||||
@Getter
|
||||
private final String name;
|
||||
|
||||
@Getter
|
||||
private final String shortName;
|
||||
|
||||
@Getter
|
||||
private final BufferedImage icon;
|
||||
|
||||
@Getter
|
||||
private final boolean isDarkManuscript;
|
||||
|
||||
Book(int id, String shortName, String name)
|
||||
{
|
||||
this.item = id;
|
||||
this.isDarkManuscript = false;
|
||||
this.shortName = shortName;
|
||||
this.name = name;
|
||||
this.icon = getImage(Integer.toString(id));
|
||||
}
|
||||
|
||||
Book(int id)
|
||||
{
|
||||
this.item = id;
|
||||
this.isDarkManuscript = true;
|
||||
this.name = "Dark Manuscript";
|
||||
this.shortName = "Dark Manuscript";
|
||||
this.icon = getImage(Integer.toString(id));
|
||||
}
|
||||
|
||||
private static BufferedImage getImage(String name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ImageIO.read(Book.class.getResourceAsStream("items/" + name + ".png"));
|
||||
}
|
||||
catch (IOException | IllegalArgumentException e)
|
||||
{
|
||||
throw new RuntimeException("Cannot load book " + name, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* 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.kourendlibrary;
|
||||
|
||||
import java.awt.Color;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
|
||||
class BookPanel extends JPanel
|
||||
{
|
||||
private JLabel location = new JLabel();
|
||||
|
||||
BookPanel(Book b)
|
||||
{
|
||||
GroupLayout layout = new GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
|
||||
JLabel image = new JLabel(new ImageIcon(b.getIcon()));
|
||||
JLabel name = new JLabel(b.getShortName());
|
||||
location.setFont(FontManager.getRunescapeSmallFont());
|
||||
|
||||
layout.setVerticalGroup(layout.createParallelGroup()
|
||||
.addComponent(image)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(name)
|
||||
.addComponent(location)
|
||||
)
|
||||
);
|
||||
|
||||
layout.setHorizontalGroup(layout.createSequentialGroup()
|
||||
.addComponent(image)
|
||||
.addGap(8)
|
||||
.addGroup(layout.createParallelGroup()
|
||||
.addComponent(name)
|
||||
.addComponent(location)
|
||||
)
|
||||
);
|
||||
|
||||
// AWT's Z order is weird. This put image at the back of the stack
|
||||
setComponentZOrder(image, getComponentCount() - 1);
|
||||
}
|
||||
|
||||
public void setLocation(String location)
|
||||
{
|
||||
this.location.setText(location);
|
||||
}
|
||||
|
||||
public void setIsTarget(boolean target)
|
||||
{
|
||||
location.setForeground(target ? Color.GREEN : Color.WHITE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* 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.kourendlibrary;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.Point3D;
|
||||
|
||||
class Bookcase
|
||||
{
|
||||
public Bookcase(Point3D location)
|
||||
{
|
||||
this.location = location;
|
||||
this.index = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Getter
|
||||
private final Point3D location;
|
||||
|
||||
@Getter
|
||||
private final List<Integer> index;
|
||||
|
||||
@Getter
|
||||
private boolean isBookSet;
|
||||
|
||||
/**
|
||||
* Book in this bookcase as found by the player.
|
||||
* Will be correct as long as isBookSet is true, unless the library has reset;
|
||||
*/
|
||||
@Getter
|
||||
private Book book;
|
||||
|
||||
/**
|
||||
* Books that can be in this slot. Will only be populated if library.state != SolvedState.NO_DATA
|
||||
*/
|
||||
@Getter
|
||||
private Set<Book> possibleBooks = new HashSet<>();
|
||||
|
||||
public void clearBook()
|
||||
{
|
||||
book = null;
|
||||
isBookSet = false;
|
||||
}
|
||||
|
||||
public void setBook(Book book)
|
||||
{
|
||||
this.book = book;
|
||||
this.isBookSet = true;
|
||||
}
|
||||
|
||||
public String getLocationString()
|
||||
{
|
||||
StringBuilder b = new StringBuilder();
|
||||
|
||||
boolean north = location.getY() > 3815;
|
||||
boolean west = location.getX() < 1625;
|
||||
if (north && west)
|
||||
{
|
||||
b.append("Northwest");
|
||||
}
|
||||
else if (north)
|
||||
{
|
||||
b.append("Northeast");
|
||||
}
|
||||
else if (west)
|
||||
{
|
||||
b.append("Southwest");
|
||||
}
|
||||
else
|
||||
{
|
||||
b.append("Center");
|
||||
}
|
||||
|
||||
b.append(" ");
|
||||
|
||||
switch (location.getZ())
|
||||
{
|
||||
case 0:
|
||||
b.append("ground floor");
|
||||
break;
|
||||
case 1:
|
||||
b.append("middle floor");
|
||||
break;
|
||||
case 2:
|
||||
b.append("top floor");
|
||||
break;
|
||||
}
|
||||
|
||||
if (KourendLibraryPlugin.debug)
|
||||
{
|
||||
b.append(" ").append(index.stream().map(Object::toString).collect(Collectors.joining(", ")));
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* 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.kourendlibrary;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics2D;
|
||||
|
||||
import java.awt.Polygon;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Perspective;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.Point3D;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
|
||||
import static net.runelite.api.Perspective.getCanvasTilePoly;
|
||||
|
||||
public class KourendLibraryOverlay extends Overlay
|
||||
{
|
||||
private final static Point LIBRARY_CENTER = new Point(1632, 3807);
|
||||
private final static int MAXIMUM_DISTANCE = 24;
|
||||
private final static int ROUGH_ENABLE_DISTANCE = 45;
|
||||
|
||||
private final Library library;
|
||||
private final Client client;
|
||||
|
||||
@Inject
|
||||
KourendLibraryOverlay(Library library, Client client)
|
||||
{
|
||||
this.library = library;
|
||||
this.client = client;
|
||||
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D g, java.awt.Point parent)
|
||||
{
|
||||
Player player = client.getLocalPlayer();
|
||||
if (player == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Point playerLoc = player.getWorldLocation();
|
||||
|
||||
if (playerLoc.distanceTo(LIBRARY_CENTER) > ROUGH_ENABLE_DISTANCE)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Bookcase> allBookcases = library.getBookcasesOnLevel(client.getPlane());
|
||||
|
||||
if (allBookcases == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Bookcase bookcase : allBookcases)
|
||||
{
|
||||
// AABB
|
||||
Point3D caseLoc = bookcase.getLocation();
|
||||
if (Math.abs(playerLoc.getX() - caseLoc.getX()) > MAXIMUM_DISTANCE
|
||||
|| Math.abs(playerLoc.getY() - caseLoc.getY()) > MAXIMUM_DISTANCE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Point localBookcase = Perspective.worldToLocal(client, caseLoc.toPoint());
|
||||
Point screenBookcase = Perspective.worldToCanvas(client, localBookcase.getX(), localBookcase.getY(), caseLoc.getZ(), 25);
|
||||
|
||||
if (screenBookcase != null)
|
||||
{
|
||||
boolean bookIsKnown = bookcase.isBookSet();
|
||||
Book book = bookcase.getBook();
|
||||
Set<Book> possible = bookcase.getPossibleBooks();
|
||||
if (bookIsKnown && book == null)
|
||||
{
|
||||
for (Book b : possible)
|
||||
{
|
||||
if (b != null && b.isDarkManuscript())
|
||||
{
|
||||
book = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bookIsKnown && possible.size() == 1)
|
||||
{
|
||||
book = possible.iterator().next();
|
||||
bookIsKnown = true;
|
||||
}
|
||||
Color color = bookIsKnown ? Color.ORANGE : Color.WHITE;
|
||||
|
||||
// Render the poly on the floor
|
||||
if (!(bookIsKnown && book == null) && (library.getState() == SolvedState.NO_DATA || book != null || possible.size() > 0))
|
||||
{
|
||||
Polygon poly = getCanvasTilePoly(client, localBookcase);
|
||||
if (poly != null)
|
||||
{
|
||||
OverlayUtil.renderPolygon(g, poly, color);
|
||||
}
|
||||
}
|
||||
|
||||
int height = 0;
|
||||
// If the book is singled out, render the text and the book's icon
|
||||
if (bookIsKnown)
|
||||
{
|
||||
if (book != null)
|
||||
{
|
||||
FontMetrics fm = g.getFontMetrics();
|
||||
Rectangle2D bounds = fm.getStringBounds(book.getShortName(), g);
|
||||
height = (int) bounds.getHeight() + book.getIcon().getHeight() + 6;
|
||||
Point textLoc = new Point(
|
||||
(int) (screenBookcase.getX() - (bounds.getWidth() / 2)),
|
||||
screenBookcase.getY() - (height / 2) + (int) bounds.getHeight()
|
||||
);
|
||||
OverlayUtil.renderTextLocation(g, textLoc, book.getShortName(), color);
|
||||
g.drawImage(
|
||||
book.getIcon(),
|
||||
screenBookcase.getX() - (book.getIcon().getWidth() / 2),
|
||||
screenBookcase.getY() + (height / 2) - book.getIcon().getHeight(),
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise render up to 9 icons of the possible books in the bookcase in a square
|
||||
final int BOOK_ICON_SIZE = 32;
|
||||
Book[] books = possible.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.limit(9)
|
||||
.toArray(Book[]::new);
|
||||
if (books.length > 1 && books.length <= 9)
|
||||
{
|
||||
int cols = (int) Math.ceil(Math.sqrt(books.length));
|
||||
int rows = (int) Math.ceil((double) books.length / cols);
|
||||
height = rows * BOOK_ICON_SIZE;
|
||||
int xbase = screenBookcase.getX() - ((cols * BOOK_ICON_SIZE) / 2);
|
||||
int ybase = screenBookcase.getY() - rows * BOOK_ICON_SIZE / 2;
|
||||
|
||||
for (int i = 0; i < books.length; i++)
|
||||
{
|
||||
int col = i % cols;
|
||||
int row = i / cols;
|
||||
int x = col * BOOK_ICON_SIZE;
|
||||
int y = row * BOOK_ICON_SIZE;
|
||||
if (row == rows - 1)
|
||||
{
|
||||
x += (BOOK_ICON_SIZE * (books.length % rows)) / 2;
|
||||
}
|
||||
g.drawImage(books[i].getIcon(), xbase + x, ybase + y, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the bookcase's ID on top
|
||||
if (KourendLibraryPlugin.debug)
|
||||
{
|
||||
FontMetrics fm = g.getFontMetrics();
|
||||
String str = bookcase.getIndex().stream().map(Object::toString).collect(Collectors.joining(", "));
|
||||
Rectangle2D bounds = fm.getStringBounds(str, g);
|
||||
Point textLoc = new Point((int) (screenBookcase.getX() - (bounds.getWidth() / 2)), screenBookcase.getY() - (height / 2));
|
||||
OverlayUtil.renderTextLocation(g, textLoc, str, Color.WHITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Render the customer's wanted book on their head and a poly under their feet
|
||||
LibraryCustomer customer = library.getCustomer();
|
||||
if (customer != null)
|
||||
{
|
||||
client.getNpcs().stream()
|
||||
.filter(n -> n.getId() == customer.getId())
|
||||
.forEach(n ->
|
||||
{
|
||||
Book b = library.getCustomerBook();
|
||||
Point local = n.getLocalLocation();
|
||||
Polygon poly = getCanvasTilePoly(client, local);
|
||||
OverlayUtil.renderPolygon(g, poly, Color.WHITE);
|
||||
Point screen = Perspective.worldToCanvas(client, local.getX(), local.getY(), client.getPlane(), n.getLogicalHeight());
|
||||
if (screen != null)
|
||||
{
|
||||
g.drawImage(b.getIcon(), screen.getX() - (b.getIcon().getWidth() / 2), screen.getY() - b.getIcon().getHeight(), null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* 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.kourendlibrary;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.inject.Singleton;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import net.runelite.client.ui.PluginPanel;
|
||||
|
||||
@Singleton
|
||||
public class KourendLibraryPanel extends PluginPanel
|
||||
{
|
||||
@Inject
|
||||
private Library library;
|
||||
|
||||
private final HashMap<Book, BookPanel> bookPanels = new HashMap<>();
|
||||
|
||||
void init()
|
||||
{
|
||||
GroupLayout layout = new GroupLayout(this);
|
||||
setLayout(layout);
|
||||
|
||||
JPanel books = new JPanel(new GridBagLayout());
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.weightx = 1;
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
Stream.of(Book.values())
|
||||
.filter(b -> !b.isDarkManuscript())
|
||||
.sorted(Comparator.comparing(Book::getShortName))
|
||||
.forEach(b ->
|
||||
{
|
||||
BookPanel p = new BookPanel(b);
|
||||
bookPanels.put(b, p);
|
||||
books.add(p, c);
|
||||
c.gridy++;
|
||||
});
|
||||
|
||||
JButton reset = new JButton("Reset");
|
||||
reset.addActionListener(e ->
|
||||
{
|
||||
library.reset();
|
||||
update();
|
||||
});
|
||||
|
||||
layout.setHorizontalGroup(layout.createParallelGroup()
|
||||
.addComponent(books)
|
||||
.addComponent(reset)
|
||||
);
|
||||
layout.setVerticalGroup(layout.createSequentialGroup()
|
||||
.addComponent(books)
|
||||
.addGap(4)
|
||||
.addComponent(reset)
|
||||
);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
Book customerBook = library.getCustomerBook();
|
||||
for (Map.Entry<Book, BookPanel> b : bookPanels.entrySet())
|
||||
{
|
||||
b.getValue().setIsTarget(customerBook == b.getKey());
|
||||
}
|
||||
|
||||
HashMap<Book, HashSet<String>> bookLocations = new HashMap<>();
|
||||
|
||||
for (Bookcase bookcase : library.getBookcases())
|
||||
{
|
||||
if (bookcase.getBook() != null)
|
||||
{
|
||||
bookLocations.computeIfAbsent(bookcase.getBook(), a -> new HashSet<>()).add(bookcase.getLocationString());
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Book book : bookcase.getPossibleBooks())
|
||||
{
|
||||
if (book != null)
|
||||
{
|
||||
bookLocations.computeIfAbsent(book, a -> new HashSet<>()).add(bookcase.getLocationString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<Book, BookPanel> e : bookPanels.entrySet())
|
||||
{
|
||||
HashSet<String> locs = bookLocations.get(e.getKey());
|
||||
if (locs == null || locs.size() > 3)
|
||||
{
|
||||
e.getValue().setLocation("Unknown");
|
||||
}
|
||||
else
|
||||
{
|
||||
e.getValue().setLocation("<html>" + locs.stream().collect(Collectors.joining("<br>")) + "</html>");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* 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.kourendlibrary;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.AnimationID;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.Perspective;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.Point3D;
|
||||
import net.runelite.api.events.AnimationChanged;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Kourend Library"
|
||||
)
|
||||
@Slf4j
|
||||
public class KourendLibraryPlugin extends Plugin
|
||||
{
|
||||
final static boolean debug = false;
|
||||
|
||||
@Inject
|
||||
private ClientUI ui;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private Library library;
|
||||
|
||||
@Inject
|
||||
private KourendLibraryOverlay overlay;
|
||||
|
||||
private KourendLibraryPanel panel;
|
||||
private NavigationButton navButton;
|
||||
|
||||
private Point3D lastBookcaseClick = null;
|
||||
private Point3D lastBookcaseAnimatedOn = null;
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
panel = injector.getInstance(KourendLibraryPanel.class);
|
||||
panel.init();
|
||||
|
||||
navButton = new NavigationButton(
|
||||
"Kourend Library",
|
||||
ImageIO.read(Book.class.getResourceAsStream("panel_icon.png")),
|
||||
() -> panel
|
||||
);
|
||||
|
||||
ui.getPluginToolbar().addNavigation(navButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown()
|
||||
{
|
||||
ui.getPluginToolbar().removeNavigation(navButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Overlay getOverlay()
|
||||
{
|
||||
return overlay;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onMenuOptionClicked(MenuOptionClicked menuOpt)
|
||||
{
|
||||
if (MenuAction.GAME_OBJECT_FIRST_OPTION == menuOpt.getMenuAction() && menuOpt.getMenuTarget().contains("Bookshelf"))
|
||||
{
|
||||
Point worldPoint = Perspective.regionToWorld(client, new Point(menuOpt.getId() & 127, menuOpt.getId() >> 7 & 127));
|
||||
lastBookcaseClick = new Point3D(worldPoint.getX(), worldPoint.getY(), client.getPlane());
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onAnimationChanged(AnimationChanged anim)
|
||||
{
|
||||
if (anim.getActor() == client.getLocalPlayer() && anim.getActor().getAnimation() == AnimationID.LOOKING_INTO)
|
||||
{
|
||||
lastBookcaseAnimatedOn = lastBookcaseClick;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onChatMessage(ChatMessage event)
|
||||
{
|
||||
if (lastBookcaseAnimatedOn != null && event.getType() == ChatMessageType.SERVER)
|
||||
{
|
||||
if (event.getMessage().equals("You don't find anything useful here."))
|
||||
{
|
||||
library.mark(lastBookcaseAnimatedOn, null);
|
||||
panel.update();
|
||||
lastBookcaseAnimatedOn = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final Pattern BOOK_EXTRACTOR = Pattern.compile("'<col=0000ff>(.*)</col>'");
|
||||
private static final Pattern TAG_MATCHER = Pattern.compile("(<[^>]*>)");
|
||||
|
||||
@Subscribe
|
||||
void onTick(GameTick tick)
|
||||
{
|
||||
if (lastBookcaseAnimatedOn != null)
|
||||
{
|
||||
Widget find = client.getWidget(WidgetInfo.DIALOG_SPRITE_SPRITE);
|
||||
if (find != null)
|
||||
{
|
||||
Book book = Book.byId(find.getItemId());
|
||||
if (book != null)
|
||||
{
|
||||
library.mark(lastBookcaseAnimatedOn, book);
|
||||
panel.update();
|
||||
lastBookcaseAnimatedOn = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Widget npcHead = client.getWidget(WidgetInfo.DIALOG_NPC_HEAD_MODEL);
|
||||
if (npcHead != null)
|
||||
{
|
||||
LibraryCustomer cust = LibraryCustomer.getById(npcHead.getModelId());
|
||||
if (cust != null)
|
||||
{
|
||||
Widget textw = client.getWidget(WidgetInfo.DIALOG_NPC_TEXT);
|
||||
String text = textw.getText();
|
||||
Matcher m = BOOK_EXTRACTOR.matcher(text);
|
||||
if (m.find())
|
||||
{
|
||||
String bookName = TAG_MATCHER.matcher(m.group(1).replace("<br>", " ")).replaceAll("");
|
||||
Book book = Book.byName(bookName);
|
||||
if (book == null)
|
||||
{
|
||||
log.warn("Book '{}' is not recognised", bookName);
|
||||
return;
|
||||
}
|
||||
library.setCustomer(cust, book);
|
||||
panel.update();
|
||||
}
|
||||
else if (text.contains("You can have this other book") || text.contains("please accept a token of my thanks.") || text.contains("Thanks, I'll get on with reading it."))
|
||||
{
|
||||
library.setCustomer(null, null);
|
||||
panel.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,800 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* 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.kourendlibrary;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.IntStream;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Point3D;
|
||||
|
||||
import static net.runelite.client.plugins.kourendlibrary.Book.*;
|
||||
|
||||
/**
|
||||
* Library represents a instance of the Kourend/Arceuus House library.
|
||||
* <p>
|
||||
* The library changes the locations of it's books every 60-90 minutes.
|
||||
* Of the 554 bookcases in the library, only 346 of them can ever have books.
|
||||
* 6 of the bookcases in the south-west corner of the top floor are duplicated.
|
||||
* These 6 bookcases are not handled 100% correctly due to their low chance
|
||||
* of being used to train the predictor.
|
||||
* <p>
|
||||
* Each of the 352 bookcase slots "Bookcase"s has an index which is used to
|
||||
* place the book inside of them. The game chooses one of the 5 sequences and a
|
||||
* bookcase starting index, then places a book from the sequence into every 13th
|
||||
* bookcase, by index. Each sequence contains 26 Books, consisting of 16 books
|
||||
* and 10 dark manuscripts. You can only get one dark manuscript at a time, though
|
||||
* they are all placed into shelves.
|
||||
*/
|
||||
@Singleton
|
||||
@Slf4j
|
||||
public class Library
|
||||
{
|
||||
private final Map<Point3D, Bookcase> byPoint = new HashMap<>();
|
||||
private final Map<Integer, ArrayList<Bookcase>> byLevel = new HashMap<>();
|
||||
private final List<Bookcase> byIndex = new ArrayList<>();
|
||||
|
||||
private final List<List<Book>> sequences = populateSequences();
|
||||
|
||||
private final int step;
|
||||
|
||||
@Getter
|
||||
private SolvedState state;
|
||||
|
||||
@Getter
|
||||
private Book customerBook;
|
||||
|
||||
@Getter
|
||||
private LibraryCustomer customer;
|
||||
|
||||
Library()
|
||||
{
|
||||
populateBooks();
|
||||
step = byIndex.size() / Book.values().length;
|
||||
reset();
|
||||
}
|
||||
|
||||
public synchronized List<Bookcase> getBookcasesOnLevel(int z)
|
||||
{
|
||||
return Collections.unmodifiableList(byLevel.get(z));
|
||||
}
|
||||
|
||||
public synchronized List<Bookcase> getBookcases()
|
||||
{
|
||||
return Collections.unmodifiableList(byIndex);
|
||||
}
|
||||
|
||||
public void setCustomer(LibraryCustomer customer, Book book)
|
||||
{
|
||||
this.customer = customer;
|
||||
this.customerBook = book;
|
||||
}
|
||||
|
||||
public synchronized void reset()
|
||||
{
|
||||
state = SolvedState.NO_DATA;
|
||||
for (Bookcase b : byIndex)
|
||||
{
|
||||
b.clearBook();
|
||||
b.getPossibleBooks().clear();
|
||||
}
|
||||
log.info("Library is now reset");
|
||||
}
|
||||
|
||||
public synchronized void mark(Point3D loc, Book book)
|
||||
{
|
||||
Bookcase bookcase = byPoint.get(loc);
|
||||
if (bookcase == null)
|
||||
{
|
||||
log.debug("Requested non-existent bookcase at {}", loc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bookcase.isBookSet())
|
||||
{
|
||||
// Bookcase is set from a previous mark
|
||||
// Check for a mismatch, unless it is now null and had a dark manuscript
|
||||
if (book != bookcase.getBook() && !(book == null && bookcase.getBook().isDarkManuscript()))
|
||||
{
|
||||
reset();
|
||||
}
|
||||
}
|
||||
else if (state != SolvedState.NO_DATA)
|
||||
{
|
||||
// We know all of the possible things in this shelf.
|
||||
if (book != null)
|
||||
{
|
||||
// Check to see if our guess is wrong
|
||||
if (!bookcase.getPossibleBooks().contains(book))
|
||||
{
|
||||
reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Everything is known, nothing to do
|
||||
if (state == SolvedState.COMPLETE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("Setting bookcase {} to {}", bookcase.getIndex(), book);
|
||||
for (; ; )
|
||||
{
|
||||
bookcase.setBook(book);
|
||||
|
||||
// Basing the sequences on null is not supported, though possible
|
||||
if (book == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// This is one of the 6 bookcases with 2 ids. Not fully supported.
|
||||
if (bookcase.getIndex().size() != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int bookcaseIndex = bookcase.getIndex().get(0);
|
||||
|
||||
state = SolvedState.INCOMPLETE;
|
||||
|
||||
// Map each sequence to the number of bookcases that match the sequence
|
||||
// return 0 if it is a mismatch.
|
||||
// Keep in mind that Bookcases with dark manuscripts may be set to null.
|
||||
int[] certainty = sequences.stream().mapToInt(sequence ->
|
||||
{
|
||||
int zero = getBookcaseZeroIndexForSequenceWithBook(sequence, bookcaseIndex, book);
|
||||
|
||||
int found = 0;
|
||||
for (int i = 0; i < byIndex.size(); i++)
|
||||
{
|
||||
int ai = (i + zero) % byIndex.size();
|
||||
Bookcase iBookcase = byIndex.get(ai);
|
||||
if (i % step == 0)
|
||||
{
|
||||
int seqI = i / step;
|
||||
if (iBookcase.isBookSet() && seqI < sequence.size())
|
||||
{
|
||||
Book seqBook = sequence.get(seqI);
|
||||
boolean isSeqManuscript = seqBook == null || seqBook.isDarkManuscript();
|
||||
if (!((isSeqManuscript && iBookcase.getBook() == null) || (iBookcase.getBook() == seqBook)))
|
||||
{
|
||||
log.debug("Bailing @ i={} ai={} {}; {} != {}", i, ai, iBookcase.getIndex(), iBookcase.getBook(), seqBook);
|
||||
found = 0;
|
||||
break;
|
||||
}
|
||||
found++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only bail if this isn't a double bookcase
|
||||
if (iBookcase.isBookSet() && iBookcase.getBook() != null && iBookcase.getIndex().size() == 1)
|
||||
{
|
||||
log.debug("Bailing @ i={} ai={} {}; {} is set", i, ai, iBookcase.getIndex(), iBookcase.getBook());
|
||||
found = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}).toArray();
|
||||
log.info("Certainty is now {}", certainty);
|
||||
|
||||
for (Bookcase b : byIndex)
|
||||
{
|
||||
b.getPossibleBooks().clear();
|
||||
}
|
||||
|
||||
// Write the most likely sequences onto the bookcases
|
||||
int max = IntStream.of(certainty).max().getAsInt();
|
||||
|
||||
// We have books set, but 0 sequences match, Something is wrong, reset.
|
||||
if (max == 0)
|
||||
{
|
||||
reset();
|
||||
continue;
|
||||
}
|
||||
|
||||
IntStream.range(0, sequences.size())
|
||||
.filter(i -> certainty[i] == max)
|
||||
.forEach(isequence ->
|
||||
{
|
||||
List<Book> sequence = sequences.get(isequence);
|
||||
int zero = getBookcaseZeroIndexForSequenceWithBook(sequence, bookcaseIndex, book);
|
||||
|
||||
for (int i = 0; i < byIndex.size(); i++)
|
||||
{
|
||||
int ai = (i + zero) % byIndex.size();
|
||||
Bookcase iBookcase = byIndex.get(ai);
|
||||
if (iBookcase.getBook() == null)
|
||||
{
|
||||
int iseq = i / step;
|
||||
if (i % step == 0 && iseq < sequence.size())
|
||||
{
|
||||
Book seqBook = sequence.get(iseq);
|
||||
iBookcase.getPossibleBooks().add(seqBook);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (IntStream.range(0, certainty.length).filter(i -> certainty[i] == max).count() == 1)
|
||||
{
|
||||
state = SolvedState.COMPLETE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the bookcase index that is index zero in the sequence, identifying by the book in bookcase
|
||||
*/
|
||||
private int getBookcaseZeroIndexForSequenceWithBook(List<Book> sequences, int bookcaseIndex, Book book)
|
||||
{
|
||||
int bookSequence = sequences.indexOf(book);
|
||||
assert bookSequence >= 0;
|
||||
|
||||
bookcaseIndex -= step * bookSequence;
|
||||
for (; bookcaseIndex < 0; )
|
||||
{
|
||||
bookcaseIndex += byIndex.size();
|
||||
}
|
||||
return bookcaseIndex;
|
||||
}
|
||||
|
||||
private List<List<Book>> populateSequences()
|
||||
{
|
||||
List<List<Book>> books = Arrays.asList(
|
||||
Arrays.asList(
|
||||
DARK_MANUSCRIPT_13516,
|
||||
KILLING_OF_A_KING,
|
||||
DARK_MANUSCRIPT_13520,
|
||||
IDEOLOGY_OF_DARKNESS,
|
||||
RADAS_JOURNEY,
|
||||
TRANSVERGENCE_THEORY,
|
||||
TRISTESSAS_TRAGEDY,
|
||||
DARK_MANUSCRIPT_13523,
|
||||
DARK_MANUSCRIPT_13521,
|
||||
RADAS_CENSUS,
|
||||
TREACHERY_OF_ROYALTY,
|
||||
HOSIDIUS_LETTER,
|
||||
DARK_MANUSCRIPT_13519,
|
||||
RICKTORS_DIARY_7,
|
||||
DARK_MANUSCRIPT_13514,
|
||||
EATHRAM_RADA_EXTRACT,
|
||||
DARK_MANUSCRIPT_13522,
|
||||
VARLAMORE_ENVOY,
|
||||
WINTERTODT_PARABLE,
|
||||
TWILL_ACCORD,
|
||||
DARK_MANUSCRIPT_13515,
|
||||
BYRNES_CORONATION_SPEECH,
|
||||
DARK_MANUSCRIPT_13517,
|
||||
SOUL_JORUNEY,
|
||||
DARK_MANUSCRIPT_13518,
|
||||
TRANSPORTATION_INCANTATIONS
|
||||
),
|
||||
Arrays.asList(
|
||||
DARK_MANUSCRIPT_13516,
|
||||
KILLING_OF_A_KING,
|
||||
DARK_MANUSCRIPT_13520,
|
||||
IDEOLOGY_OF_DARKNESS,
|
||||
RADAS_JOURNEY,
|
||||
TRANSVERGENCE_THEORY,
|
||||
TRISTESSAS_TRAGEDY,
|
||||
DARK_MANUSCRIPT_13523,
|
||||
DARK_MANUSCRIPT_13521,
|
||||
RADAS_CENSUS,
|
||||
TREACHERY_OF_ROYALTY,
|
||||
HOSIDIUS_LETTER,
|
||||
VARLAMORE_ENVOY,
|
||||
DARK_MANUSCRIPT_13519,
|
||||
RICKTORS_DIARY_7,
|
||||
DARK_MANUSCRIPT_13514,
|
||||
EATHRAM_RADA_EXTRACT,
|
||||
DARK_MANUSCRIPT_13522,
|
||||
SOUL_JORUNEY,
|
||||
WINTERTODT_PARABLE,
|
||||
TWILL_ACCORD,
|
||||
DARK_MANUSCRIPT_13515,
|
||||
BYRNES_CORONATION_SPEECH,
|
||||
DARK_MANUSCRIPT_13517,
|
||||
DARK_MANUSCRIPT_13518,
|
||||
TRANSPORTATION_INCANTATIONS
|
||||
),
|
||||
Arrays.asList(
|
||||
RICKTORS_DIARY_7,
|
||||
VARLAMORE_ENVOY,
|
||||
DARK_MANUSCRIPT_13514,
|
||||
EATHRAM_RADA_EXTRACT,
|
||||
IDEOLOGY_OF_DARKNESS,
|
||||
DARK_MANUSCRIPT_13516,
|
||||
DARK_MANUSCRIPT_13521,
|
||||
RADAS_CENSUS,
|
||||
DARK_MANUSCRIPT_13515,
|
||||
KILLING_OF_A_KING,
|
||||
DARK_MANUSCRIPT_13520,
|
||||
TREACHERY_OF_ROYALTY,
|
||||
HOSIDIUS_LETTER,
|
||||
DARK_MANUSCRIPT_13519,
|
||||
BYRNES_CORONATION_SPEECH,
|
||||
DARK_MANUSCRIPT_13517,
|
||||
SOUL_JORUNEY,
|
||||
DARK_MANUSCRIPT_13522,
|
||||
WINTERTODT_PARABLE,
|
||||
TWILL_ACCORD,
|
||||
RADAS_JOURNEY,
|
||||
TRANSVERGENCE_THEORY,
|
||||
TRISTESSAS_TRAGEDY,
|
||||
DARK_MANUSCRIPT_13523,
|
||||
DARK_MANUSCRIPT_13518,
|
||||
TRANSPORTATION_INCANTATIONS
|
||||
),
|
||||
Arrays.asList(
|
||||
RADAS_CENSUS,
|
||||
DARK_MANUSCRIPT_13522,
|
||||
RICKTORS_DIARY_7,
|
||||
DARK_MANUSCRIPT_13514,
|
||||
EATHRAM_RADA_EXTRACT,
|
||||
DARK_MANUSCRIPT_13516,
|
||||
KILLING_OF_A_KING,
|
||||
DARK_MANUSCRIPT_13520,
|
||||
HOSIDIUS_LETTER,
|
||||
DARK_MANUSCRIPT_13519,
|
||||
DARK_MANUSCRIPT_13521,
|
||||
WINTERTODT_PARABLE,
|
||||
TWILL_ACCORD,
|
||||
DARK_MANUSCRIPT_13515,
|
||||
BYRNES_CORONATION_SPEECH,
|
||||
DARK_MANUSCRIPT_13517,
|
||||
IDEOLOGY_OF_DARKNESS,
|
||||
RADAS_JOURNEY,
|
||||
TRANSVERGENCE_THEORY,
|
||||
TRISTESSAS_TRAGEDY,
|
||||
DARK_MANUSCRIPT_13523,
|
||||
TREACHERY_OF_ROYALTY,
|
||||
DARK_MANUSCRIPT_13518,
|
||||
TRANSPORTATION_INCANTATIONS,
|
||||
SOUL_JORUNEY,
|
||||
VARLAMORE_ENVOY
|
||||
),
|
||||
Arrays.asList(
|
||||
RADAS_CENSUS,
|
||||
TRANSVERGENCE_THEORY,
|
||||
TREACHERY_OF_ROYALTY,
|
||||
RADAS_JOURNEY,
|
||||
KILLING_OF_A_KING,
|
||||
DARK_MANUSCRIPT_13520,
|
||||
VARLAMORE_ENVOY,
|
||||
DARK_MANUSCRIPT_13522,
|
||||
BYRNES_CORONATION_SPEECH,
|
||||
DARK_MANUSCRIPT_13517,
|
||||
HOSIDIUS_LETTER,
|
||||
DARK_MANUSCRIPT_13516,
|
||||
DARK_MANUSCRIPT_13519,
|
||||
TRISTESSAS_TRAGEDY,
|
||||
DARK_MANUSCRIPT_13523,
|
||||
DARK_MANUSCRIPT_13521,
|
||||
RICKTORS_DIARY_7,
|
||||
DARK_MANUSCRIPT_13514,
|
||||
IDEOLOGY_OF_DARKNESS,
|
||||
WINTERTODT_PARABLE,
|
||||
TWILL_ACCORD,
|
||||
SOUL_JORUNEY,
|
||||
DARK_MANUSCRIPT_13515,
|
||||
EATHRAM_RADA_EXTRACT,
|
||||
DARK_MANUSCRIPT_13518,
|
||||
TRANSPORTATION_INCANTATIONS
|
||||
)
|
||||
);
|
||||
|
||||
for (int i = 0; i < books.size(); i++)
|
||||
{
|
||||
assert new HashSet<>(books.get(i)).size() == books.get(i).size();
|
||||
books.set(i, Collections.unmodifiableList(books.get(i)));
|
||||
}
|
||||
return Collections.unmodifiableList(books);
|
||||
}
|
||||
|
||||
private void add(int x, int y, int z, int i)
|
||||
{
|
||||
// 'i' is added as a parameter for readability
|
||||
Point3D p = new Point3D(x, y, z);
|
||||
Bookcase b = byPoint.get(p);
|
||||
if (b == null)
|
||||
{
|
||||
b = new Bookcase(p);
|
||||
byPoint.put(p, b);
|
||||
byLevel.computeIfAbsent(z, a -> new ArrayList<>()).add(b);
|
||||
}
|
||||
b.getIndex().add(i);
|
||||
assert i == byIndex.size();
|
||||
byIndex.add(b);
|
||||
}
|
||||
|
||||
private void populateBooks()
|
||||
{
|
||||
add(1626, 3795, 0, 0);
|
||||
add(1625, 3793, 0, 1);
|
||||
add(1623, 3793, 0, 2);
|
||||
add(1620, 3792, 0, 3);
|
||||
add(1624, 3792, 0, 4);
|
||||
add(1626, 3788, 0, 5);
|
||||
add(1626, 3787, 0, 6);
|
||||
add(1624, 3784, 0, 7);
|
||||
add(1623, 3784, 0, 8);
|
||||
add(1621, 3784, 0, 9);
|
||||
add(1615, 3785, 0, 10);
|
||||
add(1615, 3788, 0, 11);
|
||||
add(1615, 3790, 0, 12);
|
||||
add(1614, 3790, 0, 13);
|
||||
add(1614, 3788, 0, 14);
|
||||
add(1614, 3786, 0, 15);
|
||||
add(1612, 3784, 0, 16);
|
||||
add(1610, 3784, 0, 17);
|
||||
add(1609, 3784, 0, 18);
|
||||
add(1607, 3786, 0, 19);
|
||||
add(1607, 3789, 0, 20);
|
||||
add(1607, 3795, 0, 21);
|
||||
add(1607, 3796, 0, 22);
|
||||
add(1607, 3799, 0, 23);
|
||||
add(1610, 3801, 0, 24);
|
||||
add(1612, 3801, 0, 25);
|
||||
add(1618, 3801, 0, 26);
|
||||
add(1620, 3801, 0, 27);
|
||||
add(1620, 3814, 0, 28);
|
||||
add(1618, 3814, 0, 29);
|
||||
add(1617, 3814, 0, 30);
|
||||
add(1615, 3816, 0, 31);
|
||||
add(1615, 3817, 0, 32);
|
||||
add(1615, 3820, 0, 33);
|
||||
add(1614, 3820, 0, 34);
|
||||
add(1614, 3817, 0, 35);
|
||||
add(1614, 3816, 0, 36);
|
||||
add(1612, 3814, 0, 37);
|
||||
add(1610, 3814, 0, 38);
|
||||
add(1607, 3816, 0, 39);
|
||||
add(1607, 3817, 0, 40);
|
||||
add(1607, 3820, 0, 41);
|
||||
add(1607, 3826, 0, 42);
|
||||
add(1607, 3828, 0, 43);
|
||||
add(1609, 3831, 0, 44);
|
||||
add(1612, 3831, 0, 45);
|
||||
add(1614, 3831, 0, 46);
|
||||
add(1619, 3831, 0, 47);
|
||||
add(1621, 3831, 0, 48);
|
||||
add(1624, 3831, 0, 49);
|
||||
add(1626, 3829, 0, 50);
|
||||
add(1626, 3827, 0, 51);
|
||||
add(1624, 3823, 0, 52);
|
||||
add(1622, 3823, 0, 53);
|
||||
add(1620, 3823, 0, 54);
|
||||
add(1621, 3822, 0, 55);
|
||||
add(1624, 3822, 0, 56);
|
||||
add(1626, 3820, 0, 57);
|
||||
add(1639, 3821, 0, 58);
|
||||
add(1639, 3822, 0, 59);
|
||||
add(1639, 3827, 0, 60);
|
||||
add(1639, 3829, 0, 61);
|
||||
add(1642, 3831, 0, 62);
|
||||
add(1645, 3831, 0, 63);
|
||||
add(1646, 3829, 0, 64);
|
||||
add(1646, 3827, 0, 65);
|
||||
add(1646, 3826, 0, 66);
|
||||
add(1647, 3827, 0, 67);
|
||||
add(1647, 3829, 0, 68);
|
||||
add(1647, 3830, 0, 69);
|
||||
add(1652, 3831, 0, 70);
|
||||
add(1653, 3831, 0, 71);
|
||||
add(1656, 3831, 0, 72);
|
||||
add(1658, 3829, 0, 73);
|
||||
add(1658, 3826, 0, 74);
|
||||
add(1658, 3825, 0, 75);
|
||||
add(1658, 3820, 0, 76);
|
||||
add(1658, 3819, 0, 77);
|
||||
add(1658, 3816, 0, 78);
|
||||
add(1655, 3814, 0, 79);
|
||||
add(1654, 3814, 0, 80);
|
||||
add(1651, 3817, 0, 81);
|
||||
add(1651, 3819, 0, 82);
|
||||
add(1651, 3820, 0, 83);
|
||||
add(1650, 3821, 0, 84);
|
||||
add(1650, 3819, 0, 85);
|
||||
add(1650, 3816, 0, 86);
|
||||
add(1648, 3814, 0, 87);
|
||||
add(1646, 3814, 0, 88);
|
||||
add(1645, 3814, 0, 89);
|
||||
add(1607, 3820, 1, 90);
|
||||
add(1607, 3821, 1, 91);
|
||||
add(1609, 3822, 1, 92);
|
||||
add(1612, 3823, 1, 93);
|
||||
add(1611, 3823, 1, 94);
|
||||
add(1607, 3824, 1, 95);
|
||||
add(1607, 3825, 1, 96);
|
||||
add(1607, 3827, 1, 97);
|
||||
add(1611, 3831, 1, 98);
|
||||
add(1612, 3831, 1, 99);
|
||||
add(1613, 3831, 1, 100);
|
||||
add(1617, 3831, 1, 101);
|
||||
add(1618, 3831, 1, 102);
|
||||
add(1620, 3831, 1, 103);
|
||||
add(1624, 3831, 1, 104);
|
||||
add(1624, 3829, 1, 105);
|
||||
add(1624, 3825, 1, 106);
|
||||
add(1624, 3824, 1, 107);
|
||||
add(1624, 3819, 1, 108);
|
||||
add(1624, 3817, 1, 109);
|
||||
add(1623, 3816, 1, 110);
|
||||
add(1621, 3816, 1, 111);
|
||||
add(1617, 3816, 1, 112);
|
||||
add(1616, 3816, 1, 113);
|
||||
add(1611, 3816, 1, 114);
|
||||
add(1609, 3816, 1, 115);
|
||||
add(1620, 3820, 1, 116);
|
||||
add(1620, 3822, 1, 117);
|
||||
add(1620, 3824, 1, 118);
|
||||
add(1620, 3825, 1, 119);
|
||||
add(1620, 3827, 1, 120);
|
||||
add(1621, 3826, 1, 121);
|
||||
add(1621, 3822, 1, 122);
|
||||
add(1621, 3820, 1, 123);
|
||||
add(1607, 3788, 1, 124);
|
||||
add(1607, 3789, 1, 125);
|
||||
add(1609, 3790, 1, 126);
|
||||
add(1611, 3790, 1, 127);
|
||||
add(1613, 3790, 1, 128);
|
||||
add(1614, 3789, 1, 129);
|
||||
add(1615, 3788, 1, 130);
|
||||
add(1615, 3790, 1, 131);
|
||||
add(1614, 3791, 1, 132);
|
||||
add(1613, 3791, 1, 133);
|
||||
add(1610, 3791, 1, 134);
|
||||
add(1609, 3791, 1, 135);
|
||||
add(1608, 3791, 1, 136);
|
||||
add(1607, 3793, 1, 137);
|
||||
add(1607, 3794, 1, 138);
|
||||
add(1608, 3799, 1, 139);
|
||||
add(1610, 3799, 1, 140);
|
||||
add(1615, 3799, 1, 141);
|
||||
add(1616, 3799, 1, 142);
|
||||
add(1621, 3799, 1, 143);
|
||||
add(1623, 3799, 1, 144);
|
||||
add(1624, 3798, 1, 145);
|
||||
add(1624, 3796, 1, 146);
|
||||
add(1624, 3792, 1, 147);
|
||||
add(1624, 3791, 1, 148);
|
||||
add(1623, 3789, 1, 149);
|
||||
add(1621, 3789, 1, 150);
|
||||
add(1620, 3788, 1, 151);
|
||||
add(1621, 3788, 1, 152);
|
||||
add(1624, 3787, 1, 153);
|
||||
add(1624, 3786, 1, 154);
|
||||
add(1619, 3784, 1, 155);
|
||||
add(1618, 3784, 1, 156);
|
||||
add(1616, 3784, 1, 157);
|
||||
add(1612, 3784, 1, 158);
|
||||
add(1611, 3784, 1, 159);
|
||||
add(1625, 3801, 1, 160);
|
||||
add(1625, 3802, 1, 161);
|
||||
add(1625, 3803, 1, 162);
|
||||
add(1625, 3804, 1, 163);
|
||||
add(1625, 3806, 1, 164);
|
||||
add(1625, 3807, 1, 165);
|
||||
add(1625, 3808, 1, 166);
|
||||
add(1625, 3809, 1, 167);
|
||||
add(1625, 3811, 1, 168);
|
||||
add(1625, 3812, 1, 169);
|
||||
add(1625, 3813, 1, 170);
|
||||
add(1625, 3814, 1, 171);
|
||||
add(1626, 3815, 1, 172);
|
||||
add(1627, 3815, 1, 173);
|
||||
add(1631, 3815, 1, 174);
|
||||
add(1632, 3815, 1, 175);
|
||||
add(1633, 3815, 1, 176);
|
||||
add(1634, 3815, 1, 177);
|
||||
add(1638, 3815, 1, 178);
|
||||
add(1639, 3815, 1, 179);
|
||||
add(1640, 3814, 1, 180);
|
||||
add(1640, 3813, 1, 181);
|
||||
add(1640, 3803, 1, 182);
|
||||
add(1640, 3802, 1, 183);
|
||||
add(1640, 3801, 1, 184);
|
||||
add(1639, 3800, 1, 185);
|
||||
add(1638, 3800, 1, 186);
|
||||
add(1634, 3800, 1, 187);
|
||||
add(1633, 3800, 1, 188);
|
||||
add(1632, 3800, 1, 189);
|
||||
add(1631, 3800, 1, 190);
|
||||
add(1627, 3800, 1, 191);
|
||||
add(1626, 3800, 1, 192);
|
||||
add(1641, 3817, 1, 193);
|
||||
add(1641, 3818, 1, 194);
|
||||
add(1641, 3819, 1, 195);
|
||||
add(1641, 3824, 1, 196);
|
||||
add(1641, 3825, 1, 197);
|
||||
add(1641, 3829, 1, 198);
|
||||
add(1645, 3831, 1, 199);
|
||||
add(1646, 3831, 1, 200);
|
||||
add(1647, 3831, 1, 201);
|
||||
add(1648, 3831, 1, 202);
|
||||
add(1649, 3830, 1, 203);
|
||||
add(1649, 3828, 1, 204);
|
||||
add(1650, 3829, 1, 205);
|
||||
add(1652, 3831, 1, 206);
|
||||
add(1653, 3831, 1, 207);
|
||||
add(1658, 3827, 1, 208);
|
||||
add(1658, 3826, 1, 209);
|
||||
add(1658, 3823, 1, 210);
|
||||
add(1658, 3822, 1, 211);
|
||||
add(1658, 3821, 1, 212);
|
||||
add(1658, 3820, 1, 213);
|
||||
add(1656, 3816, 1, 214);
|
||||
add(1655, 3816, 1, 215);
|
||||
add(1651, 3816, 1, 216);
|
||||
add(1649, 3816, 1, 217);
|
||||
add(1648, 3816, 1, 218);
|
||||
add(1644, 3816, 1, 219);
|
||||
add(1643, 3816, 1, 220);
|
||||
add(1607, 3785, 2, 221);
|
||||
add(1607, 3786, 2, 222);
|
||||
add(1607, 3796, 2, 223);
|
||||
add(1607, 3797, 2, 224);
|
||||
add(1608, 3799, 2, 225);
|
||||
add(1610, 3799, 2, 226);
|
||||
add(1611, 3799, 2, 227);
|
||||
add(1618, 3799, 2, 228);
|
||||
add(1621, 3799, 2, 229);
|
||||
add(1624, 3797, 2, 230);
|
||||
add(1624, 3795, 2, 231);
|
||||
add(1624, 3794, 2, 232);
|
||||
add(1624, 3792, 2, 233);
|
||||
add(1623, 3791, 2, 234);
|
||||
add(1622, 3791, 2, 235);
|
||||
add(1618, 3792, 2, 236);
|
||||
add(1618, 3793, 2, 237);
|
||||
add(1618, 3794, 2, 238);
|
||||
add(1617, 3793, 2, 239);
|
||||
add(1617, 3792, 2, 240);
|
||||
add(1618, 3790, 2, 241);
|
||||
add(1620, 3790, 2, 242);
|
||||
add(1622, 3790, 2, 243);
|
||||
add(1624, 3789, 2, 244);
|
||||
add(1624, 3788, 2, 245);
|
||||
add(1624, 3786, 2, 246);
|
||||
add(1624, 3785, 2, 247);
|
||||
add(1623, 3784, 2, 248);
|
||||
add(1621, 3784, 2, 249);
|
||||
add(1611, 3784, 2, 250);
|
||||
add(1609, 3784, 2, 251);
|
||||
add(1612, 3789, 2, 252);
|
||||
add(1612, 3791, 2, 253);
|
||||
add(1612, 3794, 2, 254);
|
||||
add(1613, 3793, 2, 255);
|
||||
add(1613, 3792, 2, 256);
|
||||
add(1613, 3791, 2, 257);
|
||||
add(1617, 3791, 2, 258);
|
||||
add(1617, 3793, 2, 259);
|
||||
add(1618, 3794, 2, 260);
|
||||
add(1618, 3792, 2, 261);
|
||||
add(1619, 3791, 2, 262);
|
||||
add(1623, 3791, 2, 263);
|
||||
add(1623, 3790, 2, 264);
|
||||
add(1622, 3790, 2, 265);
|
||||
add(1619, 3790, 2, 266);
|
||||
add(1611, 3816, 2, 267);
|
||||
add(1610, 3816, 2, 268);
|
||||
add(1609, 3816, 2, 269);
|
||||
add(1607, 3817, 2, 270);
|
||||
add(1607, 3819, 2, 271);
|
||||
add(1607, 3829, 2, 272);
|
||||
add(1608, 3831, 2, 273);
|
||||
add(1610, 3831, 2, 274);
|
||||
add(1611, 3831, 2, 275);
|
||||
add(1622, 3831, 2, 276);
|
||||
add(1623, 3831, 2, 277);
|
||||
add(1624, 3829, 2, 278);
|
||||
add(1624, 3828, 2, 279);
|
||||
add(1624, 3821, 2, 280);
|
||||
add(1624, 3819, 2, 281);
|
||||
add(1622, 3816, 2, 282);
|
||||
add(1620, 3816, 2, 283);
|
||||
add(1618, 3816, 2, 284);
|
||||
add(1615, 3821, 2, 285);
|
||||
add(1617, 3821, 2, 286);
|
||||
add(1619, 3822, 2, 287);
|
||||
add(1619, 3824, 2, 288);
|
||||
add(1618, 3826, 2, 289);
|
||||
add(1617, 3826, 2, 290);
|
||||
add(1615, 3827, 2, 291);
|
||||
add(1616, 3827, 2, 292);
|
||||
add(1618, 3827, 2, 293);
|
||||
add(1620, 3826, 2, 294);
|
||||
add(1620, 3824, 2, 295);
|
||||
add(1620, 3822, 2, 296);
|
||||
add(1620, 3821, 2, 297);
|
||||
add(1619, 3820, 2, 298);
|
||||
add(1617, 3820, 2, 299);
|
||||
add(1615, 3820, 2, 300);
|
||||
add(1641, 3818, 2, 301);
|
||||
add(1641, 3820, 2, 302);
|
||||
add(1641, 3821, 2, 303);
|
||||
add(1641, 3829, 2, 304);
|
||||
add(1643, 3831, 2, 305);
|
||||
add(1644, 3831, 2, 306);
|
||||
add(1654, 3831, 2, 307);
|
||||
add(1656, 3831, 2, 308);
|
||||
add(1658, 3830, 2, 309);
|
||||
add(1658, 3828, 2, 310);
|
||||
add(1658, 3818, 2, 311);
|
||||
add(1658, 3817, 2, 312);
|
||||
add(1656, 3816, 2, 313);
|
||||
add(1655, 3816, 2, 314);
|
||||
add(1652, 3816, 2, 315);
|
||||
add(1648, 3817, 2, 316);
|
||||
add(1648, 3819, 2, 317);
|
||||
add(1648, 3821, 2, 318);
|
||||
add(1649, 3823, 2, 319);
|
||||
add(1650, 3823, 2, 320);
|
||||
add(1652, 3823, 2, 321);
|
||||
add(1654, 3822, 2, 322);
|
||||
add(1654, 3820, 2, 323);
|
||||
add(1655, 3820, 2, 324);
|
||||
add(1655, 3821, 2, 325);
|
||||
add(1655, 3823, 2, 326);
|
||||
add(1653, 3824, 2, 327);
|
||||
add(1652, 3824, 2, 328);
|
||||
add(1649, 3824, 2, 329);
|
||||
add(1648, 3824, 2, 330);
|
||||
add(1647, 3822, 2, 331);
|
||||
add(1647, 3820, 2, 332);
|
||||
add(1647, 3818, 2, 333);
|
||||
add(1645, 3816, 2, 334);
|
||||
add(1644, 3816, 2, 335);
|
||||
add(1625, 3802, 2, 336);
|
||||
add(1625, 3804, 2, 337);
|
||||
add(1625, 3811, 2, 338);
|
||||
add(1625, 3812, 2, 339);
|
||||
add(1627, 3815, 2, 340);
|
||||
add(1628, 3815, 2, 341);
|
||||
add(1635, 3815, 2, 342);
|
||||
add(1637, 3815, 2, 343);
|
||||
add(1638, 3815, 2, 344);
|
||||
add(1640, 3813, 2, 345);
|
||||
add(1640, 3811, 2, 346);
|
||||
add(1640, 3810, 2, 347);
|
||||
add(1638, 3800, 2, 348);
|
||||
add(1632, 3800, 2, 349);
|
||||
add(1630, 3800, 2, 350);
|
||||
add(1629, 3800, 2, 351);
|
||||
add(1627, 3800, 2, 352);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* 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.kourendlibrary;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.Getter;
|
||||
|
||||
import net.runelite.api.NpcID;
|
||||
|
||||
public enum LibraryCustomer
|
||||
{
|
||||
VILLIA(NpcID.VILLIA, "Villia"),
|
||||
PROFESSOR_GRACKLEBONE(NpcID.PROFESSOR_GRACKLEBONE, "Prof. Gracklebone"),
|
||||
Sam(NpcID.SAM_7049, "Sam");
|
||||
|
||||
@Getter
|
||||
private final int id;
|
||||
|
||||
@Getter
|
||||
private final String name;
|
||||
|
||||
private static final Map<Integer, LibraryCustomer> byId = buildIdMap();
|
||||
|
||||
LibraryCustomer(int id, String name)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static LibraryCustomer getById(int id)
|
||||
{
|
||||
return byId.get(id);
|
||||
}
|
||||
|
||||
private static Map<Integer, LibraryCustomer> buildIdMap()
|
||||
{
|
||||
Map<Integer, LibraryCustomer> byId = new HashMap<>();
|
||||
for (LibraryCustomer c : values())
|
||||
{
|
||||
byId.put(c.id, c);
|
||||
}
|
||||
return byId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* 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.kourendlibrary;
|
||||
|
||||
public enum SolvedState
|
||||
{
|
||||
NO_DATA,
|
||||
INCOMPLETE,
|
||||
COMPLETE;
|
||||
}
|
||||
@@ -61,7 +61,7 @@ import net.runelite.api.events.WidgetHiddenChanged;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import static net.runelite.api.widgets.WidgetID.BARROWS_REWARD_GROUP_ID;
|
||||
import static net.runelite.api.widgets.WidgetID.CLUE_SCROLL_REWARD_GROUP_ID;
|
||||
import static net.runelite.api.widgets.WidgetID.HUNTER_LEVEL_UP_GROUP_ID;
|
||||
import static net.runelite.api.widgets.WidgetID.DIALOG_SPRITE_GROUP_ID;
|
||||
import static net.runelite.api.widgets.WidgetID.LEVEL_UP_GROUP_ID;
|
||||
import static net.runelite.api.widgets.WidgetID.QUEST_COMPLETED_GROUP_ID;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
@@ -253,9 +253,9 @@ public class ScreenshotPlugin extends Plugin
|
||||
fileName = parseLevelUpWidget(WidgetInfo.LEVEL_UP_SKILL, WidgetInfo.LEVEL_UP_LEVEL);
|
||||
break;
|
||||
}
|
||||
case HUNTER_LEVEL_UP_GROUP_ID:
|
||||
case DIALOG_SPRITE_GROUP_ID:
|
||||
{
|
||||
fileName = parseLevelUpWidget(WidgetInfo.HUNTER_LEVEL_UP_SKILL, WidgetInfo.HUNTER_LEVEL_UP_LEVEL);
|
||||
fileName = parseLevelUpWidget(WidgetInfo.DIALOG_SPRITE_SPRITE, WidgetInfo.DIALOG_SPRITE_TEXT);
|
||||
break;
|
||||
}
|
||||
case QUEST_COMPLETED_GROUP_ID:
|
||||
|
||||
|
After Width: | Height: | Size: 679 B |
|
After Width: | Height: | Size: 658 B |
|
After Width: | Height: | Size: 661 B |
|
After Width: | Height: | Size: 676 B |
|
After Width: | Height: | Size: 635 B |
|
After Width: | Height: | Size: 655 B |
|
After Width: | Height: | Size: 621 B |
|
After Width: | Height: | Size: 607 B |
|
After Width: | Height: | Size: 602 B |
|
After Width: | Height: | Size: 631 B |
|
After Width: | Height: | Size: 783 B |
|
After Width: | Height: | Size: 811 B |
|
After Width: | Height: | Size: 872 B |
|
After Width: | Height: | Size: 854 B |
|
After Width: | Height: | Size: 868 B |
|
After Width: | Height: | Size: 802 B |
|
After Width: | Height: | Size: 686 B |
|
After Width: | Height: | Size: 749 B |
|
After Width: | Height: | Size: 735 B |
|
After Width: | Height: | Size: 854 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 816 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 947 B |
|
After Width: | Height: | Size: 738 B |
|
After Width: | Height: | Size: 2.3 KiB |
@@ -35,10 +35,10 @@ import net.runelite.api.Client;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.WidgetHiddenChanged;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import static net.runelite.api.widgets.WidgetID.HUNTER_LEVEL_UP_GROUP_ID;
|
||||
import static net.runelite.api.widgets.WidgetID.DIALOG_SPRITE_GROUP_ID;
|
||||
import static net.runelite.api.widgets.WidgetID.LEVEL_UP_GROUP_ID;
|
||||
import static net.runelite.api.widgets.WidgetInfo.HUNTER_LEVEL_UP_LEVEL;
|
||||
import static net.runelite.api.widgets.WidgetInfo.HUNTER_LEVEL_UP_SKILL;
|
||||
import static net.runelite.api.widgets.WidgetInfo.DIALOG_SPRITE_SPRITE;
|
||||
import static net.runelite.api.widgets.WidgetInfo.DIALOG_SPRITE_TEXT;
|
||||
import static net.runelite.api.widgets.WidgetInfo.LEVEL_UP_LEVEL;
|
||||
import static net.runelite.api.widgets.WidgetInfo.LEVEL_UP_SKILL;
|
||||
import static net.runelite.api.widgets.WidgetInfo.PACK;
|
||||
@@ -197,18 +197,18 @@ public class ScreenshotPluginTest
|
||||
public void testHunter()
|
||||
{
|
||||
Widget widget = mock(Widget.class);
|
||||
when(widget.getId()).thenReturn(PACK(HUNTER_LEVEL_UP_GROUP_ID, 0));
|
||||
when(widget.getId()).thenReturn(PACK(DIALOG_SPRITE_GROUP_ID, 0));
|
||||
|
||||
Widget skillChild = mock(Widget.class);
|
||||
when(client.getWidget(Matchers.eq(HUNTER_LEVEL_UP_SKILL))).thenReturn(skillChild);
|
||||
when(client.getWidget(Matchers.eq(DIALOG_SPRITE_SPRITE))).thenReturn(skillChild);
|
||||
|
||||
Widget levelChild = mock(Widget.class);
|
||||
when(client.getWidget(Matchers.eq(HUNTER_LEVEL_UP_LEVEL))).thenReturn(levelChild);
|
||||
when(client.getWidget(Matchers.eq(DIALOG_SPRITE_TEXT))).thenReturn(levelChild);
|
||||
|
||||
when(skillChild.getText()).thenReturn("Congratulations, you just advanced a Hunter level.");
|
||||
when(levelChild.getText()).thenReturn("Your Hunter level is now 2.");
|
||||
|
||||
assertEquals("Hunter(2)", screenshotPlugin.parseLevelUpWidget(HUNTER_LEVEL_UP_SKILL, HUNTER_LEVEL_UP_LEVEL));
|
||||
assertEquals("Hunter(2)", screenshotPlugin.parseLevelUpWidget(DIALOG_SPRITE_SPRITE, DIALOG_SPRITE_TEXT));
|
||||
|
||||
WidgetHiddenChanged event = new WidgetHiddenChanged();
|
||||
event.setWidget(widget);
|
||||
|
||||