Repository reorganisation
Unified kotlin and java into just src/main Unified the rs09 and core packages Took all content out of the core package, and placed it into the new content package Reorganised all source code relating to content to be easier to find and explore
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
import core.api.*
|
||||
import org.rs09.consts.Items
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.IntType
|
||||
|
||||
class CarvedEvilTurnipListener : InteractionListener {
|
||||
val knife = Items.KNIFE_946
|
||||
val evilTurnip = Items.EVIL_TURNIP_12134
|
||||
val carvedEvilTurnip = Items.CARVED_EVIL_TURNIP_12153
|
||||
|
||||
override fun defineListeners() {
|
||||
onUseWith(IntType.ITEM, evilTurnip, knife) { player, used, with ->
|
||||
if(removeItem(player, used.asItem())) {
|
||||
sendMessage(player, "You carve a scary face into the evil turnip.")
|
||||
sendMessage(player, "Wooo! It's enough to give you nightmares.")
|
||||
return@onUseWith addItem(player, carvedEvilTurnip)
|
||||
}
|
||||
return@onUseWith false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package content.global.skill.summoning;
|
||||
|
||||
import core.game.event.SummoningPointsRechargeEvent;
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the option used on the summoning obelisk.
|
||||
* @author 'Vexia
|
||||
* @author Emperor
|
||||
*/
|
||||
@Initializable
|
||||
public final class ObeliskOptionPlugin extends OptionHandler {
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
switch (option) {
|
||||
case "infuse-pouch":
|
||||
SummoningCreator.open(player, true);
|
||||
return true;
|
||||
case "renew-points":
|
||||
if (player.getSkills().getLevel(Skills.SUMMONING) == player.getSkills().getStaticLevel(Skills.SUMMONING)) {
|
||||
player.getPacketDispatch().sendMessage("You already have full summoning points.");
|
||||
return true;
|
||||
}
|
||||
player.visualize(Animation.create(8502), Graphics.create(1308));
|
||||
player.getAudioManager().send(4214);
|
||||
player.getSkills().setLevel(Skills.SUMMONING, player.getSkills().getStaticLevel(Skills.SUMMONING));
|
||||
player.dispatch(new SummoningPointsRechargeEvent(node));
|
||||
player.getPacketDispatch().sendMessage("You renew your summoning points.");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
SceneryDefinition.setOptionHandler("infuse-pouch", this);
|
||||
SceneryDefinition.setOptionHandler("renew-points", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package content.global.skill.summoning;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
import core.cache.def.impl.ItemDefinition;
|
||||
import core.game.component.Component;
|
||||
import core.game.component.ComponentDefinition;
|
||||
import core.game.component.ComponentPlugin;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import kotlin.Unit;
|
||||
import core.plugin.ClassScanner;
|
||||
|
||||
/**
|
||||
* Represents a component plugin used to handle the summoning creation of a
|
||||
* node.
|
||||
* @author 'Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public final class SummoningCreationPlugin extends ComponentPlugin {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ComponentDefinition.put(669, this);
|
||||
ComponentDefinition.put(673, this);
|
||||
ClassScanner.definePlugin(new ObeliskHandler());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, final Component component, int opcode, int button, final int slot, int itemId) {
|
||||
switch (button) {
|
||||
case 18:
|
||||
case 17:
|
||||
SummoningCreator.configure(player, button == 17);
|
||||
break;
|
||||
}
|
||||
switch (component.getId()) {
|
||||
case 669:
|
||||
case 673:
|
||||
switch (opcode) {
|
||||
case 155:
|
||||
case 196:
|
||||
case 124:
|
||||
case 199:
|
||||
SummoningCreator.create(player, getItemAmount(opcode), component.getId() == 669 ? SummoningPouch.forSlot(slot > 50 ? slot -1 : slot) : SummoningScroll.forId(slot > 50 ? slot -1 : slot));
|
||||
break;
|
||||
case 234:
|
||||
sendInputDialogue(player, true, "Enter the amount:", (value) -> {
|
||||
SummoningCreator.create(player, (int) value, component.getId() == 669 ? SummoningPouch.forSlot(slot > 50 ? slot -1 : slot) : SummoningScroll.forId(slot > 50 ? slot -1 : slot));
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
return true;
|
||||
case 166:
|
||||
SummoningCreator.list(player, SummoningPouch.forSlot(slot > 50 ? slot -1 : slot));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 168:
|
||||
player.getPacketDispatch().sendMessage(ItemDefinition.forId(SummoningScroll.forId(slot > 50 ? slot -1 : slot).getItemId()).getExamine());
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to get the item amount based on id.
|
||||
* @param opcode the opcode.
|
||||
* @return the amount to make.
|
||||
*/
|
||||
private final int getItemAmount(final int opcode) {
|
||||
return opcode == 155 ? 1 : opcode == 196 ? 5 : opcode == 124 ? 10 : opcode == 199 ? 28 : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the use with handler for an obelisk.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
public static final class ObeliskHandler extends UseWithHandler {
|
||||
|
||||
/**
|
||||
* Represents the ids of the obelisks.
|
||||
*/
|
||||
private static final int[] IDS = new int[] { 28716, 28719, 28722, 28725, 28278, 28731, 28734 };
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ObeliskHandler} {@code Object}.
|
||||
*/
|
||||
public ObeliskHandler() {
|
||||
super(12047, 12043, 12059, 12019, 12009, 12778, 12049, 12055, 12808, 2067, 12064, 12091, 12800, 12053, 12065, 12021, 12818, 12781, 12798, 12814, 12073, 12075, 12077, 12079, 12081, 12083, 12087, 12071, 12051, 12095, 12097, 12099, 12101, 12103, 12105, 12107, 12816, 12041, 12061, 12007, 12035, 12027, 12531, 12812, 12784, 12710, 12023, 12085, 12037, 12015, 12045, 12123, 12031, 12029, 12033, 12820, 12057, 12792, 12069, 12011, 12782, 12794, 12013, 12025, 12017, 12039, 12089, 12093, 12802, 12804, 12806, 12788, 12776, 12786, 12796, 12822, 12790);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
for (int id : IDS) {
|
||||
addHandler(id, OBJECT_TYPE, this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(NodeUsageEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
SummoningCreator.open(player, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
package content.global.skill.summoning;
|
||||
|
||||
import core.cache.def.impl.CS2Mapping;
|
||||
import core.game.component.Component;
|
||||
import core.game.node.entity.skill.SkillPulse;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.scenery.Scenery;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
|
||||
/**
|
||||
* Represents a utility class of creating summoning nodes.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class SummoningCreator {
|
||||
|
||||
/**
|
||||
* Represents the animation used when creating a node.
|
||||
*/
|
||||
private static final Animation ANIMATION = new Animation(9068);
|
||||
|
||||
/**
|
||||
* Represents the params used for the accessmask on the pouch creating
|
||||
* interface.
|
||||
*/
|
||||
private static final Object[] POUCH_PARAMS = new Object[] { "List<col=FF9040>", "Infuse-X<col=FF9040>", "Infuse-All<col=FF9040>", "Infuse-10<col=FF9040>", "Infuse-5<col=FF9040>", "Infuse<col=FF9040>", 20, 4, 669 << 16 | 15 };
|
||||
|
||||
/**
|
||||
* Represents the params used for the accessmask on the scrollc reating
|
||||
* interface.
|
||||
*/
|
||||
private static final Object[] SCROLL_PARAMS = new Object[] { "Transform-X<col=ff9040>", "Transform-All<col=ff9040>", "Transform-10<col=ff9040>", "Transform-5<col=ff9040>", "Transform<col=ff9040>", 20, 4, 673 << 16 | 15 };
|
||||
|
||||
/**
|
||||
* Represents the summoning component.
|
||||
*/
|
||||
private static final Component SUMMONING_COMPONENT = new Component(669);
|
||||
|
||||
/**
|
||||
* Represents the scroll component.
|
||||
*/
|
||||
private static final Component SCROLL_COMPONENT = new Component(673);
|
||||
|
||||
/**
|
||||
* Method used to open the creation screen.
|
||||
* @param player the player.
|
||||
*/
|
||||
public static final void open(final Player player, final boolean pouch) {
|
||||
configure(player, pouch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to configure a creation interface.
|
||||
* @param player the player.
|
||||
* @param pouch the pouch.
|
||||
*/
|
||||
public static final void configure(final Player player, final boolean pouch) {
|
||||
player.getInterfaceManager().open(pouch ? SUMMONING_COMPONENT : SCROLL_COMPONENT);
|
||||
player.getPacketDispatch().sendRunScript(pouch ? 757 : 765, pouch ? "Iiissssss" : "Iiisssss", pouch ? POUCH_PARAMS : SCROLL_PARAMS);
|
||||
player.getPacketDispatch().sendIfaceSettings(pouch ? 190 : 126, 15, pouch ? 669 : 673, 0, 78);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to create a summoning node type.
|
||||
* @param player the player.
|
||||
* @param amount the amount.
|
||||
* @param node the node.
|
||||
*/
|
||||
public static void create(final Player player, final int amount, Object node) {
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
player.getPulseManager().run(new CreatePulse(player, null, SummoningNode.parse(node), amount));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to list the items needed for a pouch.
|
||||
* @param pouch the pouch.
|
||||
*/
|
||||
public static void list(final Player player, final SummoningPouch pouch) {
|
||||
player.getPacketDispatch().sendMessage((String) CS2Mapping.forId(1186).getMap().get(pouch.getPouchId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the skill pulse used to create a summoning node.
|
||||
* @author 'Vexia
|
||||
*/
|
||||
public static final class CreatePulse extends SkillPulse<Item> {
|
||||
|
||||
/**
|
||||
* Represents the summoning node type.
|
||||
*/
|
||||
private final SummoningCreator.SummoningNode type;
|
||||
|
||||
/**
|
||||
* Represents the object.
|
||||
*/
|
||||
private Scenery object;
|
||||
|
||||
/**
|
||||
* Represents the amount to make.
|
||||
*/
|
||||
private int amount;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SummoningCreator} {@code Object}.
|
||||
* @param player the player.
|
||||
* @param node the node.
|
||||
* @param type the type.
|
||||
* @param amount the amount.
|
||||
*/
|
||||
public CreatePulse(Player player, Item node, final SummoningCreator.SummoningNode type, final int amount) {
|
||||
super(player, node);
|
||||
this.type = type;
|
||||
this.amount = amount;
|
||||
this.object = RegionManager.getObject(new Location(2209, 5344, 0));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkRequirements() {
|
||||
player.getInterfaceManager().close();
|
||||
if (player.getSkills().getStaticLevel(Skills.SUMMONING) < type.getLevel()) {
|
||||
player.getPacketDispatch().sendMessage("You need a Summoning level of at least " + type.getLevel() + " in order to do this.");
|
||||
return false;
|
||||
}
|
||||
if (amount == 0) {
|
||||
player.getPacketDispatch().sendMessage("You don't have the required item(s) to make this.");
|
||||
return false;
|
||||
}
|
||||
for (Item i : type.getRequired()) {
|
||||
if (!player.getInventory().containsItem(i)) {
|
||||
player.getPacketDispatch().sendMessage("You don't have the required item(s) to make this.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void animate() {
|
||||
player.lock(3);
|
||||
player.animate(ANIMATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
super.stop();
|
||||
player.getPacketDispatch().sendSceneryAnimation(object, new Animation(8510));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reward() {
|
||||
if (getDelay() == 1) {
|
||||
setDelay(4);
|
||||
player.getPacketDispatch().sendSceneryAnimation(object, Animation.create(8509));
|
||||
player.getAudioManager().send(4164); // 4277 also sounds the same
|
||||
return false;
|
||||
}
|
||||
player.getPacketDispatch().sendSceneryAnimation(object, Animation.create(8510));
|
||||
for (int i = 0; i < amount; i++) {
|
||||
for (Item item : type.getRequired()) {
|
||||
if (!player.getInventory().containsItem(item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (player.getInventory().remove(type.getRequired())) {
|
||||
final Item item = type.getProduct();
|
||||
player.getInventory().add(item);
|
||||
player.getSkills().addExperience(Skills.SUMMONING, type.getExperience(), true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a summoning node type.
|
||||
* @author 'Vexia
|
||||
*/
|
||||
public static class SummoningNode {
|
||||
|
||||
/**
|
||||
* Represents the base object.
|
||||
*/
|
||||
private final Object base;
|
||||
|
||||
/**
|
||||
* Represents the required items.
|
||||
*/
|
||||
private final Item[] required;
|
||||
|
||||
/**
|
||||
* Represents the product.
|
||||
*/
|
||||
private final Item product;
|
||||
|
||||
/**
|
||||
* Represents the experience.
|
||||
*/
|
||||
private final double experience;
|
||||
|
||||
/**
|
||||
* Represents the level.
|
||||
*/
|
||||
private final int level;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SummoningCreator} {@code Object}.
|
||||
* @param required the required items.
|
||||
* @param product the product.
|
||||
* @param experience the experience.
|
||||
* @param level the level.
|
||||
*/
|
||||
public SummoningNode(final Object base, Item[] required, Item product, double experience, int level) {
|
||||
this.base = base;
|
||||
this.required = required;
|
||||
this.product = product;
|
||||
this.experience = experience;
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the required.
|
||||
* @return The required.
|
||||
*/
|
||||
public Item[] getRequired() {
|
||||
return required;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the product.
|
||||
* @return The product.
|
||||
*/
|
||||
public Item getProduct() {
|
||||
return product;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the experience.
|
||||
* @return The experience.
|
||||
*/
|
||||
public double getExperience() {
|
||||
return experience;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the level.
|
||||
* @return The level.
|
||||
*/
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the base.
|
||||
* @return The base.
|
||||
*/
|
||||
public Object getBase() {
|
||||
return base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to check if the base is a pouch.
|
||||
* @return the pouch.
|
||||
*/
|
||||
public boolean isPouch() {
|
||||
return base instanceof SummoningPouch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to parse a summoning node.
|
||||
* @param node the node.
|
||||
* @return the summoning node.
|
||||
*/
|
||||
public static SummoningNode parse(final Object node) {
|
||||
final Item[] required = node instanceof SummoningPouch ? ((SummoningPouch) node).getItems() : createList(((SummoningScroll) node).getItems());
|
||||
final Item product = node instanceof SummoningPouch ? new Item(((SummoningPouch) node).getPouchId(), 1) : new Item(((SummoningScroll) node).getItemId(), 10);
|
||||
final int level = node instanceof SummoningPouch ? ((SummoningPouch) node).getLevelRequired() : ((SummoningScroll) node).getLevel();
|
||||
final double experience = node instanceof SummoningPouch ? ((SummoningPouch) node).getCreateExperience() : ((SummoningScroll) node).getExperience();
|
||||
return new SummoningNode(node, required, product, experience, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to create the list.
|
||||
* @param ids the ids.
|
||||
* @return the array of items.
|
||||
*/
|
||||
private static final Item[] createList(final int... ids) {
|
||||
Item[] list = new Item[ids.length];
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
list[i] = new Item(ids[i], 1);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,585 @@
|
||||
package content.global.skill.summoning;
|
||||
|
||||
import core.game.node.item.Item;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents a summoning pouch.
|
||||
* @author Emperor
|
||||
*/
|
||||
public enum SummoningPouch {
|
||||
|
||||
/**
|
||||
* Represents a spirit wolf pouch.
|
||||
*/
|
||||
SPIRIT_WOLF_POUCH(0, 12047, 1, 4.8, 6829, 0.1, 1, false, new Item(12158), new Item(12155), new Item(2859), new Item(12183, 7)),
|
||||
|
||||
/**
|
||||
* Represents a dreadfowl pouch.
|
||||
*/
|
||||
DREADFOWL_POUCH(1, 12043, 4, 9.3, 6825, 0.1, 1, false, new Item(12158), new Item(12155), new Item(2138), new Item(12183, 8)),
|
||||
|
||||
/**
|
||||
* Represents a spirit spider pouch.
|
||||
*/
|
||||
SPIRIT_SPIDER_POUCH(2, 12059, 10, 12.6, 6841, 0.2, 2, false, new Item(12158), new Item(12155), new Item(6291), new Item(12183, 8)),
|
||||
|
||||
/**
|
||||
* Represents a thorny snail pouch.
|
||||
*/
|
||||
THORNY_SNAIL_POUCH(3, 12019, 13, 12.6, 6806, 0.2, 2, false, new Item(12158), new Item(12155), new Item(3363), new Item(12183, 9)),
|
||||
|
||||
/**
|
||||
* Represents a granite crab pouch.
|
||||
*/
|
||||
GRANITE_CRAB_POUCH(4, 12009, 16, 31.6, 6796, 0.2, 2, false, new Item(12158), new Item(12155), new Item(440), new Item(12183, 7)),
|
||||
|
||||
/**
|
||||
* Represents a spirit mosquito pouch.
|
||||
*/
|
||||
SPIRIT_MOSQUITO_POUCH(5, 12778, 17, 46.5, 7331, 0.5, 2, false, new Item(12158), new Item(12155), new Item(6319), new Item(12183, 1)),
|
||||
|
||||
/**
|
||||
* Represents a desrrt wyrm pouch.
|
||||
*/
|
||||
DESERT_WYRM_POUCH(6, 12049, 18, 31.2, 6831, 0.4, 1, false, new Item(12159), new Item(12155), new Item(1783), new Item(12183, 45)),
|
||||
|
||||
/**
|
||||
* Represents a spirit scorpion pouch.
|
||||
*/
|
||||
SPIRIT_SCORPION_POUCH(7, 12055, 19, 83.2, 6837, 0.9, 2, false, new Item(12160), new Item(12155), new Item(3095), new Item(12183, 57)),
|
||||
|
||||
/**
|
||||
* Represents a spirit tz-kih pouch.
|
||||
*/
|
||||
SPIRIT_TZ_KIH_POUCH(8, 12808, 22, 96.8, 7361, 1.1, 3, false, new Item(12160), new Item(12168), new Item(12155), new Item(12183, 64)),
|
||||
|
||||
/**
|
||||
* Represents an albino rat pouch.
|
||||
*/
|
||||
ALBINO_RAT_POUCH(9, 12067, 23, 202.4, 6847, 2.3, 1, false, new Item(12163), new Item(12155), new Item(2134), new Item(12183, 75)),
|
||||
|
||||
/**
|
||||
* Represents a spirit kalphite pouch.
|
||||
*/
|
||||
SPIRIT_KALPHITE_POUCH(10, 12063, 25, 220, 6994, 2.5, 3,false, new Item(12163), new Item(12155), new Item(3138), new Item(12183, 51)),
|
||||
|
||||
/**
|
||||
* Represents a compost mound pouch.
|
||||
*/
|
||||
COMPOST_MOUND_POUCH(11, 12091, 28, 49.8, 6871, 0.6, 6, false, new Item(12159), new Item(12155), new Item(6032), new Item(12183, 47)),
|
||||
|
||||
/**
|
||||
* Represents a giant chinchompa pouch.
|
||||
*/
|
||||
GIANT_CHINCHOMPA_POUCH(12, 12800, 29, 255.2, 7353, 2.9, 1, false, new Item(12163), new Item(12155), new Item(10033), new Item(12183, 84)),
|
||||
|
||||
/**
|
||||
* Represents a vampire bat pouch.
|
||||
*/
|
||||
VAMPIRE_BAT_POUCH(13, 12053, 31, 136, 6835, 1.5, 4, false, new Item(12160), new Item(12155), new Item(3325), new Item(12183, 81)),
|
||||
|
||||
/**
|
||||
* Represents a honey badger pouch.
|
||||
*/
|
||||
HONEY_BADGER_POUCH(14, 12065, 32, 140.8, 6845, 1.6, 4, false, new Item(12160), new Item(12155), new Item(12156), new Item(12183, 84)),
|
||||
|
||||
/**
|
||||
* Represents a beaver pouch.
|
||||
*/
|
||||
BEAVER_POUCH(15, 12021, 33, 57.6, 6808, 0.7, 4, true, new Item(12159), new Item(12155), new Item(1519), new Item(12183, 72)),
|
||||
|
||||
/**
|
||||
* Represents a void ravager pouch.
|
||||
*/
|
||||
VOID_RAVAGER_POUCH(16, 12818, 34, 59.6, 7370, 0.7, 4, false, new Item(12159), new Item(12164), new Item(12155), new Item(12183, 74)),
|
||||
|
||||
/**
|
||||
* Represents a void spinner pouch.
|
||||
*/
|
||||
VOID_SPINNER_POUCH(17, 12780, 34, 59.6, 7333, 0.7, 4, true, new Item(12163), new Item(12166), new Item(12155), new Item(12183, 74)),
|
||||
|
||||
/**
|
||||
* Represents a void torcher pouch.
|
||||
*/
|
||||
VOID_TORCHER_POUCH(18, 12798, 34, 59.6, 7351, 0.7, 4, false, new Item(12163), new Item(12167), new Item(12155), new Item(12183, 74)),
|
||||
|
||||
/**
|
||||
* Represents a void shifter pouch.
|
||||
*/
|
||||
VOID_SHIFTER_POUCH(19, 12814, 34, 59.6, 7367, 0.7, 4, false, new Item(12163), new Item(12165), new Item(12155), new Item(12183, 74)),
|
||||
|
||||
/**
|
||||
* Represents a bronze minotaur pouch.
|
||||
*/
|
||||
BRONZE_MINOTAUR_POUCH(64, 12073, 36, 316.8, 6853, 3.6, 3, false, new Item(12163), new Item(12155), new Item(2349), new Item(12183, 102)),
|
||||
|
||||
/**
|
||||
* Represents an iron minotaur pouch.
|
||||
*/
|
||||
IRON_MINOTAUR_POUCH(65, 12075, 46, 404.8, 6855, 4.6, 9, false, new Item(12163), new Item(12155), new Item(2351), new Item(12183, 125)),
|
||||
|
||||
/**
|
||||
* Represents a steel minotaur pouch.
|
||||
*/
|
||||
STEEL_MINOTAUR_POUCH(66, 12077, 56, 492.8, 6857, 5.6, 9, false, new Item(12163), new Item(12155), new Item(2353), new Item(12183, 141)),
|
||||
|
||||
/**
|
||||
* Represents a mithril minotaur pouch.
|
||||
*/
|
||||
MITHRIL_MINOTAUR_POUCH(67, 12079, 66, 580.8, 6859, 6.6, 9,false, new Item(12163), new Item(12155), new Item(2359), new Item(12183, 152)),
|
||||
|
||||
/**
|
||||
* Represents an adamant minotaur pouch.
|
||||
*/
|
||||
ADAMANT_MINOTAUR_POUCH(68, 12081, 76, 668.8, 6861, 7.6, 9, false, new Item(12163), new Item(12155), new Item(2361), new Item(12183, 144)),
|
||||
|
||||
/**
|
||||
* Represents a rune minotaur pouch.
|
||||
*/
|
||||
RUNE_MINOTAUR_POUCH(69, 12083, 86, 756.8, 6863, 8.6, 9, false, new Item(12163), new Item(12155), new Item(2363), new Item(12183, 1)),
|
||||
|
||||
/**
|
||||
* Represents a bull ant pouch.
|
||||
*/
|
||||
BULL_ANT_POUCH(20, 12087, 40, 52.8, 6867, 0.6, 5, false, new Item(12158), new Item(12155), new Item(6010), new Item(12183, 11)),
|
||||
|
||||
/**
|
||||
* Represents a macaw pouch.
|
||||
*/
|
||||
MACAW_POUCH(21, 12071, 41, 72.4, 6851, 0.8, 5, true, new Item(12159), new Item(12155), new Item(249), new Item(12183, 78)),
|
||||
|
||||
/**
|
||||
* Represents an evil turnip pouch.
|
||||
*/
|
||||
EVIL_TURNIP_POUCH(22, 12051, 42, 184.8, 6833, 2.1, 5, false, new Item(12160), new Item(12155), new Item(12153), new Item(12183, 104)),
|
||||
|
||||
/**
|
||||
* Represents a spirit cockatrice pouch.
|
||||
*/
|
||||
SPIRIT_COCKATRICE_POUCH(23, 12095, 43, 75.2, 6875, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12109), new Item(12183, 88)),
|
||||
|
||||
/**
|
||||
* Represents a spirit guthatrice pouch.
|
||||
*/
|
||||
SPIRIT_GUTHATRICE_POUCH(24, 12097, 43, 75.2, 6877, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12111), new Item(12183, 88)),
|
||||
|
||||
/**
|
||||
* Represents a spirit saratrice pouch.
|
||||
*/
|
||||
SPIRIT_SARATRICE_POUCH(25, 12099, 43, 75.2, 6879, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12113), new Item(12183, 88)),
|
||||
|
||||
/**
|
||||
* Represents a spirit zamatrice pouch.
|
||||
*/
|
||||
SPIRIT_ZAMATRICE_POUCH(26, 12101, 43, 75.2, 6881, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12115), new Item(12183, 88)),
|
||||
|
||||
/**
|
||||
* Represents a spirit pengatrice pouch.
|
||||
*/
|
||||
SPIRIT_PENGATRICE_POUCH(27, 12103, 43, 75.2, 6883, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12117), new Item(12183, 88)),
|
||||
|
||||
/**
|
||||
* Represents a coraxatrice pouch.
|
||||
*/
|
||||
SPIRIT_CORAXATRICE_POUCH(28, 12105, 43, 75.2, 6885, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12119), new Item(12183, 88)),
|
||||
|
||||
/**
|
||||
* Represents a vulatrice pouch.
|
||||
*/
|
||||
SPIRIT_VULATRICE(29, 12107, 43, 75.2, 6887, 0.9, 5, false, new Item(12159), new Item(12155), new Item(12121), new Item(12183, 88)),
|
||||
|
||||
/**
|
||||
* Represents a pyrelord pouch.
|
||||
*/
|
||||
PYRELORD_POUCH(30, 12816, 46, 202.4, 7377, 2.3, 5, false, new Item(12160), new Item(12155), new Item(590), new Item(12183, 111)),
|
||||
|
||||
/**
|
||||
* Represents a magpie pouch.
|
||||
*/
|
||||
MAGPIE_POUCH(31, 12041, 47, 83.2, 6824, 0.9, 5, true, new Item(12159), new Item(12155), new Item(1635), new Item(12183, 88)),
|
||||
|
||||
/**
|
||||
* Represents a bloated leech pouch.
|
||||
*/
|
||||
BLOATED_LEECH_POUCH(32, 12061, 49, 215.2, 6843, 2.4, 5, false, new Item(12160), new Item(12155), new Item(2132), new Item(12183, 117)),
|
||||
|
||||
/**
|
||||
* Represents a spirit terrorbird pouch.
|
||||
*/
|
||||
SPIRIT_TERRORBIRD_POUCH(33, 12007, 52, 68.4, 6794, 0.8, 6, true, new Item(12158), new Item(12155), new Item(9978), new Item(12183, 12)),
|
||||
|
||||
/**
|
||||
* Represents an abyssal parasite pouch.
|
||||
*/
|
||||
ABYSSAL_PARASITE_POUCH(34, true,12035, 54, 94.8, 6818, 1.1, 6, false, new Item(12159), new Item(12155), new Item(12161), new Item(12183, 106)),
|
||||
|
||||
/**
|
||||
* Represents a spirit jelly pouch.
|
||||
*/
|
||||
SPIRIT_JELLY_POUCH(35, 12027, 55, 484, 6992, 5.5, 6, false, new Item(12163), new Item(12155), new Item(1937), new Item(12183, 151)),
|
||||
|
||||
/**
|
||||
* Represents an ibis pouch.
|
||||
*/
|
||||
IBIS_POUCH(36, 12531, 56, 98.8, 6991, 1.1, 6, true, new Item(12159), new Item(12155), new Item(311), new Item(12183, 109)),
|
||||
|
||||
/**
|
||||
* Represents a spirit kyatt pouch.
|
||||
*/
|
||||
SPIRIT_KYATT_POUCH(37, 12812, 57, 501.6, 7365, 5.7, 6, false, new Item(12163), new Item(12155), new Item(10103), new Item(12183, 153)),
|
||||
|
||||
/**
|
||||
* Represents a spirit larupia pouch.
|
||||
*/
|
||||
SPIRIT_LARUPIA_POUCH(38, 12784, 57, 501.6, 7337, 5.7, 6, false, new Item(12163), new Item(12155), new Item(10095), new Item(12183, 155)),
|
||||
|
||||
/**
|
||||
* Represents a spirit graahk pouch.
|
||||
*/
|
||||
SPIRIT_GRAAHK_POUCH(39, 12810, 57, 501.6, 7363, 5.7, 6, false, new Item(12163), new Item(12155), new Item(10099), new Item(12183, 154)),
|
||||
|
||||
/**
|
||||
* Represents a karamthulhu overlord pouch.
|
||||
*/
|
||||
KARAMTHULHU_POUCH(40, 12023, 58, 510.4, 6809, 5.8, 6, false, new Item(12163), new Item(12155), new Item(6667), new Item(12183, 144)),
|
||||
|
||||
/**
|
||||
* Represents a smoke devil pouch.
|
||||
*/
|
||||
SMOKE_DEVIL_POUCH(41, 12085, 61, 268, 6865, 3, 7, false, new Item(12160), new Item(12155), new Item(9736), new Item(12183, 141)),
|
||||
|
||||
/**
|
||||
* Represents an abyssal lurker pouch.
|
||||
*/
|
||||
ABYSSAL_LUKRER(42, true,12037, 62, 109.6, 6820, 1.9, 9, false, new Item(12159), new Item(12155), new Item(12161), new Item(12183, 119)),
|
||||
|
||||
/**
|
||||
* Represents a spirit cobra pouch.
|
||||
*/
|
||||
SPIRIT_COBRA_POUCH(43, 12015, 63, 276.8, 6802, 3.1, 6, false, new Item(12160), new Item(12155), new Item(6287), new Item(12183, 116)),
|
||||
|
||||
/**
|
||||
* Represents a stranger plant pouch.
|
||||
*/
|
||||
STRANGER_PLANT_POUCH(44, 12045, 64, 281.6, 6827, 3.2, 6, false, new Item(12160), new Item(12155), new Item(8431), new Item(12183, 128)),
|
||||
|
||||
/**
|
||||
* Represents a barker toad pouch.
|
||||
*/
|
||||
BARKER_TOAD_POUCH(45, 12123, 66, 87, 6889, 1, 7, false, new Item(12158), new Item(12155), new Item(2150), new Item(12183, 11)),
|
||||
|
||||
/**
|
||||
* Represents a war tortoise pouch.
|
||||
*/
|
||||
WAR_TORTOISE_POUCH(46, 12031, 67, 58.6, 6815, 0.7, 7, true, new Item(12158), new Item(12155), new Item(7939), new Item(12183, 1)),
|
||||
|
||||
/**
|
||||
* Represents a bunyip pouch.
|
||||
*/
|
||||
BUNYIP_POUCH(47, 12029, 68, 119.2, 6813, 1.4, 7, true, new Item(12159), new Item(12155), new Item(383), new Item(12183, 110)),
|
||||
|
||||
/**
|
||||
* Represents a fruit bat pouch.
|
||||
*/
|
||||
FRUIT_BAT_POUCH(48, 12033, 69, 121.2, 6817, 1.4, 8, true, new Item(12159), new Item(12155), new Item(1963), new Item(12183, 130)),
|
||||
|
||||
/**
|
||||
* Represents a ravenous locust pouch.
|
||||
*/
|
||||
RAVENOUS_LOCUST_POUCH(49, 12820, 70, 132, 7372, 1.5, 4, false, new Item(12160), new Item(12155), new Item(1933), new Item(12183, 79)),
|
||||
|
||||
/**
|
||||
* Represents an arctic bear pouch.
|
||||
*/
|
||||
ARCTIC_BEAR_POUCH(50, 12057, 71, 93.2, 6839, 1.1, 8, false, new Item(12158), new Item(12155), new Item(10117), new Item(12183, 14)),
|
||||
|
||||
/**
|
||||
* Represents a Phoenix
|
||||
*/
|
||||
PHOENIX_POUCH(50, 14623, 72, 93.2, 8575, 1.1, 8, false, new Item(12160, 1), new Item(12183, 165), new Item(12155, 1), new Item(14616, 1)),
|
||||
|
||||
/**
|
||||
* Represents an obsidian golem pouch.
|
||||
*/
|
||||
OBSIDIAN_GOLEM_POUCH(51, 12792, 73, 642.4, 7345, 7.3, 8, false, new Item(12163), new Item(12155), new Item(12168), new Item(12183, 195)),
|
||||
|
||||
/**
|
||||
* Represents a granite lobster pouch.
|
||||
*/
|
||||
GRANITE_LOBSTER_POUCH(52, 12069, 74, 325.6, 6849, 3.7, 8, false, new Item(12160), new Item(12155), new Item(6979), new Item(12183, 166)),
|
||||
|
||||
/**
|
||||
* Represents a praying mantis pouch.
|
||||
*/
|
||||
PRAYING_MANTIS_POUCH(53, 12011, 75, 329.6, 6798, 3.6, 8, false, new Item(12160), new Item(12155), new Item(2460), new Item(12183, 168)),
|
||||
|
||||
/**
|
||||
* Represents a forge regent pouch.
|
||||
*/
|
||||
FORGE_REGENT_BEAST(54, 12782, 76, 134, 7335, 1.5, 9, false, new Item(12159), new Item(12155), new Item(10020), new Item(12183, 141)),
|
||||
|
||||
/**
|
||||
* Represents a talon beast pouch.
|
||||
*/
|
||||
TALON_BEAST_POUCH(55, 12794, 77, 1015.2, 7347, 3.8, 9, false, new Item(12160), new Item(12155), new Item(12162), new Item(12183, 174)),
|
||||
|
||||
/**
|
||||
* Represents a giant ent pouch.
|
||||
*/
|
||||
GIANT_ENT_POUCH(56, 12013, 78, 136.8, 6800, 1.6, 8, false, new Item(12159), new Item(5933), new Item(12155), new Item(12183, 124)),
|
||||
|
||||
/**
|
||||
* Represents a hydra pouch.
|
||||
*/
|
||||
HYDRA_POUCH(60, 12025, 80, 140.8, 6811, 1.6, 9, false, new Item(12159), new Item(571), new Item(12183, 128)),
|
||||
|
||||
/**
|
||||
* Represents a spirit dagannoth pouch.
|
||||
*/
|
||||
SPIRIT_DAGANNOTH_POUCH(61, 12017, 83, 364.8, 6804, 4.1, 9, false, new Item(12160), new Item(6155), new Item(12183, 1)),
|
||||
|
||||
/**
|
||||
* Represents a unicorn stallion pouch.
|
||||
*/
|
||||
UNICORN_STALLION_POUCH(70, 12039, 88, 154.4, 6822, 1.8, 9, true, new Item(12159), new Item(237), new Item(12183, 203)),
|
||||
|
||||
/**
|
||||
* Represents a wolpertinger pouch.
|
||||
*/
|
||||
WOLPERTINGER_POUCH(72, 12089, 92, 404.8, 6869, 4.5, 10, false, new Item(12160), new Item(2859), new Item(3226), new Item(12183, 203)),
|
||||
|
||||
/**
|
||||
* Represents a pack yak pouch.
|
||||
*/
|
||||
PACK_YAK_POUCH(75, 12093, 96, 422.4, 6873, 4.8, 10, true, new Item(12160), new Item(10818), new Item(12183, 211)),
|
||||
|
||||
/**
|
||||
* Represents a fire titan pouch.
|
||||
*/
|
||||
FIRE_TITAN_POUCH(57, 12802, 79, 695.2, 7355, 7.9, 9, false, new Item(12163), new Item(1442), new Item(12155), new Item(12183, 198)),
|
||||
|
||||
/**
|
||||
* Represents a moss titan pouch.
|
||||
*/
|
||||
MOSS_TITAN_POUCH(58, 12804, 79, 695.2, 7357, 7.9, 9, false, new Item(12163), new Item(1440), new Item(12155), new Item(12183, 198)),
|
||||
|
||||
/**
|
||||
* Represents an ice titan pouch.
|
||||
*/
|
||||
ICE_TITAN_POUCH(59, 12806, 79, 695.2, 7359, 7.9, 9, false, new Item(12163), new Item(1438), new Item(1444), new Item(12155), new Item(12183, 198)),
|
||||
|
||||
/**
|
||||
* Represents a lava titan pouch.
|
||||
*/
|
||||
LAVA_TITAN_POUCH(62, 12788, 83, 730.4, 7341, 8.3, 9, false, new Item(12163), new Item(12168), new Item(12155), new Item(12183, 219)),
|
||||
|
||||
/**
|
||||
* Represents a swamp titan pouch.
|
||||
*/
|
||||
SWAMP_TITAN_POUCH(63, 12776, 85, 373.6, 7329, 4.2, 9, false, new Item(12160), new Item(10149), new Item(12155), new Item(12183, 150)),
|
||||
|
||||
/**
|
||||
* Represents a geyser titan pouch.
|
||||
*/
|
||||
GEYSER_TITAN_POUCH(71, 12786, 89, 783.2, 7339, 8.9, 9, false, new Item(12163), new Item(1444), new Item(12155), new Item(12183, 222)),
|
||||
|
||||
/**
|
||||
* Represents an abyssal titan pouch.
|
||||
*/
|
||||
ABYSSAL_TITAN_POUCH(73, true,12796, 93, 163.2, 7349, 1.9, 10, false, new Item(12159), new Item(12161), new Item(12155), new Item(12183, 113)),
|
||||
|
||||
/**
|
||||
* Represents an iron titan pouch.
|
||||
*/
|
||||
IRON_TITAN_POUCH(74, 12822, 95, 417.6, 7375, 4.7, 10, false, new Item(12160), new Item(1115), new Item(12155), new Item(12183, 198)),
|
||||
|
||||
/**
|
||||
* Represents a steel titan pouch.
|
||||
*/
|
||||
STEEL_TITAN_POUCH(76, 12790, 99, 435.2, 7343, 4.9, 10, false, new Item(12160), new Item(1119), new Item(12155), new Item(12183, 178)),
|
||||
|
||||
SACRED_CLAY_POUCH_1(-1, 14422, 1, 0, 8240, 0, 1, false, new Item(14182)),
|
||||
SACRED_CLAY_POUCH_2(-1, 14424, 20, 0, 8242, 0, 3, false, new Item(14184)),
|
||||
SACRED_CLAY_POUCH_3(-1, 14426, 40, 0, 8244, 0, 5, false, new Item(14186)),
|
||||
SACRED_CLAY_POUCH_4(-1, 14428, 60, 0, 8246, 0, 7, false, new Item(14188)),
|
||||
SACRED_CLAY_POUCH_5(-1, 14430, 80, 0, 8248, 0, 9, false, new Item(14190));
|
||||
|
||||
/**
|
||||
* The mapping.
|
||||
*/
|
||||
private static final Map<Integer, SummoningPouch> POUCHES = new HashMap<Integer, SummoningPouch>();
|
||||
|
||||
/**
|
||||
* Populate the mapping.
|
||||
*/
|
||||
static {
|
||||
for (SummoningPouch pouch : SummoningPouch.values()) {
|
||||
POUCHES.put(pouch.pouchId, pouch);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a summoning pouch object from the mapping.
|
||||
* @param pouchId The pouch item id.
|
||||
* @return The {@code SummoningPouch} {@code Object}, <br> or {@code null}
|
||||
* if the pouch didn't exist.
|
||||
*/
|
||||
public static SummoningPouch get(int pouchId) {
|
||||
return POUCHES.get(pouchId);
|
||||
}
|
||||
|
||||
/**
|
||||
* The slot id.
|
||||
*/
|
||||
private final int slot;
|
||||
|
||||
/**
|
||||
* The pouch item id.
|
||||
*/
|
||||
private final int pouchId;
|
||||
|
||||
/**
|
||||
* The level required to create this pouch.
|
||||
*/
|
||||
private final int levelRequired;
|
||||
|
||||
/**
|
||||
* The experience gained when creating this pouch.
|
||||
*/
|
||||
private final double createExperience;
|
||||
|
||||
/**
|
||||
* The familiar npc id.
|
||||
*/
|
||||
private final int npcId;
|
||||
|
||||
/**
|
||||
* The experience gained when summoning the familiar.
|
||||
*/
|
||||
private final double summonExperience;
|
||||
|
||||
/**
|
||||
* The summon cost.
|
||||
*/
|
||||
private final int summonCost;
|
||||
|
||||
/**
|
||||
* Is the familiar peaceful
|
||||
*/
|
||||
private final boolean peaceful;
|
||||
|
||||
/**
|
||||
* The items required to create this pouch.
|
||||
*/
|
||||
private final Item[] items;
|
||||
|
||||
public boolean abyssal;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SummoningPouch} {@code Object}.
|
||||
* @param pouchId The pouch item id.
|
||||
* @param levelRequired The level required to create.
|
||||
* @param createExperience The experience gained when creating a pouch.
|
||||
* @param npcId The familiar's NPC id.
|
||||
* @param summonExperience The experience gained when summoning.
|
||||
* @param summonCost The amount of summoning points to drain when summoned.
|
||||
* @param peaceful Determines whether the familiar is peaceful and should attack.
|
||||
* @param items The items required to create this pouch.
|
||||
*/
|
||||
private SummoningPouch(int slot, int pouchId, int levelRequired, double createExperience, int npcId, double summonExperience, int summonCost, boolean peaceful, Item... items) {
|
||||
this.slot = slot;
|
||||
this.pouchId = pouchId;
|
||||
this.levelRequired = levelRequired;
|
||||
this.createExperience = createExperience;
|
||||
this.npcId = npcId;
|
||||
this.summonExperience = summonExperience;
|
||||
this.summonCost = summonCost;
|
||||
this.peaceful = peaceful;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
private SummoningPouch(int slot, boolean abyssal, int pouchId, int levelRequired, double createExperience, int npcId, double summonExperience, int summonCost, boolean peaceful, Item... items) {
|
||||
this(slot, pouchId, levelRequired, createExperience, npcId, summonExperience, summonCost, peaceful, items);
|
||||
this.abyssal = abyssal;
|
||||
}
|
||||
/**
|
||||
* Gets the summoning pouch for the given slot.
|
||||
* @param slot The slot.
|
||||
* @return The summoning pouch.
|
||||
*/
|
||||
public static SummoningPouch forSlot(int slot) {
|
||||
for (SummoningPouch pouch : SummoningPouch.values()) {
|
||||
if (pouch.getSlot() == slot) {
|
||||
return pouch;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pouchId
|
||||
*/
|
||||
public int getPouchId() {
|
||||
return pouchId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the levelRequired
|
||||
*/
|
||||
public int getLevelRequired() {
|
||||
return levelRequired;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the createExperience
|
||||
*/
|
||||
public double getCreateExperience() {
|
||||
return createExperience;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the npcId
|
||||
*/
|
||||
public int getNpcId() {
|
||||
return npcId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the summonExperience
|
||||
*/
|
||||
public double getSummonExperience() {
|
||||
return summonExperience;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of points to decrease the summoning points with when
|
||||
* summoned.
|
||||
* @return The amount of points.
|
||||
*/
|
||||
public int getSummonCost() {
|
||||
return summonCost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether the familiar is peaceful
|
||||
*/
|
||||
public boolean getPeaceful() { return peaceful; }
|
||||
|
||||
/**
|
||||
* @return the items
|
||||
*/
|
||||
public Item[] getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the slot
|
||||
*/
|
||||
public int getSlot() {
|
||||
return slot;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package content.global.skill.summoning;
|
||||
|
||||
/**
|
||||
* Represents a summoning scroll.
|
||||
* @author 'Vexia
|
||||
*/
|
||||
public enum SummoningScroll {
|
||||
HOWL_SCROLL(0, 12425, 0.1, 1, 12047), DREADFOWL_STRIKE_SCROLL(1, 12445, 0.1, 4, 12043), EGG_SPAWN_SCROLL(2, 12428, 0.2, 10, 12059), SLIME_SPRAY_SCROLL(3, 12459, 0.2, 13, 12019), STONY_SHELL_SCROLL(4, 12533, 0.2, 16, 12009), PESTER_SCROLL(5, 12838, 0.5, 17, 12778), ELECTRIC_LASH_SCROLL(6, 12460, 0.4, 18, 12049), VENOM_SHOT_SCROLL(7, 12432, 0.9, 19, 12055), FIREBALL_ASSAULT_SCROLL(8, 12839, 1.1, 22, 12808), CHEESE_FEAST_SCROLL(9, 12430, 2.3, 23, 12067), SANDSTORM_SCROLL(10, 12446, 2.5, 25, 12063), GENERATE_COMPOST_SCROLL(11, 12440, 0.6, 28, 12091), EXPLODE_SCROLL(12, 12834, 2.9, 29, 12800), VAMPYRE_TOUCH_SCROLL(13, 12447, 1.5, 31, 12053), INSANE_FEROCITY_SCROLL(14, 12433, 1.6, 32, 12065), MULTICHOP_SCROLL(15, 12429, 0.7, 33, 12021), CALL_TO_ARMS_SCROLL1(16, 12443, 0.7, 34, 12818), CALL_TO_ARMS_SCROLL2(17, 12443, 0.7, 34, 12814), CALL_TO_ARMS_SCROLL3(18, 12443, 0.7, 34, 12780), CALL_TO_ARMS_SCROLL4(19, 12443, 0.7, 34, 12798), BRONZE_BULL_RUSH_SCROLL(64, 12461, 3.6, 36, 12073), UNBURDEN_SCROLL(20, 12431, 0.6, 40, 12087), HERBCALL_SCROLL(21, 12422, 0.8, 41, 12071), EVIL_FLAMES_SCROLL(22, 12448, 2.1, 42, 12051), PETRIFYING_GAZE_SCROLL1(23, 12458, 0.9, 43, 12095), PETRIFYING_GAZE_SCROLL2(24, 12458, 0.9, 43, 12097), PETRIFYING_GAZE_SCROLL3(25, 12458, 0.9, 43, 12099), PETRIFYING_GAZE_SCROLL4(26, 12458, 0.9, 43, 12101), PETRIFYING_GAZE_SCROLL5(27, 12458, 0.9, 43, 12103), PETRIFYING_GAZE_SCROLL6(28, 12458, 0.9, 43, 12105), PETRIFYING_GAZE_SCROLL7(29, 12458, 0.9, 43, 12107), IRON_BULL_RUSH_SCROLL(65, 12462, 4.6, 46, 12075), IMMENSE_HEAT_SCROLL(30, 12829, 2.3, 46, 12816), THIEVING_FINGERS_SCROLL(31, 12426, 47, 167, 12041), BLOOD_DRAIN_SCROLL(32, 12444, 2.4, 49, 12061), TIRELESS_RUN_SCROLL(33, 12441, 0.8, 52, 12007), ABYSSAL_DRAIN_SCROLL(34, 12454, 1.1, 54, 12035), DISSOLVE_SCROLL(35, 12453, 5.5, 55, 12027), STEEL_BULL_RUSH_SCROLL(66, 12463, 5.6, 56, 12077), FISH_RAIN_SCROLL(36, 12424, 1.1, 56, 12531), AMBUSH_SCROLL(37, 12836, 5.7, 57, 12812), RENDING_SCROLL(38, 12840, 5.7, 57, 12784), GOAD_SCROLL(39, 12835, 5.7, 57, 12810), DOOMSPHERE_SCROLL(40, 12455, 5.8, 58, -1), DUST_CLOUD_SCROLL(41, 12468, 3.0, 61, 12085), ABYSSAL_STEALTH_SCROLL(42, 12427, 1.9, 62, 12037), OPHIDIAN_INCUBATION_SCROLL(43, 12436, 3.1, 63, 12015), POISONOUS_BLAST_SCROLL(44, 12467, 3.2, 64, 12045), MITHRIL_BULL_RUSH_SCROLL(67, 12464, 6.6, 66, 12079), TOAD_BARK_SCROLL(45, 12452, 1.0, 66, 12123), TESTUDO_SCROLL(46, 12439, 0.7, 67, 12031), SWALLOW_WHOLE_SCROLL(47, 12438, 1.4, 68, 12029), FRUITFALL_SCROLL(48, 12423, 1.4, 69, 12033), FAMINE_SCROLL(49, 12830, 1.5, 70, 12820), ARCTIC_BLAST_SCROLL(50, 12451, 1.1, 71, 12057),
|
||||
// RISE_FROM_THE_ASHES_SCROLL(51, 14622, 8.0, 277, -1),
|
||||
VOLCANIC_STRENGTH_SCROLL(51, 12826, 7.3, 73, 12792), CRUSHING_CLAW_SCROLL(52, 12449, 3.7, 74, 12069), MANTIS_STRIKE_SCROLL(53, 12450, 3.7, 75, 12011), INFERNO_SCROLL(54, 12841, 1.5, 76, 12782), ADAMANT_BULL_RUSH_SCROLL(68, 12465, 7.6, 76, 12081), DEADLY_CLAW_SCROLL(55, 12831, 11.0, 77, 12162), ACORN_MISSILE_SCROLL(56, 12457, 1.6, 78, 12013), TITANS_CONSTITUTION_SCROLL1(57, 12824, 7.9, 79, 12802), TITANS_CONSTITUTION_SCROLL2(58, 12824, 7.9, 79, 12806), TITANS_CONSTITUTION_SCROLL3(59, 12824, 7.9, 79, 12804), REGROWTH_SCROLL(60, 12442, 1.6, 80, 12025), SPIKE_SHOT_SCROLL(61, 12456, 4.1, 83, 12017), EBON_THUNDER_SCROLL(62, 12837, 8.3, 83, 12788), SWAMP_PLAGUE_SCROLL(63, 12832, 4.1, 85, 12776), RUNE_BULL_RUSH_SCROLL(69, 12466, 8.6, 86, 12083), HEALING_AURA_SCROLL(70, 12434, 1.8, 88, 12039), BOIL_SCROLL(71, 12833, 8.9, 89, 12786), MAGIC_FOCUS_SCROLL(72, 12437, 4.6, 92, 12089), ESSENCE_SHIPMENT_SCROLL(73, 12827, 1.9, 93, 12796), IRON_WITHIN_SCROLL(74, 12828, 4.7, 95, 12822), WINTER_STORAGE_SCROLL(75, 12435, 4.8, 96, 12093), STEEL_OF_LEGENDS_SCROLL(76, 12825, 4.9, 99, 12790),
|
||||
CLAY_DEPOSIT_SCROLL_1(-1, 14421, 0, 1, 14422),
|
||||
CLAY_DEPOSIT_SCROLL_2(-1, 14421, 0, 20, 14424),
|
||||
CLAY_DEPOSIT_SCROLL_3(-1, 14421, 0, 40, 14426),
|
||||
CLAY_DEPOSIT_SCROLL_4(-1, 14421, 0, 60, 14428),
|
||||
CLAY_DEPOSIT_SCROLL_5(-1, 14421, 0, 80, 14430);
|
||||
|
||||
/**
|
||||
* The level required.
|
||||
*/
|
||||
private int level;
|
||||
|
||||
/**
|
||||
* The item id needed.
|
||||
*/
|
||||
private int itemId;
|
||||
|
||||
/**
|
||||
* The slot id.
|
||||
*/
|
||||
private int slotId;
|
||||
|
||||
/**
|
||||
* The xp gained.
|
||||
*/
|
||||
private double xp;
|
||||
|
||||
/**
|
||||
* The items required.
|
||||
*/
|
||||
private int[] items;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SummoningScroll} {@code Object}.
|
||||
* @param level
|
||||
* @param itemId
|
||||
* @param xp
|
||||
* @param slotId
|
||||
* @param items
|
||||
*/
|
||||
SummoningScroll(int slotId, int itemId, double xp, int level, int... items) {
|
||||
this.level = level;
|
||||
this.itemId = itemId;
|
||||
this.xp = xp;
|
||||
this.slotId = slotId;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public int getPouch(){
|
||||
return items[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the level.
|
||||
* @return The level.
|
||||
*/
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the itemId.
|
||||
* @return The itemId.
|
||||
*/
|
||||
public int getItemId() {
|
||||
return itemId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the slotId.
|
||||
* @return The slotId.
|
||||
*/
|
||||
public int getSlotId() {
|
||||
return slotId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the xp.
|
||||
* @return The xp.
|
||||
*/
|
||||
public double getExperience() {
|
||||
return xp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the items.
|
||||
* @return The items.
|
||||
*/
|
||||
public int[] getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the summoning value for the id.
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
public static SummoningScroll forId(int id) {
|
||||
for (SummoningScroll scroll : SummoningScroll.values()) {
|
||||
if (scroll.slotId == id) {
|
||||
return scroll;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static SummoningScroll forItemId(int id) {
|
||||
for (SummoningScroll scroll : SummoningScroll.values()) {
|
||||
if (scroll.itemId == id) {
|
||||
return scroll;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the scroll for the given pouch item id.
|
||||
* @param pouchId The pouch item id.
|
||||
* @return The scroll.
|
||||
*/
|
||||
public static SummoningScroll forPouch(int pouchId) {
|
||||
for (SummoningScroll scroll : SummoningScroll.values()) {
|
||||
if (scroll.items[0] == pouchId) {
|
||||
return scroll;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import content.global.skill.summoning.familiar.BurdenBeast
|
||||
import content.global.skill.summoning.familiar.FamiliarSpecial
|
||||
import core.game.interaction.InterfaceListener
|
||||
|
||||
class SummoningTabListener : InterfaceListener {
|
||||
override fun defineInterfaceListeners() {
|
||||
on(662) { player, _, opcode, buttonID, _, _ ->
|
||||
when(buttonID) {
|
||||
51 -> {
|
||||
if (player.getFamiliarManager().hasFamiliar()) {
|
||||
player.getFamiliarManager().getFamiliar().call()
|
||||
} else {
|
||||
player.getPacketDispatch().sendMessage("You don't have a follower.")
|
||||
}
|
||||
}
|
||||
67 -> {
|
||||
if (player.getFamiliarManager().hasFamiliar()) {
|
||||
if (!player.getFamiliarManager().getFamiliar().isBurdenBeast()) {
|
||||
player.getPacketDispatch().sendMessage("Your familiar is not a beast of burden.")
|
||||
return@on true
|
||||
}
|
||||
val beast = player.getFamiliarManager().getFamiliar() as BurdenBeast;
|
||||
if (beast.getContainer().isEmpty()) {
|
||||
player.getPacketDispatch().sendMessage("Your familiar is not carrying any items.")
|
||||
return@on true
|
||||
}
|
||||
beast.withdrawAll();
|
||||
return@on true
|
||||
}
|
||||
player.getPacketDispatch().sendMessage("You don't have a follower.");
|
||||
}
|
||||
53 -> {
|
||||
if (player.getFamiliarManager().hasFamiliar()) {
|
||||
if(opcode == 155) {
|
||||
// Dismiss familiar
|
||||
player.getDialogueInterpreter().open("dismiss_dial");
|
||||
} else if(opcode == 196) {
|
||||
// Dismiss now
|
||||
player.getFamiliarManager().dismiss(false);
|
||||
}
|
||||
} else {
|
||||
player.getPacketDispatch().sendMessage("You don't have a follower.");
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
if (player.getFamiliarManager().hasFamiliar()) {
|
||||
player.getFamiliarManager().getFamiliar().executeSpecialMove(FamiliarSpecial(player));
|
||||
} else {
|
||||
player.getPacketDispatch().sendMessage("You don't have a follower.");
|
||||
}
|
||||
}
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,608 @@
|
||||
package content.global.skill.summoning;
|
||||
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.game.component.Component;
|
||||
import core.game.activity.ActivityManager;
|
||||
import core.game.activity.ActivityPlugin;
|
||||
import core.game.activity.CutscenePlugin;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.global.action.ClimbActionHandler;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.quest.Quest;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.scenery.Scenery;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.build.DynamicRegion;
|
||||
import core.game.world.map.path.Pathfinder;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.net.packet.PacketRepository;
|
||||
import core.net.packet.context.CameraContext;
|
||||
import core.net.packet.context.CameraContext.CameraType;
|
||||
import core.net.packet.context.MinimapStateContext;
|
||||
import core.net.packet.out.CameraViewPacket;
|
||||
import core.net.packet.out.MinimapState;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.ClassScanner;
|
||||
|
||||
/**
|
||||
* Handles the summoning training room.
|
||||
* @author Emperor
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class SummoningTrainingRoom extends OptionHandler {
|
||||
|
||||
/**
|
||||
* Represents the wolf bones item.
|
||||
*/
|
||||
private static final Item BONES = new Item(2859, 2);
|
||||
|
||||
/**
|
||||
* Represents the trapdoor key.
|
||||
*/
|
||||
private static final Item TRAPDOOR_KEY = new Item(12528);
|
||||
|
||||
/**
|
||||
* Represents the howl scroll item.
|
||||
*/
|
||||
private static final Item HOWL_SCROLL = new Item(12425);
|
||||
|
||||
/**
|
||||
* Represents the wolf pouch.
|
||||
*/
|
||||
private static final Item WOLF_POUCH = new Item(12047);
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
SceneryDefinition.forId(28675).getHandlers().put("option:open", this);
|
||||
SceneryDefinition.forId(28676).getHandlers().put("option:climb-down", this);
|
||||
SceneryDefinition.forId(28653).getHandlers().put("option:climb-down", this);
|
||||
SceneryDefinition.forId(28572).getHandlers().put("option:climb-up", this);
|
||||
SceneryDefinition.forId(28676).getHandlers().put("option:close", this);
|
||||
SceneryDefinition.forId(28714).getHandlers().put("option:climb", this);
|
||||
SceneryDefinition.forId(28586).getHandlers().put("option:search", this);
|
||||
ActivityManager.register(new FluffyCutscene());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(final Player player, Node node, String option) {
|
||||
Scenery object = (Scenery) node;
|
||||
Location loc = null;
|
||||
Quest quest = player.getQuestRepository().getQuest("Wolf Whistle");
|
||||
int questVal = quest.getStage(player) == 0 ? 0 : quest.getStage(player) > 0 && quest.getStage(player) < 100 ? 5 : 28893;
|
||||
switch (option) {
|
||||
case "close":
|
||||
player.getConfigManager().set(1178, questVal == 28893 ? 32989 : (1 << 11) + questVal);
|
||||
return true;
|
||||
case "open":
|
||||
if (quest.getStage(player) < 40) {
|
||||
player.getPacketDispatch().sendMessage("The trapdoor is locked.");
|
||||
return true;
|
||||
} else if (quest.getStage(player) == 40) {
|
||||
if (player.getAttribute("has-key", false) || player.getInventory().remove(TRAPDOOR_KEY)) {
|
||||
player.setAttribute("has-key", true);
|
||||
player.getConfigManager().set(1178, (2 << 11) + questVal, true);
|
||||
} else {
|
||||
player.getPacketDispatch().sendMessage("The trapdoor is locked.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
player.getConfigManager().set(1178, questVal == 28893 ? 28893 : (2 << 11) + questVal);
|
||||
return true;
|
||||
case "climb-down":
|
||||
if (object.getId() == 28653) {
|
||||
if (quest.getStage(player) == 50) {
|
||||
final CutscenePlugin plugin = player.getAttribute("in-cutscene", null);
|
||||
if (plugin != null) {
|
||||
plugin.stop(true);
|
||||
} else {
|
||||
ClimbActionHandler.climbLadder(player, object, option);
|
||||
}
|
||||
} else {
|
||||
ClimbActionHandler.climbLadder(player, object, option);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!object.getLocation().equals(Location.create(2927, 3444, 0))) {
|
||||
return false;
|
||||
}
|
||||
loc = Location.create(2209, 5348, 0);
|
||||
break;
|
||||
case "climb":
|
||||
if (!object.getLocation().equals(Location.create(2209, 5349, 0))) {
|
||||
return false;
|
||||
}
|
||||
loc = Location.create(2926, 3444, 0);
|
||||
break;
|
||||
case "climb-up":
|
||||
switch (quest.getStage(player)) {
|
||||
case 10:
|
||||
case 50:
|
||||
if (player.getFamiliarManager().hasFamiliar()) {
|
||||
player.getPacketDispatch().sendMessage("You can't bring a familiar up there.");
|
||||
return true;
|
||||
}
|
||||
if (quest.getStage(player) == 50 && (!player.getInventory().containsItem(WOLF_POUCH) || !player.getInventory().containsItem(HOWL_SCROLL))) {
|
||||
player.getDialogueInterpreter().sendDialogues(player, null, "I should bring my spirit wolf pouch and howl scroll", "with me up there.");
|
||||
return true;
|
||||
}
|
||||
ActivityManager.start(player, "fluffy cutscene", false);
|
||||
break;
|
||||
case 100:
|
||||
case 60:
|
||||
ClimbActionHandler.climbLadder(player, (Scenery) node, option);
|
||||
break;
|
||||
default:
|
||||
player.getDialogueInterpreter().sendDialogue("There is a loud crash from upstairs, followed by the tinkling of", "broken glass.");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
case "search":
|
||||
if (quest.getStage(player) == 30 && !player.getAttribute("searched-body", false)) {
|
||||
if (!player.getInventory().hasSpaceFor(BONES)) {
|
||||
player.getPacketDispatch().sendMessage("You search the dead body but find nothing.");
|
||||
return true;
|
||||
}
|
||||
if (!player.getInventory().containsItem(BONES) && player.getInventory().add(BONES)) {
|
||||
player.setAttribute("/save:searched-body", true);
|
||||
player.getPacketDispatch().sendMessage("You search the dead body and find two wolf bones.");
|
||||
return true;
|
||||
} else {
|
||||
player.getPacketDispatch().sendMessage("You search the dead body but find nothing.");
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
player.getPacketDispatch().sendMessage("You search the dead body but find nothing.");
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
ClimbActionHandler.climb(player, new Animation(828), loc);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the cutscene used during wolf whistle.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
public static final class FluffyCutscene extends CutscenePlugin {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FluffyCutscene} {@code Object}.
|
||||
*/
|
||||
public FluffyCutscene() {
|
||||
super("fluffy cutscene");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FluffyCutscene} {@code Object}.
|
||||
* @param player the player.
|
||||
*/
|
||||
public FluffyCutscene(final Player player) {
|
||||
this();
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityPlugin newInstance(Player p) throws Throwable {
|
||||
return new FluffyCutscene(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
player.getDialogueInterpreter().open(392932, this);
|
||||
player.setAttribute("wolf-dial", player.getDialogueInterpreter().getDialogue());
|
||||
player.setAttribute("in-cutscene", this);
|
||||
player.lock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
super.end();
|
||||
player.removeAttribute("in-cutscene");
|
||||
player.getFamiliarManager().dismiss();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getSpawnLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getStartLocation() {
|
||||
return base.transform(46, 50, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure() {
|
||||
region = DynamicRegion.create(11573);
|
||||
setRegionBase();
|
||||
registerRegion(region.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
ClassScanner.definePlugin(new FluffyDialogue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the dialogue used during the fluffy cutscene.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
public static final class FluffyDialogue extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* Represents the scared animation.
|
||||
*/
|
||||
private static final Animation SCARED_ANIMATION = new Animation(2836);
|
||||
|
||||
/**
|
||||
* Represents the wolpertiner graphic.
|
||||
*/
|
||||
private static final Graphics GRAPHIC = new Graphics(1522);
|
||||
|
||||
/**
|
||||
* Represents the shudder animation.
|
||||
*/
|
||||
private static final Animation SHUDDER_ANIMATION = new Animation(8506);
|
||||
|
||||
/**
|
||||
* Represents the death animation.
|
||||
*/
|
||||
private static final Animation DEATH_ANIMATION = new Animation(8507);
|
||||
|
||||
/**
|
||||
* Represents the cutscene instance.
|
||||
*/
|
||||
private CutscenePlugin cutscene;
|
||||
|
||||
/**
|
||||
* Represents the quest instance.
|
||||
*/
|
||||
private Quest quest;
|
||||
|
||||
/**
|
||||
* Represents the fluffy npc.
|
||||
*/
|
||||
private NPC fluffy;
|
||||
|
||||
/**
|
||||
* Represents the wolf npc.
|
||||
*/
|
||||
private NPC wolf;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FluffyDialogue} {@code Object}.
|
||||
*/
|
||||
public FluffyDialogue() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FluffyDialogue} {@code Object}.
|
||||
* @param player the player.
|
||||
*/
|
||||
public FluffyDialogue(final Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new FluffyDialogue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
cutscene = (CutscenePlugin) args[0];
|
||||
quest = player.getQuestRepository().getQuest("Wolf Whistle");
|
||||
fluffy = NPC.create(6990, cutscene.getBase().transform(41, 52, 1));
|
||||
fluffy.init();
|
||||
fluffy.faceTemporary(player, 1);
|
||||
Location b = cutscene.getBase().transform(42, 50, 0);
|
||||
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.POSITION, b.getX(), b.getY(), 244, 1, 100));
|
||||
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.ROTATION, b.getX() + 1, b.getY(), 244, 1, 100));
|
||||
switch (quest.getStage(player)) {
|
||||
case 10:
|
||||
player("Come on then little, fluffy...");
|
||||
break;
|
||||
case 50:
|
||||
player("Mustn't look round, bunny will eat me.", "Mustn't look round, bunny will eat me.", "Mustn't look round, bunny will eat me.");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (quest.getStage(player)) {
|
||||
case 10:
|
||||
switch (stage) {
|
||||
case 0:
|
||||
close();
|
||||
GameWorld.getPulser().submit(new Pulse(1, player, fluffy) {
|
||||
int counter = 0;
|
||||
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
switch (++counter) {
|
||||
case 2:
|
||||
player.face(fluffy);
|
||||
break;
|
||||
case 5:
|
||||
player("Gigantic...");
|
||||
stage = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
});
|
||||
break;
|
||||
case 1:
|
||||
player("scary-looking...");
|
||||
stage = 2;
|
||||
break;
|
||||
case 2:
|
||||
player("razor-fanged...");
|
||||
stage = 3;
|
||||
break;
|
||||
case 3:
|
||||
player("bunny...");
|
||||
stage = 4;
|
||||
break;
|
||||
case 4:
|
||||
close();
|
||||
int x = player.getLocation().getX() + 1;
|
||||
int y = player.getLocation().getY() - 1;
|
||||
int height = 300;
|
||||
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.POSITION, x, y, height, 1, 100));
|
||||
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.ROTATION, x + 1000, y + 13, height, 1, 100));
|
||||
player.faceLocation(cutscene.getBase().transform(44, 50, 1));
|
||||
GameWorld.getPulser().submit(new Pulse(1, player, fluffy) {
|
||||
int counter = 0;
|
||||
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
switch (++counter) {
|
||||
case 3:
|
||||
fluffy.sendChat("Mrooowr?");
|
||||
break;
|
||||
case 6:
|
||||
player("What is that thing?");
|
||||
stage = 5;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
});
|
||||
break;
|
||||
case 5:
|
||||
player("Maybe, if I leave quitely, it won't notice me.");
|
||||
stage = 6;
|
||||
break;
|
||||
case 6:
|
||||
close();
|
||||
GameWorld.getPulser().submit(new Pulse(1, player, fluffy) {
|
||||
int counter = 0;
|
||||
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
switch (++counter) {
|
||||
case 2:
|
||||
Pathfinder.find(fluffy, cutscene.getBase().transform(41, 51, 1)).walk(fluffy);
|
||||
break;
|
||||
case 4:
|
||||
fluffy.face(player);
|
||||
fluffy.graphics(GRAPHIC);
|
||||
break;
|
||||
case 5:
|
||||
fluffy.sendChat("Raaaarw!");
|
||||
break;
|
||||
case 8:
|
||||
int x = player.getLocation().getX() - 4;
|
||||
int y = player.getLocation().getY();
|
||||
int height = 270;
|
||||
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.POSITION, x, y, height, 1, 100));
|
||||
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.ROTATION, x + 1, y, height, 1, 100));
|
||||
interpreter.sendDialogue("A chilling, unnatural fear envelops you!");
|
||||
stage = 7;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
});
|
||||
break;
|
||||
case 7:
|
||||
player("It's coming to get me!");
|
||||
player.animate(SCARED_ANIMATION);
|
||||
player.sendChat("It's coming to get me!");
|
||||
stage = 8;
|
||||
break;
|
||||
case 8:
|
||||
end();
|
||||
GameWorld.getPulser().submit(new Pulse(2) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
player.animate(Animation.create(827));
|
||||
return true;
|
||||
}
|
||||
|
||||
});
|
||||
cutscene.stop(true);
|
||||
quest.setStage(player, 20);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 50:// second cutscene.
|
||||
switch (stage) {
|
||||
case 0:
|
||||
fluffy.faceLocation(cutscene.getBase().transform(40, 53, 1));
|
||||
player("Okay, I have the spirit wolf pouch, so it can't hurt me...");
|
||||
stage = 1;
|
||||
break;
|
||||
case 1:
|
||||
player("...I hope.");
|
||||
stage = 2;
|
||||
break;
|
||||
case 2:
|
||||
int x = player.getLocation().getX() + 1;
|
||||
int y = player.getLocation().getY() - 1;
|
||||
int height = 300;
|
||||
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.POSITION, x, y, height, 1, 100));
|
||||
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.ROTATION, x + 1000, y + 13, height, 1, 100));
|
||||
player.faceLocation(cutscene.getBase().transform(44, 50, 1));
|
||||
close();
|
||||
player("Oh, good. It's too busy gnawing to notice me.");
|
||||
stage = 3;
|
||||
break;
|
||||
case 3:
|
||||
fluffy.faceTemporary(player, 1);
|
||||
fluffy.sendChat("Raaaarw!");
|
||||
player("I spoke too soon!");
|
||||
stage = 4;
|
||||
break;
|
||||
case 4:
|
||||
player("I'll use the spirit wolf pouch. I hope this works.");
|
||||
stage = 5;
|
||||
break;
|
||||
case 5:
|
||||
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.RESET, 0 + 1000, 0 + 13, 0, 1, 100));
|
||||
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 0));
|
||||
player.unlock();
|
||||
player.getLocks().lockMovement(10000000);
|
||||
player.getInterfaceManager().openTab(new Component(149));
|
||||
stage = -5;
|
||||
break;
|
||||
case -5:
|
||||
player.setAttribute("in-cutscene", cutscene);
|
||||
close();
|
||||
stage = 6;
|
||||
break;
|
||||
case 6:
|
||||
Location l = cutscene.getBase().transform(46, 50, 0);
|
||||
x = l.getX() + 1;
|
||||
y = l.getY() - 2;
|
||||
height = 440;
|
||||
player.lock();
|
||||
player.getLocks().lockMovement(100000);
|
||||
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.POSITION, x, y, height, 1, 95));
|
||||
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.ROTATION, x + 1000, y + 17, height, 1, 95));
|
||||
wolf = player.getFamiliarManager().getFamiliar();
|
||||
GameWorld.getPulser().submit(new Pulse(1, player, fluffy) {
|
||||
int counter;
|
||||
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
switch (++counter) {
|
||||
case 1:
|
||||
wolf.sendChat("Grrrrrrrrrrrrrrrr...");
|
||||
break;
|
||||
case 2:
|
||||
fluffy.sendChat("Whiiiiiine!");
|
||||
break;
|
||||
case 4:
|
||||
player("Get that thing!");
|
||||
stage = 7;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 7:
|
||||
player.getLocks().lockMovement(1000000);
|
||||
player.lock();
|
||||
close();
|
||||
fluffy.animate(SHUDDER_ANIMATION);
|
||||
if (player.getInventory().remove(HOWL_SCROLL)) {
|
||||
player.getDialogueInterpreter().setDialogue(this);
|
||||
player.getDialogueInterpreter().getDialogue().setStage(8);
|
||||
GameWorld.getPulser().submit(new Pulse(1, player, fluffy, wolf) {
|
||||
int counter;
|
||||
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
switch (++counter) {
|
||||
case 2:
|
||||
wolf.animate(Animation.create(8293));
|
||||
Projectile.magic(wolf, fluffy, 1333, 40, 36, 50, 5).send();
|
||||
player.getSkills().updateLevel(Skills.SUMMONING, -2, 0);
|
||||
break;
|
||||
case 5:
|
||||
fluffy.animate(DEATH_ANIMATION);
|
||||
break;
|
||||
case 12:
|
||||
fluffy.clear();
|
||||
wolf.face(player);
|
||||
player.face(player);
|
||||
player("Well, that certainly seems to have got rid of the giant", "wolpertinger.");
|
||||
stage = 8;
|
||||
player.getDialogueInterpreter().setDialogue(FluffyDialogue.this);
|
||||
player.getDialogueInterpreter().getDialogue().setStage(8);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
player("Come on, let's go tell Pikkupstix.");
|
||||
stage = 9;
|
||||
break;
|
||||
case 9:
|
||||
wolf.clear();
|
||||
player("They both vanished! I'm sure Pikkupstix will be able to", "explain this to me.");
|
||||
stage = 10;
|
||||
break;
|
||||
case 10:
|
||||
end();
|
||||
quest.setStage(player, 60);
|
||||
cutscene.stop(true);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean close() {
|
||||
return super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
super.end();
|
||||
if (player.getFamiliarManager().hasFamiliar()) {
|
||||
player.getFamiliarManager().getFamiliar().dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 392932 };
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Abyssal Lurker familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class AbyssalLurkerNPC extends BurdenBeast {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code AbyssalLurkerNPC} {@code Object}.
|
||||
*/
|
||||
public AbyssalLurkerNPC() {
|
||||
this(null, 6820);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code AbyssalLurkerNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public AbyssalLurkerNPC(Player owner, int id) {
|
||||
super(owner, id, 4100, 12037, 3, 7, WeaponInterface.STYLE_CAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new AbyssalLurkerNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllowed(Player owner, Item item) {
|
||||
if (item.getId() != 1436 && item.getId() != 7936) {
|
||||
owner.getPacketDispatch().sendMessage("Your familiar can only hold unnoted essence.");
|
||||
return false;
|
||||
}
|
||||
return super.isAllowed(owner, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
visualize(Animation.create(7682), Graphics.create(0));
|
||||
owner.getSkills().updateLevel(Skills.AGILITY, 4);
|
||||
owner.getSkills().updateLevel(Skills.THIEVING, 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visualizeSpecialMove() {
|
||||
owner.visualize(new Animation(7660), new Graphics(1296));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6820, 6821 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the Abyssal Parasite familiar.
|
||||
* @author Aero
|
||||
* @note do the shit for the abbys.
|
||||
*/
|
||||
@Initializable
|
||||
public class AbyssalParasiteNPC extends BurdenBeast {
|
||||
|
||||
/**
|
||||
* The special move flag.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private boolean specialMove = false;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code AbyssalParasiteNPC} {@code Object}.
|
||||
*/
|
||||
public AbyssalParasiteNPC() {
|
||||
this(null, 6818);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code AbyssalParasiteNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public AbyssalParasiteNPC(Player owner, int id) {
|
||||
super(owner, id, 3000, 12035, 1, 7);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new AbyssalParasiteNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllowed(Player owner, Item item) {
|
||||
if (item.getId() != 1436 && item.getId() != 7936) {
|
||||
owner.getPacketDispatch().sendMessage("Your familiar can only hold unnoted essence.");
|
||||
return false;
|
||||
}
|
||||
return super.isAllowed(owner, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
final Entity target = special.getTarget();
|
||||
if (!canCombatSpecial(target)) {
|
||||
return false;
|
||||
}
|
||||
faceTemporary(target, 2);
|
||||
sendFamiliarHit(target, 7);
|
||||
visualize(Animation.create(7672), Graphics.create(1422));
|
||||
Projectile.magic(this, target, 1423, 40, 36, 51, 10).send();
|
||||
target.getSkills().decrementPrayerPoints(RandomFunction.random(1, 3));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6818, 6819 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Abyssal Titan familiar.
|
||||
* @author Aero
|
||||
* @author Splinter
|
||||
*/
|
||||
@Initializable
|
||||
public class AbyssalTitanNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code AbyssalTitanNPC} {@code Object}.
|
||||
*/
|
||||
public AbyssalTitanNPC() {
|
||||
this(null, 7349);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code AbyssalTitanNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public AbyssalTitanNPC(Player owner, int id) {
|
||||
super(owner, id, 3200, 12796, 6, WeaponInterface.STYLE_ACCURATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new AbyssalTitanNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
Player player = owner;
|
||||
if (!player.getInventory().containsItem(new Item(1436, 1)) && !player.getInventory().containsItem(new Item(7936, 1))) {
|
||||
player.sendMessage("You have no essence to send to the bank.");
|
||||
return false;
|
||||
}
|
||||
int RUNE_ESSENCE_AMOUNT = player.getInventory().getAmount(1436);
|
||||
int PURE_ESSENCE_AMOUNT = player.getInventory().getAmount(7936);
|
||||
player.getInventory().remove(new Item(1436, RUNE_ESSENCE_AMOUNT), new Item(7936, PURE_ESSENCE_AMOUNT));
|
||||
player.getBank().add(new Item(1436, RUNE_ESSENCE_AMOUNT), new Item(7936, PURE_ESSENCE_AMOUNT));
|
||||
player.sendMessage("The titan sends " + RUNE_ESSENCE_AMOUNT + " rune essence and " + PURE_ESSENCE_AMOUNT + " pure essence to your bank.");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visualizeSpecialMove() {
|
||||
owner.visualize(Animation.create(7660), Graphics.create(1316));
|
||||
this.visualize(Animation.create(7694), Graphics.create(1457));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7349, 7350 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Albino Rat familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class AlbinoRatNPC extends Forager {
|
||||
|
||||
/**
|
||||
* The cheese item.
|
||||
*/
|
||||
private static final Item CHEESE = new Item(1985, 4);
|
||||
|
||||
/**
|
||||
* Constructs a new {@code AlbinoRatNPC} {@code Object}.
|
||||
*/
|
||||
public AlbinoRatNPC() {
|
||||
this(null, 6847);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code AlbinoRatNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public AlbinoRatNPC(Player owner, int id) {
|
||||
super(owner, id, 2200, 12067, 6, WeaponInterface.STYLE_ACCURATE, CHEESE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new AlbinoRatNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
if (produceItem(CHEESE)) {
|
||||
owner.lock(7);
|
||||
visualize(Animation.create(4934), Graphics.create(1384));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6847, 6848 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Arctic Bear familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class ArcticBearNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ArcticBearNPC} {@code Object}.
|
||||
*/
|
||||
public ArcticBearNPC() {
|
||||
this(null, 6839);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ArcticBearNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public ArcticBearNPC(Player owner, int id) {
|
||||
super(owner, id, 2800, 12057, 6, WeaponInterface.STYLE_CONTROLLED);
|
||||
boosts.add(new SkillBonus(Skills.HUNTER, 7));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new ArcticBearNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
Entity target = special.getTarget();
|
||||
if (!canCombatSpecial(target)) {
|
||||
return false;
|
||||
}
|
||||
animate(Animation.create(4926));
|
||||
graphics(Graphics.create(1405));
|
||||
Projectile p = Projectile.magic(this, target, 1406, 40, 40, 1, 10);
|
||||
p.setSpeed(25);
|
||||
p.send();
|
||||
sendFamiliarHit(target, 15, Graphics.create(1407));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6839, 6840 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.dialogue.FacialExpression;
|
||||
import core.game.node.entity.npc.Metamorphosis;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.plugin.Initializable;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Handles the baby chinchompa pet.
|
||||
* @author Empathy
|
||||
*
|
||||
*/
|
||||
@Initializable
|
||||
public class BabyChinchompaNPC extends Metamorphosis {
|
||||
|
||||
/**
|
||||
* The chinchompa ids.
|
||||
*/
|
||||
private static final int[] CHINCHOMPA_IDS = new int[] { 8643, 8644, 8657, 8658 };
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BabyChinchompaNPC} object.
|
||||
*/
|
||||
public BabyChinchompaNPC() {
|
||||
super(CHINCHOMPA_IDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin getDialoguePlugin() {
|
||||
return new BabyChinchompaDialogue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRandomNpcId() {
|
||||
int i = RandomFunction.getRandom(getIds().length - 1);
|
||||
if (getIds()[i] == 8658) {
|
||||
int x = RandomFunction.getRandom(30);
|
||||
if (x == 1) {
|
||||
return getIds()[i];
|
||||
} else {
|
||||
return getIds()[i-1];
|
||||
}
|
||||
}
|
||||
return getIds()[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the BabyChinchompa Dialogue.
|
||||
* @author Empathy
|
||||
*
|
||||
*/
|
||||
public final class BabyChinchompaDialogue extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BabyChinchompaDialogue} {@code Object}.
|
||||
*/
|
||||
public BabyChinchompaDialogue() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BabyChinchompaDialogue} {@code Object}.
|
||||
*
|
||||
* @param player the player.
|
||||
*/
|
||||
public BabyChinchompaDialogue(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new BabyChinchompaDialogue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
npc = (NPC) args[0];
|
||||
interpreter.sendDialogues(npc, FacialExpression.OLD_NORMAL, npc.getId() != 8658 ? "Squeak! Squeak!" : "Squeaka! Squeaka!");
|
||||
stage = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (stage) {
|
||||
case 0:
|
||||
end();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 8643, 8644, 8657, 8658 };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Barker Toad familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class BarkerToadNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BarkerToadNPC} {@code Object}.
|
||||
*/
|
||||
public BarkerToadNPC() {
|
||||
this(null, 6889);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BarkerToadNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public BarkerToadNPC(Player owner, int id) {
|
||||
super(owner, id, 800, 12123, 6, WeaponInterface.STYLE_AGGRESSIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new BarkerToadNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
final Entity target = special.getTarget();
|
||||
if (!canCombatSpecial(target)) {
|
||||
return false;
|
||||
}
|
||||
animate(getProperties().getAttackAnimation());
|
||||
graphics(Graphics.create(1403));
|
||||
sendFamiliarHit(target, 8, Graphics.create(1404));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6889, 6890 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.dialogue.FacialExpression;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Handles the beaver dialgoue.
|
||||
* @author Empathy
|
||||
*
|
||||
*/
|
||||
@Initializable
|
||||
public final class BeaverDialogue extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BeaverDialogue} {@code Object}.
|
||||
*/
|
||||
public BeaverDialogue() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BeaverDialogue} {@code Object}.
|
||||
*
|
||||
* @param player the player.
|
||||
*/
|
||||
public BeaverDialogue(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new BeaverDialogue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
npc = (NPC) args[0];
|
||||
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "How much wood would a woodchuck chuck if a", "woodchuck could chuck wood?");
|
||||
stage = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (stage) {
|
||||
case 0:
|
||||
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Approximately 32,768 depending on his woodcutting", "level.");
|
||||
stage = 1;
|
||||
break;
|
||||
case 1:
|
||||
end();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 8635 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.scenery.Scenery;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Direction;
|
||||
import core.game.world.map.path.Pathfinder;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the Beaver familiar.
|
||||
* @author Vexia
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class BeaverNPC extends Forager {
|
||||
|
||||
/**
|
||||
* The items to foraged.
|
||||
*/
|
||||
private static final Item[] ITEMS = new Item[] { new Item(1511), new Item(2862), new Item(1521), new Item(1519), new Item(6333), new Item(10810), new Item(1517), new Item(6332), new Item(12581), new Item(960), new Item(8778) };
|
||||
|
||||
/**
|
||||
* The tree names the scroll can be casted on.
|
||||
*/
|
||||
private static final String[] TREE_NAMES = new String[] { "Tree", "Oak", "Hollow", "Willow", "Arctic pine", "Eucalyptus", "Maple", "Yew", "Magic", "Cursed magic" };
|
||||
|
||||
/**
|
||||
* If multi chopping.
|
||||
*/
|
||||
private boolean multiChop;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BeaverNPC} {@code Object}.
|
||||
*/
|
||||
public BeaverNPC() {
|
||||
this(null, 6808);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BeaverNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public BeaverNPC(Player owner, int id) {
|
||||
super(owner, id, 2700, 12021, 6, ITEMS);
|
||||
boosts.add(new SkillBonus(Skills.WOODCUTTING, 2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new BeaverNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
final Scenery object = (Scenery) special.getNode();
|
||||
if (!isTree(object.getName())) {
|
||||
owner.getPacketDispatch().sendMessages("This scroll only works on naturally growing, oak, willow, arctic pine", "teak, mahogany, maple, yew, and magic trees.");
|
||||
return false;
|
||||
}
|
||||
if (owner.getInventory().freeSlots() == 0) {
|
||||
return false;
|
||||
}
|
||||
if (object.getLocation().getDistance(getLocation()) > 5) {
|
||||
owner.getPacketDispatch().sendMessages("The beaver is a little too far from the tree for the scroll to work - stand", "closer.");
|
||||
return false;
|
||||
}
|
||||
Direction dir = Direction.getLogicalDirection(getLocation(), object.getLocation());
|
||||
Pathfinder.find(getLocation(), object.getLocation().transform(dir)).walk(this);
|
||||
final int ticks = 2 + (int) Math.floor(owner.getLocation().getDistance(object.getLocation().transform(dir)) * 0.5);
|
||||
owner.lock(ticks);
|
||||
multiChop = true;
|
||||
getPulseManager().clear();
|
||||
GameWorld.getPulser().submit(new Pulse(ticks, owner, this) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
lock(11);
|
||||
owner.lock(11);
|
||||
faceLocation(object.getLocation());
|
||||
animate(Animation.create(7722));
|
||||
GameWorld.getPulser().submit(new Pulse(1, owner, BeaverNPC.this) {
|
||||
int counter;
|
||||
boolean recieved = false;
|
||||
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
switch (++counter) {
|
||||
default:
|
||||
if (counter > 3) {
|
||||
if (RandomFunction.random(12) < 4) {
|
||||
owner.getInventory().add(ITEMS[RandomFunction.random(ITEMS.length)], owner);
|
||||
recieved = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
if (!recieved) {
|
||||
owner.getInventory().add(ITEMS[RandomFunction.random(ITEMS.length)], owner);
|
||||
}
|
||||
multiChop = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startFollowing() {
|
||||
if (multiChop) {
|
||||
return;
|
||||
}
|
||||
super.startFollowing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if its a tree.
|
||||
* @param name the name.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
private boolean isTree(final String name) {
|
||||
for (String s : TREE_NAMES) {
|
||||
if (s.equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6808 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the Bloated Leech familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class BloatedLeechNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BloatedLeechNPC} {@code Object}.
|
||||
*/
|
||||
public BloatedLeechNPC() {
|
||||
this(null, 6843);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BloatedLeechNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public BloatedLeechNPC(Player owner, int id) {
|
||||
super(owner, id, 3400, 12061, 6, WeaponInterface.STYLE_ACCURATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new BloatedLeechNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
owner.getStateManager().remove(EntityState.POISONED);
|
||||
for (int i = 0; i < Skills.SKILL_NAME.length; i++) {
|
||||
if (owner.getSkills().getLevel(i) < owner.getSkills().getStaticLevel(i)) {
|
||||
owner.getSkills().setLevel(i, owner.getSkills().getStaticLevel(i));
|
||||
}
|
||||
}
|
||||
owner.getSkills().rechargePrayerPoints();
|
||||
getImpactHandler().manualHit(owner, RandomFunction.random(2), HitsplatType.NORMAL);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6843, 6844 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Bull Ant familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class BullAntNPC extends BurdenBeast {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BullAntNPC} {@code Object}.
|
||||
*/
|
||||
public BullAntNPC() {
|
||||
this(null, 6867);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BullAntNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public BullAntNPC(Player owner, int id) {
|
||||
super(owner, id, 3000, 12087, 12, 9, WeaponInterface.STYLE_CONTROLLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new BullAntNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
if (owner.getSettings().getRunEnergy() >= 100) {
|
||||
owner.getPacketDispatch().sendMessage("You already have full run energy.");
|
||||
return false;
|
||||
}
|
||||
int amount = owner.getSkills().getStaticLevel(Skills.AGILITY) / 2;
|
||||
visualize(Animation.create(7896), Graphics.create(1382));
|
||||
owner.getSettings().updateRunEnergy(-amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visualizeSpecialMove() {
|
||||
owner.visualize(new Animation(7660), new Graphics(1296));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6867, 6868 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.combat.ImpactHandler;
|
||||
import core.game.consumable.Consumable;
|
||||
import content.data.consumables.Consumables;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.cooking.CookableItems;
|
||||
import content.global.skill.fishing.Fish;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.Initializable;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the Bunyip familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class BunyipNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* The fish.
|
||||
*/
|
||||
private static final int[] FISH = new int[] { 317, 327, 3150, 345, 321, 353, 335, 341, 349, 3379, 331, 5004, 359, 10138, 5001, 377, 363, 371, 2148, 7944, 3142, 383, 395, 389, 401, 405, 407 };
|
||||
|
||||
/**
|
||||
* The time since the last heal.
|
||||
*/
|
||||
private int lastHeal;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BunyipNPC} {@code Object}.
|
||||
*/
|
||||
public BunyipNPC() {
|
||||
this(null, 6813);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BunyipNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public BunyipNPC(Player owner, int id) {
|
||||
super(owner, id, 4400, 12029, 3, WeaponInterface.STYLE_ACCURATE);
|
||||
setLastHeal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new BunyipNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if (lastHeal < GameWorld.getTicks()) {
|
||||
setLastHeal();
|
||||
owner.graphics(Graphics.create(1507), 1);
|
||||
// Since https://runescape.wiki/w/Bunyip?oldid=391088 (2008-04-02)
|
||||
// "The bunyip will automatically heal two hitpoints approximately every 15 seconds up to a player's maximum."
|
||||
// Since https://runescape.wiki/w/Bunyip?oldid=400848 (2008-04-06)
|
||||
// "The healing effect of the Bunyip can restore up to 352 hitpoints over its summoning duration of 44 minutes."
|
||||
// Numbers were multiplied by 10 with the constitution update on 2010-03-10 (https://runescape.wiki/w/Bunyip?oldid=2345672)
|
||||
owner.getSkills().heal(2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPoisonImmune() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the last heal.
|
||||
*/
|
||||
public void setLastHeal() {
|
||||
this.lastHeal = GameWorld.getTicks() + (int) (15 / 0.6);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
Fish fish = Fish.forItem(special.getItem());
|
||||
Player player = owner;
|
||||
if (fish == null) {
|
||||
player.sendMessage("You can't use this special on an object like that.");
|
||||
return false;
|
||||
}
|
||||
Consumable consumable = Consumables.getConsumableById(special.getItem().getId() + 2);
|
||||
if (consumable == null) {
|
||||
player.sendMessage("Error: Report to admin.");
|
||||
return false;
|
||||
}
|
||||
if (player.getSkills().getLevel(Skills.COOKING) < CookableItems.forId(special.getItem().getId()).level) {
|
||||
player.sendMessage("You need a Cooking level of at least " + CookableItems.forId(special.getItem().getId()).level + " in order to do that.");
|
||||
return false;
|
||||
}
|
||||
if (player.getInventory().remove(special.getItem())) {
|
||||
animate(Animation.create(7747));
|
||||
graphics(Graphics.create(1481));
|
||||
final int healthEffectValue = consumable.getHealthEffectValue(player);
|
||||
if (healthEffectValue > 0) {
|
||||
owner.getSkills().heal(consumable.getHealthEffectValue(player));
|
||||
} else {
|
||||
owner.getImpactHandler().manualHit(player, healthEffectValue, ImpactHandler.HitsplatType.NORMAL);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visualizeSpecialMove() {
|
||||
owner.visualize(Animation.create(7660), Graphics.create(1316));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleFamiliarTick() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureFamiliar() {
|
||||
UseWithHandler.addHandler(6813, UseWithHandler.NPC_TYPE, new UseWithHandler(FISH) {
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
addHandler(6814, UseWithHandler.NPC_TYPE, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(NodeUsageEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Fish fish = Fish.forItem(event.getUsedItem());
|
||||
Consumable consumable = Consumables.getConsumableById(fish.getItem().getId() + 2);
|
||||
if (consumable == null) {
|
||||
return true;
|
||||
}
|
||||
player.lock(1);
|
||||
Item runes = new Item(555, RandomFunction.random(1, consumable.getHealthEffectValue(player)));
|
||||
if (player.getInventory().remove(event.getUsedItem())) {
|
||||
player.animate(Animation.create(2779));
|
||||
Projectile.create(player, event.getUsedWith().asNpc(), 1435).send();
|
||||
player.getInventory().add(runes);
|
||||
player.sendMessage("The bunyip transmutes the fish into some water runes.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6813, 6814 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.component.CloseEvent;
|
||||
import core.game.component.Component;
|
||||
import core.game.container.Container;
|
||||
import core.game.container.access.InterfaceContainer;
|
||||
import core.game.system.config.ItemConfigParser;
|
||||
import content.global.skill.summoning.SummoningPouch;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.GroundItem;
|
||||
import core.game.node.item.GroundItemManager;
|
||||
import core.game.node.item.Item;
|
||||
/**
|
||||
* Represents a beast of burden familiar.
|
||||
* @author Emperor
|
||||
*/
|
||||
public abstract class BurdenBeast extends Familiar {
|
||||
|
||||
/**
|
||||
* The container.
|
||||
*/
|
||||
protected Container container;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BurdenBeast} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The NPC id.
|
||||
* @param ticks The amount of ticks.
|
||||
* @param pouchId The pouch id.
|
||||
* @param specialCost The special move cost.
|
||||
* @param containerSize The container size.
|
||||
* @param attackStyle the style.
|
||||
*/
|
||||
public BurdenBeast(Player owner, int id, int ticks, int pouchId, int specialCost, int containerSize, int attackStyle) {
|
||||
super(owner, id, ticks, pouchId, specialCost, attackStyle);
|
||||
this.container = new Container(containerSize).register(new BurdenContainerListener(owner));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BurdenBeast} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The NPC id.
|
||||
* @param ticks The amount of ticks.
|
||||
* @param pouchId The pouch id.
|
||||
* @param specialCost The special move cost.
|
||||
* @param containerSize The container size.
|
||||
*/
|
||||
public BurdenBeast(Player owner, int id, int ticks, int pouchId, int specialCost, int containerSize) {
|
||||
this(owner, id, ticks, pouchId, specialCost, containerSize, WeaponInterface.STYLE_DEFENSIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismiss() {
|
||||
if (owner.getInterfaceManager().hasMainComponent(671)) {
|
||||
owner.getInterfaceManager().close();
|
||||
}
|
||||
|
||||
for (Item item : container.toArray()) {
|
||||
if (item != null) {
|
||||
GroundItemManager.create(new GroundItem(item, location, 500, owner));
|
||||
}
|
||||
}
|
||||
|
||||
container.clear();
|
||||
super.dismiss();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBurdenBeast() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPoisonImmune() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the item is allowed to be stored.
|
||||
* @param owner The owner.
|
||||
* @param item The item to store.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean isAllowed(Player owner, Item item) {
|
||||
if (item.getValue() > 50000) {
|
||||
owner.getPacketDispatch().sendMessage("This item is too valuable to trust to this familiar.");
|
||||
return false;
|
||||
}
|
||||
if (!item.getDefinition().isTradeable()) {
|
||||
owner.getPacketDispatch().sendMessage("You can't trade this item, not even to your familiar.");
|
||||
return false;
|
||||
}
|
||||
if ((!SummoningPouch.get(getPouchId()).abyssal && (item.getId() == 1436 || item.getId() == 7936))|| !item.getDefinition().getConfiguration(ItemConfigParser.BANKABLE, true)) {
|
||||
owner.getPacketDispatch().sendMessage("You can't store " + item.getName().toLowerCase() + " in this familiar.");
|
||||
return false;
|
||||
}
|
||||
if(SummoningPouch.get(this.getPouchId()).abyssal){
|
||||
if(!item.getName().toLowerCase().contains("essence")) {
|
||||
owner.getPacketDispatch().sendMessage("You can only give unnoted essence to this familiar.");
|
||||
return false;
|
||||
}
|
||||
if(item.getId() == 1437 || item.getId() == 7937) {
|
||||
owner.getPacketDispatch().sendMessage("You can't give noted essence to this familiar.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers an item.
|
||||
* @param item The item to store.
|
||||
* @param amount The amount to store.
|
||||
* @param withdraw If the player is withdrawing.
|
||||
*/
|
||||
public void transfer(Item item, int amount, boolean withdraw) {
|
||||
if (this instanceof Forager && !withdraw) {
|
||||
owner.getPacketDispatch().sendMessage("You can't store your items in this familiar.");
|
||||
return;
|
||||
}
|
||||
if (item == null || owner == null) {
|
||||
return;
|
||||
}
|
||||
if (!withdraw && !isAllowed(owner, new Item(item.getId(), item.getDefinition().isStackable() ? amount : 1))) {
|
||||
return;
|
||||
}
|
||||
Container to = withdraw ? owner.getInventory() : container;
|
||||
Container from = withdraw ? container : owner.getInventory();
|
||||
int fromAmount = from.getAmount(item);
|
||||
if (amount > fromAmount) {
|
||||
amount = fromAmount;
|
||||
}
|
||||
int maximum = to.getMaximumAdd(item);
|
||||
if (amount > maximum) {
|
||||
amount = maximum;
|
||||
}
|
||||
if (amount < 1) {
|
||||
if (withdraw) {
|
||||
owner.getPacketDispatch().sendMessage("Not enough space in your inventory.");
|
||||
} else {
|
||||
owner.getPacketDispatch().sendMessage("Your familiar can't carry any more items.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!item.getDefinition().isStackable() && item.getSlot() > -1) {
|
||||
from.replace(null, item.getSlot());
|
||||
to.add(new Item(item.getId(), 1));
|
||||
amount--;
|
||||
}
|
||||
if (amount > 0) {
|
||||
item = new Item(item.getId(), amount);
|
||||
if (from.remove(item)) {
|
||||
to.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Withdraws the full container.
|
||||
*/
|
||||
public void withdrawAll() {
|
||||
for (int i = 0; i < container.capacity(); i++) {
|
||||
Item item = container.get(i);
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
int amount = owner.getInventory().getMaximumAdd(item);
|
||||
if (item.getAmount() > amount) {
|
||||
item = new Item(item.getId(), amount);
|
||||
container.remove(item, false);
|
||||
owner.getInventory().add(item, false);
|
||||
} else {
|
||||
container.replace(null, i, false);
|
||||
owner.getInventory().add(item, false);
|
||||
}
|
||||
}
|
||||
container.update();
|
||||
owner.getInventory().update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the beast of burden interface.
|
||||
*/
|
||||
public void openInterface() {
|
||||
if (getContainer().itemCount() == 0 && this instanceof Forager) {
|
||||
owner.getPacketDispatch().sendMessage("Your familiar is not carrying any items that you can withdraw.");
|
||||
return;
|
||||
}
|
||||
owner.getInterfaceManager().open(new Component(671)).setCloseEvent(new CloseEvent() {
|
||||
@Override
|
||||
public boolean close(Player player, Component c) {
|
||||
player.getInterfaceManager().closeSingleTab();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
container.shift();
|
||||
owner.getInterfaceManager().openSingleTab(new Component(665));
|
||||
InterfaceContainer.generateItems(owner, owner.getInventory().toArray(), new String[] { "Examine", "Store-X", "Store-All", "Store-10", "Store-5", "Store-1" }, 665, 0, 7, 4, 93);
|
||||
InterfaceContainer.generateItems(owner, container.toArray(), new String[] { "Examine", "Withdraw-X", "Withdraw-All", "Withdraw-10", "Withdraw-5", "Withdraw-1" }, 671, 27, 5, 6, 30);
|
||||
container.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item container.
|
||||
* @return The container.
|
||||
*/
|
||||
public Container getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.container.Container;
|
||||
import core.game.container.ContainerEvent;
|
||||
import core.game.container.ContainerListener;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.PacketRepository;
|
||||
import core.net.packet.context.ContainerContext;
|
||||
import core.net.packet.out.ContainerPacket;
|
||||
|
||||
/**
|
||||
* The beast of burden container listener.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class BurdenContainerListener implements ContainerListener {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BurdenContainerListener} {@code Object}.
|
||||
* @param player The player.
|
||||
*/
|
||||
public BurdenContainerListener(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Container c, ContainerEvent event) {
|
||||
PacketRepository.send(ContainerPacket.class, new ContainerContext(player, -1, -2, 30, event.getItems(), false, event.getSlots()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(Container c) {
|
||||
PacketRepository.send(ContainerPacket.class, new ContainerContext(player, -1, -2, 30, c.toArray(), c.capacity(), false));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import static core.api.ContentAPIKt.*;
|
||||
import core.game.component.Component;
|
||||
import core.game.component.ComponentDefinition;
|
||||
import core.game.component.ComponentPlugin;
|
||||
import core.game.container.Container;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import kotlin.Unit;
|
||||
|
||||
/**
|
||||
* Handles the beast of burden interface.
|
||||
* @author Emperor
|
||||
*/
|
||||
@Initializable
|
||||
public final class BurdenInterfacePlugin extends ComponentPlugin {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ComponentDefinition.put(665, this);
|
||||
ComponentDefinition.put(671, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
|
||||
if (!player.getFamiliarManager().hasFamiliar() || !player.getFamiliarManager().getFamiliar().isBurdenBeast()) {
|
||||
return false;
|
||||
}
|
||||
final BurdenBeast beast = (BurdenBeast) player.getFamiliarManager().getFamiliar();
|
||||
final boolean withdraw = component.getId() == 671;
|
||||
final Container container = withdraw ? beast.getContainer() : player.getInventory();
|
||||
final Item item = slot >= 0 && slot < container.capacity() ? container.get(slot) : null;
|
||||
if (item == null && button != 29) {
|
||||
return true;
|
||||
}
|
||||
switch (opcode) {
|
||||
case 155:
|
||||
if (button == 29) {
|
||||
beast.withdrawAll();
|
||||
return true;
|
||||
}
|
||||
beast.transfer(item, 1, withdraw);
|
||||
return true;
|
||||
case 196:
|
||||
beast.transfer(item, 5, withdraw);
|
||||
return true;
|
||||
case 124:
|
||||
beast.transfer(item, 10, withdraw);
|
||||
return true;
|
||||
case 199:
|
||||
beast.transfer(item, container.getAmount(item), withdraw);
|
||||
return true;
|
||||
case 234:
|
||||
sendInputDialogue(player, true, "Enter the amount:", (value) -> {
|
||||
beast.transfer(item, (int) value, withdraw);
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
break;
|
||||
case 168:
|
||||
player.getPacketDispatch().sendMessage(item.getDefinition().getExamine());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.ClassScanner;
|
||||
|
||||
/**
|
||||
* Handles the loading of a cockatrice familiar.
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public final class CockatriceFamiliarNPC implements Plugin<Object> {
|
||||
|
||||
/**
|
||||
* The cockatrice egg.
|
||||
*/
|
||||
private static final Item COCKATRICE_EGG = new Item(12109);
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ClassScanner.definePlugin(new SpiritCockatrice());
|
||||
ClassScanner.definePlugin(new SpiritGuthatrice());
|
||||
ClassScanner.definePlugin(new SpiritZamatrice());
|
||||
ClassScanner.definePlugin(new SpiritPengatrice());
|
||||
ClassScanner.definePlugin(new SpiritCoraxatrice());
|
||||
ClassScanner.definePlugin(new SpiritVulatrice());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fireEvent(String identifier, Object... args) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a petrified gaze.
|
||||
* @param familiar the familiar.
|
||||
* @param special the special.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean petrifyingGaze(final Familiar familiar, final FamiliarSpecial special, final int skill) {
|
||||
final Entity target = special.getTarget();
|
||||
if (!familiar.canCombatSpecial(target)) {
|
||||
return false;
|
||||
}
|
||||
familiar.faceTemporary(target, 2);
|
||||
familiar.visualize(Animation.create(7762), Graphics.create(1467));
|
||||
GameWorld.getPulser().submit(new Pulse(1, familiar.getOwner(), familiar, target) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
target.getSkills().updateLevel(skill, -3, 0);
|
||||
Projectile.magic(familiar, target, 1468, 40, 36, 71, 10).send();
|
||||
familiar.sendFamiliarHit(target, 10, Graphics.create(1469));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the spirit cockatrice.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class SpiritCockatrice extends Forager {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritCockatrice} {@code Object}.
|
||||
*/
|
||||
public SpiritCockatrice() {
|
||||
this(null, 6875);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritCockatrice} {@code Object}.
|
||||
* @param owner the owner.
|
||||
* @param id the id.
|
||||
*/
|
||||
public SpiritCockatrice(Player owner, int id) {
|
||||
super(owner, id, 3600, 12095, 3, WeaponInterface.STYLE_CAST, COCKATRICE_EGG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritCockatrice(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return petrifyingGaze(this, special, Skills.DEFENCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6875, 6876 };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the spirit guthatrice.
|
||||
* @author Vexia
|
||||
*/
|
||||
public class SpiritGuthatrice extends Forager {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritGuthatrice} {@code Object}.
|
||||
*/
|
||||
public SpiritGuthatrice() {
|
||||
this(null, 6877);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritGuthatrice} {@code Object}.
|
||||
* @param owner the owner.
|
||||
* @param id the id.
|
||||
*/
|
||||
public SpiritGuthatrice(Player owner, int id) {
|
||||
super(owner, id, 3600, 12097, 3, WeaponInterface.STYLE_CAST, COCKATRICE_EGG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritGuthatrice(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return petrifyingGaze(this, special, Skills.ATTACK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6877, 6878 };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the spirit zamatrice.
|
||||
* @author Vexia
|
||||
*/
|
||||
public class SpiritZamatrice extends Forager {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritZamatrice} {@code Object}.
|
||||
*/
|
||||
public SpiritZamatrice() {
|
||||
this(null, 6881);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritZamatrice} {@code Object}.
|
||||
* @param owner the owner.
|
||||
* @param id the id.
|
||||
*/
|
||||
public SpiritZamatrice(Player owner, int id) {
|
||||
super(owner, id, 3600, 12101, 3, WeaponInterface.STYLE_CAST, COCKATRICE_EGG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritZamatrice(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return petrifyingGaze(this, special, Skills.STRENGTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6881, 6882 };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the spirit pengatrice.
|
||||
* @author Vexia
|
||||
*/
|
||||
public class SpiritPengatrice extends Forager {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritPengatrice} {@code Object}.
|
||||
*/
|
||||
public SpiritPengatrice() {
|
||||
this(null, 6883);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritPengatrice} {@code Object}.
|
||||
* @param owner the owner.
|
||||
* @param id the id.
|
||||
*/
|
||||
public SpiritPengatrice(Player owner, int id) {
|
||||
super(owner, id, 3600, 12103, 3, WeaponInterface.STYLE_CAST, COCKATRICE_EGG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritPengatrice(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return petrifyingGaze(this, special, Skills.MAGIC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6883, 6884 };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the Spirit Coraxatrice familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
public class SpiritCoraxatrice extends Forager {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritCoraxatriceNPC} {@code Object}.
|
||||
*/
|
||||
public SpiritCoraxatrice() {
|
||||
this(null, 6885);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritCoraxatriceNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SpiritCoraxatrice(Player owner, int id) {
|
||||
super(owner, id, 3600, 12105, 3, WeaponInterface.STYLE_CAST, COCKATRICE_EGG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritCoraxatrice(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return petrifyingGaze(this, special, Skills.SUMMONING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6885, 6886 };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the Spirit Vulatrice familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
public class SpiritVulatrice extends Forager {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritVulatriceNPC} {@code Object}.
|
||||
*/
|
||||
public SpiritVulatrice() {
|
||||
this(null, 6887);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritVulatriceNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SpiritVulatrice(Player owner, int id) {
|
||||
super(owner, id, 3600, 12107, 3, WeaponInterface.STYLE_CAST, COCKATRICE_EGG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritVulatrice(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return petrifyingGaze(this, special, Skills.RANGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6887, 6888 };
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import content.global.skill.farming.CompostBin;
|
||||
import content.global.skill.farming.CompostBins;
|
||||
import core.game.dialogue.DialogueInterpreter;
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.scenery.Scenery;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import core.tools.RandomFunction;
|
||||
import org.rs09.consts.Items;
|
||||
import core.plugin.ClassScanner;
|
||||
|
||||
/**
|
||||
* Represents the Compost Mound familiar.
|
||||
* @author Vexia
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class CompostMoundNPC extends Forager {
|
||||
|
||||
/**
|
||||
* The product items.
|
||||
*/
|
||||
private static final Item[] ITEMS = new Item[] { new Item(6032), new Item(6034), new Item(5318), new Item(5319), new Item(5324), new Item(5322), new Item(5320), new Item(5323), new Item(5321), new Item(5305), new Item(5307), new Item(5308), new Item(5306), new Item(5309), new Item(5310), new Item(5311), new Item(5101), new Item(5102), new Item(5103), new Item(5104), new Item(5105), new Item(5106), new Item(5096), new Item(5097), new Item(5098), new Item(5099), new Item(5100), new Item(5291), new Item(5292), new Item(5293), new Item(5294), new Item(5295), new Item(12176), new Item(5296), new Item(5298), new Item(5299), new Item(5300), new Item(5301), new Item(5302), new Item(5303), new Item(5304) };
|
||||
|
||||
/**
|
||||
* Constructs a new {@code CompostMoundNPC} {@code Object}.
|
||||
*/
|
||||
public CompostMoundNPC() {
|
||||
this(null, 6871);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code CompostMoundNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public CompostMoundNPC(Player owner, int id) {
|
||||
super(owner, id, 2400, 12091, 12, WeaponInterface.STYLE_AGGRESSIVE, ITEMS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new CompostMoundNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureFamiliar() {
|
||||
ClassScanner.definePlugin(new CompostBucketPlugin());
|
||||
if (!DialogueInterpreter.contains(getIds()[1])) {
|
||||
ClassScanner.definePlugin(new CompostMoundDialogue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPoisonImmune() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
final Scenery object = (Scenery) special.getNode();
|
||||
if (!object.getName().equals("Compost Bin")) {
|
||||
owner.getPacketDispatch().sendMessage("This scroll can only be used on an empty compost bin.");
|
||||
return false;
|
||||
}
|
||||
CompostBins cbin = CompostBins.forObject(special.getNode().asScenery());
|
||||
if(cbin == null){
|
||||
return false;
|
||||
}
|
||||
CompostBin bin = cbin.getBinForPlayer(owner);
|
||||
if(bin.isFinished() || bin.isFull() || bin.isClosed()){
|
||||
return false;
|
||||
}
|
||||
final boolean superCompost = RandomFunction.random(10) == 1;
|
||||
faceLocation(object.getLocation());
|
||||
Item toAdd = new Item(superCompost ? Items.PINEAPPLE_2114 : Items.POTATO_1942);
|
||||
toAdd.setAmount(15);
|
||||
bin.addItem(toAdd);
|
||||
bin.close();
|
||||
animate(Animation.create(7775));
|
||||
graphics(Graphics.create(1424));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6871, 6872 };
|
||||
}
|
||||
|
||||
/**
|
||||
* The compost bucket plugin.
|
||||
* @author Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
public class CompostBucketPlugin extends UseWithHandler {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code CompostBucketPlugin} {@code Object}.
|
||||
*/
|
||||
public CompostBucketPlugin() {
|
||||
super(1925);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
addHandler(6871, NPC_TYPE, this);
|
||||
addHandler(6872, NPC_TYPE, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(NodeUsageEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final Familiar familiar = (Familiar) event.getUsedWith();
|
||||
if (!player.getFamiliarManager().isOwner(familiar)) {
|
||||
return true;
|
||||
}
|
||||
player.animate(Animation.create(895));
|
||||
familiar.animate(Animation.create(7775));
|
||||
player.getInventory().replace(ITEMS[0], event.getUsedItem().getSlot());
|
||||
familiar.getImpactHandler().manualHit(player, 2, HitsplatType.NORMAL);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The compost dialogue.
|
||||
* @author Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
public class CompostMoundDialogue extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code CompostDialogue} {@code Object}.
|
||||
*/
|
||||
public CompostMoundDialogue() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code CompostDialogue} {@code Object}.
|
||||
* @param player the player.
|
||||
*/
|
||||
public CompostMoundDialogue(final Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new CompostMoundDialogue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
options("Chat", "Withdraw", "Farming boost");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (stage) {
|
||||
case 0:
|
||||
switch (buttonId) {
|
||||
case 1:
|
||||
npc("Schlorp, splort, splort, splutter shclorp?", "(What we be doin' 'ere, zur?)");
|
||||
stage = 10;
|
||||
break;
|
||||
case 2:
|
||||
end();
|
||||
Forager forager = (Forager) player.getFamiliarManager().getFamiliar();
|
||||
forager.openInterface();
|
||||
break;
|
||||
case 3:
|
||||
player("Can you boost my Farming stat, please?");
|
||||
stage = 30;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
player("Oh, I have a few things to take care of here, is all.");
|
||||
stage++;
|
||||
break;
|
||||
case 11:
|
||||
npc("Schorp, splutter, splutter. Schlup schorp.", "(Aye, right ye are, zur. Oi'll be roight there.)");
|
||||
stage++;
|
||||
break;
|
||||
case 12:
|
||||
end();
|
||||
break;
|
||||
case 30:
|
||||
npc("Schlup glorp sputter!", "(Oi do believe oi can!)");
|
||||
stage++;
|
||||
break;
|
||||
case 31:
|
||||
if (player.getSkills().getLevel(Skills.FARMING) > player.getSkills().getStaticLevel(Skills.FARMING)) {
|
||||
end();
|
||||
player.getPacketDispatch().sendMessage("Your stat cannot be boosted this way right now.");
|
||||
return true;
|
||||
}
|
||||
player.getSkills().updateLevel(Skills.FARMING, (int) (1 + (player.getSkills().getStaticLevel(Skills.FARMING) * 0.02)));
|
||||
player.getPacketDispatch().sendMessage("The Compost mound has boosted your Farming stat.");
|
||||
end();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return CompostMoundNPC.this.getIds();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import core.cache.def.impl.NPCDefinition;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.gather.SkillingResource;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.GroundItemManager;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.scenery.Scenery;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Direction;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.ClassScanner;
|
||||
|
||||
/**
|
||||
* Represents the Desert Wyrm familiar.
|
||||
* @author Vexia
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public final class DesertWyrmNPC extends Forager {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code DesertWyrmNPC} {@code Object}.
|
||||
*/
|
||||
public DesertWyrmNPC() {
|
||||
this(null, 6831);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code DesertWyrmNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public DesertWyrmNPC(Player owner, int id) {
|
||||
super(owner, id, 1900, 12049, 6, WeaponInterface.STYLE_AGGRESSIVE);
|
||||
boosts.add(new SkillBonus(Skills.MINING, 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new DesertWyrmNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
final Entity target = (Entity) special.getNode();
|
||||
if (!canCombatSpecial(target)) {
|
||||
return false;
|
||||
}
|
||||
faceTemporary((Entity) special.getNode(), 2);
|
||||
visualize(new Animation(7795), new Graphics(1410));
|
||||
Projectile.magic(this, target, 1411, 40, 36, 51, 10).send();
|
||||
sendFamiliarHit(target, 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureFamiliar() {
|
||||
ClassScanner.definePlugin(new OptionHandler() {
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
for (int i : getIds()) {
|
||||
NPCDefinition.forId(i).getHandlers().put("option:burrow", this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(final Player player, final Node node, String option) {
|
||||
final Scenery rock = getClosestRock(player);
|
||||
if (!player.getFamiliarManager().isOwner((Familiar) node)) {
|
||||
return true;
|
||||
}
|
||||
if (((NPC) node).getLocks().isMovementLocked()) {
|
||||
return true;
|
||||
}
|
||||
if (rock == null) {
|
||||
player.getPacketDispatch().sendMessage("There are no rocks around here for the desert wyrm to mine from!");
|
||||
return true;
|
||||
}
|
||||
final SkillingResource resource = SkillingResource.forId(rock.getId());
|
||||
if (resource == null) {
|
||||
player.getPacketDispatch().sendMessage("There are no rocks around here for the desert wyrm to mine from!");
|
||||
return true;
|
||||
}
|
||||
final Familiar familiar = (Familiar) node;
|
||||
player.lock(9);
|
||||
familiar.lock(8);
|
||||
familiar.visualize(new Animation(7800), new Graphics(1412));
|
||||
GameWorld.getPulser().submit(new Pulse(1, player, familiar) {
|
||||
int counter;
|
||||
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
switch (++counter) {
|
||||
case 4:
|
||||
familiar.setInvisible(true);
|
||||
break;
|
||||
case 8:
|
||||
familiar.call();
|
||||
GroundItemManager.create(new Item(resource.getReward()), familiar.getLocation(), player);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the closest combat rock.
|
||||
* @return the object.
|
||||
*/
|
||||
public Scenery getClosestRock(Player player) {
|
||||
List<Scenery> rocks = new ArrayList<>(20);
|
||||
for (int k = 0; k < 7; k++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Direction dir = Direction.get(i);
|
||||
Location loc = player.getLocation().transform(dir.getStepX() * k, dir.getStepY() * k, 0);
|
||||
Scenery object = RegionManager.getObject(loc);
|
||||
if (object != null && object.getName().equals("Rocks")) {
|
||||
rocks.add(object);
|
||||
}
|
||||
}
|
||||
}
|
||||
int ordinal = 0;
|
||||
Scenery o = null;
|
||||
for (Scenery r : rocks) {
|
||||
SkillingResource resource = SkillingResource.forId(r.getId());
|
||||
if (resource != null && resource.ordinal() > ordinal) {
|
||||
ordinal = resource.ordinal();
|
||||
o = r;
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6831, 6832 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.dialogue.DialogueInterpreter;
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.plugin.Initializable;
|
||||
import content.global.skill.summoning.pet.Pet;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents the dialogue plugin used to dismiss a follower.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class DismissDialoguePlugin extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code DismissDialoguePlugin} {@code Object}.
|
||||
*/
|
||||
public DismissDialoguePlugin() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code DismissDialoguePlugin} {@code Object}.
|
||||
* @param player the player.
|
||||
*/
|
||||
public DismissDialoguePlugin(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new DismissDialoguePlugin(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
if (player.getFamiliarManager().getFamiliar() instanceof Pet) {
|
||||
interpreter.sendOptions("Free pet", "Yes", "No");
|
||||
} else {
|
||||
interpreter.sendOptions("Dismiss Familiar", "Yes", "No");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (stage) {
|
||||
case 0:
|
||||
switch (buttonId) {
|
||||
case 1:
|
||||
if (player.getFamiliarManager().getFamiliar() instanceof Pet) {
|
||||
interpreter.sendDialogues(player, null, "Run along; I'm setting you free.");
|
||||
} else {
|
||||
end();
|
||||
}
|
||||
player.getFamiliarManager().dismiss(false);
|
||||
stage = 1;
|
||||
break;
|
||||
case 2:
|
||||
end();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
end();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { DialogueInterpreter.getDialogueKey("dismiss_dial") };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.BattleState;
|
||||
import core.game.node.entity.combat.CombatStyle;
|
||||
import core.game.node.entity.combat.CombatSwingHandler;
|
||||
import core.game.node.entity.combat.InteractionType;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.combat.MeleeSwingHandler;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.impl.Animator.Priority;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the dreadfowl familiar.
|
||||
* @author Emperor
|
||||
*/
|
||||
@Initializable
|
||||
public final class DreadfowlNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* If the special move is toggled.
|
||||
*/
|
||||
private boolean specialMove;
|
||||
|
||||
/**
|
||||
* The combat handler.
|
||||
*/
|
||||
private static final CombatSwingHandler COMBAT_HANDLER = new MeleeSwingHandler() {
|
||||
|
||||
@Override
|
||||
public InteractionType canSwing(Entity entity, Entity victim) {
|
||||
if (((DreadfowlNPC) entity).specialMove) {
|
||||
return CombatStyle.MAGIC.getSwingHandler().canSwing(entity, victim);
|
||||
}
|
||||
return super.canSwing(entity, victim);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int swing(Entity entity, Entity victim, BattleState state) {
|
||||
DreadfowlNPC npc = (DreadfowlNPC) entity;
|
||||
if (npc.specialMove) {
|
||||
npc.specialMove(new FamiliarSpecial(victim));
|
||||
npc.specialMove = false;
|
||||
return -1;
|
||||
}
|
||||
npc.specialMove = RandomFunction.randomize(10) == 0;
|
||||
return super.swing(entity, victim, state);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs a new {@code DreadfowlNPC} {@code Object}.
|
||||
*/
|
||||
public DreadfowlNPC() {
|
||||
this(null, 6825);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code DreadfowlNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The NPC id.
|
||||
*/
|
||||
public DreadfowlNPC(Player owner, int id) {
|
||||
super(owner, id, 400, 12043, 3, WeaponInterface.STYLE_CAST);
|
||||
super.setCombatHandler(COMBAT_HANDLER);
|
||||
boosts.add(new SkillBonus(Skills.FARMING, 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new DreadfowlNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
final Entity target = (Entity) special.getNode();
|
||||
if (!canAttack(target)) {
|
||||
return false;
|
||||
}
|
||||
if (!owner.getProperties().getCombatPulse().isAttacking() && !owner.inCombat()) {
|
||||
owner.getPacketDispatch().sendMessage("Your familiar can only attack when you're in combat.");
|
||||
return false;
|
||||
}
|
||||
if (getProperties().getCombatPulse().getNextAttack() > GameWorld.getTicks() || CombatStyle.MAGIC.getSwingHandler().canSwing(this, target) == InteractionType.NO_INTERACT) {
|
||||
specialMove = true;
|
||||
getProperties().getCombatPulse().attack(target);
|
||||
return true;
|
||||
}
|
||||
visualize(new Animation(5387, Priority.HIGH), Graphics.create(1523));
|
||||
Projectile.magic(this, target, 1318, 40, 36, 51, 10).send();
|
||||
int ticks = 2 + (int) Math.floor(getLocation().getDistance(target.getLocation()) * 0.5);
|
||||
getProperties().getCombatPulse().setNextAttack(4);
|
||||
GameWorld.getPulser().submit(new Pulse(ticks, this, target) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
BattleState state = new BattleState(DreadfowlNPC.this, target);
|
||||
int hit = 0;
|
||||
if (CombatStyle.MAGIC.getSwingHandler().isAccurateImpact(DreadfowlNPC.this, target)) {
|
||||
hit = RandomFunction.randomize(3);
|
||||
}
|
||||
state.setEstimatedHit(hit);
|
||||
target.getImpactHandler().handleImpact(owner, hit, CombatStyle.MAGIC, state);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6825, 6826 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.summoning.familiar.Familiar;
|
||||
import content.global.skill.summoning.familiar.FamiliarSpecial;
|
||||
|
||||
public abstract class ElementalTitanNPC extends Familiar {
|
||||
|
||||
private static final int scrollHealAmount = 8;
|
||||
private static final double scrollDefenceBoostPercent = 0.125;
|
||||
|
||||
public ElementalTitanNPC(Player owner, int id, int ticks, int pouchId, int specialCost, int attackStyle) {
|
||||
super(owner, id, ticks, pouchId, specialCost, attackStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
raises defence by 12.5% and heals 8 hp (with ability to over heal)
|
||||
*/
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
int currentDefenceLevel = owner.getSkills().getLevel(Skills.DEFENCE);
|
||||
int maximumDefenceLevel = owner.getSkills().getStaticLevel(Skills.DEFENCE);
|
||||
owner.getSkills().updateLevel(Skills.DEFENCE,
|
||||
(int)((1.0 + scrollDefenceBoostPercent) * currentDefenceLevel),
|
||||
(int)((1.0 + scrollDefenceBoostPercent) * maximumDefenceLevel));
|
||||
int currentHp = owner.getSkills().getLifepoints();
|
||||
int maxHp = owner.getSkills().getMaximumLifepoints() + scrollHealAmount;
|
||||
int healAmount = Math.min(maxHp - currentHp, scrollHealAmount);
|
||||
if (healAmount> 0) {
|
||||
owner.getSkills().healNoRestrictions(healAmount);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
owner.sendMessage("You are already at maximum hitpoints!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Evil Turnip familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class EvilTurnipNPC extends Forager {
|
||||
|
||||
/**
|
||||
* The evil turnip item.
|
||||
*/
|
||||
private static final Item EVIL_TURNIP = new Item(12136);
|
||||
|
||||
/**
|
||||
* Constructs a new {@code EvilTurnipNPC} {@code Object}.
|
||||
*/
|
||||
public EvilTurnipNPC() {
|
||||
this(null, 6833);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code EvilTurnipNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public EvilTurnipNPC(Player owner, int id) {
|
||||
super(owner, id, 3000, 12051, 6, WeaponInterface.STYLE_RANGE_ACCURATE, EVIL_TURNIP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new EvilTurnipNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
final Entity target = (Entity) special.getNode();
|
||||
if (!canCombatSpecial(target)) {
|
||||
return false;
|
||||
}
|
||||
int ticks = 2 + (int) Math.floor(getLocation().getDistance(target.getLocation()) * 0.5);
|
||||
getSkills().heal(2);
|
||||
faceTemporary(target, 2);
|
||||
sendFamiliarHit(target, 10);
|
||||
animate(Animation.create(8251));
|
||||
target.graphics(Graphics.create(1329), ticks);
|
||||
target.getSkills().updateLevel(Skills.MAGIC, -1, 0);
|
||||
Projectile.magic(this, target, 1330, 40, 36, 51, 10).send();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRandom() {
|
||||
return 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6833, 6834 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,772 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import content.global.skill.summoning.SummoningScroll;
|
||||
import content.global.skill.summoning.pet.Pet;
|
||||
import core.cache.def.impl.NPCDefinition;
|
||||
import core.game.interaction.MovementPulse;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.BattleState;
|
||||
import core.game.node.entity.combat.CombatStyle;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.impl.PulseType;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.map.path.Pathfinder;
|
||||
import core.game.world.map.zone.ZoneRestriction;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Plugin;
|
||||
import core.tools.RandomFunction;
|
||||
import core.game.node.entity.combat.CombatPulse;
|
||||
import core.game.node.entity.combat.CombatSwingHandler;
|
||||
import core.tools.SystemLogger;
|
||||
import core.game.world.GameWorld;
|
||||
import content.global.skill.summoning.SummoningPouch;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a familiar.
|
||||
* @author Emperor
|
||||
*/
|
||||
public abstract class Familiar extends NPC implements Plugin<Object> {
|
||||
|
||||
/**
|
||||
* The summon graphics for a small familiar.
|
||||
*/
|
||||
protected static final Graphics SMALL_SUMMON_GRAPHIC = Graphics.create(1314);
|
||||
|
||||
/**
|
||||
* The spawn graphics for a large familiar.
|
||||
*/
|
||||
protected static final Graphics LARGE_SUMMON_GRAPHIC = Graphics.create(1315);
|
||||
|
||||
/**
|
||||
* The special animation.
|
||||
*/
|
||||
protected static final Animation SPECIAL_ANIMATION = Animation.create(7660);
|
||||
|
||||
/**
|
||||
* The special graphic.
|
||||
*/
|
||||
protected static final Graphics SPECIAL_GRAPHIC = Graphics.create(1316);
|
||||
|
||||
/**
|
||||
* The owner.
|
||||
*/
|
||||
protected Player owner;
|
||||
|
||||
/**
|
||||
* The amount of ticks left.
|
||||
*/
|
||||
protected int ticks;
|
||||
|
||||
/**
|
||||
* The initial amount of ticks.
|
||||
*/
|
||||
protected int maximumTicks;
|
||||
|
||||
/**
|
||||
* The amount of special points left.
|
||||
*/
|
||||
protected int specialPoints = 60;
|
||||
|
||||
/**
|
||||
* The pouch id.
|
||||
*/
|
||||
private final int pouchId;
|
||||
|
||||
/**
|
||||
* The special move cost.
|
||||
*/
|
||||
private final int specialCost;
|
||||
|
||||
private final SummoningPouch pouch;
|
||||
|
||||
/**
|
||||
* The combat reward.
|
||||
*/
|
||||
private CombatSwingHandler combatHandler;
|
||||
|
||||
/**
|
||||
* If the familiar is a combat familiar.
|
||||
*/
|
||||
protected boolean combatFamiliar;
|
||||
|
||||
/**
|
||||
* If the familiars special is charged.
|
||||
*/
|
||||
protected boolean charged;
|
||||
|
||||
/**
|
||||
* The invisible familiar boosts.
|
||||
*/
|
||||
protected List<SkillBonus> boosts = new ArrayList<>(20);
|
||||
|
||||
/**
|
||||
* The attack style.
|
||||
*/
|
||||
private final int attackStyle;
|
||||
|
||||
private boolean firstCall = true;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Familiar} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The NPC id.
|
||||
* @param ticks The ticks left.
|
||||
* @param pouchId The pouch.
|
||||
* @param specialCost The special move cost.
|
||||
* @param attackStyle the style.
|
||||
*/
|
||||
public Familiar(Player owner, int id, int ticks, int pouchId, int specialCost, final int attackStyle) {
|
||||
super(id, null);
|
||||
this.owner = owner;
|
||||
this.maximumTicks = ticks;
|
||||
this.ticks = ticks;
|
||||
this.pouchId = pouchId;
|
||||
this.pouch = SummoningPouch.get(pouchId);
|
||||
this.specialCost = specialCost;
|
||||
this.combatFamiliar = NPCDefinition.forId(getOriginalId() + 1).getName().equals(getName());
|
||||
this.attackStyle = attackStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Familiar} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The NPC id.
|
||||
* @param ticks The ticks left.
|
||||
* @param pouchId The pouch.
|
||||
* @param specialCost The special move cost.
|
||||
*/
|
||||
public Familiar(Player owner, int id, int ticks, int pouchId, int specialCost) {
|
||||
this(owner, id, ticks, pouchId, specialCost, WeaponInterface.STYLE_DEFENSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the familiar.
|
||||
* @param loc The location.
|
||||
*/
|
||||
public void init(Location loc, boolean call) {
|
||||
location = loc;
|
||||
if (location == null) {
|
||||
location = owner.getLocation();
|
||||
setInvisible(true);
|
||||
}
|
||||
super.init();
|
||||
startFollowing();
|
||||
sendConfiguration();
|
||||
if (call) {
|
||||
call();
|
||||
}
|
||||
owner.getInterfaceManager().openInfoBars();
|
||||
if (getZoneMonitor().isInZone("Wilderness")) {
|
||||
transform();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
init(getSpawnLocation(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTickActions() {
|
||||
if (ticks-- % 50 == 0) {
|
||||
updateSpecialPoints(-15);
|
||||
owner.getSkills().updateLevel(Skills.SUMMONING, -1, 0);
|
||||
if (!getText().isEmpty()) {
|
||||
super.sendChat(getText());
|
||||
}
|
||||
}
|
||||
sendTimeRemaining();
|
||||
switch (ticks) {
|
||||
case 100:
|
||||
owner.getPacketDispatch().sendMessage("<col=ff0000>You have 1 minute before your familiar vanishes.");
|
||||
break;
|
||||
case 50:
|
||||
owner.getPacketDispatch().sendMessage("<col=ff0000>You have 30 seconds before your familiar vanishes.");
|
||||
break;
|
||||
case 0:
|
||||
if (isBurdenBeast() && !((BurdenBeast) this).getContainer().isEmpty()) {
|
||||
owner.getPacketDispatch().sendMessage("<col=ff0000>Your familiar has dropped all the items it was holding.");
|
||||
} else {
|
||||
owner.getPacketDispatch().sendMessage("<col=ff0000>Your familiar has vanished.");
|
||||
}
|
||||
dismiss();
|
||||
return;
|
||||
}
|
||||
CombatPulse combat = owner.getProperties().getCombatPulse();
|
||||
if (!isInvisible() && !getProperties().getCombatPulse().isAttacking() && (combat.isAttacking() || owner.inCombat())) {
|
||||
Entity victim = combat.getVictim();
|
||||
if (victim == null) {
|
||||
victim = owner.getAttribute("combat-attacker");
|
||||
}
|
||||
if (combat.getVictim() != this && victim != null && !victim.isInvisible() && getProperties().isMultiZone() && owner.getProperties().isMultiZone() && isCombatFamiliar() && !isBurdenBeast() && !isPeacefulFamiliar()) {
|
||||
getProperties().getCombatPulse().attack(victim);
|
||||
}
|
||||
}
|
||||
if ((!isInvisible() && owner.getLocation().getDistance(getLocation()) > 12) || (isInvisible() && ticks % 25 == 0)) {
|
||||
if (!call()) {
|
||||
setInvisible(true);
|
||||
}
|
||||
} else if (!getPulseManager().hasPulseRunning()) {
|
||||
startFollowing();
|
||||
}
|
||||
handleFamiliarTick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAttackable(Entity entity, CombatStyle style, boolean message) {
|
||||
if (entity == owner) {
|
||||
if(message) {
|
||||
owner.getPacketDispatch().sendMessage("You can't just betray your own familiar like that!");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (entity instanceof Player) {
|
||||
if (!owner.isAttackable(entity, style, message)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!getProperties().isMultiZone()) {
|
||||
if (entity instanceof Player && !((Player) entity).getProperties().isMultiZone()) {
|
||||
if(message) {
|
||||
((Player) entity).getPacketDispatch().sendMessage("You have to be in multicombat to attack a player's familiar.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (entity instanceof Player) {
|
||||
if(message) {
|
||||
((Player) entity).getPacketDispatch().sendMessage("This familiar is not in the a multicombat zone.");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (entity instanceof Player) {
|
||||
if (!((Player) entity).getSkullManager().isWilderness()) {
|
||||
if(message) {
|
||||
((Player) entity).getPacketDispatch().sendMessage("You have to be in the wilderness to attack a player's familiar.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!owner.getSkullManager().isWilderness()) {
|
||||
if(message) {
|
||||
((Player) entity).getPacketDispatch().sendMessage("This familiar's owner is not in the wilderness.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return super.isAttackable(entity, style, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegionInactivity() {
|
||||
call();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CombatSwingHandler getSwingHandler(boolean swing) {
|
||||
if (combatHandler != null) {
|
||||
return combatHandler;
|
||||
}
|
||||
return super.getSwingHandler(swing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Familiar} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The NPC id.
|
||||
* @return The familiar.
|
||||
*/
|
||||
public abstract Familiar construct(Player owner, int id);
|
||||
|
||||
/**
|
||||
* Executes the special move.
|
||||
* @param special The familiar special object.
|
||||
* @return {@code True} if the move was executed.
|
||||
*/
|
||||
protected abstract boolean specialMove(FamiliarSpecial special);
|
||||
|
||||
/**
|
||||
* Handles the familiar special tick.
|
||||
*/
|
||||
protected void handleFamiliarTick() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures use with events, and other plugin related content..
|
||||
*/
|
||||
protected void configureFamiliar() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the forced chat text for this familiar.
|
||||
* @return The forced chat text.
|
||||
*/
|
||||
protected String getText() {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the familiar into the Wilderness combat form.
|
||||
*/
|
||||
public void transform() {
|
||||
if (isCombatFamiliar()) {
|
||||
transform(getOriginalId() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshTimer() {
|
||||
ticks = maximumTicks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the time remaining.
|
||||
*/
|
||||
private void sendTimeRemaining() {
|
||||
int minutes = ticks / 100;
|
||||
int centiminutes = ticks % 100;
|
||||
owner.varpManager.get(1176)
|
||||
.setVarbit(7, minutes)
|
||||
.setVarbit(6, centiminutes > 49 ? 1 : 0)
|
||||
.send(owner);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the familiar can execute its special move and does so if able.
|
||||
* @param special The familiar special object.
|
||||
*/
|
||||
public void executeSpecialMove(FamiliarSpecial special) {
|
||||
if (special.getNode() == this) {
|
||||
return;
|
||||
}
|
||||
if (specialCost > specialPoints) {
|
||||
owner.getPacketDispatch().sendMessage("Your familiar does not have enough special move points left.");
|
||||
return;
|
||||
}
|
||||
SummoningScroll scroll = SummoningScroll.forPouch(pouchId);
|
||||
if (scroll == null) {
|
||||
owner.getPacketDispatch().sendMessage("Invalid scroll for pouch " + pouchId + " - report!");
|
||||
return;
|
||||
}
|
||||
if (!owner.getInventory().contains(scroll.getItemId(), 1)) {
|
||||
owner.getPacketDispatch().sendMessage("You do not have enough scrolls left to do this special move.");
|
||||
return;
|
||||
}
|
||||
if (owner.getLocation().getDistance(getLocation()) > 15) {
|
||||
owner.getPacketDispatch().sendMessage("Your familiar is too far away to use that scroll, or it cannot see you.");
|
||||
return;
|
||||
}
|
||||
if (specialMove(special)) {
|
||||
setAttribute("special-delay", GameWorld.getTicks() + 3);
|
||||
owner.getInventory().remove(new Item(scroll.getItemId()));
|
||||
owner.getAudioManager().send(4161);
|
||||
visualizeSpecialMove();
|
||||
updateSpecialPoints(specialCost);
|
||||
owner.getSkills().addExperience(Skills.SUMMONING, scroll.getExperience(), true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the special move visualization for the owner.
|
||||
*/
|
||||
public void visualizeSpecialMove() {
|
||||
owner.visualize(Animation.create(7660), Graphics.create(1316));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a familiar hit.
|
||||
* @param target the target.
|
||||
* @param maxHit the max hit.
|
||||
* @param graphics the graphics.
|
||||
*/
|
||||
public void sendFamiliarHit(final Entity target, final int maxHit, final Graphics graphics) {
|
||||
final int ticks = 2 + (int) Math.floor(getLocation().getDistance(target.getLocation()) * 0.5);
|
||||
getProperties().getCombatPulse().setNextAttack(4);
|
||||
GameWorld.getPulser().submit(new Pulse(ticks, this, target) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
BattleState state = new BattleState(Familiar.this, target);
|
||||
int hit = 0;
|
||||
if (getCombatStyle().getSwingHandler().isAccurateImpact(Familiar.this, target)) {
|
||||
hit = RandomFunction.randomize(maxHit);
|
||||
}
|
||||
state.setEstimatedHit(hit);
|
||||
target.getImpactHandler().handleImpact(owner, hit, CombatStyle.MELEE, state);
|
||||
if (graphics != null) {
|
||||
target.graphics(graphics);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a projectile to the target.
|
||||
* @param target the target.
|
||||
* @param projectileId the projectile id.
|
||||
*/
|
||||
public void projectile(final Entity target, final int projectileId) {
|
||||
Projectile.magic(this, target, projectileId, 40, 36, 51, 10).send();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a familiar hit.
|
||||
* @param maxHit the max hit.
|
||||
*/
|
||||
public void sendFamiliarHit(final Entity target, final int maxHit) {
|
||||
sendFamiliarHit(target, maxHit, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this familiar can attack the target (used mainly for special
|
||||
* moves).
|
||||
*/
|
||||
public boolean canAttack(Entity target, boolean message) {
|
||||
if (!target.isAttackable(owner, owner.getProperties().getCombatPulse().getStyle(), true)) {
|
||||
return false;
|
||||
}
|
||||
if (target.getLocation().getDistance(getLocation()) > 8) {
|
||||
if (message) {
|
||||
owner.getPacketDispatch().sendMessage("That target is too far.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (target.getLocks().isInteractionLocked() || !target.isAttackable(this, CombatStyle.MAGIC, true)) {
|
||||
return false;
|
||||
}
|
||||
return isCombatFamiliar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAttack(Entity target) {
|
||||
return canAttack(target, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a familiar can perform a combat special attack.
|
||||
* @param target the target.
|
||||
* @param message show message.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean canCombatSpecial(Entity target, boolean message) {
|
||||
if (!canAttack(target, message)) {
|
||||
return false;
|
||||
}
|
||||
if (!isOwnerAttackable()) {
|
||||
return false;
|
||||
}
|
||||
if (getAttribute("special-delay", 0) > GameWorld.getTicks()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a faimiliar can perform a combat special attack.
|
||||
* @param target the target.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean canCombatSpecial(Entity target) {
|
||||
return canCombatSpecial(target, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the owner is attackable.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean isOwnerAttackable() {
|
||||
if (!owner.getProperties().getCombatPulse().isAttacking() && !owner.inCombat() && !getProperties().getCombatPulse().isAttacking()) {
|
||||
owner.getPacketDispatch().sendMessage("Your familiar cannot fight whilst you are not in combat.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the combat style.
|
||||
* @return the style.
|
||||
*/
|
||||
public CombatStyle getCombatStyle() {
|
||||
return CombatStyle.MAGIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts a players battle state.
|
||||
* @param state the state.
|
||||
*/
|
||||
public void adjustPlayerBattle(final BattleState state) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts following the owner.
|
||||
*/
|
||||
public void startFollowing() {
|
||||
getPulseManager().run(new MovementPulse(this, owner, Pathfinder.DUMB) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
return false;
|
||||
}
|
||||
}, PulseType.STANDARD);
|
||||
face(owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finalizeDeath(Entity killer) {
|
||||
dismiss();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the familiar is a combat familiar.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean isCombatFamiliar() {
|
||||
return combatFamiliar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the familiar packets.
|
||||
*/
|
||||
public void sendConfiguration() {
|
||||
owner.getConfigManager().set(448, getPouchId());
|
||||
owner.getConfigManager().set(1174, getOriginalId());
|
||||
owner.getConfigManager().set(1175, specialCost << 23);
|
||||
sendTimeRemaining();
|
||||
updateSpecialPoints(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the familiar.
|
||||
*/
|
||||
//int spamTimer = 0;
|
||||
public boolean call() {
|
||||
Location destination = getSpawnLocation();
|
||||
if (destination == null) {
|
||||
//owner.getPacketDispatch().sendMessage("Your familiar is too big to fit here. Try calling it again when you are standing");
|
||||
//owner.getPacketDispatch().sendMessage("somewhere with more space.");
|
||||
//spamTimer = 50;
|
||||
return false;
|
||||
}
|
||||
setInvisible(getZoneMonitor().isRestricted(ZoneRestriction.FOLLOWERS) && !owner.getLocks().isLocked("enable_summoning"));
|
||||
getProperties().setTeleportLocation(destination);
|
||||
if (!(this instanceof Pet)) {
|
||||
if(firstCall) {
|
||||
owner.getAudioManager().send(4366);
|
||||
firstCall = false;
|
||||
} else {
|
||||
owner.getAudioManager().send(188);
|
||||
}
|
||||
if (size() > 1) {
|
||||
graphics(LARGE_SUMMON_GRAPHIC);
|
||||
} else {
|
||||
graphics(SMALL_SUMMON_GRAPHIC);
|
||||
}
|
||||
}
|
||||
if (getProperties().getCombatPulse().isAttacking()) {
|
||||
startFollowing();
|
||||
} else {
|
||||
face(owner);
|
||||
}
|
||||
if (!isRenderable() && owner.isActive()) {
|
||||
// SystemLogger.logErr(this.getClass(), "Familiar in inactive region!");
|
||||
getWalkingQueue().update();
|
||||
getUpdateMasks().prepare(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the spawning location of the familiar.
|
||||
* @return The spawn location.
|
||||
*/
|
||||
public Location getSpawnLocation() {
|
||||
return RegionManager.getSpawnLocation(owner, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismisses the familiar.
|
||||
*/
|
||||
public void dismiss() {
|
||||
clear();
|
||||
getPulseManager().clear();
|
||||
owner.getInterfaceManager().removeTabs(7);
|
||||
owner.getFamiliarManager().setFamiliar(null);
|
||||
owner.getConfigManager().set(448, -1);
|
||||
owner.getConfigManager().set(1176, 0);
|
||||
owner.getConfigManager().set(1175, 182986);
|
||||
owner.getConfigManager().set(1174, -1);
|
||||
if (owner.getSkullManager().isWilderness()) {
|
||||
owner.getAppearance().sync();
|
||||
}
|
||||
owner.getInterfaceManager().setViewedTab(3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the special move points.
|
||||
* @param diff The difference to decrease with.
|
||||
*/
|
||||
public void updateSpecialPoints(int diff) {
|
||||
specialPoints -= diff;
|
||||
if (specialPoints > 60) {
|
||||
specialPoints = 60;
|
||||
}
|
||||
owner.getConfigManager().set(1177, specialPoints);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
for (int id : getIds()) {
|
||||
if (FamiliarManager.getFamiliars().containsKey(id)) {
|
||||
SystemLogger.logErr(this.getClass(), "Familiar " + id + " was already registered!");
|
||||
return null;
|
||||
}
|
||||
FamiliarManager.getFamiliars().put(id, this);
|
||||
configureFamiliar();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fireEvent(String identifier, Object... args) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the charged.
|
||||
* @return The charged.
|
||||
*/
|
||||
public boolean isCharged() {
|
||||
if (charged) {
|
||||
owner.getPacketDispatch().sendMessage("Your familiar is already charging its attack!");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a familiar boost.
|
||||
* @param skill the skill.
|
||||
* @return the boost.
|
||||
*/
|
||||
public int getBoost(int skill) {
|
||||
SkillBonus bonus = null;
|
||||
for (SkillBonus b : boosts) {
|
||||
if (b.getSkillId() == skill) {
|
||||
bonus = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bonus == null) {
|
||||
return 0;
|
||||
}
|
||||
return (int) bonus.getBonus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Charges a familiar.
|
||||
*/
|
||||
public void charge() {
|
||||
setCharged(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the charged.
|
||||
* @param charged The charged to set.
|
||||
*/
|
||||
public void setCharged(boolean charged) {
|
||||
this.charged = charged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the familiar is a beast of burden.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean isBurdenBeast() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isPeacefulFamiliar() {
|
||||
return pouch.getPeaceful();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the NPC ids.
|
||||
* @return The npc ids.
|
||||
*/
|
||||
public abstract int[] getIds();
|
||||
|
||||
/**
|
||||
* Gets the pouch id.
|
||||
* @return The pouch id.
|
||||
*/
|
||||
public int getPouchId() {
|
||||
return pouchId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the owner.
|
||||
* @return The owner.
|
||||
*/
|
||||
public Player getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the owner.
|
||||
* @param owner The owner to set.
|
||||
*/
|
||||
public void setOwner(Player owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the combatHandler.
|
||||
* @return The combatHandler.
|
||||
*/
|
||||
public CombatSwingHandler getCombatHandler() {
|
||||
return combatHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the combatHandler.
|
||||
* @param combatHandler The combatHandler to set.
|
||||
*/
|
||||
public void setCombatHandler(CombatSwingHandler combatHandler) {
|
||||
this.combatHandler = combatHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the view animation for remote viewing.
|
||||
* @return the animation.
|
||||
*/
|
||||
public Animation getViewAnimation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exp style.
|
||||
* @return the style.
|
||||
*/
|
||||
public int getAttackStyle() {
|
||||
return attackStyle;
|
||||
}
|
||||
|
||||
public int getTicks() {
|
||||
return ticks;
|
||||
}
|
||||
|
||||
public int getSpecialPoints() {
|
||||
return specialPoints;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the dialogue plugin used for familiars.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class FamiliarDialoguePlugin extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FamiliarDialoguePlugin} {@code Object}.
|
||||
*/
|
||||
public FamiliarDialoguePlugin() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FamiliarDialoguePlugin} {@code Object}.
|
||||
* @param player the player.
|
||||
*/
|
||||
public FamiliarDialoguePlugin(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new FamiliarDialoguePlugin(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
npc = (NPC) args[0];
|
||||
if (!(npc instanceof Familiar)) {
|
||||
return false;
|
||||
}
|
||||
final Familiar f = (Familiar) npc;
|
||||
if (f.getOwner() != player) {
|
||||
player.getPacketDispatch().sendMessage("This is not your follower.");
|
||||
return true;
|
||||
}
|
||||
// if (f.getDetails().getType() == FamiliarType.PET) {TODO:Pet
|
||||
// if (player.getSkills().getLevel(Skills.SUMMONING) < ((PetDetails)
|
||||
// f.getDetails()).getPet().getSummoningLevel() + 10) {
|
||||
// interpreter.sendDialogues(npc, null, "Grumble...!");
|
||||
// int lvl = ((PetDetails) f.getDetails()).getPet().getSummoningLevel()
|
||||
// + 10;
|
||||
// if (lvl > 99) {
|
||||
// player.getPacketDispatch().sendMessage("It is impossible to talk to this pet.");//dragon,
|
||||
// chamerelon, monket..etc
|
||||
// return true;
|
||||
// }
|
||||
// player.getPacketDispatch().sendMessage("You need a summoning level of "
|
||||
// + lvl + " in order to communicate with your pet.");
|
||||
// stage = 99;
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
stage = RandomFunction.random(1, 3);
|
||||
switch (stage) {
|
||||
case 1:
|
||||
interpreter.sendDialogues(npc, null, "Are we going to be walking all day?");
|
||||
stage = 1;
|
||||
break;
|
||||
case 2:
|
||||
interpreter.sendDialogues(npc, null, "Yer lookin' tired. You should have a nap.");
|
||||
stage = 20;
|
||||
break;
|
||||
case 3:
|
||||
interpreter.sendDialogues(npc, null, "I could do wi' a cup of tea, mind.");
|
||||
stage = 30;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (stage) {
|
||||
case 1:// random first.
|
||||
interpreter.sendDialogues(player, null, "Well, I could carry you if you like.");
|
||||
stage = 10;
|
||||
break;
|
||||
case 10:
|
||||
interpreter.sendDialogues(npc, null, "That would be great!");
|
||||
stage = 11;
|
||||
break;
|
||||
case 11:
|
||||
interpreter.sendDialogues(player, null, "You know, you won't grow up to be big and strong", "if you keep getting carried everywhere.");
|
||||
stage = 12;
|
||||
break;
|
||||
case 12:
|
||||
interpreter.sendDialogues(npc, null, "I know, I know.");
|
||||
stage = 99;
|
||||
break;
|
||||
case 2:// random second dial.
|
||||
interpreter.sendDialogues(npc, null, "Yer lookin' tired. You should have a nap.");
|
||||
stage = 20;
|
||||
break;
|
||||
case 20:
|
||||
interpreter.sendDialogues(player, null, "Is it me who needs a rest or you?");
|
||||
stage = 21;
|
||||
break;
|
||||
case 21:
|
||||
interpreter.sendDialogues(npc, null, "Well, if you took one, I might too...");
|
||||
stage = 22;
|
||||
break;
|
||||
case 22:
|
||||
interpreter.sendDialogues(player, null, "Yeah, I thought as much.");
|
||||
stage = 23;
|
||||
break;
|
||||
case 23:
|
||||
interpreter.sendDialogues(npc, null, "Grumble...");
|
||||
stage = 99;
|
||||
break;
|
||||
case 3:// random third dial.
|
||||
interpreter.sendDialogues(npc, null, "I could do wi' a cup of tea, mind.");
|
||||
stage = 30;
|
||||
break;
|
||||
case 30:
|
||||
interpreter.sendDialogues(player, null, "I don't know if a cup of tea would be good for you.");
|
||||
stage = 31;
|
||||
break;
|
||||
case 31:
|
||||
interpreter.sendDialogues(npc, null, "Fair 'nuff, then.");
|
||||
stage = 99;
|
||||
break;
|
||||
case 99:
|
||||
end();
|
||||
player.getFamiliarManager().getFamiliar().startFollowing();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 761, 762, 763, 764, 765, 766, 3505, 3598, 6969, 7259, 7260, 6964, 7249, 7251, 6960, 7241, 7243, 6962, 7245, 7247, 6966, 7253, 7255, 6958, 7237, 7239, 6915, 7277, 7278, 7279, 7280, 7018, 7019, 7020, 6908, 7313, 7316, 6947, 7293, 7295, 7297, 7299, 6911, 7261, 7263, 7265, 7267, 7269, 6919, 7301, 7303, 7305, 7307, 6949, 6952, 6955, 6913, 7271, 7273, 6945, 7319, 7321, 7323, 7325, 7327, 6922, 6942, 7210, 7212, 7214, 7216, 7218, 7220, 7222, 7224, 7226, 6900, 6902, 6904, 6906, 768, 769, 770, 771, 772, 773, 3504, 8214, 6968, 7257, 7258, 6965, 7250, 7252, 6961, 7242, 7244, 6963, 7246, 7248, 6967, 7254, 7256, 6859, 7238, 7240, 6916, 7281, 7282, 7283, 7284, 7015, 7016, 7017, 6909, 7314, 7317, 11413, 6948, 7294, 7296, 7298, 7300, 6912, 7262, 7264, 7266, 7268, 7270, 6920, 7302, 7304, 7306, 7308, 6950, 6953, 6956, 6914, 7272, 7274, 13090, 6946, 7320, 7322, 7324, 7326, 7328, 6923, 6943, 7211, 7213, 7215, 7217, 7219, 7221, 7223, 7225, 7227, 6901, 6903, 6905, 6907, 774, 775, 776, 777, 778, 779, 3503, 8216, 6951, 6954, 6957 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import content.global.skill.summoning.pet.Pet;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the class used to handle the feeding of pets.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class FamiliarFeedPlugin extends UseWithHandler {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FamiliarFeedPlugin} {@code Object}.
|
||||
*/
|
||||
public FamiliarFeedPlugin() {
|
||||
super(321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 1927, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 1927, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 1927, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 1927, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 1927, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 1927, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 1927, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 1927, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 526, 1059, 225, 221, 526, 592, 12125, 12127, 12125, 12127, 12125, 12127, 12125, 12127, 12125, 12127, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 313, 12129, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 313, 12129, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 313, 12129, 2970, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 1927, 1977, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 313, 12129, 313, 12129, 313, 12129, 313, 12129, 313, 12129, 313, 12129, 12130, 12130, 12130, 12130, 12130, 313, 12129, 313, 12129, 313, 12129, 13379, 592, 592, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 221, 313, 12129, 313, 12129, 313, 12129, 313, 12129, 313, 12129, 313, 12129, 12125, 1963, 1963, 1963, 1963, 1963, 1963, 1963, 1963, 1963, 1963, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270, 2132, 2134, 2136, 2138, 10816, 9986, 9978, 321, 363, 341, 15264, 345, 377, 353, 389, 7944, 349, 331, 327, 395, 383, 317, 371, 335, 359, 15264, 15270);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
int[] ids = new int[] { 761, 762, 763, 764, 765, 766, 3505, 3598, 6969, 7259, 7260, 6964, 7249, 7251, 6960, 7241, 7243, 6962, 7245, 7247, 6966, 7253, 7255, 6958, 7237, 7239, 6915, 7277, 7278, 7279, 7280, 7018, 7019, 7020, 6908, 7313, 7316, 6947, 7293, 7295, 7297, 7299, 6911, 7261, 7263, 7265, 7267, 7269, 6919, 7301, 7303, 7305, 7307, 6949, 6952, 6955, 6913, 7271, 7273, 6945, 7319, 7321, 7323, 7325, 7327, 6922, 6942, 7210, 7212, 7214, 7216, 7218, 7220, 7222, 7224, 7226, 6900, 6902, 6904, 6906, 768, 769, 770, 771, 772, 773, 3504, 8214, 6968, 7257, 7258, 6965, 7250, 7252, 6961, 7242, 7244, 6963, 7246, 7248, 6967, 7254, 7256, 6859, 7238, 7240, 6916, 7281, 7282, 7283, 7284, 7015, 7016, 7017, 6909, 7314, 7317, 11413, 6948, 7294, 7296, 7298, 7300, 6912, 7262, 7264, 7266, 7268, 7270, 6920, 7302, 7304, 7306, 7308, 6950, 6953, 6956, 6914, 7272, 7274, 13090, 6946, 7320, 7322, 7324, 7326, 7328, 6923, 6943, 7211, 7213, 7215, 7217, 7219, 7221, 7223, 7225, 7227, 6901, 6903, 6905, 6907, 774, 775, 776, 777, 778, 779, 3503, 8216, 6951, 6954, 6957 };
|
||||
for (int i : ids) {
|
||||
addHandler(i, NPC_TYPE, this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(NodeUsageEvent event) {
|
||||
final Familiar f = (Familiar) event.getUsedWith();
|
||||
if (!(f instanceof Pet)) {
|
||||
return false;
|
||||
}
|
||||
event.getPlayer().getFamiliarManager().eat(event.getUsedItem().getId(), (Pet) f);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import content.global.skill.summoning.pet.Pets;
|
||||
import core.cache.def.impl.ItemDefinition;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the familiar items option plugin.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class FamiliarItemOptionPlugin extends OptionHandler {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
for (Pets p : Pets.values()) {
|
||||
ItemDefinition def = ItemDefinition.forId(p.getBabyItemId());
|
||||
if (def == null) {
|
||||
continue;
|
||||
}
|
||||
def.getHandlers().put("option:drop", this);
|
||||
def.getHandlers().put("option:release", this);
|
||||
if (p.getGrownItemId() > -1) {
|
||||
ItemDefinition.forId(p.getGrownItemId()).getHandlers().put("option:drop", this);
|
||||
ItemDefinition.forId(p.getGrownItemId()).getHandlers().put("option:release", this);
|
||||
}
|
||||
if (p.getOvergrownItemId() > -1) {
|
||||
ItemDefinition.forId(p.getOvergrownItemId()).getHandlers().put("option:drop", this);
|
||||
ItemDefinition.forId(p.getOvergrownItemId()).getHandlers().put("option:release", this);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
switch (option) {
|
||||
case "drop":
|
||||
player.getFamiliarManager().summon(((Item) node), true);
|
||||
return true;
|
||||
case "release":
|
||||
if (((Item) node).getId() == 7771) {
|
||||
player.getFamiliarManager().summon(((Item) node), true);
|
||||
return true;
|
||||
}
|
||||
if (player.getInventory().remove(((Item) node))) {
|
||||
player.getDialogueInterpreter().sendDialogues(player, null, "Run along; I'm setting you free.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWalk() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,488 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import content.global.skill.summoning.pet.Pet;
|
||||
import content.global.skill.summoning.pet.Pets;
|
||||
import core.cache.def.impl.ItemDefinition;
|
||||
import core.game.component.Component;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.summoning.SummoningPouch;
|
||||
import content.global.skill.summoning.pet.PetDetails;
|
||||
import core.game.node.entity.combat.BattleState;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.zone.ZoneRestriction;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Handles a player's familiar.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class FamiliarManager {
|
||||
|
||||
/**
|
||||
* The familiars mapping.
|
||||
*/
|
||||
private static final Map<Integer, Familiar> FAMILIARS = new HashMap<>();
|
||||
|
||||
/**
|
||||
* The pet details mapping, sorted by item id.
|
||||
*/
|
||||
private final Map<Integer, PetDetails> petDetails = new HashMap<Integer, PetDetails>();
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The familiar.
|
||||
*/
|
||||
private Familiar familiar;
|
||||
|
||||
/**
|
||||
* The combat level difference when using summoning.
|
||||
*/
|
||||
private int summoningCombatLevel;
|
||||
|
||||
/**
|
||||
* If the player has a summoning pouch.
|
||||
*/
|
||||
private boolean hasPouch;
|
||||
|
||||
/**
|
||||
* The list of insured pets.
|
||||
*/
|
||||
private List<Pets> insuredPets = new ArrayList<>(20);
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FamiliarManager} {@code Object}.
|
||||
* @param player The player.
|
||||
*/
|
||||
public FamiliarManager(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public final void parse(JSONObject familiarData){
|
||||
JSONArray petDetails = (JSONArray) familiarData.get("petDetails");
|
||||
for(int i = 0 ; i < petDetails.size(); i++){
|
||||
JSONObject detail = (JSONObject) petDetails.get(i);
|
||||
PetDetails details = new PetDetails(0);
|
||||
details.updateHunger(Double.parseDouble(detail.get("hunger").toString()));
|
||||
details.updateGrowth(Double.parseDouble(detail.get("growth").toString()));
|
||||
details.setStage(Integer.parseInt(detail.get("stage").toString()));
|
||||
this.petDetails.put(Integer.parseInt(detail.get("petId").toString()),details);
|
||||
}
|
||||
|
||||
if(familiarData.containsKey("currentPet")){
|
||||
int currentPet = Integer.parseInt( familiarData.get("currentPet").toString());
|
||||
PetDetails details = this.petDetails.get(currentPet);
|
||||
Pets pets = Pets.forId(currentPet);
|
||||
if (details == null) {
|
||||
details = new PetDetails(pets.getGrowthRate() == 0.0 ? 100.0 : 0.0);
|
||||
this.petDetails.put(currentPet, details);
|
||||
}
|
||||
familiar = new Pet(player, details, currentPet, pets.getNpcId(details.getStage()));
|
||||
} else if(familiarData.containsKey("familiar")){
|
||||
JSONObject currentFamiliar = (JSONObject) familiarData.get("familiar");
|
||||
int familiarId = Integer.parseInt( currentFamiliar.get("originalId").toString());
|
||||
familiar = FAMILIARS.get(familiarId).construct(player,familiarId);
|
||||
familiar.ticks = Integer.parseInt( currentFamiliar.get("ticks").toString());
|
||||
familiar.specialPoints = Integer.parseInt( currentFamiliar.get("specialPoints").toString());
|
||||
JSONArray famInv = (JSONArray) currentFamiliar.get("inventory");
|
||||
if(famInv != null){
|
||||
((BurdenBeast) familiar).container.parse(famInv);
|
||||
}
|
||||
familiar.setAttribute("hp",Integer.parseInt( currentFamiliar.get("lifepoints").toString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the player logs in.
|
||||
*/
|
||||
public void login() {
|
||||
if (hasFamiliar()) {
|
||||
familiar.init();
|
||||
}
|
||||
player.getFamiliarManager().setConfig(243269632);
|
||||
}
|
||||
|
||||
/**
|
||||
* Summons a familiar.
|
||||
* @param item The item.
|
||||
* @param pet If the familiar is a pet.
|
||||
* @param deleteItem we should delete the item.
|
||||
*/
|
||||
public void summon(Item item, boolean pet, boolean deleteItem) {
|
||||
boolean renew = false;
|
||||
if (hasFamiliar()) {
|
||||
if(familiar.getPouchId() == item.getId()) {
|
||||
renew = true;
|
||||
} else {
|
||||
player.getPacketDispatch().sendMessage("You already have a follower.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (player.getZoneMonitor().isRestricted(ZoneRestriction.FOLLOWERS) && !player.getLocks().isLocked("enable_summoning")) {
|
||||
player.getPacketDispatch().sendMessage("This is a Summoning-free area.");
|
||||
return;
|
||||
}
|
||||
if (pet) {
|
||||
summonPet(item, deleteItem);
|
||||
return;
|
||||
}
|
||||
final SummoningPouch pouch = SummoningPouch.get(item.getId());
|
||||
if (pouch == null) {
|
||||
return;
|
||||
}
|
||||
if (player.getSkills().getStaticLevel(Skills.SUMMONING) < pouch.getLevelRequired()) {
|
||||
player.getPacketDispatch().sendMessage("You need a Summoning level of " + pouch.getLevelRequired() + " to summon this familiar.");
|
||||
return;
|
||||
}
|
||||
if (player.getSkills().getLevel(Skills.SUMMONING) < pouch.getSummonCost()) {
|
||||
player.getPacketDispatch().sendMessage("You need at least " + pouch.getSummonCost() + " Summoning points to summon this familiar.");
|
||||
return;
|
||||
}
|
||||
final int npcId = pouch.getNpcId();
|
||||
Familiar fam = !renew ? FAMILIARS.get(npcId) : familiar;
|
||||
if (fam == null) {
|
||||
player.getPacketDispatch().sendMessage("Invalid familiar " + npcId + " - report on 2009scape github");
|
||||
return;
|
||||
}
|
||||
if(!renew) {
|
||||
fam = fam.construct(player, npcId);
|
||||
if (fam.getSpawnLocation() == null) {
|
||||
player.getPacketDispatch().sendMessage("The spirit in this pouch is too big to summon here. You will need to move to a larger");
|
||||
player.getPacketDispatch().sendMessage("area.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!player.getInventory().remove(item)) {
|
||||
return;
|
||||
}
|
||||
player.getSkills().updateLevel(Skills.SUMMONING, -pouch.getSummonCost(), 0);
|
||||
player.getSkills().addExperience(Skills.SUMMONING, pouch.getSummonExperience());
|
||||
if(!renew) {
|
||||
familiar = fam;
|
||||
spawnFamiliar();
|
||||
} else {
|
||||
familiar.refreshTimer();
|
||||
}
|
||||
if (player.getSkullManager().isWilderness()) {
|
||||
player.getAppearance().sync();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Summons a familiar.
|
||||
* @param item the item.
|
||||
* @param pet the pet.
|
||||
*/
|
||||
public void summon(final Item item, boolean pet) {
|
||||
summon(item, pet, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Morphs a pet.
|
||||
* @param item the item.
|
||||
* @param deleteItem the item.
|
||||
* @param location the location.
|
||||
*/
|
||||
public void morphPet(final Item item, boolean deleteItem, Location location) {
|
||||
if (hasFamiliar()) {
|
||||
familiar.dismiss();
|
||||
}
|
||||
summonPet(item, deleteItem, true, location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Summons a pet.
|
||||
* @param item the item.
|
||||
* @param deleteItem the item.
|
||||
*/
|
||||
private boolean summonPet(final Item item, boolean deleteItem) {
|
||||
return summonPet(item, deleteItem, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Summons a pet.
|
||||
* @param item the item.
|
||||
* @param morph the pet.
|
||||
*/
|
||||
private boolean summonPet(final Item item, boolean deleteItem, boolean morph, Location location) {
|
||||
final int itemId = item.getId();
|
||||
if (itemId > 8850 && itemId < 8900) {
|
||||
return false;
|
||||
}
|
||||
Pets pets = Pets.forId(itemId);
|
||||
if (pets == null) {
|
||||
return false;
|
||||
}
|
||||
if (player.getSkills().getStaticLevel(Skills.SUMMONING) < pets.getSummoningLevel()) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a summoning level of " + pets.getSummoningLevel() + " to summon this.");
|
||||
return false;
|
||||
}
|
||||
int baseItemId = pets.getBabyItemId();
|
||||
PetDetails details = petDetails.get(baseItemId);
|
||||
if (details == null) {
|
||||
details = new PetDetails(pets.getGrowthRate() == 0.0 ? 100.0 : 0.0);
|
||||
petDetails.put(baseItemId, details);
|
||||
}
|
||||
int id = pets.getItemId(details.getStage());
|
||||
if (itemId != id) {
|
||||
player.getPacketDispatch().sendMessage("This is not the right pet, grow the pet correctly.");
|
||||
return true;
|
||||
}
|
||||
int npcId = pets.getNpcId(details.getStage());
|
||||
if (npcId > 0) {
|
||||
familiar = new Pet(player, details, itemId, npcId);
|
||||
if (deleteItem) {
|
||||
player.animate(new Animation(827));
|
||||
player.getInventory().remove(item);
|
||||
}
|
||||
if (morph) {
|
||||
morphFamiliar(location);
|
||||
} else {
|
||||
spawnFamiliar();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Morphs the current familiar.
|
||||
* @param location the location.
|
||||
*/
|
||||
public void morphFamiliar(Location location) {
|
||||
familiar.init(location, false);
|
||||
player.getInterfaceManager().openTab(new Component(662));
|
||||
player.getInterfaceManager().setViewedTab(7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns the current familiar.
|
||||
*/
|
||||
public void spawnFamiliar() {
|
||||
familiar.init();
|
||||
player.getInterfaceManager().openTab(new Component(662));
|
||||
player.getInterfaceManager().setViewedTab(7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the pet eat.
|
||||
* @param foodId The food item id.
|
||||
* @param npc The pet NPC.
|
||||
*/
|
||||
public void eat(int foodId, Pet npc) {
|
||||
if (npc != familiar) {
|
||||
player.getPacketDispatch().sendMessage("This isn't your pet!");
|
||||
return;
|
||||
}
|
||||
Pet pet = (Pet) familiar;
|
||||
Pets pets = Pets.forId(pet.getItemId());
|
||||
if (pets == null) {
|
||||
return;
|
||||
}
|
||||
for (int food : pets.getFood()) {
|
||||
if (food == foodId) {
|
||||
player.getInventory().remove(new Item(foodId));
|
||||
player.getPacketDispatch().sendMessage("Your pet happily eats the " + ItemDefinition.forId(food).getName() + ".");
|
||||
player.animate(new Animation(827));
|
||||
npc.getDetails().updateHunger(-15.0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
player.getPacketDispatch().sendMessage("Nothing interesting happens.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Picks up a pet.
|
||||
*/
|
||||
public void pickup() {
|
||||
if (player.getInventory().freeSlots() == 0) {
|
||||
player.getPacketDispatch().sendMessage("You don't have enough room in your inventory.");
|
||||
return;
|
||||
}
|
||||
Pet pet = ((Pet) familiar);
|
||||
PetDetails details = pet.getDetails();
|
||||
if (player.getInventory().add(new Item(pet.getPet().getItemId(details.getStage())))) {
|
||||
player.animate(Animation.create(827));
|
||||
player.getFamiliarManager().dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the battle state.
|
||||
* @param state the state.
|
||||
*/
|
||||
public void adjustBattleState(final BattleState state) {
|
||||
if (!hasFamiliar()) {
|
||||
return;
|
||||
}
|
||||
familiar.adjustPlayerBattle(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a boost from a familiar.
|
||||
* @param skill the skill.
|
||||
* @return the boosted level.
|
||||
*/
|
||||
public int getBoost(int skill) {
|
||||
if (!hasFamiliar()) {
|
||||
return 0;
|
||||
}
|
||||
return familiar.getBoost(skill);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player has an active familiar.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean hasFamiliar() {
|
||||
return familiar != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player has an active familiar and is a pet.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean hasPet() {
|
||||
return hasFamiliar() && familiar instanceof Pet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismisses the familiar.
|
||||
* @param saveDetails the details of a pet.
|
||||
*/
|
||||
public void dismiss(boolean saveDetails) {
|
||||
if (hasPet() && !saveDetails) {
|
||||
removeDetails(((Pet) familiar).getItemId());
|
||||
}
|
||||
if (hasFamiliar()) {
|
||||
familiar.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismisses the familiar.
|
||||
*/
|
||||
public void dismiss() {
|
||||
dismiss(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the details for this pet.
|
||||
* @param itemId The item id of the pet.
|
||||
*/
|
||||
public void removeDetails(int itemId) {
|
||||
Pets pets = Pets.forId(itemId);
|
||||
if (pets == null) {
|
||||
return;
|
||||
}
|
||||
petDetails.remove(pets.getBabyItemId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if it's the owner of a familiar.
|
||||
* @param familiar the familiar
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean isOwner(Familiar familiar) {
|
||||
if (!hasFamiliar()) {
|
||||
return false;
|
||||
}
|
||||
if (this.familiar != familiar) {
|
||||
player.getPacketDispatch().sendMessage("This is not your familiar.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a config value.
|
||||
* @param value the value.
|
||||
*/
|
||||
public void setConfig(int value) {
|
||||
int current = player.getConfigManager().get(1160);
|
||||
int newVal = current + value;
|
||||
player.getConfigManager().set(1160, newVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the familiar.
|
||||
* @return The familiar.
|
||||
*/
|
||||
public Familiar getFamiliar() {
|
||||
return familiar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the familiar.
|
||||
* @param familiar The familiar to set.
|
||||
*/
|
||||
public void setFamiliar(Familiar familiar) {
|
||||
this.familiar = familiar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the familiars.
|
||||
* @return The familiars.
|
||||
*/
|
||||
public static Map<Integer, Familiar> getFamiliars() {
|
||||
return FAMILIARS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the usingSummoning.
|
||||
* @return The usingSummoning.
|
||||
*/
|
||||
public boolean isUsingSummoning() {
|
||||
return hasPouch || hasFamiliar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hasPouch.
|
||||
* @return The hasPouch.
|
||||
*/
|
||||
public boolean isHasPouch() {
|
||||
return hasPouch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the hasPouch.
|
||||
* @param hasPouch The hasPouch to set.
|
||||
*/
|
||||
public void setHasPouch(boolean hasPouch) {
|
||||
this.hasPouch = hasPouch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the summoningCombatLevel.
|
||||
* @return The summoningCombatLevel.
|
||||
*/
|
||||
public int getSummoningCombatLevel() {
|
||||
return summoningCombatLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the summoningCombatLevel.
|
||||
* @param summoningCombatLevel The summoningCombatLevel to set.
|
||||
*/
|
||||
public void setSummoningCombatLevel(int summoningCombatLevel) {
|
||||
this.summoningCombatLevel = summoningCombatLevel;
|
||||
}
|
||||
|
||||
|
||||
public Map<Integer, PetDetails> getPetDetails() {
|
||||
return petDetails;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.cache.def.impl.NPCDefinition;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.player.FaceLocationFlag;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the class used for handling the npc options of familiars.
|
||||
* @author Emperor
|
||||
* @author 'Vexia
|
||||
* @version 2.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class FamiliarNPCOptionPlugin extends OptionHandler {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
NPCDefinition.setOptionHandler("pick-up", this);
|
||||
NPCDefinition.setOptionHandler("interact-with", this);
|
||||
NPCDefinition.setOptionHandler("interact", this);
|
||||
NPCDefinition.setOptionHandler("store", this);
|
||||
NPCDefinition.setOptionHandler("withdraw", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(final Player player, Node node, String option) {
|
||||
if (!(node instanceof Familiar)) {
|
||||
return false;
|
||||
}
|
||||
Familiar familiar = (Familiar) node;
|
||||
if (familiar.getOwner() != player) {
|
||||
player.getPacketDispatch().sendMessage("This is not your familiar.");
|
||||
return true;
|
||||
}
|
||||
switch (option) {
|
||||
case "pick-up":
|
||||
player.faceLocation(FaceLocationFlag.getFaceLocation(player, familiar));
|
||||
player.getFamiliarManager().pickup();
|
||||
break;
|
||||
case "interact-with":
|
||||
player.getDialogueInterpreter().open(343823);
|
||||
break;
|
||||
case "interact":
|
||||
player.getDialogueInterpreter().open(node.getId(), node);
|
||||
break;
|
||||
case "store":
|
||||
case "withdraw":
|
||||
if (!familiar.isBurdenBeast()) {
|
||||
player.getPacketDispatch().sendMessage("This is not a beast of burden.");
|
||||
break;
|
||||
}
|
||||
((BurdenBeast) familiar).openInterface();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* A class which represents a familiar special.
|
||||
* @author Aero
|
||||
*/
|
||||
public class FamiliarSpecial {
|
||||
|
||||
/**
|
||||
* The node.
|
||||
*/
|
||||
private Node node;
|
||||
|
||||
/**
|
||||
* The interface id.
|
||||
*/
|
||||
private int interfaceID;
|
||||
|
||||
/**
|
||||
* The component.
|
||||
*/
|
||||
private int component;
|
||||
|
||||
/**
|
||||
* The item.
|
||||
*/
|
||||
private Item item;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FamiliarSpecial} {@code Object}.
|
||||
* @param node The node.
|
||||
*/
|
||||
public FamiliarSpecial(Node node) {
|
||||
this(node, -1, -1, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FamiliarSpecial} {@code Object}.
|
||||
* @param node The node.
|
||||
* @param interfaceID The interface id.
|
||||
* @param component The component.
|
||||
* @param item The item.
|
||||
*/
|
||||
public FamiliarSpecial(Node node, int interfaceID, int component, Item item) {
|
||||
this.node = node;
|
||||
this.interfaceID = interfaceID;
|
||||
this.component = component;
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the node.
|
||||
* @return The node.
|
||||
*/
|
||||
public Node getNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the node.
|
||||
* @param node The node to set.
|
||||
*/
|
||||
public void setNode(Node node) {
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the interfaceID.
|
||||
* @return The interfaceID.
|
||||
*/
|
||||
public int getInterfaceID() {
|
||||
return interfaceID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the interfaceID.
|
||||
* @param interfaceID The interfaceID to set.
|
||||
*/
|
||||
public void setInterfaceID(int interfaceID) {
|
||||
this.interfaceID = interfaceID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the component.
|
||||
* @return The component.
|
||||
*/
|
||||
public int getComponent() {
|
||||
return component;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the component.
|
||||
* @param component The component to set.
|
||||
*/
|
||||
public void setComponent(int component) {
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item.
|
||||
* @return The item.
|
||||
*/
|
||||
public Item getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the item.
|
||||
* @param item The item to set.
|
||||
*/
|
||||
public void setItem(Item item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the target.
|
||||
* @return the target.
|
||||
*/
|
||||
public Entity getTarget() {
|
||||
return (Entity) node;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents the Fire Titan familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class FireTitanNPC extends ElementalTitanNPC {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FireTitanNPC} {@code Object}.
|
||||
*/
|
||||
public FireTitanNPC() {
|
||||
this(null, 7355);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FireTitanNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public FireTitanNPC(Player owner, int id) {
|
||||
super(owner, id, 6200, 12802, 20, WeaponInterface.STYLE_CAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new FireTitanNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7355, 7356 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.GameWorld;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents a forager familiar.
|
||||
* @author Vexia
|
||||
*/
|
||||
public abstract class Forager extends BurdenBeast {
|
||||
|
||||
/**
|
||||
* The items to product if passive with no restrictions.
|
||||
*/
|
||||
private final Item[] items;
|
||||
|
||||
/**
|
||||
* The delay until the next random passive product.
|
||||
*/
|
||||
private int passiveDelay;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Forager} {@code Object}.
|
||||
* @param owner the owner.
|
||||
* @param id the id.
|
||||
* @param ticks the ticks.
|
||||
* @param pouchId the pouch id.
|
||||
* @param specialCost the special cost.
|
||||
*/
|
||||
public Forager(Player owner, int id, int ticks, int pouchId, int specialCost, int attackStyle, final Item... items) {
|
||||
super(owner, id, ticks, pouchId, specialCost, 30, attackStyle);
|
||||
this.items = items;
|
||||
setRandomPassive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Forager} {@code Object}.
|
||||
* @param owner the owner.
|
||||
* @param id the id.
|
||||
* @param ticks the ticks.
|
||||
* @param pouchId the pouch id.
|
||||
* @param specialCost the special cost.
|
||||
*/
|
||||
public Forager(Player owner, int id, int ticks, int pouchId, int specialCost, final Item... items) {
|
||||
this(owner, id, ticks, pouchId, specialCost, WeaponInterface.STYLE_DEFENSIVE, items);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFamiliarTick() {
|
||||
super.handleFamiliarTick();
|
||||
if (items != null && items.length > 0 && passiveDelay < GameWorld.getTicks()) {
|
||||
if (RandomFunction.random(getRandom()) < 4) {
|
||||
produceItem(items[RandomFunction.random(items.length)]);
|
||||
}
|
||||
setRandomPassive();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item to the container.
|
||||
* @param item the item.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean produceItem(final Item item) {
|
||||
if (!container.hasSpaceFor(item)) {
|
||||
owner.getPacketDispatch().sendMessage("Your familar is too full to collect items.");
|
||||
return false;
|
||||
}
|
||||
owner.getPacketDispatch().sendMessage(item.getAmount() == 1 ? "Your familar has produced an item." : "Your familiar has produced items.");
|
||||
return container.add(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper method for {@link #produceItem()}.
|
||||
* @return {@code True} if produced.
|
||||
*/
|
||||
public boolean produceItem() {
|
||||
if (items == null || items.length == 0) {
|
||||
return false;
|
||||
}
|
||||
return produceItem(items[RandomFunction.random(items.length)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the passive reward of a forager.
|
||||
*/
|
||||
public void handlePassiveAction() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the random mod.
|
||||
* @return the random mod.
|
||||
*/
|
||||
public int getRandom() {
|
||||
return 11;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a random passive delay.
|
||||
*/
|
||||
public void setRandomPassive() {
|
||||
passiveDelay = GameWorld.getTicks() + RandomFunction.random(100, 440);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.container.impl.EquipmentContainer;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.game.node.entity.player.link.diary.DiaryType;
|
||||
import core.game.node.item.GroundItem;
|
||||
import core.game.node.item.GroundItemManager;
|
||||
import core.game.node.scenery.Scenery;
|
||||
import core.game.node.scenery.SceneryBuilder;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.player.FaceLocationFlag;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.ClassScanner;
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.firemaking.FireMakingPulse;
|
||||
import content.global.skill.firemaking.Log;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the Forge Regent familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class ForgeRegentNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* The animation of the forge regent.
|
||||
*/
|
||||
private static final Animation FIREMAKE_ANIMATION = Animation.create(8085); // TODO FIX - this is from pyrelord
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ForgeRegentNPC} {@code Object}.
|
||||
*/
|
||||
public ForgeRegentNPC() {
|
||||
this(null, 7335);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ForgeRegentNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public ForgeRegentNPC(Player owner, int id) {
|
||||
super(owner, id, 4500, 12782, 6, WeaponInterface.STYLE_RANGE_ACCURATE);
|
||||
boosts.add(new SkillBonus(Skills.FIREMAKING, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new ForgeRegentNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureFamiliar() {
|
||||
ClassScanner.definePlugin(new ForgeRegentFiremake());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
if (!(special.getTarget() instanceof Player)) {
|
||||
owner.sendMessage("You can't use this special on an npc.");
|
||||
return false;
|
||||
}
|
||||
Player target = special.getTarget().asPlayer();
|
||||
if (!canCombatSpecial(target)) {
|
||||
return false;
|
||||
}
|
||||
if (target.getInventory().freeSlots() < 1) {
|
||||
owner.sendMessage("The target doesn't have enough inventory space.");
|
||||
return false;
|
||||
}
|
||||
Item weapon = target.getEquipment().get(EquipmentContainer.SLOT_WEAPON);
|
||||
Item shield = target.getEquipment().get(EquipmentContainer.SLOT_SHIELD);
|
||||
if (weapon == null && shield == null) {
|
||||
owner.sendMessage("The target doesn't have a weapon or shield.");
|
||||
return false;
|
||||
}
|
||||
Item remove = null;
|
||||
while (remove == null) {
|
||||
if (RandomFunction.random(2) == 1) {
|
||||
remove = weapon;
|
||||
} else {
|
||||
remove = shield;
|
||||
}
|
||||
}
|
||||
graphics(Graphics.create(1394));
|
||||
target.graphics(Graphics.create(1393));
|
||||
if (target.getEquipment().remove(remove)) {
|
||||
target.getInventory().add(remove);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7335, 7336 };
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the use with event of a log on a forge regent.
|
||||
*/
|
||||
public final class ForgeRegentFiremake extends UseWithHandler {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ForgeRegentFiremake} {@code Object}.
|
||||
*/
|
||||
public ForgeRegentFiremake() {
|
||||
super(1511, 2862, 1521, 1519, 6333, 10810, 1517, 6332, 12581, 1515, 1513, 13567, 10329, 10328, 7406, 7405, 7404);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
for (int id : getIds()) {
|
||||
addHandler(id, NPC_TYPE, this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(NodeUsageEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final Log log = Log.forId(event.getUsedItem().getId());
|
||||
final Familiar familiar = (Familiar) event.getUsedWith();
|
||||
final int ticks = FIREMAKE_ANIMATION.getDefinition().getDurationTicks();
|
||||
if (!player.getFamiliarManager().isOwner(familiar)) {
|
||||
return true;
|
||||
}
|
||||
if (RegionManager.getObject(familiar.getLocation()) != null || familiar.getZoneMonitor().isInZone("bank")) {
|
||||
player.getPacketDispatch().sendMessage("You can't light a fire here.");
|
||||
return false;
|
||||
}
|
||||
familiar.lock(ticks);
|
||||
familiar.animate(FIREMAKE_ANIMATION);
|
||||
if (player.getInventory().remove(event.getUsedItem())) {
|
||||
final GroundItem ground = GroundItemManager.create(event.getUsedItem(), familiar.getLocation(), player);
|
||||
GameWorld.getPulser().submit(new Pulse(ticks, player, familiar) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
if (!ground.isActive()) {
|
||||
return true;
|
||||
}
|
||||
final Scenery object = new Scenery(log.getFireId(), familiar.getLocation());
|
||||
familiar.moveStep();
|
||||
GroundItemManager.destroy(ground);
|
||||
player.getSkills().addExperience(Skills.FIREMAKING, log.getXp() + 10);
|
||||
familiar.faceLocation(FaceLocationFlag.getFaceLocation(familiar, object));
|
||||
SceneryBuilder.add(object, log.getLife(), FireMakingPulse.getAsh(player, log, object));
|
||||
if (player.getViewport().getRegion().getId() == 10806) {
|
||||
player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 1, 9);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.item.WeightedChanceItem;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.GroundItemManager;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Initializable;
|
||||
import core.tools.RandomFunction;
|
||||
import org.rs09.consts.Items;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents the Fruit Bat familiar.
|
||||
* @author Aero
|
||||
* @author afaroutdude
|
||||
*/
|
||||
@Initializable
|
||||
public class FruitBatNPC extends Forager {
|
||||
|
||||
/**
|
||||
* The random fruit to forage.
|
||||
*/
|
||||
private static final Item[] FRUIT_FORAGE = new Item[] {
|
||||
new Item(Items.PAPAYA_FRUIT_5972),
|
||||
new Item(Items.ORANGE_2108),
|
||||
new Item(Items.PINEAPPLE_2114),
|
||||
new Item(Items.LEMON_2102),
|
||||
new Item(Items.LIME_2120),
|
||||
new Item(Items.STRAWBERRY_5504),
|
||||
new Item(Items.WATERMELON_5982),
|
||||
new Item(Items.COCONUT_5974)
|
||||
};
|
||||
|
||||
/**
|
||||
* The fruit for special move fruitfall EXCEPT the papaya
|
||||
* Sourced rates from various youtube videos and the RS wiki.
|
||||
* Note the RS wiki page does not go back to 2009 but there's no
|
||||
* indication that the rates have changed over time.
|
||||
* https://www.youtube.com/watch?v=sS8ch9HkGHY
|
||||
* https://www.youtube.com/watch?v=cMTjDUOvHVM
|
||||
* https://www.youtube.com/watch?v=WrVsge_MNp4
|
||||
* https://2009scape.wiki/w/Money_making_guide/Casting_fruitfall
|
||||
*/
|
||||
private static final WeightedChanceItem[] FRUIT_FALL = new WeightedChanceItem[] {
|
||||
new WeightedChanceItem(Items.ORANGE_2108, 1, 4),
|
||||
new WeightedChanceItem(Items.PINEAPPLE_2114, 1, 3),
|
||||
new WeightedChanceItem(Items.LEMON_2102, 1, 2),
|
||||
new WeightedChanceItem(Items.LIME_2120, 1, 2),
|
||||
new WeightedChanceItem(Items.BANANA_1963, 1, 2),
|
||||
new WeightedChanceItem(0, 1, 4)
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FruitBatNPC} {@code Object}.
|
||||
*/
|
||||
public FruitBatNPC() {
|
||||
this(null, 6817);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FruitBatNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public FruitBatNPC(Player owner, int id) {
|
||||
super(owner, id, 4500, 12033, 6, FRUIT_FORAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new FruitBatNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6817 };
|
||||
}
|
||||
|
||||
/**
|
||||
* Fruitfall works as follows:
|
||||
* - 80% chance of getting anything at all, in which case a papaya is guaranteed, then
|
||||
* - increasingly small chance of getting up to 7 more fruits from the table.
|
||||
*/
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
if (owner.getAttribute("fruit-bat", 0) > GameWorld.getTicks()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final boolean anyFruit = RandomFunction.random(10) <= 8;
|
||||
final boolean goodFruit = RandomFunction.random(100) <= 2;
|
||||
final int otherFruitAmount = (!goodFruit && RandomFunction.random(10) == 1) ? RandomFunction.random(0, 1) : RandomFunction.random(0, goodFruit ? 7 : 3);
|
||||
|
||||
animate(new Animation(8320));
|
||||
graphics(new Graphics(1332, 200));
|
||||
animate(new Animation(8321), 3); // TODO - this animates the fruit bat with the splattering fruit animation, should do it for all falling fruits but Items are not Entities and therefore cannot animate
|
||||
graphics(new Graphics(1331), 4);
|
||||
owner.setAttribute("fruit-bat", GameWorld.getTicks() + 5);
|
||||
lock(4);
|
||||
GameWorld.getPulser().submit(new Pulse(4, this) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
if (anyFruit){
|
||||
class Pair {
|
||||
public final int p1;
|
||||
public final int p2;
|
||||
Pair(int p1, int p2) {
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
}
|
||||
}
|
||||
List<Pair> coords = new LinkedList<>();
|
||||
coords.add(new Pair(-1, -1));
|
||||
coords.add(new Pair(-1, 0));
|
||||
coords.add(new Pair(-1, 1));
|
||||
coords.add(new Pair(0, -1));
|
||||
coords.add(new Pair(0, 1));
|
||||
coords.add(new Pair(1, -1));
|
||||
coords.add(new Pair(1, 0));
|
||||
coords.add(new Pair(1, 1));
|
||||
Collections.shuffle(coords);
|
||||
|
||||
Pair coord = coords.remove(0);
|
||||
GroundItemManager.create(new Item(Items.PAPAYA_FRUIT_5972),
|
||||
owner.getLocation().transform(coord.p1, coord.p2, 0),
|
||||
owner);
|
||||
|
||||
for (int i = 0; i < otherFruitAmount; i++) {
|
||||
Item item = RandomFunction.rollWeightedChanceTable(FRUIT_FALL);
|
||||
if (item.getId() != 0) {
|
||||
coord = coords.remove(0);
|
||||
GroundItemManager.create(item,
|
||||
owner.getLocation().transform(coord.p1, coord.p2, 0),
|
||||
owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the Geyser Titan familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class GeyserTitanNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GeyserTitanNPC} {@code Object}.
|
||||
*/
|
||||
public GeyserTitanNPC() {
|
||||
this(null, 7339);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GeyserTitanNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public GeyserTitanNPC(Player owner, int id) {
|
||||
super(owner, id, 6900, 12786, 6, WeaponInterface.STYLE_RANGE_ACCURATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new GeyserTitanNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
if (!canCombatSpecial(special.getTarget())) {
|
||||
return false;
|
||||
}
|
||||
Entity target = special.getTarget();
|
||||
visualize(new Animation(7883), new Graphics(1375, 315));
|
||||
int maxHit = 30;
|
||||
int defBonus = 0;
|
||||
for (int i = 5; i < 11; i++) {
|
||||
defBonus += target.getProperties().getBonuses()[i];
|
||||
}
|
||||
maxHit = defBonus / 40;
|
||||
if (maxHit <= 1) {
|
||||
maxHit = RandomFunction.random(0, 3);
|
||||
}
|
||||
if (maxHit > 30) {
|
||||
maxHit = RandomFunction.random(20, 30);
|
||||
}
|
||||
Projectile.ranged(this, special.getTarget(), 1376, 300, 30, 0, 45).send();
|
||||
super.sendFamiliarHit(special.getTarget(), maxHit, Graphics.create(1377));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7339, 7340 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the Giant Chinchompa familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class GiantChinchompaNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GiantChinchompaNPC} {@code Object}.
|
||||
*/
|
||||
public GiantChinchompaNPC() {
|
||||
this(null, 7353);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GiantChinchompaNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public GiantChinchompaNPC(Player owner, int id) {
|
||||
super(owner, id, 3100, 12800, 3, WeaponInterface.STYLE_RANGE_ACCURATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new GiantChinchompaNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttack(Entity entity) {
|
||||
super.onAttack(entity);
|
||||
if (RandomFunction.random(20) == 10) {
|
||||
executeSpecialMove(new FamiliarSpecial(null));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
if (!isOwnerAttackable()) {
|
||||
return false;
|
||||
}
|
||||
final List<Entity> entitys = RegionManager.getLocalEntitys(owner, 6);
|
||||
entitys.remove(owner);
|
||||
entitys.remove(this);
|
||||
sendChat("Squeak!");
|
||||
animate(Animation.create(7758));
|
||||
graphics(Graphics.create(1364));
|
||||
GameWorld.getPulser().submit(new Pulse(3, owner, this) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
for (Entity entity : entitys) {
|
||||
if (canCombatSpecial(entity, false)) {
|
||||
entity.getImpactHandler().manualHit(GiantChinchompaNPC.this, RandomFunction.random(13), HitsplatType.NORMAL);
|
||||
}
|
||||
}
|
||||
dismiss();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7353, 7354 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import content.global.skill.farming.FarmingPatch;
|
||||
import content.global.skill.farming.PatchType;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import core.tools.RandomFunction;
|
||||
import org.rs09.consts.Items;
|
||||
|
||||
/**
|
||||
* Represents the Giant Ent familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class GiantEntNPC extends Forager {
|
||||
private static final Item[] ITEMS = new Item[] { new Item(Items.OAK_LOGS_1521) };
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GiantEntNPC} {@code Object}.
|
||||
*/
|
||||
public GiantEntNPC() {
|
||||
this(null, 6800);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GiantEntNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public GiantEntNPC(Player owner, int id) {
|
||||
super(owner, id, 4900, 12013, 6, WeaponInterface.STYLE_CONTROLLED, ITEMS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new GiantEntNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6800, 6801 };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureFamiliar() {
|
||||
UseWithHandler.addHandler(6800, UseWithHandler.NPC_TYPE, new UseWithHandler(Items.PURE_ESSENCE_7936) {
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
addHandler(6800, UseWithHandler.NPC_TYPE, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(NodeUsageEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
player.lock(1);
|
||||
int runeType = RandomFunction.random(9) < 4 ? Items.EARTH_RUNE_557 : Items.NATURE_RUNE_561;
|
||||
Item runes = new Item(runeType, 1);
|
||||
if (player.getInventory().remove(event.getUsedItem())) {
|
||||
player.getInventory().add(runes);
|
||||
player.sendMessage(String.format("The giant ent transmutes the pure essence into a %s.", runes.getName().toLowerCase()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void modifyFarmingReward(FarmingPatch fPatch, Item reward) {
|
||||
PatchType patchType = fPatch.getType();
|
||||
if(patchType == PatchType.FRUIT_TREE ||
|
||||
patchType == PatchType.BUSH ||
|
||||
patchType == PatchType.BELLADONNA ||
|
||||
patchType == PatchType.CACTUS) {
|
||||
if(RandomFunction.roll(2)) {
|
||||
reward.setAmount(2 * reward.getAmount());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.fishing.Fish;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the Granite Crab familiar.
|
||||
* @author Vexia
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class GraniteCrabNPC extends Forager {
|
||||
|
||||
/**
|
||||
* The fish item.
|
||||
*/
|
||||
private static final Item[] FISH = new Item[] { Fish.COD.getItem(), Fish.PIKE.getItem(), Fish.SEAWEED.getItem(), Fish.OYSTER.getItem() };
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GraniteCrabNPC} {@code Object}.
|
||||
*/
|
||||
public GraniteCrabNPC() {
|
||||
this(null, 6796);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GraniteCrabNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public GraniteCrabNPC(Player owner, int id) {
|
||||
super(owner, id, 1800, 12009, 12, WeaponInterface.STYLE_DEFENSIVE);
|
||||
boosts.add(new SkillBonus(Skills.FISHING, 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new GraniteCrabNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlePassiveAction() {
|
||||
if (RandomFunction.random(4) == 1) {
|
||||
final Item item = FISH[RandomFunction.random(FISH.length)];
|
||||
animate(Animation.create(8107));
|
||||
if (item.getId() == Fish.COD.getItem().getId() || item.getId() == Fish.PIKE.getItem().getId()) {
|
||||
owner.getSkills().addExperience(Skills.FISHING, 5.5);
|
||||
}
|
||||
produceItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
owner.getSkills().updateLevel(Skills.DEFENCE, 4);
|
||||
visualize(Animation.create(8109), Graphics.create(1326));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visualizeSpecialMove() {
|
||||
owner.visualize(new Animation(7660), new Graphics(1296));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6796, 6797 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.fishing.Fish;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Initializable;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the Granite Lobster familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class GraniteLobsterNPC extends Forager {
|
||||
|
||||
/**
|
||||
* The fish.
|
||||
*/
|
||||
private static final Item[] FISH = new Item[] { new Item(383), new Item(377) };
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GraniteLobsterNPC} {@code Object}.
|
||||
*/
|
||||
public GraniteLobsterNPC() {
|
||||
this(null, 6849);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GraniteLobsterNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public GraniteLobsterNPC(Player owner, int id) {
|
||||
super(owner, id, 4700, 12069, 6);
|
||||
boosts.add(new SkillBonus(Skills.FISHING, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new GraniteLobsterNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
Entity target = special.getTarget();
|
||||
if (!canCombatSpecial(target)) {
|
||||
return false;
|
||||
}
|
||||
animate(new Animation(8118));
|
||||
graphics(Graphics.create(1351));
|
||||
Projectile.ranged(this, target, 1352, 60, 40, 1, 45).send();
|
||||
sendFamiliarHit(target, 14);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlePassiveAction() {
|
||||
if (RandomFunction.random(4) == 1) {
|
||||
final Item item = FISH[RandomFunction.random(FISH.length)];
|
||||
animate(Animation.create(8107));
|
||||
Fish fish = Fish.forItem(item);
|
||||
owner.getSkills().addExperience(Skills.FISHING, fish.getExperience() * 0.10);
|
||||
produceItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6849, 6850 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.impl.Animator.Priority;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Honey Badger familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class HoneyBadgerNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code HoneyBadgerNPC} {@code Object}.
|
||||
*/
|
||||
public HoneyBadgerNPC() {
|
||||
this(null, 6845);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code HoneyBadgerNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public HoneyBadgerNPC(Player owner, int id) {
|
||||
super(owner, id, 2500, 12065, 4, WeaponInterface.STYLE_AGGRESSIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new HoneyBadgerNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visualizeSpecialMove() {
|
||||
owner.visualize(Animation.create(7660), Graphics.create(1399));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "Raaaar!";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
if (isCharged()) {
|
||||
return false;
|
||||
}
|
||||
charge();
|
||||
visualize(new Animation(7928, Priority.HIGH), Graphics.create(1397));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCharged() {
|
||||
if (charged) {
|
||||
owner.getPacketDispatch().sendMessage("Your honey badger is already enraged!");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6845, 6846 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import content.global.skill.farming.FarmingPatch;
|
||||
import content.global.skill.farming.Patch;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.scenery.Scenery;
|
||||
import core.plugin.Initializable;
|
||||
|
||||
/**
|
||||
* Represents the Hydra familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class HydraNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code HydraNPC} {@code Object}.
|
||||
*/
|
||||
public HydraNPC() {
|
||||
this(null, 6811);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code HydraNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public HydraNPC(Player owner, int id) {
|
||||
super(owner, id, 4900, 12025, 6, WeaponInterface.STYLE_RANGE_ACCURATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new HydraNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
Node node = special.getNode();
|
||||
if(node instanceof Scenery) {
|
||||
Scenery scenery = (Scenery)node;
|
||||
FarmingPatch farmingPatch = FarmingPatch.forObject(scenery);
|
||||
if(farmingPatch != null) {
|
||||
Patch patch = farmingPatch.getPatchFor(owner);
|
||||
patch.regrowIfTreeStump();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6811, 6812 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.fishing.Fish;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.GroundItemManager;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the Ibis familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class IbisNPC extends Forager {
|
||||
|
||||
/**
|
||||
* The randon fish during fish rain.
|
||||
*/
|
||||
private static final Fish[] FISH = new Fish[] { Fish.SHRIMP, Fish.BASS, Fish.COD, Fish.MACKEREL };
|
||||
|
||||
/**
|
||||
* Constructs a new {@code IbisNPC} {@code Object}.
|
||||
*/
|
||||
public IbisNPC() {
|
||||
this(null, 6991);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code IbisNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public IbisNPC(Player owner, int id) {
|
||||
super(owner, id, 3800, 12531, 12, new Item(361), new Item(373));
|
||||
boosts.add(new SkillBonus(Skills.FISHING, 3));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlePassiveAction() {
|
||||
if (RandomFunction.random(15) < 4) {
|
||||
produceItem();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean produceItem(Item item) {
|
||||
if (super.produceItem(item)) {
|
||||
if (item.getId() == 373) {
|
||||
owner.getSkills().addExperience(Skills.FISHING, 10);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new IbisNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
animate(Animation.create(8201));
|
||||
GameWorld.getPulser().submit(new Pulse(3, owner, this) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
Location loc = null;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
loc = owner.getLocation().transform(RandomFunction.random(2), RandomFunction.random(2), 0);
|
||||
if (RegionManager.getObject(loc) != null) {
|
||||
continue;
|
||||
}
|
||||
GroundItemManager.create(FISH[RandomFunction.random(FISH.length)].getItem(), loc, owner);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6991 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Ice Titan familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class IceTitanNPC extends ElementalTitanNPC {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code IceTitanNPC} {@code Object}.
|
||||
*/
|
||||
public IceTitanNPC() {
|
||||
this(null, 7359);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code IceTitanNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public IceTitanNPC(Player owner, int id) {
|
||||
super(owner, id, 6400, 12806, 20, WeaponInterface.STYLE_ACCURATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new IceTitanNPC(owner, id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void visualizeSpecialMove() {
|
||||
owner.visualize(new Animation(7660), new Graphics(1306));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7359, 7360 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.BattleState;
|
||||
import core.game.node.entity.combat.CombatStyle;
|
||||
import core.game.node.entity.combat.equipment.SwitchAttack;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Initializable;
|
||||
import core.tools.RandomFunction;
|
||||
import core.game.node.entity.combat.MultiSwingHandler;
|
||||
|
||||
/**
|
||||
* Represents the Iron Titan familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class IronTitanNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* If the titan is using its special move.
|
||||
*/
|
||||
private boolean specialMove;
|
||||
|
||||
/**
|
||||
* The attacks.
|
||||
*/
|
||||
private static final SwitchAttack[] ATTACKS = { new SwitchAttack(CombatStyle.MELEE.getSwingHandler(), Animation.create(8183)) };
|
||||
|
||||
/**
|
||||
* Constructs a new {@code IronTitanNPC} {@code Object}.
|
||||
*/
|
||||
public IronTitanNPC() {
|
||||
this(null, 7375);
|
||||
}
|
||||
/**
|
||||
* Constructs a new {@code IronTitanNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public IronTitanNPC(Player owner, int id) {
|
||||
super(owner, id, 6000, 12822, 12, WeaponInterface.STYLE_DEFENSIVE);
|
||||
super.setCombatHandler(new MultiSwingHandler(true, ATTACKS) {
|
||||
@Override
|
||||
public int swing(Entity entity, Entity victim, BattleState s) {
|
||||
int ticks = super.swing(entity, victim, s);
|
||||
if (specialMove) {
|
||||
BattleState[] states = new BattleState[3];
|
||||
for (int i = 1; i < 3; i++) {
|
||||
BattleState state = states[i] = new BattleState(entity, victim);
|
||||
int hit = 0;
|
||||
if (isAccurateImpact(entity, victim)) {
|
||||
int max = calculateHit(entity, victim, 1.0);
|
||||
state.setMaximumHit(max);
|
||||
hit = RandomFunction.random(max);
|
||||
state.setEstimatedHit(hit);
|
||||
}
|
||||
state.setEstimatedHit(hit);
|
||||
state.setStyle(getCurrent().getStyle());
|
||||
}
|
||||
states[0] = s;
|
||||
s.setTargets(states);
|
||||
specialMove = false;
|
||||
}
|
||||
return ticks;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new IronTitanNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
if (specialMove) {
|
||||
owner.getPacketDispatch().sendMessage("Your familiar is already charging its attack.");
|
||||
return false;
|
||||
}
|
||||
specialMove = true;
|
||||
visualize(Animation.create(8183), Graphics.create(1450));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7375, 7376 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.dialogue.FacialExpression;
|
||||
import core.game.node.entity.npc.Metamorphosis;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Handles the kalphite princess pet.
|
||||
* @author Empathy
|
||||
*
|
||||
*/
|
||||
@Initializable
|
||||
public class KalphiteNPC extends Metamorphosis {
|
||||
|
||||
/**
|
||||
* The kalphite ids.
|
||||
*/
|
||||
private static final int[] KALPHITE_IDS = new int[] { 8602, 8603 };
|
||||
|
||||
/**
|
||||
* Constructs a new {@code KalphiteNPC} object.
|
||||
*/
|
||||
public KalphiteNPC() {
|
||||
super(KALPHITE_IDS);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DialoguePlugin getDialoguePlugin() {
|
||||
return new KalphitePrincessDialogue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the KalphitePrincess dialogue.
|
||||
* @author Empathy
|
||||
*
|
||||
*/
|
||||
public final class KalphitePrincessDialogue extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code KalphitePrincessDialogue} {@code Object}.
|
||||
*/
|
||||
public KalphitePrincessDialogue() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code KalphitePrincessDialogue} {@code Object}.
|
||||
*
|
||||
* @param player the player.
|
||||
*/
|
||||
public KalphitePrincessDialogue(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new KalphitePrincessDialogue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
npc = (NPC) args[0];
|
||||
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "What is it with your kind and potato cactus?");
|
||||
stage = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (stage) {
|
||||
case 0:
|
||||
interpreter.sendDialogues(npc, FacialExpression.OLD_NORMAL, "Truthfully?");
|
||||
stage = 1;
|
||||
break;
|
||||
case 1:
|
||||
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Yeah, please.");
|
||||
stage = 2;
|
||||
break;
|
||||
case 2:
|
||||
interpreter.sendDialogues(npc, FacialExpression.OLD_NORMAL, "Soup. We make a fine soup with it.");
|
||||
stage = 3;
|
||||
break;
|
||||
case 3:
|
||||
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Kalphites can cook?");
|
||||
stage = 4;
|
||||
break;
|
||||
case 4:
|
||||
interpreter.sendDialogues(npc, FacialExpression.OLD_NORMAL, "Nah, we just collect it and put it there because we", "know fools like yourself will come down looking for it", "then inevitably be killed by my mother.");
|
||||
stage = 5;
|
||||
break;
|
||||
case 5:
|
||||
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Evidently not, that's how I got you!");
|
||||
stage = 6;
|
||||
break;
|
||||
case 6:
|
||||
interpreter.sendDialogues(npc, FacialExpression.OLD_NORMAL, "Touch�.");
|
||||
stage = 7;
|
||||
break;
|
||||
case 7:
|
||||
end();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 8602, 8603 };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents the Karamthulhu Overlord familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class KaramthulhuOverlordNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code KaramthulhuOverlordNPC} {@code Object}.
|
||||
*/
|
||||
public KaramthulhuOverlordNPC() {
|
||||
this(null, 6809);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code KaramthulhuOverlordNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public KaramthulhuOverlordNPC(Player owner, int id) {
|
||||
super(owner, id, 4400, 12023, 3, WeaponInterface.STYLE_RANGE_ACCURATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new KaramthulhuOverlordNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6809, 6810 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.TeleportManager.TeleportType;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.zone.impl.WildernessZone;
|
||||
import core.plugin.Initializable;
|
||||
|
||||
/**
|
||||
* Represents the lava titan's dialogue
|
||||
*/
|
||||
@Initializable
|
||||
public final class LavaTitanDialogue extends DialoguePlugin {
|
||||
|
||||
public LavaTitanDialogue() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code LavaTitanDialogue} {@code Object}.
|
||||
* @param player the player.
|
||||
*/
|
||||
public LavaTitanDialogue(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new LavaTitanDialogue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
npc = (NPC) args[0];
|
||||
if (!(npc instanceof Familiar)) {
|
||||
return false;
|
||||
}
|
||||
final Familiar fam = (Familiar) npc;
|
||||
if (fam.getOwner() != player) {
|
||||
player.getPacketDispatch().sendMessage("This is not your familiar.");
|
||||
return true;
|
||||
} else {
|
||||
interpreter.sendOptions("Select an Option", "Chat", "Teleport to Lava Maze");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (buttonId) {
|
||||
case 1:
|
||||
player.sendMessage("The lava titan does not feel like talking now.");
|
||||
end();
|
||||
break;
|
||||
case 2:
|
||||
if (!WildernessZone.checkTeleport(player, 20)) {
|
||||
player.sendMessage("You cannot teleport with the Lava Titan above level 20 wilderness.");
|
||||
end();
|
||||
} else {
|
||||
player.getTeleporter().send(new Location(3048, 3820), TeleportType.NORMAL);
|
||||
end();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 8700 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents the Lava Titan familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class LavaTitanNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code LavaTitanNPC} {@code Object}.
|
||||
*/
|
||||
public LavaTitanNPC() {
|
||||
this(null, 7341);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code LavaTitanNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public LavaTitanNPC(Player owner, int id) {
|
||||
super(owner, id, 6100, 12788, 4, WeaponInterface.STYLE_AGGRESSIVE);
|
||||
boosts.add(new SkillBonus(Skills.MINING, 10));
|
||||
boosts.add(new SkillBonus(Skills.FIREMAKING, 10));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new LavaTitanNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7341, 7342 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.cache.def.impl.NPCDefinition;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the plugin used to handle the lava titan familiar
|
||||
*/
|
||||
@Initializable
|
||||
public final class LavaTitanOptionPlugin extends OptionHandler {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
NPCDefinition.forId(7341).getHandlers().put("option:interact", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(final Player player, Node node, String option) {
|
||||
player.getDialogueInterpreter().open(8700, node.asNpc());
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.GroundItemManager;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.ClassScanner;
|
||||
import core.plugin.Initializable;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the Macaw familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class MacawNPC extends Forager {
|
||||
|
||||
/**
|
||||
* The herb items.
|
||||
*/
|
||||
private static final Item[] HERBS = new Item[] { new Item(249), new Item(251), new Item(253), new Item(255), new Item(257), new Item(2998), new Item(12172), new Item(259), new Item(261), new Item(263), new Item(3000), new Item(265), new Item(2481), new Item(267), new Item(269) };
|
||||
|
||||
/**
|
||||
* The delay until the next special.
|
||||
*/
|
||||
private int specialDelay;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MacawNPC} {@code Object}.
|
||||
*/
|
||||
public MacawNPC() {
|
||||
this(null, 6851);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MacawNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public MacawNPC(Player owner, int id) {
|
||||
super(owner, id, 3100, 12071, 12, HERBS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new MacawNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object object) throws Throwable {
|
||||
ClassScanner.definePlugin(new MacawDialogue());
|
||||
return super.newInstance(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
if (specialDelay > GameWorld.getTicks()) {
|
||||
owner.getPacketDispatch().sendMessage("You must wait one minute until using the macaws special again.");
|
||||
return false;
|
||||
}
|
||||
final Item herb = HERBS[RandomFunction.random(HERBS.length)];
|
||||
animate(Animation.create(8013));
|
||||
graphics(Graphics.create(1321), 2);
|
||||
GameWorld.getPulser().submit(new Pulse(5, owner) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
GroundItemManager.create(herb, getLocation(), owner);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
specialDelay = GameWorld.getTicks() + 100;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the macaw dialogue.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class MacawDialogue extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* The familiar.
|
||||
*/
|
||||
private Familiar familiar;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MacawDialogue} {@code Object}.
|
||||
*/
|
||||
public MacawDialogue() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MacawDialogue} {@code Object}.
|
||||
* @param player the player.
|
||||
*/
|
||||
public MacawDialogue(final Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new MacawDialogue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
familiar = (Familiar) args[0];
|
||||
options("Chat", "Remote view", "Withdraw");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (stage) {
|
||||
case 0:
|
||||
switch (buttonId) {
|
||||
case 1:
|
||||
npc("Awh! Gimme the rum! Gimme the rum!");
|
||||
stage++;
|
||||
break;
|
||||
case 2:
|
||||
end();
|
||||
RemoteViewer.openDialogue(player, familiar);
|
||||
break;
|
||||
case 3:
|
||||
end();
|
||||
((BurdenBeast) familiar).openInterface();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
player(" I don't think you'll like the stuff. Besides, I think there", "is a law about feeding birds alcohol.");
|
||||
stage++;
|
||||
break;
|
||||
case 2:
|
||||
end();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return MacawNPC.this.getIds();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Animation getViewAnimation() {
|
||||
return Animation.create(8013);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRandom() {
|
||||
return 40;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6851, 6852 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.crafting.gem.Gems;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Magpie familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class MagpieNPC extends Forager {
|
||||
|
||||
/**
|
||||
* The items to forage.
|
||||
*/
|
||||
private static final Item[] ITEMS = new Item[] { Gems.SAPPHIRE.getUncut(), Gems.EMERALD.getUncut(), Gems.RUBY.getUncut(), Gems.DIAMOND.getUncut() };
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MagpieNPC} {@code Object}.
|
||||
*/
|
||||
public MagpieNPC() {
|
||||
this(null, 6824);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MagpieNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public MagpieNPC(Player owner, int id) {
|
||||
super(owner, id, 3400, 12041, 3, ITEMS);
|
||||
boosts.add(new SkillBonus(Skills.THIEVING, 3));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new MagpieNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
visualize(Animation.create(8020), Graphics.create(1336));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visualizeSpecialMove() {
|
||||
owner.getSkills().updateLevel(Skills.THIEVING, 2);
|
||||
owner.visualize(new Animation(7660), new Graphics(1296));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRandom() {
|
||||
return 14;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6824 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,342 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.CombatStyle;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.ClassScanner;
|
||||
import core.plugin.Initializable;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* The plugin used to load the minotaur familiar npcs.
|
||||
* @author Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class MinotaurFamiliarNPC implements Plugin<Object> {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ClassScanner.definePlugin(new BronzeMinotaurNPC());
|
||||
ClassScanner.definePlugin(new IronMinotaurNPC());
|
||||
ClassScanner.definePlugin(new SteelMinotaurNPC());
|
||||
ClassScanner.definePlugin(new MithrilMinotaurNPC());
|
||||
ClassScanner.definePlugin(new AdamantMinotaurNPC());
|
||||
ClassScanner.definePlugin(new RuneMinotaurNPC());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fireEvent(String identifier, Object... args) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the bullrush special.
|
||||
* @param familiar the familiar.
|
||||
* @param special the special.
|
||||
* @param maxHit the max hit.
|
||||
*/
|
||||
public boolean bullRush(final Familiar familiar, final FamiliarSpecial special, final int maxHit) {
|
||||
final Entity target = (Entity) special.getNode();
|
||||
if (!familiar.canCombatSpecial(target)) {
|
||||
return false;
|
||||
}
|
||||
familiar.sendFamiliarHit(target, RandomFunction.random(maxHit));
|
||||
Projectile.magic(familiar, target, 1497, 80, 36, 70, 10).send();
|
||||
familiar.visualize(Animation.create(8026), Graphics.create(1496));
|
||||
if (!(familiar instanceof BronzeMinotaurNPC || familiar instanceof RuneMinotaurNPC) && RandomFunction.random(10) < 6) {
|
||||
final int ticks = 2 + (int) Math.floor(familiar.getLocation().getDistance(target.getLocation()) * 0.5);
|
||||
GameWorld.getPulser().submit(new Pulse(ticks) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
target.getStateManager().set(EntityState.STUNNED, 4);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the Bronze Minotaur familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
public class BronzeMinotaurNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BronzeMinotaurNPC} {@code Object}.
|
||||
*/
|
||||
public BronzeMinotaurNPC() {
|
||||
this(null, 6853);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BronzeMinotaurNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public BronzeMinotaurNPC(Player owner, int id) {
|
||||
super(owner, id, 3000, 12073, 6, WeaponInterface.STYLE_DEFENSIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new BronzeMinotaurNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return bullRush(this, special, 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPoisonImmune() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6853, 6854 };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the Iron Minotaur familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
public class IronMinotaurNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code IronMinotaurNPC} {@code Object}.
|
||||
*/
|
||||
public IronMinotaurNPC() {
|
||||
this(null, 6855);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code IronMinotaurNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public IronMinotaurNPC(Player owner, int id) {
|
||||
super(owner, id, 3700, 12075, 6, WeaponInterface.STYLE_DEFENSIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new IronMinotaurNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return bullRush(this, special, 6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPoisonImmune() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6855, 6856 };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the Steel Minotaur familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
public class SteelMinotaurNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SteelMinotaurNPC} {@code Object}.
|
||||
*/
|
||||
public SteelMinotaurNPC() {
|
||||
this(null, 6857);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SteelMinotaurNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SteelMinotaurNPC(Player owner, int id) {
|
||||
super(owner, id, 4600, 12077, 6, WeaponInterface.STYLE_DEFENSIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SteelMinotaurNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return bullRush(this, special, 9);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CombatStyle getCombatStyle() {
|
||||
return CombatStyle.MELEE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPoisonImmune() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6857, 6858 };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the Mithril Minotaur familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
public class MithrilMinotaurNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MithrilMinotaurNPC} {@code Object}.
|
||||
*/
|
||||
public MithrilMinotaurNPC() {
|
||||
this(null, 6859);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MithrilMinotaurNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public MithrilMinotaurNPC(Player owner, int id) {
|
||||
super(owner, id, 5500, 12079, 6, WeaponInterface.STYLE_DEFENSIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new MithrilMinotaurNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return bullRush(this, special, 13);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPoisonImmune() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6859, 6860 };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the Adamant Minotaur familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
public class AdamantMinotaurNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code AdamantMinotaurNPC} {@code Object}.
|
||||
*/
|
||||
public AdamantMinotaurNPC() {
|
||||
this(null, 6861);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code AdamantMinotaurNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public AdamantMinotaurNPC(Player owner, int id) {
|
||||
super(owner, id, 6600, 12081, 6, WeaponInterface.STYLE_DEFENSIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new AdamantMinotaurNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return bullRush(this, special, 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CombatStyle getCombatStyle() {
|
||||
return CombatStyle.MELEE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPoisonImmune() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6861, 6862 };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the Rune Minotaur familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
public class RuneMinotaurNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code RuneMinotaurNPC} {@code Object}.
|
||||
*/
|
||||
public RuneMinotaurNPC() {
|
||||
this(null, 6863);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code RuneMinotaurNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public RuneMinotaurNPC(Player owner, int id) {
|
||||
super(owner, id, 15100, 12083, 6, WeaponInterface.STYLE_DEFENSIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new RuneMinotaurNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return bullRush(this, special, 20);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPoisonImmune() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6863, 6864 };
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents the Moss Titan familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class MossTitanNPC extends ElementalTitanNPC {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MossTitanNPC} {@code Object}.
|
||||
*/
|
||||
public MossTitanNPC() {
|
||||
this(null, 7357);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MossTitanNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public MossTitanNPC(Player owner, int id) {
|
||||
super(owner, id, 5800, 12804, 20, WeaponInterface.STYLE_AGGRESSIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new MossTitanNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7357, 7358 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Obsidian Golem familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class ObsidianGolemNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ObsidianGolemNPC} {@code Object}.
|
||||
*/
|
||||
public ObsidianGolemNPC() {
|
||||
this(null, 7345);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ObsidianGolemNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public ObsidianGolemNPC(Player owner, int id) {
|
||||
super(owner, id, 5500, 12792, 12, WeaponInterface.STYLE_AGGRESSIVE);
|
||||
boosts.add(new SkillBonus(Skills.MINING, 7));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new ObsidianGolemNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
graphics(Graphics.create(1465));
|
||||
owner.getSkills().updateLevel(Skills.STRENGTH, 9);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "Onwards, to Glory!";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7345, 7346 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.system.config.ItemConfigParser;
|
||||
import core.plugin.Initializable;
|
||||
import content.global.skill.summoning.SummoningScroll;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Pack Yak familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class PackYakNPC extends BurdenBeast {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PackYakNPC} {@code Object}.
|
||||
*/
|
||||
public PackYakNPC() {
|
||||
this(null, 6873);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PackYakNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public PackYakNPC(Player owner, int id) {
|
||||
super(owner, id, 5800, 12093, 12, 30, WeaponInterface.STYLE_AGGRESSIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new PackYakNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
Player player = owner;
|
||||
Item item = new Item(special.getItem().getId(), 1);
|
||||
if (item.getId() == SummoningScroll.WINTER_STORAGE_SCROLL.getItemId()) {
|
||||
return false;
|
||||
}
|
||||
if (!item.getDefinition().getConfiguration(ItemConfigParser.BANKABLE, true)) {
|
||||
player.sendMessage("A magical force prevents you from banking this item");
|
||||
return false;
|
||||
}
|
||||
Item remove = item;
|
||||
if (!item.getDefinition().isUnnoted()) {
|
||||
remove = new Item(item.getId(), 1);
|
||||
item = new Item(item.getNoteChange(), 1);
|
||||
}
|
||||
if (player.getInventory().remove(remove) && player.getBank().add(item)) {
|
||||
player.getDialogueInterpreter().close();
|
||||
graphics(Graphics.create(1358));
|
||||
player.getPacketDispatch().sendMessage("The pak yak has sent an item to your bank.");
|
||||
} else {
|
||||
player.getPacketDispatch().sendMessage("The pak yak can't send that item to your bank.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visualizeSpecialMove() {
|
||||
owner.visualize(Animation.create(7660), Graphics.create(1316));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6873, 6874 };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getText() {
|
||||
return "Baroo!";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents the Praying Mantis familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class PrayingMantisNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PrayingMantisNPC} {@code Object}.
|
||||
*/
|
||||
public PrayingMantisNPC() {
|
||||
this(null, 6798);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PrayingMantisNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public PrayingMantisNPC(Player owner, int id) {
|
||||
super(owner, id, 6900, 12011, 6, WeaponInterface.STYLE_ACCURATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new PrayingMantisNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6798, 6799 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.player.link.diary.DiaryType;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.crafting.jewellery.JewelleryCrafting;
|
||||
import content.global.skill.firemaking.FireMakingPulse;
|
||||
import content.global.skill.firemaking.Log;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.GroundItem;
|
||||
import core.game.node.item.GroundItemManager;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.scenery.Scenery;
|
||||
import core.game.node.scenery.SceneryBuilder;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.game.world.update.flag.player.FaceLocationFlag;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.ClassScanner;
|
||||
|
||||
/**
|
||||
* Represents the Pyrelord familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class PyreLordNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* The animation of the pyre lord.
|
||||
*/
|
||||
private static final Animation FIREMAKE_ANIMATION = Animation.create(8085);
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PyreLordNPC} {@code Object}.
|
||||
*/
|
||||
public PyreLordNPC() {
|
||||
this(null, 7377);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PyreLordNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public PyreLordNPC(Player owner, int id) {
|
||||
super(owner, id, 3200, 12816, 6, WeaponInterface.STYLE_AGGRESSIVE);
|
||||
boosts.add(new SkillBonus(Skills.FIREMAKING, 3));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new PyreLordNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureFamiliar() {
|
||||
ClassScanner.definePlugin(new PyreLordFiremake());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
final Item item = (Item) special.getNode();
|
||||
if (item.getId() != 2357) {
|
||||
owner.getPacketDispatch().sendMessage("You can only use this special on gold bars.");
|
||||
return false;
|
||||
}
|
||||
owner.lock(1);
|
||||
animate(Animation.create(8081));
|
||||
owner.graphics(Graphics.create(1463));
|
||||
JewelleryCrafting.open(owner);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7377, 7378 };
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the use with event of a log on a pyrelord.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class PyreLordFiremake extends UseWithHandler {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PyreLordFiremake} {@code Object}.
|
||||
*/
|
||||
public PyreLordFiremake() {
|
||||
super(1511, 2862, 1521, 1519, 6333, 10810, 1517, 6332, 12581, 1515, 1513, 13567, 10329, 10328, 7406, 7405, 7404);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
for (int id : getIds()) {
|
||||
addHandler(id, NPC_TYPE, this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(NodeUsageEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final Log log = Log.forId(event.getUsedItem().getId());
|
||||
final Familiar familiar = (Familiar) event.getUsedWith();
|
||||
final int ticks = FIREMAKE_ANIMATION.getDefinition().getDurationTicks();
|
||||
if (!player.getFamiliarManager().isOwner(familiar)) {
|
||||
return true;
|
||||
}
|
||||
if (RegionManager.getObject(familiar.getLocation()) != null || familiar.getZoneMonitor().isInZone("bank")) {
|
||||
player.getPacketDispatch().sendMessage("You can't light a fire here.");
|
||||
return false;
|
||||
}
|
||||
familiar.lock(ticks);
|
||||
familiar.animate(FIREMAKE_ANIMATION);
|
||||
if (player.getInventory().remove(event.getUsedItem())) {
|
||||
final GroundItem ground = GroundItemManager.create(event.getUsedItem(), familiar.getLocation(), player);
|
||||
GameWorld.getPulser().submit(new Pulse(ticks, player, familiar) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
if (!ground.isActive()) {
|
||||
return true;
|
||||
}
|
||||
final Scenery object = new Scenery(log.getFireId(), familiar.getLocation());
|
||||
familiar.moveStep();
|
||||
GroundItemManager.destroy(ground);
|
||||
player.getSkills().addExperience(Skills.FIREMAKING, log.getXp() + 10);
|
||||
familiar.faceLocation(FaceLocationFlag.getFaceLocation(familiar, object));
|
||||
SceneryBuilder.add(object, log.getLife(), FireMakingPulse.getAsh(player, log, object));
|
||||
if (player.getViewport().getRegion().getId() == 10806) {
|
||||
player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 1, 9);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.consumable.Consumable;
|
||||
import content.data.consumables.Consumables;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Ravenous Locust familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class RavenousLocustNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code RavenousLocustNPC} {@code Object}.
|
||||
*/
|
||||
public RavenousLocustNPC() {
|
||||
this(null, 7372);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code RavenousLocustNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public RavenousLocustNPC(Player owner, int id) {
|
||||
super(owner, id, 2400, 12820, 12, WeaponInterface.STYLE_ACCURATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new RavenousLocustNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
Entity target = special.getTarget();
|
||||
if (!canCombatSpecial(target)) {
|
||||
return false;
|
||||
}
|
||||
animate(getProperties().getAttackAnimation());
|
||||
graphics(Graphics.create(1346));
|
||||
target.graphics(Graphics.create(1347));
|
||||
if (target instanceof Player) {
|
||||
Player p = target.asPlayer();
|
||||
for (Item item : p.getInventory().toArray()) {
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
Consumable consumable = Consumables.getConsumableById(item.getId());
|
||||
if (consumable != null) {
|
||||
p.getInventory().remove(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7372, 7373 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.dialogue.DialogueInterpreter;
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Handles the remote viewing dialogue.
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public final class RemoteViewDialogue extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* The familiar instance.
|
||||
*/
|
||||
private Familiar familiar;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code RemoteViewDialogue} {@code Object}.
|
||||
*/
|
||||
public RemoteViewDialogue() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code RemoteViewDialogue} {@code Object}.
|
||||
* @param player the player.
|
||||
*/
|
||||
public RemoteViewDialogue(final Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new RemoteViewDialogue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
familiar = (Familiar) args[0];
|
||||
options("North", "East", "South", "West", "Straight up");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
end();
|
||||
RemoteViewer.create(player, familiar, familiar.getViewAnimation(), RemoteViewer.ViewType.values()[-1 + buttonId]).startViewing();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { DialogueInterpreter.getDialogueKey(RemoteViewer.DIALOGUE_NAME) };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Direction;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.net.packet.PacketRepository;
|
||||
import core.net.packet.context.CameraContext;
|
||||
import core.net.packet.context.CameraContext.CameraType;
|
||||
import core.net.packet.out.CameraViewPacket;
|
||||
|
||||
/**
|
||||
* Handles the remote viewing of an area.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class RemoteViewer {
|
||||
|
||||
/**
|
||||
* The dialogue name to use.
|
||||
*/
|
||||
public static final String DIALOGUE_NAME = "remote-view";
|
||||
|
||||
/**
|
||||
* The remote camera height.
|
||||
*/
|
||||
public static final int HEIGHT = 1000;
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The familiar.
|
||||
*/
|
||||
private final Familiar familiar;
|
||||
|
||||
/**
|
||||
* The animation to start viewing.
|
||||
*/
|
||||
private final Animation animation;
|
||||
|
||||
/**
|
||||
* The view type.
|
||||
*/
|
||||
private final ViewType type;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code RemoteViewer} {@code Object}.
|
||||
* @param player the player.
|
||||
* @param familiar the familiar.
|
||||
* @param animation the animation.
|
||||
* @param type the type.
|
||||
*/
|
||||
public RemoteViewer(Player player, Familiar familiar, Animation animation, ViewType type) {
|
||||
this.player = player;
|
||||
this.familiar = familiar;
|
||||
this.animation = animation;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a remote view object.
|
||||
* @param player the player.
|
||||
* @param familiar the familiar.
|
||||
* @param animation the animation.
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
public static RemoteViewer create(final Player player, Familiar familiar, Animation animation, ViewType type) {
|
||||
return new RemoteViewer(player, familiar, animation, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts viewing an area.
|
||||
*/
|
||||
public void startViewing() {
|
||||
player.lock();
|
||||
familiar.animate(animation);
|
||||
player.getPacketDispatch().sendMessage("You send the " + familiar.getName().toLowerCase() + " to fly " + (type == ViewType.STRAIGHT_UP ? "directly up" : "to the " + type.name().toLowerCase()) + "...");
|
||||
GameWorld.getPulser().submit(new Pulse(5) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
view();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Views the area from the view type.
|
||||
*/
|
||||
private void view() {
|
||||
if (!canView()) {
|
||||
return;
|
||||
}
|
||||
sendCamera(type.getXOffset(), type.getYOffset(), type.getXRot(), type.getYRot());
|
||||
GameWorld.getPulser().submit(new Pulse(13) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
reset();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a remote view can start.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
private boolean canView() {
|
||||
// player.getPacketDispatch().sendMessage("There seems to be an obstruction in the direction; the familiar cannot fly there");
|
||||
if (!familiar.isActive()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the camera packet.
|
||||
*/
|
||||
private void reset() {
|
||||
familiar.call();
|
||||
player.unlock();
|
||||
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.RESET, 0, 0, HEIGHT, 1, 100));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a camera packet.
|
||||
* @param xRot the xRot.
|
||||
* @param yRot the yRot.
|
||||
*/
|
||||
private void sendCamera(int xOffset, int yOffset, final int xRot, final int yRot) {
|
||||
final Location location = type.getLocationTransform(player);
|
||||
final int x = location.getX() + xOffset;
|
||||
final int y = location.getY() + yOffset;
|
||||
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.POSITION, x, y, HEIGHT, 1, 100));
|
||||
PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.ROTATION, x + xRot, y + yRot, HEIGHT, 1, 90));
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the remote viewing dialogue.
|
||||
* @param player the player.
|
||||
* @param familiar the familiar.
|
||||
*/
|
||||
public static void openDialogue(final Player player, final Familiar familiar) {
|
||||
player.getDialogueInterpreter().open(DIALOGUE_NAME, familiar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player.
|
||||
* @return The player.
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the familiar.
|
||||
* @return The familiar.
|
||||
*/
|
||||
public Familiar getFamiliar() {
|
||||
return familiar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the animation.
|
||||
* @return The animation.
|
||||
*/
|
||||
public Animation getAnimation() {
|
||||
return animation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type.
|
||||
* @return The type.
|
||||
*/
|
||||
public ViewType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* A view type.
|
||||
* @author Vexia
|
||||
*/
|
||||
public enum ViewType {
|
||||
NORTH(Direction.NORTH, 0, 0, 0, 0), EAST(Direction.WEST, 0, 0, 0, 0), SOUTH(Direction.SOUTH, 0, 0, 0, 0), WEST(Direction.EAST, 0, 0, 0, 0), STRAIGHT_UP(null, 0, 0, 0, 0);
|
||||
|
||||
/**
|
||||
* The direction.
|
||||
*/
|
||||
private final Direction direction;
|
||||
|
||||
/**
|
||||
* The data for the camera.
|
||||
*/
|
||||
private final int[] data;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ViewType} {@code Object}.
|
||||
* @param data the data.
|
||||
*/
|
||||
private ViewType(Direction direction, int... data) {
|
||||
this.direction = direction;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the transformed location.
|
||||
* @param player the player.
|
||||
* @return the location.
|
||||
*/
|
||||
public Location getLocationTransform(final Player player) {
|
||||
if (this == STRAIGHT_UP) {
|
||||
return player.getLocation();
|
||||
}
|
||||
return player.getLocation().transform(direction, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the direction.
|
||||
* @return The direction.
|
||||
*/
|
||||
public Direction getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the x offset.
|
||||
* @return the offset.
|
||||
*/
|
||||
public int getXOffset() {
|
||||
return data[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the y offset.
|
||||
* @return the offset.
|
||||
*/
|
||||
public int getYOffset() {
|
||||
return data[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the x rotation.
|
||||
* @return the rotation.
|
||||
*/
|
||||
public int getXRot() {
|
||||
return data[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the y rot.
|
||||
* @return the rot.
|
||||
*/
|
||||
public int getYRot() {
|
||||
return data[3];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data.
|
||||
* @return The data.
|
||||
*/
|
||||
public int[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import core.cache.def.impl.NPCDefinition;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Plugin;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the Smoke Devil familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class SmokeDevilNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SmokeDevilNPC} {@code Object}.
|
||||
*/
|
||||
public SmokeDevilNPC() {
|
||||
this(null, 6865);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SmokeDevilNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SmokeDevilNPC(Player owner, int id) {
|
||||
super(owner, id, 4800, 12085, 6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SmokeDevilNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureFamiliar() {
|
||||
NPCDefinition.setOptionHandler("flames", new OptionHandler() {
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
final Familiar familiar = (Familiar) node;
|
||||
if (!player.getFamiliarManager().isOwner(familiar)) {
|
||||
return true;
|
||||
}
|
||||
// TODO:
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
if (!isOwnerAttackable()) {
|
||||
return false;
|
||||
}
|
||||
final List<Entity> entitys = RegionManager.getLocalEntitys(this, 1);
|
||||
entitys.remove(this);
|
||||
entitys.remove(owner);
|
||||
visualize(Animation.create(7820), Graphics.create(1375));
|
||||
for (Entity e : entitys) {
|
||||
if (super.canCombatSpecial(e, false)) {
|
||||
e.getImpactHandler().manualHit(this, RandomFunction.random(6), HitsplatType.NORMAL);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6865, 6866 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.dialogue.FacialExpression;
|
||||
import core.game.node.entity.npc.Metamorphosis;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Handles the metamorphosis of the zulrah pet.
|
||||
* @author Empathy
|
||||
*
|
||||
*/
|
||||
@Initializable
|
||||
public class SnakelingNPC extends Metamorphosis {
|
||||
|
||||
/**
|
||||
* The snakeling ids.
|
||||
*/
|
||||
public static final int[] SNAKELING_IDS = new int[] { 8626, 8627, 8628 };
|
||||
|
||||
/**
|
||||
*
|
||||
* Constructs a new {@code SnakelingNPC} object.
|
||||
*/
|
||||
public SnakelingNPC() {
|
||||
super(SNAKELING_IDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin getDialoguePlugin() {
|
||||
return new PetSnakelingDialogue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the pet snakeling dialogue.
|
||||
* @author Empathy
|
||||
*
|
||||
*/
|
||||
public final class PetSnakelingDialogue extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PetSnakelingDialogue} {@code Object}.
|
||||
*/
|
||||
public PetSnakelingDialogue() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PetSnakelingDialogue} {@code Object}.
|
||||
*
|
||||
* @param player the player.
|
||||
*/
|
||||
public PetSnakelingDialogue(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new PetSnakelingDialogue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
npc = (NPC) args[0];
|
||||
player("Hey little snake!");
|
||||
stage = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (stage) {
|
||||
case 0:
|
||||
npc(FacialExpression.OLD_NORMAL, "Soon, Zulrah shall establish dominion over this plane.");
|
||||
stage = 1;
|
||||
break;
|
||||
case 1:
|
||||
player("Wanna play fetch?");
|
||||
stage = 2;
|
||||
break;
|
||||
case 2:
|
||||
npc(FacialExpression.OLD_NORMAL, "Submit to the almighty Zulrah.");
|
||||
stage = 3;
|
||||
break;
|
||||
case 3:
|
||||
player("Walkies? Or slidies...?");
|
||||
stage = 4;
|
||||
break;
|
||||
case 4:
|
||||
npc(FacialExpression.OLD_NORMAL, "Zulrah's wilderness as a God will soon be demonstrated.");
|
||||
stage = 5;
|
||||
break;
|
||||
case 5:
|
||||
player("I give up...");
|
||||
stage = 6;
|
||||
break;
|
||||
case 6:
|
||||
end();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return SNAKELING_IDS;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* Represents the Spirit Cobra familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class SpiritCobraNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritCobraNPC} {@code Object}.
|
||||
*/
|
||||
public SpiritCobraNPC() {
|
||||
this(null, 6802);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritCobraNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SpiritCobraNPC(Player owner, int id) {
|
||||
super(owner, id, 5600, 12015, 3, WeaponInterface.STYLE_ACCURATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritCobraNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
final Item item = (Item) special.getNode();
|
||||
final Egg egg = Egg.forEgg(item);
|
||||
if (egg == null) {
|
||||
owner.getPacketDispatch().sendMessage("You can't use the special move on this item.");
|
||||
return false;
|
||||
}
|
||||
owner.getInventory().replace(egg.getProduct(), item.getSlot());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6802, 6803 };
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an incubated egg.
|
||||
* @author Vexia
|
||||
*/
|
||||
public enum Egg {
|
||||
COCKATRICE(new Item(1944), new Item(12109)), SARATRICE(new Item(10533), new Item(12113)), ZAMATRICE(new Item(10532), new Item(12115)), GUTHATRICE(new Item(10531), new Item(12111)), CORACATRICE(new Item(11964), new Item(12119)), PENGATRICE(new Item(12483), new Item(12117)), VULATRICE(new Item(11695), new Item(12121));
|
||||
|
||||
/**
|
||||
* The egg item.
|
||||
*/
|
||||
private final Item egg;
|
||||
|
||||
/**
|
||||
* The product.
|
||||
*/
|
||||
private final Item product;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Egg} {@code Object}.
|
||||
* @param egg the egg.
|
||||
* @param product the product.
|
||||
*/
|
||||
private Egg(Item egg, Item product) {
|
||||
this.egg = egg;
|
||||
this.product = product;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the egg for the item.
|
||||
* @param item the item.
|
||||
* @return the egg.
|
||||
*/
|
||||
public static Egg forEgg(final Item item) {
|
||||
for (Egg egg : values()) {
|
||||
if (egg.getEgg().getId() == item.getId()) {
|
||||
return egg;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the egg.
|
||||
* @return The egg.
|
||||
*/
|
||||
public Item getEgg() {
|
||||
return egg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the product.
|
||||
* @return The product.
|
||||
*/
|
||||
public Item getProduct() {
|
||||
return product;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents the Spirit Dagannoth familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class SpiritDagannothNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritDagannothNPC} {@code Object}.
|
||||
*/
|
||||
public SpiritDagannothNPC() {
|
||||
this(null, 6804);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritDagannothNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SpiritDagannothNPC(Player owner, int id) {
|
||||
super(owner, id, 5700, 12017, 6, WeaponInterface.STYLE_CONTROLLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritDagannothNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6804, 6805 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.TeleportManager.TeleportType;
|
||||
import core.game.world.map.Location;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.world.map.zone.impl.WildernessZone;
|
||||
|
||||
/**
|
||||
* Represents the spirit graahk's dialogue
|
||||
* @author Splinter
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class SpiritGraahkDialogue extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GertrudesCatDialogue} {@code Object}.
|
||||
*/
|
||||
public SpiritGraahkDialogue() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GertrudesCatDialogue} {@code Object}.
|
||||
* @param player the player.
|
||||
*/
|
||||
public SpiritGraahkDialogue(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new SpiritGraahkDialogue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
npc = (NPC) args[0];
|
||||
if (!(npc instanceof Familiar)) {
|
||||
return false;
|
||||
}
|
||||
final Familiar fam = (Familiar) npc;
|
||||
if (fam.getOwner() != player) {
|
||||
player.getPacketDispatch().sendMessage("This is not your familiar.");
|
||||
return true;
|
||||
} else {
|
||||
interpreter.sendOptions("Select an Option", "Chat", "Teleport");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (buttonId) {
|
||||
case 1:
|
||||
player.sendMessage("The Graahk does not feel like talking now.");
|
||||
end();
|
||||
break;
|
||||
case 2:
|
||||
if (!WildernessZone.checkTeleport(player, 20)) {
|
||||
player.sendMessage("You cannot teleport with the Graahk above level 20 wilderness.");
|
||||
end();
|
||||
} else {
|
||||
player.getTeleporter().send(new Location(2786, 3002), TeleportType.NORMAL);
|
||||
end();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7353, 7364 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents the Spirit Graahk familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class SpiritGraahkNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritGraahkNPC} {@code Object}.
|
||||
*/
|
||||
public SpiritGraahkNPC() {
|
||||
this(null, 7363);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritGraahkNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SpiritGraahkNPC(Player owner, int id) {
|
||||
super(owner, id, 4900, 12810, 3, WeaponInterface.STYLE_AGGRESSIVE);
|
||||
boosts.add(new SkillBonus(Skills.HUNTER, 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritGraahkNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
if (!super.isOwnerAttackable()) {
|
||||
return false;
|
||||
}
|
||||
call();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7363, 7364 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.cache.def.impl.NPCDefinition;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the plugin used to handle the spirit graahk familiar
|
||||
* @author Splinter
|
||||
*/
|
||||
@Initializable
|
||||
public final class SpiritGraahkOptionPlugin extends OptionHandler {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
NPCDefinition.forId(7363).getHandlers().put("option:interact", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(final Player player, Node node, String option) {
|
||||
player.getDialogueInterpreter().open(7353, node.asNpc());
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
|
||||
/**
|
||||
* Represents the Spirit Jelly familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class SpiritJellyNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritJellyNPC} {@code Object}.
|
||||
*/
|
||||
public SpiritJellyNPC() {
|
||||
this(null, 6992);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritJellyNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SpiritJellyNPC(Player owner, int id) {
|
||||
super(owner, id, 4300, 12027, 6, WeaponInterface.STYLE_AGGRESSIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritJellyNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
final Entity target = (Entity) special.getNode();
|
||||
if (!canCombatSpecial(target)) {
|
||||
return false;
|
||||
}
|
||||
faceTemporary(target, 2);
|
||||
sendFamiliarHit(target, 13);
|
||||
animate(Animation.create(8575));
|
||||
Projectile.magic(this, target, 1360, 40, 36, 51, 10).send();
|
||||
target.getSkills().updateLevel(Skills.ATTACK, -3, target.getSkills().getStaticLevel(Skills.ATTACK) - 3);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6992, 6993 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Spirit Kalphite familiar.
|
||||
* @author Vexia
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class SpiritKalphiteNPC extends BurdenBeast {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritKalphiteNPC} {@code Object}.
|
||||
*/
|
||||
public SpiritKalphiteNPC() {
|
||||
this(null, 6994);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritKalphiteNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SpiritKalphiteNPC(Player owner, int id) {
|
||||
super(owner, id, 2200, 12063, 6, 6, WeaponInterface.STYLE_DEFENSIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritKalphiteNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
if (!isOwnerAttackable()) {
|
||||
return false;
|
||||
}
|
||||
final List<Entity> entitys = RegionManager.getLocalEntitys(owner, 6);
|
||||
visualize(Animation.create(8517), Graphics.create(1350));
|
||||
GameWorld.getPulser().submit(new Pulse(1, owner) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
int count = 0;
|
||||
for (Entity entity : entitys) {
|
||||
if (count > 5) {
|
||||
return true;
|
||||
}
|
||||
if (!canCombatSpecial(entity)) {
|
||||
continue;
|
||||
}
|
||||
Projectile.magic(SpiritKalphiteNPC.this, entity, 1349, 40, 36, 50, 5).send();
|
||||
sendFamiliarHit(entity, 20);
|
||||
count++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "Hsssss!";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6994, 6995 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.TeleportManager.TeleportType;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.zone.impl.WildernessZone;
|
||||
|
||||
/**
|
||||
* Represents the spirit kyatt's dialogue
|
||||
* @author Splinter
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class SpiritKyattDialogue extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GertrudesCatDialogue} {@code Object}.
|
||||
*/
|
||||
public SpiritKyattDialogue() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GertrudesCatDialogue} {@code Object}.
|
||||
* @param player the player.
|
||||
*/
|
||||
public SpiritKyattDialogue(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new SpiritKyattDialogue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
npc = (NPC) args[0];
|
||||
if (!(npc instanceof Familiar)) {
|
||||
return false;
|
||||
}
|
||||
final Familiar f = (Familiar) npc;
|
||||
if (f.getOwner() != player) {
|
||||
player.getPacketDispatch().sendMessage("This is not your follower.");
|
||||
return true;
|
||||
} else {
|
||||
interpreter.sendOptions("Select an Option", "Chat", "Teleport");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (buttonId) {
|
||||
case 1:
|
||||
player.sendMessage("The Kyatt does not feel like talking now.");
|
||||
end();
|
||||
break;
|
||||
case 2:
|
||||
if (!WildernessZone.checkTeleport(player, 20)) {
|
||||
player.sendMessage("You cannot teleport with the Kyatt above level 20 wilderness.");
|
||||
end();
|
||||
} else {
|
||||
player.getTeleporter().send(new Location(2326, 3636), TeleportType.NORMAL);
|
||||
end();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7365, 7366 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents the Spirit Kyatt familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class SpiritKyattNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritKyattNPC} {@code Object}.
|
||||
*/
|
||||
public SpiritKyattNPC() {
|
||||
this(null, 7366);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritKyattNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SpiritKyattNPC(Player owner, int id) {
|
||||
super(owner, id, 4900, 12812, 3, WeaponInterface.STYLE_ACCURATE);
|
||||
boosts.add(new SkillBonus(Skills.HUNTER, 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritKyattNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
if (!super.isOwnerAttackable()) {
|
||||
return false;
|
||||
}
|
||||
call();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7365, 7366 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.cache.def.impl.NPCDefinition;
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.scenery.Scenery;
|
||||
import core.game.node.scenery.SceneryBuilder;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the plugin used to handle the spirit kyatt familiar and the summoning area.
|
||||
* @author Splinter
|
||||
*/
|
||||
@Initializable
|
||||
public final class SpiritKyattOptionPlugin extends OptionHandler {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
NPCDefinition.forId(7365).getHandlers().put("option:interact", this);
|
||||
SceneryDefinition.forId(28741).getHandlers().put("option:open", this);
|
||||
SceneryDefinition.forId(28743).getHandlers().put("option:climb-up", this);
|
||||
SceneryDefinition.forId(28743).getHandlers().put("option:climb-up", this);
|
||||
SceneryDefinition.forId(14910).getHandlers().put("option:take", this);
|
||||
SceneryDefinition.forId(14912).getHandlers().put("option:take", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
private final Item BRONZE_AXE = new Item(1351, 1);
|
||||
private final Item BRONZE_PICKAXE = new Item(1265, 1);
|
||||
|
||||
@Override
|
||||
public boolean handle(final Player player, Node node, String option) {
|
||||
switch(node.getId()){
|
||||
case 7365:
|
||||
player.getDialogueInterpreter().open(7365, node.asNpc());
|
||||
break;
|
||||
case 28741:
|
||||
player.animate(new Animation(827));
|
||||
player.teleport(new Location(2333, 10015));
|
||||
break;
|
||||
case 28743:
|
||||
player.animate(new Animation(828));
|
||||
player.teleport(new Location(2328, 3646));
|
||||
break;
|
||||
case 14912:
|
||||
if (!player.getInventory().add(BRONZE_AXE)) {
|
||||
player.getPacketDispatch().sendMessage("You don't have enough inventory space.");
|
||||
return true;
|
||||
}
|
||||
SceneryBuilder.replace(((Scenery) node), ((Scenery) node).transform(14908), 500);
|
||||
break;
|
||||
case 14910:
|
||||
if (!player.getInventory().add(BRONZE_PICKAXE)) {
|
||||
player.getPacketDispatch().sendMessage("You don't have enough inventory space.");
|
||||
return true;
|
||||
}
|
||||
SceneryBuilder.replace(((Scenery) node), ((Scenery) node).transform(14908), 500);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Spirit Larupia familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class SpiritLarupiaNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritLarupiaNPC} {@code Object}.
|
||||
*/
|
||||
public SpiritLarupiaNPC() {
|
||||
this(null, 7337);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritLarupiaNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SpiritLarupiaNPC(Player owner, int id) {
|
||||
super(owner, id, 4900, 12784, 6, WeaponInterface.STYLE_CONTROLLED);
|
||||
boosts.add(new SkillBonus(Skills.HUNTER, 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritLarupiaNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
final Entity target = special.getTarget();
|
||||
if (!canCombatSpecial(target)) {
|
||||
return false;
|
||||
}
|
||||
target.getSkills().updateLevel(Skills.STRENGTH, -1, target.getSkills().getStaticLevel(Skills.STRENGTH) - 1);
|
||||
faceTemporary(target, 2);
|
||||
projectile(target, 1371);
|
||||
sendFamiliarHit(target, 10);
|
||||
visualize(Animation.create(5229), Graphics.create(1370));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7337, 7338 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Spirit Mosquito familiar.
|
||||
* @author Vexia
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class SpiritMosquitoNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritMosquitoNPC} {@code Object}.
|
||||
*/
|
||||
public SpiritMosquitoNPC() {
|
||||
this(null, 7331);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritMosquitoNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SpiritMosquitoNPC(Player owner, int id) {
|
||||
super(owner, id, 1200, 12778, 3, WeaponInterface.STYLE_ACCURATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritMosquitoNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
final Entity target = (Entity) special.getNode();
|
||||
if (!canAttack(target)) {
|
||||
return false;
|
||||
}
|
||||
visualize(Animation.create(8032), Graphics.create(1442));
|
||||
getProperties().getCombatPulse().attack(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPoisonImmune() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7331, 7332 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents the Spirit Pengatrice familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
public class SpiritPengatriceNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritPengatriceNPC} {@code Object}.
|
||||
*/
|
||||
public SpiritPengatriceNPC() {
|
||||
this(null, 6883);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritPengatriceNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SpiritPengatriceNPC(Player owner, int id) {
|
||||
super(owner, id, 3600, 12103, 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritPengatriceNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6883, 6884 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.BattleState;
|
||||
import core.game.node.entity.combat.CombatStyle;
|
||||
import core.game.node.entity.combat.equipment.Weapon;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Spirit Scorpion familiar.
|
||||
* @author Vexia
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class SpiritScorpionNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritScorpionNPC} {@code Object}.
|
||||
*/
|
||||
public SpiritScorpionNPC() {
|
||||
this(null, 6837);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritScorpionNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SpiritScorpionNPC(Player owner, int id) {
|
||||
super(owner, id, 1700, 12055, 6, WeaponInterface.STYLE_CONTROLLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritScorpionNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustPlayerBattle(BattleState state) {
|
||||
if (state.getStyle() == CombatStyle.RANGE) {
|
||||
final Weapon weapon = state.getWeapon();
|
||||
if (isCharged() && new Item(weapon.getId() + 6).getName().startsWith(weapon.getName())) {
|
||||
final Entity victim = state.getVictim();
|
||||
setCharged(false);
|
||||
victim.getStateManager().register(EntityState.POISONED, false, 10, owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
if (isCharged()) {
|
||||
return false;
|
||||
}
|
||||
charge();
|
||||
owner.graphics(new Graphics(1355, 180), 2);
|
||||
visualize(new Animation(6261), new Graphics(1354, 95));
|
||||
Projectile.create(this, owner, 1355, 95, 50, 50, 10).send();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6837, 6838 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.GroundItemManager;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the Spirit Spider familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class SpiritSpiderNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* The red spider egg item.
|
||||
*/
|
||||
private static final Item EGG = new Item(223);
|
||||
|
||||
/**
|
||||
* The delay until the next chance of random eggs.
|
||||
*/
|
||||
private int eggDelay = GameWorld.getTicks() + 500;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritSpiderNPC} {@code Object}.
|
||||
*/
|
||||
public SpiritSpiderNPC() {
|
||||
this(null, 6841);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritSpiderNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SpiritSpiderNPC(Player owner, int id) {
|
||||
super(owner, id, 1500, 12059, 6, WeaponInterface.STYLE_CONTROLLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFamiliarTick() {
|
||||
super.handleFamiliarTick();
|
||||
if (eggDelay < GameWorld.getTicks()) {
|
||||
if (RandomFunction.random(25) == 5) {
|
||||
createEggs();
|
||||
sendChat("Clicketyclack");
|
||||
eggDelay = GameWorld.getTicks() + 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritSpiderNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
createEggs();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates red spider eggs.
|
||||
*/
|
||||
private void createEggs() {
|
||||
final int amount = RandomFunction.random(8);
|
||||
Location location = null;
|
||||
for (int i = 0; i < amount; i++) {
|
||||
location = getEggLocation();
|
||||
if (location == null) {
|
||||
continue;
|
||||
}
|
||||
owner.getPacketDispatch().sendPositionedGraphic(1342, 0, 0, location);
|
||||
GroundItemManager.create(EGG, location, owner);
|
||||
}
|
||||
animate(Animation.create(5328));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the egg location.
|
||||
* @return the location.
|
||||
*/
|
||||
private Location getEggLocation() {
|
||||
Location loc = owner.getLocation().transform(RandomFunction.random(2) == 1 ? -RandomFunction.random(2) : RandomFunction.random(2), RandomFunction.random(2) == 1 ? -RandomFunction.random(2) : RandomFunction.random(2), 0);
|
||||
if (loc.equals(owner.getLocation()) || !RegionManager.isTeleportPermitted(loc) || RegionManager.getObject(loc) != null) {
|
||||
return null;
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6841, 6842 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Spirit Terrorbird familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class SpiritTerrorbirdNPC extends BurdenBeast {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritTerrorbirdNPC} {@code Object}.
|
||||
*/
|
||||
public SpiritTerrorbirdNPC() {
|
||||
this(null, 6794);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritTerrorbirdNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SpiritTerrorbirdNPC(Player owner, int id) {
|
||||
super(owner, id, 3600, 12007, 8, 12, WeaponInterface.STYLE_CONTROLLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritTerrorbirdNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
visualize(Animation.create(1009), Graphics.create(1521));
|
||||
owner.getSkills().updateLevel(Skills.AGILITY, 2);
|
||||
owner.getSettings().updateRunEnergy(-owner.getSkills().getStaticLevel(Skills.AGILITY) / 2.0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visualizeSpecialMove() {
|
||||
owner.visualize(new Animation(7660), new Graphics(1295));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6794, 6795 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Spirit Tz-Kih familiar.
|
||||
* @author Vexia
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class SpiritTzKihNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritTzKihNPC} {@code Object}.
|
||||
*/
|
||||
public SpiritTzKihNPC() {
|
||||
this(null, 7361);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritTzKihNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SpiritTzKihNPC(Player owner, int id) {
|
||||
super(owner, id, 1800, 12808, 6, WeaponInterface.STYLE_CAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritTzKihNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
final List<Entity> entitys = RegionManager.getLocalEntitys(owner, 8);
|
||||
if (entitys.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
boolean success = false;
|
||||
Entity target = null;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (entitys.size() >= i) {
|
||||
target = entitys.get(i);
|
||||
if (target == null || target == this || target == owner) {
|
||||
continue;
|
||||
}
|
||||
if (!canCombatSpecial(target)) {
|
||||
continue;
|
||||
}
|
||||
success = true;
|
||||
sendFamiliarHit(target, 7, Graphics.create(1329));
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
animate(Animation.create(8257));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7361, 7362 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.activity.CutscenePlugin;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Direction;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.path.Path;
|
||||
import core.game.world.map.path.Pathfinder;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Handles the Spirit wolf familiar.
|
||||
* @author Emperor
|
||||
*/
|
||||
@Initializable
|
||||
public final class SpiritWolfNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Represents the cutscene during wolf whistle.
|
||||
*/
|
||||
private CutscenePlugin cutscene;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritWolfNPC} {@code Object}.
|
||||
*/
|
||||
public SpiritWolfNPC() {
|
||||
this(null, 6829);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpiritWolfNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The NPC id.
|
||||
*/
|
||||
public SpiritWolfNPC(Player owner, int id) {
|
||||
super(owner, id, 600, 12047, 3, WeaponInterface.STYLE_ACCURATE);
|
||||
if (owner != null) {
|
||||
cutscene = (CutscenePlugin) owner.getAttribute("in-cutscene", null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SpiritWolfNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
super.init();
|
||||
if (cutscene != null) {
|
||||
getProperties().setTeleportLocation(cutscene.getBase().transform(44, 52, 1));
|
||||
faceLocation(cutscene.getBase().transform(42, 53, 1));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startFollowing() {
|
||||
if (cutscene != null) {
|
||||
return;
|
||||
}
|
||||
super.startFollowing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean call() {
|
||||
if (cutscene != null) {
|
||||
return true;
|
||||
}
|
||||
return super.call();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
if (!(special.getNode() instanceof NPC)) {
|
||||
owner.getPacketDispatch().sendMessage("You can only target monsters with this special move.");
|
||||
return false;
|
||||
}
|
||||
final NPC npc = (NPC) special.getNode();
|
||||
if (npc.getWalkRadius() > 20) { // Usually indicates special NPC.
|
||||
owner.getPacketDispatch().sendMessage("This monster won't get intimidated by your familiar.");
|
||||
return false;
|
||||
}
|
||||
if (cutscene != null) {
|
||||
if (npc.getId() != 6990) {
|
||||
owner.getPacketDispatch().sendMessage("You can't do this right now.");
|
||||
return false;
|
||||
}
|
||||
DialoguePlugin dial = owner.getAttribute("wolf-dial", null);
|
||||
if (dial != null) {
|
||||
dial.handle(0, 0);
|
||||
} else {
|
||||
cutscene.stop(true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!canAttack(npc)) {
|
||||
return false;
|
||||
}
|
||||
visualizeSpecialMove();
|
||||
owner.getAudioManager().send(4265);
|
||||
faceTemporary(npc, owner, 2);
|
||||
super.visualize(Animation.create(8293), new Graphics(1334, 96));
|
||||
Projectile.magic(this, npc, 1333, 40, 36, 50, 5).send();
|
||||
GameWorld.getPulser().submit(new Pulse(2, this, npc) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
npc.faceTemporary(SpiritWolfNPC.this, 2);
|
||||
Location destination = npc.getLocation().transform(Direction.getLogicalDirection(location, npc.getLocation()), 3);
|
||||
Path path = Pathfinder.find(npc, destination);
|
||||
path.walk(npc);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getSpawnLocation() {
|
||||
if (cutscene != null) {
|
||||
return cutscene.getBase().transform(44, 52, 1);
|
||||
}
|
||||
return super.getSpawnLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6829, 6830 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.BattleState;
|
||||
import core.game.node.entity.combat.CombatStyle;
|
||||
import core.game.node.entity.combat.equipment.SwitchAttack;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Initializable;
|
||||
import core.tools.RandomFunction;
|
||||
import core.game.node.entity.combat.MultiSwingHandler;
|
||||
|
||||
/**
|
||||
* Handles the Steel titan familiar.
|
||||
* @author Emperor
|
||||
*/
|
||||
@Initializable
|
||||
public final class SteelTitanNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* If the titan is using its special move.
|
||||
*/
|
||||
private boolean specialMove;
|
||||
|
||||
/**
|
||||
* The attacks.
|
||||
*/
|
||||
private static final SwitchAttack[] ATTACKS = { new SwitchAttack(CombatStyle.RANGE.getSwingHandler(), Animation.create(8190), null, null, Projectile.create(null, null, 1445, 60, 36, 41, 46)), new SwitchAttack(CombatStyle.MAGIC.getSwingHandler(), Animation.create(8190), null, null, Projectile.create(null, null, 1445, 60, 36, 41, 46)), new SwitchAttack(CombatStyle.MELEE.getSwingHandler(), Animation.create(8183)) };
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SteelTitanNPC} {@code Object}.
|
||||
*/
|
||||
public SteelTitanNPC() {
|
||||
this(null, 7343);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SteelTitanNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The NPC id.
|
||||
*/
|
||||
public SteelTitanNPC(Player owner, int id) {
|
||||
super(owner, id, 6400, 12790, 12, WeaponInterface.STYLE_RANGE_ACCURATE);
|
||||
super.setCombatHandler(new MultiSwingHandler(true, ATTACKS) {
|
||||
@Override
|
||||
public int swing(Entity entity, Entity victim, BattleState s) {
|
||||
int ticks = super.swing(entity, victim, s);
|
||||
if (specialMove) {
|
||||
BattleState[] states = new BattleState[4];
|
||||
for (int i = 1; i < 4; i++) {
|
||||
BattleState state = states[i] = new BattleState(entity, victim);
|
||||
int hit = 0;
|
||||
if (isAccurateImpact(entity, victim)) {
|
||||
int max = calculateHit(entity, victim, 1.0);
|
||||
state.setMaximumHit(max);
|
||||
hit = RandomFunction.random(max);
|
||||
}
|
||||
state.setEstimatedHit(hit);
|
||||
state.setStyle(getCurrent().getStyle());
|
||||
}
|
||||
states[0] = s;
|
||||
s.setTargets(states);
|
||||
specialMove = false;
|
||||
}
|
||||
return ticks;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SteelTitanNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7343, 7344 };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean specialMove(FamiliarSpecial special) {
|
||||
if (specialMove) {
|
||||
owner.getPacketDispatch().sendMessage("Your familiar is already charging its attack.");
|
||||
return false;
|
||||
}
|
||||
specialMove = true;
|
||||
visualize(Animation.create(8183), Graphics.create(1449));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the Stranger Plant familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class StrangerPlantNPC extends Forager {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code StrangerPlantNPC} {@code Object}.
|
||||
*/
|
||||
public StrangerPlantNPC() {
|
||||
this(null, 6827);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code StrangerPlantNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public StrangerPlantNPC(Player owner, int id) {
|
||||
super(owner, id, 4900, 12045, 6, new Item(464));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new StrangerPlantNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
if (!canCombatSpecial(special.getTarget())) {
|
||||
return false;
|
||||
}
|
||||
Entity target = special.getTarget();
|
||||
if (RandomFunction.random(2) == 1) {
|
||||
target.getStateManager().register(EntityState.POISONED, false, 40, target);
|
||||
}
|
||||
animate(Animation.create(8211));
|
||||
Projectile.ranged(this, target, 1508, 50, 40, 1, 45).send();
|
||||
target.graphics(Graphics.create(1511));
|
||||
sendFamiliarHit(target, 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6827, 6828 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.cache.def.impl.ItemDefinition;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.diary.DiaryType;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.world.map.zone.ZoneBorders;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Handles summoning a familiar.
|
||||
* @author Emperor
|
||||
*/
|
||||
@Initializable
|
||||
public final class SummonFamiliarPlugin extends OptionHandler {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ItemDefinition.setOptionHandler("summon", this);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
Item item = (Item) node;
|
||||
if (!player.getQuestRepository().isComplete("Wolf Whistle") && player.getAttribute("in-cutscene", null) == null) {
|
||||
player.getPacketDispatch().sendMessage("You have to complete Wolf Whistle before you can summon a familiar.");
|
||||
return true;
|
||||
}
|
||||
player.getFamiliarManager().summon(item, false);
|
||||
|
||||
// Achievement diary handlers
|
||||
if (player.getFamiliarManager().hasFamiliar()
|
||||
&& player.getFamiliarManager().getFamiliar() instanceof IbisNPC
|
||||
&& (new ZoneBorders(3011, 3222, 3017, 3229, 0).insideBorder(player)
|
||||
|| new ZoneBorders(3011, 3220, 3015, 3221, 0).insideBorder(player))) {
|
||||
player.getAchievementDiaryManager().finishTask(player,DiaryType.FALADOR, 2, 9);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents the Swamp Titan familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class SwampTitanNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SwampTitanNPC} {@code Object}.
|
||||
*/
|
||||
public SwampTitanNPC() {
|
||||
this(null, 7329);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SwampTitanNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public SwampTitanNPC(Player owner, int id) {
|
||||
super(owner, id, 5600, 12776, 6, WeaponInterface.STYLE_ACCURATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new SwampTitanNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7329, 7330 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents the Talon Beast familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class TalonBeastNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code TalonBeastNPC} {@code Object}.
|
||||
*/
|
||||
public TalonBeastNPC() {
|
||||
this(null, 7347);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code TalonBeastNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public TalonBeastNPC(Player owner, int id) {
|
||||
super(owner, id, 4900, 12794, 6, WeaponInterface.STYLE_AGGRESSIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new TalonBeastNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7347, 7348 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.BattleState;
|
||||
import core.game.node.entity.combat.CombatStyle;
|
||||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.impl.Animator.Priority;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the Thorny Snail familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class ThornySnailNPC extends BurdenBeast {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ThornySnailNPC} {@code Object}.
|
||||
*/
|
||||
public ThornySnailNPC() {
|
||||
this(null, 6806);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ThornySnailNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public ThornySnailNPC(Player owner, int id) {
|
||||
super(owner, id, 1600, 12019, 3, 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new ThornySnailNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
final Entity target = (Entity) special.getNode();
|
||||
if (!canCombatSpecial(target)) {
|
||||
return false;
|
||||
}
|
||||
visualizeSpecialMove();
|
||||
visualize(new Animation(8148, Priority.HIGH), Graphics.create(1385));
|
||||
Projectile.magic(this, target, 1386, 40, 36, 51, 10).send();
|
||||
int ticks = 2 + (int) Math.floor(getLocation().getDistance(target.getLocation()) * 0.5);
|
||||
getProperties().getCombatPulse().setNextAttack(4);
|
||||
faceTemporary(target, 2);
|
||||
GameWorld.getPulser().submit(new Pulse(ticks, this, target) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
BattleState state = new BattleState(ThornySnailNPC.this, target);
|
||||
int hit = 0;
|
||||
if (CombatStyle.MAGIC.getSwingHandler().isAccurateImpact(ThornySnailNPC.this, target)) {
|
||||
hit = RandomFunction.randomize(8);
|
||||
}
|
||||
state.setEstimatedHit(hit);
|
||||
target.getImpactHandler().handleImpact(owner, hit, CombatStyle.MAGIC, state);
|
||||
target.graphics(new Graphics(1387));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPoisonImmune() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6806, 6807 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.cache.def.impl.NPCDefinition;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.state.EntityState;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.ClassScanner;
|
||||
|
||||
/**
|
||||
* Represents the Unicorn Stallion familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class UnicornStallionNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code UnicornStallion} {@code Object}.
|
||||
*/
|
||||
public UnicornStallionNPC() {
|
||||
this(null, 6822);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code UnicornStallion} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public UnicornStallionNPC(Player owner, int id) {
|
||||
super(owner, id, 5400, 12039, 20, WeaponInterface.STYLE_CONTROLLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new UnicornStallionNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
Player player = (Player) special.getNode();
|
||||
player.getAudioManager().send(4372);
|
||||
visualize(Animation.create(8267), Graphics.create(1356));
|
||||
player.getSkills().heal((int) (player.getSkills().getMaximumLifepoints() * 0.15));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureFamiliar() {
|
||||
ClassScanner.definePlugin(new OptionHandler() {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
NPCDefinition.forId(6822).getHandlers().put("option:cure", this);
|
||||
NPCDefinition.forId(6823).getHandlers().put("option:cure", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
Familiar familiar = (Familiar) node;
|
||||
if (!player.getFamiliarManager().isOwner(familiar)) {
|
||||
return true;
|
||||
}
|
||||
Player owner = player;
|
||||
if (owner.getSkills().getLevel(Skills.MAGIC) < 2) {
|
||||
player.sendMessage("You don't have enough summoning points left");
|
||||
return true;
|
||||
}
|
||||
if (!owner.getStateManager().hasState(EntityState.POISONED)) {
|
||||
player.sendMessage("You are not poisoned.");
|
||||
return true;
|
||||
}
|
||||
player.getAudioManager().send(4372);
|
||||
familiar.visualize(Animation.create(8267), Graphics.create(1356));
|
||||
player.getStateManager().remove(EntityState.POISONED);
|
||||
player.getSkills().updateLevel(Skills.SUMMONING, -2, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visualizeSpecialMove() {
|
||||
owner.visualize(Animation.create(7660), Graphics.create(1298));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6822, 6823 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Initializable;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the Vampire Bat familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class VampireBatNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code VampireBatNPC} {@code Object}.
|
||||
*/
|
||||
public VampireBatNPC() {
|
||||
this(null, 6835);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code VampireBatNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public VampireBatNPC(Player owner, int id) {
|
||||
super(owner, id, 3300, 12053, 4, WeaponInterface.STYLE_CONTROLLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new VampireBatNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
final Entity target = (Entity) special.getNode();
|
||||
if (!canCombatSpecial(target)) {
|
||||
return false;
|
||||
} else {
|
||||
if (RandomFunction.random(10) < 4) {
|
||||
owner.getSkills().heal(2);
|
||||
}
|
||||
visualize(Animation.create(8275), Graphics.create(1323));
|
||||
target.getImpactHandler().manualHit(this, RandomFunction.random(12), HitsplatType.NORMAL);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6835, 6836 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import core.game.node.entity.npc.Metamorphosis;
|
||||
|
||||
/**
|
||||
* Handles the metamorphosis of Vet'ion Jr.
|
||||
* @author Empathy
|
||||
*
|
||||
*/
|
||||
@Initializable
|
||||
public class VetionNPC extends Metamorphosis {
|
||||
|
||||
/**
|
||||
* The Vet'ion Ids.
|
||||
*/
|
||||
public static final int[] VETION_IDS = new int[] { 8600, 8654 };
|
||||
|
||||
/**
|
||||
*
|
||||
* Constructs a new{@code VetionNPC} object.
|
||||
*/
|
||||
public VetionNPC() {
|
||||
super(VETION_IDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin getDialoguePlugin() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.cache.def.impl.NPCDefinition;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.combat.BattleState;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.ClassScanner;
|
||||
|
||||
/**
|
||||
* The plugin used to load void familiar npcs.
|
||||
* @author Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class VoidFamiliarNPC implements Plugin<Object> {
|
||||
|
||||
/**
|
||||
* The foraging items.
|
||||
*/
|
||||
private static final Item[] ITEMS = new Item[] { new Item(434), new Item(440), new Item(453), new Item(444), new Item(447) };
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ClassScanner.definePlugin(new VoidRavagerNPC());
|
||||
ClassScanner.definePlugin(new VoidShifterNPC());
|
||||
ClassScanner.definePlugin(new VoidSpinnerNPC());
|
||||
ClassScanner.definePlugin(new VoidTorcherNPC());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fireEvent(String identifier, Object... args) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the call to arms scroll.
|
||||
* @param special the special.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean callToArms(Familiar familiar, FamiliarSpecial special) {
|
||||
final Player owner = familiar.getOwner();
|
||||
owner.lock();
|
||||
GameWorld.getPulser().submit(new Pulse(1, owner) {
|
||||
int counter;
|
||||
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
switch (++counter) {
|
||||
case 1:
|
||||
owner.visualize(Animation.create(8136), Graphics.create(1503));
|
||||
break;
|
||||
case 3:
|
||||
owner.unlock();
|
||||
owner.getProperties().setTeleportLocation(Location.create(2659, 2658, 0));
|
||||
owner.visualize(Animation.create(8137), Graphics.create(1502));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the Void Ravager familiar.
|
||||
* @author Vexia
|
||||
* @author Aero
|
||||
*/
|
||||
public final class VoidRavagerNPC extends Forager {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code VoidRavagerNPC} {@code Object}.
|
||||
*/
|
||||
public VoidRavagerNPC() {
|
||||
this(null, 7370);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code VoidRavagerNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public VoidRavagerNPC(Player owner, int id) {
|
||||
super(owner, id, 2700, 12818, 3, WeaponInterface.STYLE_AGGRESSIVE, ITEMS);
|
||||
boosts.add(new SkillBonus(Skills.MINING, 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new VoidRavagerNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return callToArms(this, special);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7370, 7371 };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the Void Shifter familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
public class VoidShifterNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code VoidShifterNPC} {@code Object}.
|
||||
*/
|
||||
public VoidShifterNPC() {
|
||||
this(null, 7367);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code VoidShifterNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public VoidShifterNPC(Player owner, int id) {
|
||||
super(owner, id, 9400, 12814, 3, WeaponInterface.STYLE_ACCURATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new VoidShifterNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustPlayerBattle(BattleState state) {
|
||||
super.adjustPlayerBattle(state);
|
||||
int percentage = (int) (owner.getSkills().getStaticLevel(Skills.HITPOINTS) * 0.10);
|
||||
if (owner.getSkills().getLifepoints() < percentage) {
|
||||
owner.getProperties().setTeleportLocation(Location.create(2659, 2658, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return callToArms(this, special);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7367, 7368 };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the Void Spinner familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
*/
|
||||
public class VoidSpinnerNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* The delay till the next heal.
|
||||
*/
|
||||
private int healDelay;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code VoidSpinnerNPC} {@code Object}.
|
||||
*/
|
||||
public VoidSpinnerNPC() {
|
||||
this(null, 7333);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code VoidSpinnerNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public VoidSpinnerNPC(Player owner, int id) {
|
||||
super(owner, id, 2700, 12780, 3, WeaponInterface.STYLE_DEFENSIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFamiliarTick() {
|
||||
super.handleFamiliarTick();
|
||||
if (healDelay < GameWorld.getTicks()) {
|
||||
getSkills().heal(1);
|
||||
healDelay = GameWorld.getTicks() + 25;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new VoidSpinnerNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return callToArms(this, special);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7333, 7334 };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the Void Torcher familiar.
|
||||
* @author Aero
|
||||
* @author Vexia
|
||||
* @note TODO: the "Strike" attack.
|
||||
*/
|
||||
public class VoidTorcherNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code VoidTorcherNPC} {@code Object}.
|
||||
*/
|
||||
public VoidTorcherNPC() {
|
||||
this(null, 7351);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code VoidTorcherNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The id.
|
||||
*/
|
||||
public VoidTorcherNPC(Player owner, int id) {
|
||||
super(owner, id, 9400, 12798, 3, WeaponInterface.STYLE_CAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new VoidTorcherNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureFamiliar() {
|
||||
ClassScanner.definePlugin(new OptionHandler() {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
for (int i : getIds()) {
|
||||
NPCDefinition.forId(i).getHandlers().put("option:strike", this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
final Familiar familiar = (Familiar) node;
|
||||
if (!player.getFamiliarManager().isOwner(familiar)) {
|
||||
return true;
|
||||
}
|
||||
// TODO:
|
||||
return true;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
return callToArms(this, special);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 7351, 7352 };
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the War tortoise familiar.
|
||||
* @author Emperor
|
||||
*/
|
||||
@Initializable
|
||||
public final class WarTortoiseNPC extends BurdenBeast {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code WarTortoiseNPC} {@code Object}.
|
||||
*/
|
||||
public WarTortoiseNPC() {
|
||||
this(null, 6815);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code WarTortoiseNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The NPC id.
|
||||
*/
|
||||
public WarTortoiseNPC(Player owner, int id) {
|
||||
super(owner, id, 4300, 12031, 20, 18, WeaponInterface.STYLE_DEFENSIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new WarTortoiseNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
owner.getSkills().updateLevel(Skills.DEFENCE, 9, owner.getSkills().getStaticLevel(Skills.DEFENCE) + 9);
|
||||
visualize(Animation.create(8288), Graphics.create(1414));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visualizeSpecialMove() {
|
||||
owner.visualize(Animation.create(7660), Graphics.create(1310));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6815, 6816 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package content.global.skill.summoning.familiar;
|
||||
|
||||
import core.plugin.Initializable;
|
||||
import core.game.node.entity.skill.SkillBonus;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
|
||||
/**
|
||||
* Represents the Wolpertinger familiar.
|
||||
* @author Aero
|
||||
*/
|
||||
@Initializable
|
||||
public class WolpertingerNPC extends Familiar {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code WolpertingerNPC} {@code Object}.
|
||||
*/
|
||||
public WolpertingerNPC() {
|
||||
this(null, 6869);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code WolpertingerNPC} {@code Object}.
|
||||
* @param owner The owner.
|
||||
* @param id The NPC id.
|
||||
*/
|
||||
public WolpertingerNPC(Player owner, int id) {
|
||||
super(owner, id, 6200, 12089, 1, WeaponInterface.STYLE_CAST);
|
||||
boosts.add(new SkillBonus(Skills.HUNTER, 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Familiar construct(Player owner, int id) {
|
||||
return new WolpertingerNPC(owner, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean specialMove(FamiliarSpecial special) {
|
||||
owner.getSkills().updateLevel(Skills.MAGIC, 7, (owner.getSkills().getStaticLevel(Skills.MAGIC) + 7));
|
||||
visualize(Animation.create(8267), Graphics.create(1464));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visualizeSpecialMove() {
|
||||
owner.visualize(Animation.create(7660), Graphics.create(1306));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6869, 6870 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package content.global.skill.summoning.pet;
|
||||
|
||||
import core.game.node.item.Item;
|
||||
|
||||
/**
|
||||
* An egg to put in the incubator.
|
||||
* @author Vexia
|
||||
*/
|
||||
public enum IncubatorEgg {
|
||||
PENGUIN(new Item(12483), 30, 30, new Item(12481)),
|
||||
RAVEN(new Item(11964), 50, 30, new Item(12484)),
|
||||
SARADOMIN_OWL(new Item(5077), 70, 60, new Item(12503)),
|
||||
ZAMORAK_HAWK(new Item(5076), 70, 60, new Item(12506)),
|
||||
GUTHIX_RAPTOR(new Item(5078), 70, 60, new Item(12509)),
|
||||
VULTURE(new Item(11965), 85, 60, new Item(12498)),
|
||||
CHAMELEON(new Item(12494), 90, 60, new Item(12492)),
|
||||
RED_DRAGON(new Item(12477), 99, 60, new Item(12469)),
|
||||
BLACK_DRAGON(new Item(12480), 99, 60, new Item(12475)),
|
||||
BLUE_DRAGON(new Item(12478), 99, 60, new Item(12471)),
|
||||
GREEN_DRAGON(new Item(12479), 99, 60, new Item(12473));
|
||||
|
||||
/**
|
||||
* The egg item.
|
||||
*/
|
||||
private final Item egg;
|
||||
|
||||
/**
|
||||
* The level.
|
||||
*/
|
||||
private final int level;
|
||||
|
||||
/**
|
||||
* The incubation time.
|
||||
*/
|
||||
private final int inucbationTime;
|
||||
|
||||
/**
|
||||
* The product item.
|
||||
*/
|
||||
private final Item product;
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code IncubatorEgg} {@Code Object}
|
||||
* @param egg the egg.
|
||||
* @param level the level.
|
||||
* @param inucbationTime the incubation time.
|
||||
* @param product the product.
|
||||
*/
|
||||
private IncubatorEgg(Item egg, int level, int inucbationTime, Item product) {
|
||||
this.egg = egg;
|
||||
this.level = level;
|
||||
this.inucbationTime = inucbationTime;
|
||||
this.product = product;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an egg by the item.
|
||||
* @param item the item.
|
||||
* @return the egg.
|
||||
*/
|
||||
public static IncubatorEgg forItem(Item item) {
|
||||
for (IncubatorEgg e : values()) {
|
||||
if (e.getEgg().getId() == item.getId()) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the egg.
|
||||
* @return the egg
|
||||
*/
|
||||
public Item getEgg() {
|
||||
return egg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the level.
|
||||
* @return the level
|
||||
*/
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the inucbationTime.
|
||||
* @return the inucbationTime
|
||||
*/
|
||||
public int getInucbationTime() {
|
||||
return inucbationTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the product.
|
||||
* @return the product
|
||||
*/
|
||||
public Item getProduct() {
|
||||
return product;
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user