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,187 @@
|
||||
package content.global.handlers.scenery
|
||||
|
||||
import core.api.*
|
||||
import core.game.node.Node
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.IronmanMode
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.Direction
|
||||
import core.game.world.map.Location
|
||||
import org.rs09.consts.NPCs
|
||||
import org.rs09.consts.Scenery
|
||||
import core.ServerConstants
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.IntType
|
||||
import content.global.handlers.npc.BankerNPC
|
||||
import core.game.world.repository.Repository
|
||||
|
||||
/**
|
||||
* Allows the user to interact with bank booths.
|
||||
*
|
||||
* @author vddCore
|
||||
*/
|
||||
class BankBoothListener : InteractionListener {
|
||||
|
||||
companion object {
|
||||
val INOPERABLE_BANK_BOOTHS = intArrayOf(
|
||||
Scenery.BANK_BOOTH_12800, Scenery.BANK_BOOTH_12801, Scenery.BANK_BOOTH_36262, Scenery.BANK_BOOTH_35648
|
||||
)
|
||||
|
||||
val BANK_BOOTHS = intArrayOf(
|
||||
Scenery.BANK_BOOTH_2213, Scenery.BANK_BOOTH_2214, Scenery.BANK_BOOTH_3045, Scenery.BANK_BOOTH_5276,
|
||||
Scenery.BANK_BOOTH_6084, Scenery.BANK_BOOTH_10517, Scenery.BANK_BOOTH_11338, Scenery.BANK_BOOTH_11402,
|
||||
Scenery.BANK_BOOTH_11758, Scenery.BANK_BOOTH_12798, Scenery.BANK_BOOTH_12799, Scenery.BANK_BOOTH_14367,
|
||||
Scenery.BANK_BOOTH_14368, Scenery.BANK_BOOTH_16700, Scenery.BANK_BOOTH_18491, Scenery.BANK_BOOTH_19230,
|
||||
Scenery.BANK_BOOTH_20325, Scenery.BANK_BOOTH_20326, Scenery.BANK_BOOTH_20327, Scenery.BANK_BOOTH_20328,
|
||||
Scenery.BANK_BOOTH_22819, Scenery.BANK_BOOTH_24914, Scenery.BANK_BOOTH_25808, Scenery.BANK_BOOTH_26972,
|
||||
Scenery.BANK_BOOTH_29085, Scenery.BANK_BOOTH_30015, Scenery.BANK_BOOTH_30016, Scenery.BANK_BOOTH_34205,
|
||||
Scenery.BANK_BOOTH_34752, Scenery.BANK_BOOTH_35647, Scenery.BANK_BOOTH_36786, Scenery.BANK_BOOTH_37474
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches an area in the order described
|
||||
* by each number with X being the location
|
||||
* of node being interacted with.
|
||||
*
|
||||
* [1]
|
||||
* [4][X][2]
|
||||
* [3]
|
||||
*/
|
||||
private fun locateAdjacentBankerLinear(node: Node): NPC? {
|
||||
for (dir in arrayOf(Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST)) {
|
||||
Repository.findNPC(node.location.transform(dir))?.let { return it as? BankerNPC }
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* If size is 1 then the following method
|
||||
* searches a square area in the following
|
||||
* order with X being the location of node
|
||||
* that was interacted with.
|
||||
*
|
||||
* ->[ ]
|
||||
* [ X ]
|
||||
* [ ]->
|
||||
*
|
||||
*/
|
||||
private fun locateAdjacentBankerSquare(node: Node, size: Int = 1): NPC? {
|
||||
for (y in (node.location.y - size)..(node.location.y + size)) {
|
||||
for (x in (node.location.x - size)..(node.location.x + size)) {
|
||||
Repository.findNPC(Location(x, y))?.let { return it as? BankerNPC }
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun tryInvokeBankerDialogue(player: Player, node: Node) {
|
||||
/**
|
||||
* First, we look for regular bankers that neatly stand in front of the bank booth.
|
||||
* If that fails, we expand the search to a larger area.
|
||||
*/
|
||||
(locateAdjacentBankerLinear(node) ?: locateAdjacentBankerSquare(node, 2))?.let {
|
||||
if (core.game.dialogue.DialogueInterpreter.contains(it.id)) {
|
||||
it.faceLocation(node.location)
|
||||
openDialogue(player, it.id, NPC(it.id, it.location))
|
||||
} else {
|
||||
openDialogue(player, NPCs.BANKER_494)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun quickBankBoothUse(player: Player, node: Node): Boolean {
|
||||
if (player.ironmanManager.checkRestriction(IronmanMode.ULTIMATE)) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (BankerNPC.checkLunarIsleRestriction(player, node)) {
|
||||
tryInvokeBankerDialogue(player, node)
|
||||
return true
|
||||
}
|
||||
|
||||
openBankAccount(player)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun regularBankBoothUse(player: Player, node: Node): Boolean {
|
||||
if (player.ironmanManager.checkRestriction(IronmanMode.ULTIMATE)) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (ServerConstants.BANK_BOOTH_QUICK_OPEN) {
|
||||
return quickBankBoothUse(player, node)
|
||||
}
|
||||
|
||||
tryInvokeBankerDialogue(player, node)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun collectBankBoothUse(player: Player, node: Node): Boolean {
|
||||
if (BankerNPC.checkLunarIsleRestriction(player, node)) {
|
||||
tryInvokeBankerDialogue(player, node)
|
||||
return true
|
||||
}
|
||||
|
||||
openGrandExchangeCollectionBox(player)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun attemptToConvertItems(player: Player, used: Node, with: Node): Boolean {
|
||||
if (!hasOption(with, "use")) {
|
||||
sendMessage(player, "You shouldn't be able to do that with object ${with.id}.")
|
||||
sendMessage(player, "Please screenshot this and report to the developers.")
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
if (!ServerConstants.BANK_BOOTH_NOTE_UIM && player.ironmanManager.checkRestriction(IronmanMode.ULTIMATE)) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (BankerNPC.checkLunarIsleRestriction(player, with)) {
|
||||
tryInvokeBankerDialogue(player, with)
|
||||
return true
|
||||
}
|
||||
|
||||
val item = used as Item
|
||||
|
||||
if (item.noteChange != item.id) {
|
||||
if (item.definition.isUnnoted) {
|
||||
val amount = amountInInventory(player, item.id)
|
||||
if (removeItem(player, Item(item.id, amount))) {
|
||||
addItem(player, item.noteChange, amount)
|
||||
}
|
||||
} else {
|
||||
var amount = item.amount
|
||||
val freeSlotCount = freeSlots(player)
|
||||
|
||||
if (amount > freeSlotCount) {
|
||||
amount = freeSlotCount
|
||||
}
|
||||
|
||||
if (removeItem(player, Item(item.id, amount))) {
|
||||
addItem(player, item.noteChange, amount)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
sendMessage(player, "This item can't be noted.")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
on(BANK_BOOTHS, IntType.SCENERY, "use-quickly", "bank", handler = ::quickBankBoothUse)
|
||||
on(BANK_BOOTHS, IntType.SCENERY, "use", handler = ::regularBankBoothUse)
|
||||
on(BANK_BOOTHS, IntType.SCENERY, "collect", handler = ::collectBankBoothUse)
|
||||
|
||||
if (ServerConstants.BANK_BOOTH_NOTE_ENABLED) {
|
||||
onUseAnyWith(IntType.SCENERY, *BANK_BOOTHS, handler = ::attemptToConvertItems)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package content.global.handlers.scenery
|
||||
|
||||
import core.api.openBankAccount
|
||||
import org.rs09.consts.Scenery
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.IntType
|
||||
|
||||
private val BANK_CHESTS = intArrayOf(
|
||||
Scenery.BANK_CHEST_3194, Scenery.BANK_CHEST_4483,
|
||||
Scenery.BANK_CHEST_10562, Scenery.BANK_CHEST_14382,
|
||||
Scenery.BANK_CHEST_16695, Scenery.BANK_CHEST_16696,
|
||||
Scenery.BANK_CHEST_21301, Scenery.BANK_CHEST_27662,
|
||||
Scenery.BANK_CHEST_27663
|
||||
)
|
||||
|
||||
/**
|
||||
* Allows the user to interact with Bank Chests.
|
||||
*
|
||||
* @author vddCore
|
||||
*/
|
||||
class BankChestListener : InteractionListener {
|
||||
override fun defineListeners() {
|
||||
on(BANK_CHESTS, IntType.SCENERY, "bank", "use") { player, node ->
|
||||
openBankAccount(player)
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package content.global.handlers.scenery
|
||||
|
||||
import core.api.restrictForIronman
|
||||
import core.game.component.CloseEvent
|
||||
import core.game.component.Component
|
||||
import core.game.container.access.InterfaceContainer
|
||||
import core.game.node.Node
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.IronmanMode
|
||||
import org.rs09.consts.Components
|
||||
import org.rs09.consts.Scenery
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.IntType
|
||||
|
||||
private val BANK_DEPOSIT_BOXES = intArrayOf(
|
||||
Scenery.BANK_DEPOSIT_BOX_9398,
|
||||
Scenery.BANK_DEPOSIT_BOX_20228,
|
||||
Scenery.BANK_DEPOSIT_BOX_25937,
|
||||
Scenery.BANK_DEPOSIT_BOX_26969,
|
||||
Scenery.BANK_DEPOSIT_BOX_34755,
|
||||
Scenery.BANK_DEPOSIT_BOX_36788,
|
||||
Scenery.BANK_DEPOSIT_BOX_39830
|
||||
)
|
||||
|
||||
/**
|
||||
* Allows the user to interact with bank deposit boxes.
|
||||
*
|
||||
* @author vddCore
|
||||
*/
|
||||
class BankDepositBoxListener : InteractionListener {
|
||||
|
||||
private fun openDepositBox(player: Player, node: Node) : Boolean {
|
||||
restrictForIronman(player, IronmanMode.ULTIMATE) {
|
||||
player.interfaceManager.open(Component(Components.BANK_DEPOSIT_BOX_11)).closeEvent = CloseEvent { p, _ ->
|
||||
p.interfaceManager.openDefaultTabs()
|
||||
return@CloseEvent true
|
||||
}
|
||||
|
||||
player.interfaceManager.removeTabs(0, 1, 2, 3, 4, 5, 6)
|
||||
InterfaceContainer.generateItems(
|
||||
player,
|
||||
player.inventory.toArray(),
|
||||
arrayOf(
|
||||
"Examine",
|
||||
"Deposit-X",
|
||||
"Deposit-All",
|
||||
"Deposit-10",
|
||||
"Deposit-5",
|
||||
"Deposit-1"
|
||||
), 11, 15, 5, 7
|
||||
)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
on(BANK_DEPOSIT_BOXES, IntType.SCENERY, "deposit", handler = ::openDepositBox)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package content.global.handlers.scenery;
|
||||
|
||||
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.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the doogle leaf plugin for this object.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public class DoogleLeafPlugin extends OptionHandler {
|
||||
|
||||
/**
|
||||
* Represents the leaf item.
|
||||
*/
|
||||
private static final Item LEAF = new Item(1573, 1);
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
SceneryDefinition.forId(31155).getHandlers().put("option:pick-leaf", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
if (!player.getInventory().add(LEAF)) {
|
||||
player.getPacketDispatch().sendMessage("You don't have have enough space in your inventory.");
|
||||
} else {
|
||||
player.getPacketDispatch().sendMessage("You pick some doogle leaves.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package content.global.handlers.scenery;
|
||||
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.game.global.action.DoorActionHandler;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.scenery.Scenery;
|
||||
import core.game.node.scenery.SceneryBuilder;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Plugin used for handling the opening/closing of (double)
|
||||
* doors/gates/fences/...
|
||||
* @author Emperor
|
||||
*/
|
||||
@Initializable
|
||||
public final class DoorManagingPlugin extends OptionHandler {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
SceneryDefinition.setOptionHandler("open", this);
|
||||
SceneryDefinition.setOptionHandler("close", this);
|
||||
SceneryDefinition.setOptionHandler("shut", this);
|
||||
SceneryDefinition.setOptionHandler("go-through", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
Scenery object = (Scenery) node;
|
||||
if (object.getType() != 9 && !player.getLocation().equals(node.getLocation()) && !player.getLocation().isNextTo(object) && object.getName().contains("cupboard")) {
|
||||
return true;
|
||||
}
|
||||
String name = object.getName().toLowerCase();
|
||||
if (name.contains("drawers") || name.contains("wardrobe") || name.contains("cupboard")) {
|
||||
switch(option) {
|
||||
case "open":
|
||||
case "go-through":
|
||||
if (object.isActive()) {
|
||||
SceneryBuilder.replace(object, object.transform(object.getId() + 1), 80);
|
||||
}
|
||||
return true;
|
||||
case "close":
|
||||
case "shut":
|
||||
SceneryBuilder.replace(object, object.transform(object.getId() - 1));
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (name.contains("trapdoor") || name.contains("trap door")) {
|
||||
Location destination = object.getLocation().transform(0, 6400, 0);
|
||||
if (!RegionManager.isTeleportPermitted(destination)) {
|
||||
player.getPacketDispatch().sendMessage("This doesn't seem to go anywhere.");
|
||||
return true;
|
||||
}
|
||||
player.getProperties().setTeleportLocation(destination);
|
||||
return true;
|
||||
}
|
||||
if (node.asScenery().getId() == 25341) {// Mithril door
|
||||
return false;
|
||||
}
|
||||
if (!name.contains("door") && !name.contains("gate") && !name.contains("fence") && !name.contains("wall") && !name.contains("exit") && !name.contains("entrance")) {
|
||||
return false;
|
||||
}
|
||||
DoorActionHandler.handleDoor(player, object);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getDestination(Node n, Node node) {
|
||||
Scenery o = (Scenery) node;
|
||||
if (o.getType() < 4 || o.getType() == 9) {
|
||||
return DoorActionHandler.getDestination((Player) n, o);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
package content.global.handlers.scenery;
|
||||
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.game.container.impl.EquipmentContainer;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
|
||||
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.node.scenery.Scenery;
|
||||
import core.game.node.scenery.SceneryBuilder;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.Initializable;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Handles the pick option of interactive scenery (non-farming cabbages,
|
||||
* potatoes, bananas, etc)
|
||||
* @author Emperor
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class FieldPickingPlugin extends OptionHandler {
|
||||
|
||||
/**
|
||||
* The picking animation to use.
|
||||
*/
|
||||
private static final Animation ANIMATION = new Animation(827);
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
for(PickingPlant p : PickingPlant.values()){
|
||||
SceneryDefinition.forId(p.objectId).getHandlers().put("option:pick",this);
|
||||
}
|
||||
SceneryDefinition.forId(3511).getHandlers().put("option:take-cutting",this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(final Player player, Node node, String option) {
|
||||
if (player.getAttribute("delay:picking", -1) > GameWorld.getTicks()) {
|
||||
return true;
|
||||
}
|
||||
final Scenery object = (Scenery) node;
|
||||
final PickingPlant plant = PickingPlant.forId(object.getId());
|
||||
if (plant == null) {
|
||||
return false;
|
||||
}
|
||||
if (!object.isActive()) {
|
||||
return true;
|
||||
}
|
||||
final Item reward = new Item(plant == PickingPlant.POTATO && RandomFunction.random(10) == 0 ? 5318 : plant.reward);
|
||||
if (!player.getInventory().hasSpaceFor(reward)) {
|
||||
player.getPacketDispatch().sendMessage("Not enough space in your inventory!");
|
||||
return true;
|
||||
}
|
||||
if (player.getInventory().freeSlot() == -1) {
|
||||
return true;
|
||||
}
|
||||
player.lock(1);
|
||||
player.setAttribute("delay:picking", GameWorld.getTicks() + (plant == PickingPlant.FLAX ? 2 : 3));
|
||||
player.animate(ANIMATION);
|
||||
if (plant.name().startsWith("NETTLES") && (player.getEquipment().get(EquipmentContainer.SLOT_HANDS) == null || player.getEquipment().get(EquipmentContainer.SLOT_HANDS) != null && !player.getEquipment().get(EquipmentContainer.SLOT_HANDS).getName().contains("glove"))) {
|
||||
player.getPacketDispatch().sendMessage("You have been stung by the nettles!");
|
||||
player.getImpactHandler().manualHit(player, 2, HitsplatType.POISON);
|
||||
return true;
|
||||
}
|
||||
if (plant.respawn != -1 && plant != PickingPlant.FLAX) {
|
||||
object.setActive(false);
|
||||
}
|
||||
GameWorld.getPulser().submit(new Pulse(1, player) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
if (!player.getInventory().add(reward)) {
|
||||
player.getPacketDispatch().sendMessage("Not enough space in your inventory!");
|
||||
return true;
|
||||
}
|
||||
if (plant == PickingPlant.FLAX) {
|
||||
handleFlaxPick(player, object, plant);
|
||||
return true;
|
||||
}
|
||||
boolean banana = plant.name().startsWith("BANANA");
|
||||
Scenery full = null;
|
||||
if (plant == PickingPlant.BANANA_TREE_4) {
|
||||
full = object.transform(2073);
|
||||
SceneryBuilder.replace(object, full);
|
||||
}
|
||||
boolean isBloomPlant = plant == PickingPlant.FUNGI_ON_LOG
|
||||
|| plant == PickingPlant.BUDDING_BRANCH
|
||||
|| plant == PickingPlant.GOLDEN_PEAR_BUSH;
|
||||
if (isBloomPlant) {
|
||||
full = object.transform(object.getId() - 1);
|
||||
SceneryBuilder.replace(object, full);
|
||||
}
|
||||
if (!isBloomPlant) {
|
||||
SceneryBuilder.replace(plant == PickingPlant.BANANA_TREE_4 ? full : object, object.transform(banana ? plant.respawn : 0), banana ? 300 : plant.respawn);
|
||||
}
|
||||
if (!plant.name().startsWith("NETTLES")) {
|
||||
player.getPacketDispatch().sendMessage("You pick a " + reward.getName().toLowerCase() + ".");
|
||||
} else {
|
||||
player.getPacketDispatch().sendMessage("You pick a handful of nettles.");
|
||||
}
|
||||
if (banana && !player.getAchievementDiaryManager().hasCompletedTask(DiaryType.KARAMJA, 0, 0)) {
|
||||
int picked = player.getAttribute("b-picked", 0);
|
||||
picked++;
|
||||
player.setAttribute("b-picked", picked);
|
||||
player.getAchievementDiaryManager().updateTask(player, DiaryType.KARAMJA, 0, 0, picked == 5);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to handle the flax picking.
|
||||
* @param player the player.
|
||||
* @param object the object.
|
||||
* @param plant the plank.
|
||||
*/
|
||||
private void handleFlaxPick(final Player player, final Scenery object, final PickingPlant plant) {
|
||||
int charge = object.getCharge();
|
||||
player.getAudioManager().send(2581);
|
||||
player.getPacketDispatch().sendMessage("You pick some flax.");
|
||||
|
||||
// Seers achievement diary
|
||||
if (player.getViewport().getRegion().getId() == 10805
|
||||
&& !player.getAchievementDiaryManager().getDiary(DiaryType.SEERS_VILLAGE).isComplete(0,0)) {
|
||||
if (player.getAttribute("diary:seers:flax-picked", 0) >= 4) {
|
||||
player.setAttribute("/save:diary:seers:flax-picked", 5);
|
||||
player.getAchievementDiaryManager().getDiary(DiaryType.SEERS_VILLAGE).updateTask(player,0,0,true);
|
||||
} else {
|
||||
player.setAttribute("/save:diary:seers:flax-picked", player.getAttribute("diary:seers:flax-picked", 0) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (charge > 1000 + RandomFunction.random(2, 8)) {
|
||||
object.setActive(false);
|
||||
object.setCharge(1000);
|
||||
SceneryBuilder.replace(object, object.transform(0), plant.respawn);
|
||||
return;
|
||||
}
|
||||
object.setCharge(charge + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a plant to be picked.
|
||||
* @author Emperor
|
||||
*/
|
||||
private static enum PickingPlant {
|
||||
POTATO(312, 1942, 30),
|
||||
WHEAT_0(313, 1947, 30),
|
||||
WHEAT_1(5583, 1947, 30),
|
||||
WHEAT_2(5584, 1947, 30),
|
||||
WHEAT_3(5585, 1947, 30),
|
||||
WHEAT_4(15506, 1947, 30),
|
||||
WHEAT_5(15507, 1947, 30),
|
||||
WHEAT_6(15508, 1947, 30),
|
||||
WHEAT_7(22300, 1947, 30),
|
||||
WHEAT_8(22473, 1947, 30),
|
||||
WHEAT_9(22474, 1947, 30),
|
||||
WHEAT_10(22475, 1947, 30),
|
||||
WHEAT_11(22476, 1947, 30),
|
||||
CABBAGE_0(1161, 1965, 30),
|
||||
CABBAGE_1(11494, 1967, 30),
|
||||
CABBAGE_2(22301, 1965, 30),
|
||||
NETTLES_0(1181, 4241, 30),
|
||||
NETTLES_1(5253, 4241, 30),
|
||||
NETTLES_2(5254, 4241, 30),
|
||||
NETTLES_3(5255, 4241, 30),
|
||||
NETTLES_4(5256, 4241, 30),
|
||||
NETTLES_5(5257, 4241, 30),
|
||||
NETTLES_6(5258, 4241, 30),
|
||||
PINEAPPLE_PLANT_0(1408, 2114, 30),
|
||||
PINEAPPLE_PLANT_1(1409, 2114, 30),
|
||||
PINEAPPLE_PLANT_2(1410, 2114, 30),
|
||||
PINEAPPLE_PLANT_3(1411, 2114, 30),
|
||||
PINEAPPLE_PLANT_4(1412, 2114, 30),
|
||||
PINEAPPLE_PLANT_5(1413, 2114, 30),
|
||||
PINEAPPLE_PLANT_6(4827, 2114, 30),
|
||||
BANANA_TREE_0(2073, 1963, 2074),
|
||||
BANANA_TREE_1(2074, 1963, 2075),
|
||||
BANANA_TREE_2(2075, 1963, 2076),
|
||||
BANANA_TREE_3(2076, 1963, 2077),
|
||||
BANANA_TREE_4(2077, 1963, 2078),
|
||||
BANANA_TREE_5(12606, 1963, 2079),
|
||||
BANANA_TREE_6(12607, 1963, 2080),
|
||||
FLAX(2646, 1779, 30),
|
||||
ONION_0(3366, 1957, 30),
|
||||
ONION_1(5538, 1957, 30),
|
||||
FUNGI_ON_LOG(3509, 2970, -1),
|
||||
BUDDING_BRANCH(3511, 2972, -1),
|
||||
GOLDEN_PEAR_BUSH(3513, 2974, -1),
|
||||
GLOWING_FUNGUS_0(4932, 4075, 30),
|
||||
GLOWING_FUNGUS_1(4933, 4075, 30),
|
||||
RARE_FLOWERS(5006, 2460, 30),
|
||||
BLACK_MUSHROOMS(6311, 4620, 30),
|
||||
KELP(12478, 7516, 30),
|
||||
RED_BANANA_TREE(12609, 7572, 30),
|
||||
BUSH(12615, 7573, 30),
|
||||
RED_FLOWERS(15846, 8938, 30),
|
||||
BLUE_FLOWERS(15872, 8936, 30),
|
||||
HARDY_GOUTWEED(18855, 3261, 30),
|
||||
HERBS_0(21668, 199, 30),
|
||||
HERBS_1(21669, 201, 30),
|
||||
HERBS_2(21670, 203, 30),
|
||||
HERBS_3(21671, 205, 30),
|
||||
FEVER_GRASS(29113, 12574, 30),
|
||||
LAVENDER(29114, 12572, 30),
|
||||
TANSYMUM(29115, 12576, 30),
|
||||
PRIMWEED(29116, 12588, 30),
|
||||
STINKBLOOM(29117, 12590, 30),
|
||||
TROLLWEISS_FLOWERS(37328, 4086, 30),
|
||||
HOLLOW_LOG(37830, 10968, 30);
|
||||
|
||||
/**
|
||||
* The object id.
|
||||
*/
|
||||
final int objectId;
|
||||
|
||||
/**
|
||||
* The reward item id.
|
||||
*/
|
||||
final int reward;
|
||||
|
||||
/**
|
||||
* The respawn duration.
|
||||
*/
|
||||
final int respawn;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code FieldPickingPlugin {@code Object}.
|
||||
* @param objectId the object id.
|
||||
* @param reward the reward.
|
||||
* @param respawn the resapwn.
|
||||
*/
|
||||
private PickingPlant(int objectId, int reward, int respawn) {
|
||||
this.objectId = objectId;
|
||||
this.reward = reward;
|
||||
this.respawn = respawn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the picking plant by the id.
|
||||
* @param objectId the id.
|
||||
* @return the picking plant.
|
||||
*/
|
||||
static PickingPlant forId(int objectId) {
|
||||
for (PickingPlant plant : values())
|
||||
if (plant.objectId == objectId)
|
||||
return plant;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package content.global.handlers.scenery;
|
||||
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.dialogue.FacialExpression;
|
||||
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.world.update.flag.context.Animation;
|
||||
import core.plugin.Plugin;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Represents the haystack plugin.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class HaystackPlugin extends OptionHandler {
|
||||
|
||||
/**
|
||||
* Represents the needle to give.
|
||||
*/
|
||||
private static final Item NEEDLE = new Item(1733);
|
||||
|
||||
/**
|
||||
* Represents the animation.
|
||||
*/
|
||||
private static final Animation ANIMATION = new Animation(827);
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
SceneryDefinition.forId(298).getHandlers().put("option:search", this);
|
||||
SceneryDefinition.forId(299).getHandlers().put("option:search", this);
|
||||
SceneryDefinition.forId(300).getHandlers().put("option:search", this);
|
||||
SceneryDefinition.forId(304).getHandlers().put("option:search", this);
|
||||
SceneryDefinition.forId(36892).getHandlers().put("option:search", this);
|
||||
SceneryDefinition.forId(36893).getHandlers().put("option:search", this);
|
||||
SceneryDefinition.forId(36894).getHandlers().put("option:search", this);
|
||||
SceneryDefinition.forId(36895).getHandlers().put("option:search", this);
|
||||
SceneryDefinition.forId(36896).getHandlers().put("option:search", this);
|
||||
SceneryDefinition.forId(36897).getHandlers().put("option:search", this);
|
||||
SceneryDefinition.forId(36898).getHandlers().put("option:search", this);
|
||||
SceneryDefinition.forId(36899).getHandlers().put("option:search", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
final Scenery object = ((Scenery) node);
|
||||
final int rand = RandomFunction.random(50);
|
||||
player.lock(2);
|
||||
player.animate(ANIMATION);
|
||||
player.getPacketDispatch().sendMessage("You search the " + object.getName().toLowerCase() + "...");
|
||||
if (rand == 1 && player.getInventory().freeSlots() > 0 || player.getInventory().containsItem(NEEDLE)) {
|
||||
player.getInventory().add(NEEDLE);
|
||||
player.getDialogueInterpreter().sendDialogues(player, FacialExpression.HALF_GUILTY, "Wow! A needle!", "Now what are the chances of finding that?");
|
||||
return true;
|
||||
}
|
||||
player.getPacketDispatch().sendMessage("You find nothing of interest.");
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package content.global.handlers.scenery;
|
||||
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.plugin.Initializable;
|
||||
import content.global.skill.agility.AgilityHandler;
|
||||
import core.game.interaction.NodeUsageEvent;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.interaction.UseWithHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
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.Plugin;
|
||||
|
||||
/**
|
||||
* Handles the janger berry plugin.
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class JangerBerryPlugin extends OptionHandler {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
UseWithHandler.addHandler(2326, UseWithHandler.OBJECT_TYPE, new UseWithHandler(954) {
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(NodeUsageEvent event) {
|
||||
Scenery object = event.getUsedWith().asScenery();
|
||||
if (object.isActive())
|
||||
SceneryBuilder.replace(object, object.transform(2325));
|
||||
event.getPlayer().getInventory().remove(event.getUsedItem());
|
||||
return true;
|
||||
}
|
||||
|
||||
});
|
||||
SceneryDefinition.forId(2325).getHandlers().put("option:swing-on", this);
|
||||
SceneryDefinition.forId(2324).getHandlers().put("option:swing-on", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
if (!player.getLocation().withinDistance(node.getLocation(), 2)) {
|
||||
player.sendMessage("I can't reach that.");
|
||||
return true;
|
||||
}
|
||||
Location end = node.getId() == 2325 ? new Location(2505, 3087, 0) : new Location(2511, 3096, 0);
|
||||
player.getPacketDispatch().sendSceneryAnimation(node.asScenery(), Animation.create(497), true);
|
||||
AgilityHandler.forceWalk(player, 0, player.getLocation(), end, Animation.create(751), 50, 22, "You skillfully swing across.", 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getDestination(Node node, Node n) {
|
||||
return n.getId() == 2324 ? new Location(2511, 3092, 0) : new Location(2501, 3087, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package content.global.handlers.scenery;
|
||||
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.game.global.action.ClimbActionHandler;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.scenery.Scenery;
|
||||
import core.game.world.map.Location;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Represents the plugin used for managing ladders.
|
||||
* @author Emperor
|
||||
* @version 2.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class LadderManagingPlugin extends OptionHandler {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
SceneryDefinition.setOptionHandler("climb-up", this);
|
||||
SceneryDefinition.setOptionHandler("climb-down", this);
|
||||
SceneryDefinition.setOptionHandler("climb", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(final Player player, Node node, final String option) {
|
||||
ClimbActionHandler.climbLadder(player, (Scenery) node, option);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getDestination(Node n, Node object) {
|
||||
return ClimbActionHandler.getDestination((Scenery) object);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package content.global.handlers.scenery;
|
||||
|
||||
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.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
@Initializable
|
||||
public class LookAtOptionPlugin extends OptionHandler {
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
for (int i = 18877; i <= 18900; i++)
|
||||
{
|
||||
SceneryDefinition.forId(i).getHandlers().put("option:look at", this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
player.getPacketDispatch().sendMessage("The " + node.getName().toLowerCase() + " seem to be going south-west.");
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package content.global.handlers.scenery
|
||||
|
||||
import core.api.*
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.audio.Audio
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.update.flag.context.Animation
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.Scenery
|
||||
|
||||
private const val GRAIN = Items.GRAIN_1947
|
||||
private const val SWEETCORN = Items.SWEETCORN_5986
|
||||
private const val EMPTY_POT = Items.EMPTY_POT_1931
|
||||
private const val POT_OF_FLOUR = Items.POT_OF_FLOUR_1933
|
||||
private const val POT_OF_CORNFLOUR = Items.POT_OF_CORNFLOUR_7468
|
||||
private val HOPPERS = intArrayOf(Scenery.HOPPER_36881, Scenery.HOPPER_2717, Scenery.HOPPER_24071, Scenery.HOPPER_2716, Scenery.HOPPER_22422)
|
||||
private val HOPPER_CONTROLS = intArrayOf(Scenery.HOPPER_CONTROLS_2718, Scenery.HOPPER_CONTROLS_2721, Scenery.HOPPER_CONTROLS_24072, Scenery.HOPPER_CONTROLS_2720, Scenery.LEVER_22424)
|
||||
private val FLOUR_BINS = intArrayOf(Scenery.FLOUR_BIN_1782, Scenery.FLOUR_BIN_5792, Scenery.FLOUR_BIN_22420, Scenery.FLOUR_BIN_22421, Scenery.FLOUR_BIN_24070, Scenery.FLOUR_BIN_36878)
|
||||
private const val VARP = 695
|
||||
private val ANIMATION = Animation(3571)
|
||||
private val SOUND = Audio(3189)
|
||||
|
||||
/**
|
||||
* Handles interactions with windmills
|
||||
* @author itsmedoggo
|
||||
*/
|
||||
class MillingListener : InteractionListener {
|
||||
override fun defineListeners() {
|
||||
on(HOPPER_CONTROLS, SCENERY, "operate", "pull") { player, _ ->
|
||||
useHopperControl(player)
|
||||
return@on true
|
||||
}
|
||||
on(FLOUR_BINS, SCENERY, "empty") { player, _ ->
|
||||
fillPot(player)
|
||||
return@on true
|
||||
}
|
||||
onUseWith(SCENERY, intArrayOf(GRAIN, SWEETCORN), *HOPPERS) { player, used, _ ->
|
||||
fillHopper(player, used.asItem())
|
||||
return@onUseWith true
|
||||
}
|
||||
onUseWith(SCENERY, EMPTY_POT, *FLOUR_BINS) { player, _, _ ->
|
||||
fillPot(player)
|
||||
return@onUseWith true
|
||||
}
|
||||
}
|
||||
|
||||
private fun useHopperControl(player: Player) {
|
||||
animate(player, ANIMATION)
|
||||
val hopperContents = getAttribute(player, "milling:hopper", 0)
|
||||
if (hopperContents == 0) {
|
||||
sendMessage(player, "You operate the empty hopper. Nothing interesting happens.")
|
||||
return
|
||||
}
|
||||
setAttribute(player, "/save:milling:hopper", 0)
|
||||
when (hopperContents) {
|
||||
GRAIN -> {
|
||||
setAttribute(player, "/save:milling:grain", (getAttribute(player, "milling:grain", 0) + 1).coerceAtMost(30 - getAttribute(player, "milling:sweetcorn", 0)))
|
||||
sendMessage(player, "You operate the hopper. The grain slides down the chute.")
|
||||
}
|
||||
SWEETCORN -> {
|
||||
setAttribute(player, "/save:milling:sweetcorn", (getAttribute(player, "milling:sweetcorn", 0) + 1).coerceAtMost(30 - getAttribute(player, "milling:grain", 0)))
|
||||
sendMessage(player, "You operate the hopper. The sweetcorn slides down the chute.")
|
||||
}
|
||||
}
|
||||
playAudio(player, SOUND)
|
||||
setVarbit(player, VARP, 0, 1, true)
|
||||
}
|
||||
|
||||
private fun fillHopper(player: Player, used: Item) {
|
||||
if (getAttribute(player, "milling:hopper", 0) == 0 && removeItem(player, used)) {
|
||||
setAttribute(player, "/save:milling:hopper", used.id)
|
||||
sendMessage(player, "You put the " + used.name.lowercase() + " in the hopper.")
|
||||
return
|
||||
}
|
||||
sendMessage(player, "There is already " + getItemName(getAttribute(player, "milling:hopper", 0)).lowercase() + " in the hopper.")
|
||||
}
|
||||
|
||||
private fun fillPot(player: Player) {
|
||||
if (!inInventory(player, EMPTY_POT)) {
|
||||
sendMessage(player, "I need an empty pot to hold the flour in.")
|
||||
return
|
||||
}
|
||||
if (removeItem(player, EMPTY_POT)) {
|
||||
if (getAttribute(player, "milling:sweetcorn", 0) > 0) {
|
||||
setAttribute(player, "/save:milling:sweetcorn", (getAttribute(player, "milling:sweetcorn", 0) - 1))
|
||||
addItem(player, POT_OF_CORNFLOUR)
|
||||
sendMessage(player, if (player.getAttribute("milling:sweetcorn", 0) > 0) "You fill a pot with cornflour from the bin." else "You fill a pot with the last of the cornflour in the bin.")
|
||||
}
|
||||
else if (getAttribute(player, "milling:grain", 0) > 0) {
|
||||
setAttribute(player, "/save:milling:grain", (getAttribute(player, "milling:grain", 0) - 1))
|
||||
addItem(player, POT_OF_FLOUR)
|
||||
sendMessage(player, if (player.getAttribute("milling:grain", 0) > 0) "You fill a pot with flour from the bin." else "You fill a pot with the last of the flour in the bin.")
|
||||
}
|
||||
if (getAttribute(player, "milling:sweetcorn", 0) + getAttribute(player, "milling:grain", 0) <= 0) {
|
||||
setVarbit(player, VARP, 0, 0, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package content.global.handlers.scenery;
|
||||
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.game.global.action.ClimbActionHandler;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.info.Rights;
|
||||
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 for the moderator objects in the p-mod room.
|
||||
* @author 'Vexia
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class ModeratorObject extends OptionHandler {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
SceneryDefinition.forId(26806).getHandlers().put("option:climb-up", this);
|
||||
SceneryDefinition.forId(26807).getHandlers().put("option:j-mod options", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
switch (option) {
|
||||
case "climb-up":
|
||||
ClimbActionHandler.climb(player, new Animation(828), Location.create(3222, 3218, 0));
|
||||
break;
|
||||
case "j-mod options":
|
||||
if (player.getDetails().getRights() == Rights.REGULAR_PLAYER) {
|
||||
return true;
|
||||
}
|
||||
player.sendMessage("Disabled...");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package content.global.handlers.scenery;
|
||||
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.game.component.CloseEvent;
|
||||
import core.game.component.Component;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.scenery.Scenery;
|
||||
import core.net.packet.PacketRepository;
|
||||
import core.net.packet.context.MinimapStateContext;
|
||||
import core.net.packet.out.MinimapState;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Handles the reading of a sign post.
|
||||
* @author 'Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class ReadSignPostPlugin extends OptionHandler {
|
||||
|
||||
/**
|
||||
* Represents the areas on the sign.
|
||||
* @author 'Vexia
|
||||
*/
|
||||
public enum Signs {
|
||||
NEAR_LUMBRIDGE(18493, "North to farms and<br> Varrock.", "The River Lum lies to<br> the south.", "West to<br>Lumbridge.", "East to Al<br>Kharid - toll<br>gate; bring some<br>money."), NEAR_VARROCK(24263, "Sheep lay this way.", "South through farms<br> to Al Kharid and<br> Lumbridge", "West to Champion's Guild<br> and Varrock south<br> gate.", "East to Al Kharid mine and<br> follow the path north to<br> Varrock east gate.");
|
||||
|
||||
public static Signs forId(int id) {
|
||||
for (Signs sign : Signs.values()) {
|
||||
if (sign == null) {
|
||||
continue;
|
||||
}
|
||||
if (sign.object == id) {
|
||||
return sign;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The object id.
|
||||
*/
|
||||
private int object;
|
||||
|
||||
/**
|
||||
* The directions.
|
||||
*/
|
||||
private String directions[];
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ReadSignPostPlugin.java} {@code Object}.
|
||||
* @param object the object.
|
||||
* @param directions the directions.
|
||||
*/
|
||||
Signs(int object, String... directions) {
|
||||
this.object = object;
|
||||
this.directions = directions;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 2));
|
||||
player.getInterfaceManager().open(new Component(135)).setCloseEvent(new CloseEvent() {
|
||||
@Override
|
||||
public boolean close(Player player, Component c) {
|
||||
PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 0));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
final Scenery object = (Scenery) node;
|
||||
Signs sign = Signs.forId(object.getId());
|
||||
if (sign == null) {
|
||||
return false;
|
||||
}
|
||||
String[] dirs = sign.directions;
|
||||
if (object.getLocation().getX() == 3107 && object.getLocation().getY() == 3296) {
|
||||
dirs[0] = "North to Draynor<br> Manor";
|
||||
dirs[1] = "South to Draynor<br> Village";
|
||||
dirs[2] = "West to Port<br> Sarim";
|
||||
dirs[3] = "East to<br> Lumbridge";
|
||||
}
|
||||
player.getPacketDispatch().sendString(dirs[0], 135, 3); // North
|
||||
player.getPacketDispatch().sendString(dirs[1], 135, 9); // South
|
||||
player.getPacketDispatch().sendString(dirs[2], 135, 12); // West
|
||||
player.getPacketDispatch().sendString(dirs[3], 135, 8); // East
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
SceneryDefinition.forId(2366).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(2367).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(2368).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(2369).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(2370).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(2371).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(4132).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(4133).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(4134).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(4135).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(5164).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(10090).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(13873).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(15522).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(18493).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(24263).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(25397).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(30039).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(30040).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(31296).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(31298).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(31299).getHandlers().put("option:read", this);
|
||||
SceneryDefinition.forId(31300).getHandlers().put("option:read", this);
|
||||
// ObjectDefinition.forId(31301).getConfigurations().put("option:read", this);//goblin village
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package content.global.handlers.scenery;
|
||||
|
||||
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.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Handles the search option.
|
||||
* @author 'Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class SearchOptionPlugin extends OptionHandler {
|
||||
|
||||
/**
|
||||
* Represents an object to search.
|
||||
* @author 'Vexia
|
||||
*/
|
||||
public enum Search {
|
||||
/**
|
||||
* Represents a search.
|
||||
*/
|
||||
DEFAULT(-1, new Item(1059, 1));
|
||||
|
||||
public static Search forId(int id) {
|
||||
for (Search search : Search.values()) {
|
||||
if (search.getObject() == id) {
|
||||
return search;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The object id.
|
||||
*/
|
||||
private int object;
|
||||
|
||||
/**
|
||||
* The item rewarded.
|
||||
*/
|
||||
private Item item;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SearchOptionPlugin.java}
|
||||
*/
|
||||
Search(int object, Item item) {
|
||||
this.object = object;
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the item.
|
||||
*/
|
||||
public Item getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the object.
|
||||
*/
|
||||
public int getObject() {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
if (node.getName().equals("Bookcase")) {
|
||||
player.getPacketDispatch().sendMessage("You search the books...");
|
||||
player.getPacketDispatch().sendMessage("You find nothing of interest to you.");
|
||||
return true;
|
||||
}
|
||||
if (node.getId() == 14743 && !player.getInventory().containItems(946) && !player.inCombat()) {
|
||||
player.getPacketDispatch().sendMessage("You mindlessly reach into the sack labeled 'knives'...");
|
||||
player.getPacketDispatch().sendMessage("Against all odds you pull out a knife without hurting yourself.",2);
|
||||
player.getInventory().add(new Item(946));
|
||||
return true;
|
||||
}
|
||||
player.getPacketDispatch().sendMessage("You search the " + node.getName().toLowerCase() + " but find nothing.");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
SceneryDefinition.setOptionHandler("search", this);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package content.global.handlers.scenery;
|
||||
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.game.container.Container;
|
||||
import core.game.container.impl.EquipmentContainer;
|
||||
import core.plugin.Initializable;
|
||||
import org.rs09.consts.Items;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface.AttackStyle;
|
||||
import core.game.node.entity.combat.equipment.WeaponInterface.WeaponInterfaces;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.diary.DiaryType;
|
||||
import core.game.node.entity.player.link.audio.Audio;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.scenery.Scenery;
|
||||
import core.game.node.scenery.SceneryBuilder;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Plugin;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Handles the slashing of a web object.
|
||||
* @author Vexia
|
||||
* @version 2.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class SlashWebPlugin extends OptionHandler {
|
||||
|
||||
/**
|
||||
* Represents the object ids.
|
||||
*/
|
||||
private static final int[] IDS = new int[] { 733, 1810, 11400, 33237 };
|
||||
|
||||
/**
|
||||
* Represents the animation of slashing a web.
|
||||
*/
|
||||
private static final Animation ANIMATION = new Animation(451);
|
||||
|
||||
/**
|
||||
* Represents the knife animation.
|
||||
*/
|
||||
private static final Animation KNIFE_ANIMATION = new Animation(911);
|
||||
|
||||
/**
|
||||
* Represents the knife item.
|
||||
*/
|
||||
private static final Item KNIFE = new Item(946);
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
for (int objectId : IDS) {
|
||||
SceneryDefinition.forId(objectId).getHandlers().put("option:slash", this);
|
||||
}
|
||||
SceneryDefinition.forId(27266).getHandlers().put("option:pass", this);
|
||||
SceneryDefinition.forId(29354).getHandlers().put("option:pass", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
final Scenery object = (Scenery) node;
|
||||
Item weapon = getWeapon(player, player.getEquipment());
|
||||
if (weapon == null) {
|
||||
weapon = getWeapon(player, player.getInventory());
|
||||
if (weapon == null) {
|
||||
if (!player.getInventory().containsItem(KNIFE)) {
|
||||
player.getPacketDispatch().sendMessage("Only a sharp blade can cut through this sticky web.");
|
||||
return true;
|
||||
}
|
||||
weapon = KNIFE;
|
||||
}
|
||||
}
|
||||
final boolean success = RandomFunction.random(2) == 1;
|
||||
player.lock(2);
|
||||
player.getAudioManager().send(new Audio(2548));
|
||||
player.animate(weapon == KNIFE ? KNIFE_ANIMATION : ANIMATION);
|
||||
if (success) {
|
||||
player.getPacketDispatch().sendMessage("You slash the web apart.");
|
||||
SceneryBuilder.replace(object, object.getId() == 27266 || object.getId() == 29354 ? object.transform(734) : object.transform(object.getId() + 1), 100);
|
||||
|
||||
// Venture through the cobwebbed corridor in Varrock Sewers
|
||||
if (object.getId() == 29354) {
|
||||
player.getAchievementDiaryManager().finishTask(player, DiaryType.VARROCK, 0, 17);
|
||||
}
|
||||
// Escape from the spider lair in Varrock Sewers with some red<br><br>spiders eggs
|
||||
if (object.getId() == 29354 && player.getInventory().containsAtLeastOneItem(Items.RED_SPIDERS_EGGS_223) && player.getLocation().getY() <= 9897) {
|
||||
player.getAchievementDiaryManager().finishTask(player, DiaryType.VARROCK, 1, 4);
|
||||
}
|
||||
} else {
|
||||
player.getPacketDispatch().sendMessage("You fail to cut through it.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the slashed weapon item.
|
||||
* @param player the player.
|
||||
* @param container the container.
|
||||
* @return the item.
|
||||
*/
|
||||
private Item getWeapon(final Player player, final Container container) {
|
||||
Item item = container instanceof EquipmentContainer ? container.get(EquipmentContainer.SLOT_WEAPON) : null;
|
||||
if (container instanceof EquipmentContainer) {
|
||||
return checkEquipmentWeapon(player, item);
|
||||
}
|
||||
for (Item i : container.toArray()) {
|
||||
if (i == null) {
|
||||
continue;
|
||||
}
|
||||
if (i.getDefinition().hasAction("wield") || i.getDefinition().hasAction("equip")) {
|
||||
item = checkEquipmentWeapon(player, i);
|
||||
if (item != null) {
|
||||
return item;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks an equipment weapon.
|
||||
* @param player the player.
|
||||
* @param item the item.
|
||||
* @return {@code Item} the item.
|
||||
*/
|
||||
private Item checkEquipmentWeapon(final Player player, final Item item) {
|
||||
if (item != null) {
|
||||
WeaponInterfaces inter = WeaponInterface.getWeaponInterface(item);
|
||||
if (inter == null) {
|
||||
return null;
|
||||
}
|
||||
boolean success = false;
|
||||
for (AttackStyle style : inter.getAttackStyles()) {
|
||||
if (style.getBonusType() == WeaponInterface.BONUS_SLASH) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package content.global.handlers.scenery;
|
||||
|
||||
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.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* @author 'Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public class SlayerDangerSignPlugin extends OptionHandler {
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
SceneryDefinition.forId(5127).getHandlers().put("option:read", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
player.getDialogueInterpreter().sendDialogue("<col=FFF0000>WARNING!", "</col>This area contains very dangerous creatures!", "Do not pass unless properly prepared!");
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package content.global.handlers.scenery;
|
||||
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.game.component.Component;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.map.Location;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Handles the spining interface open.
|
||||
* @author Adam
|
||||
*/
|
||||
@Initializable
|
||||
public class SpinSpinningWheelPlugin extends OptionHandler {
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
player.getInterfaceManager().open(new Component(459));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
SceneryDefinition.forId(2644).getHandlers().put("option:spin", this);
|
||||
SceneryDefinition.forId(4309).getHandlers().put("option:spin", this);
|
||||
SceneryDefinition.forId(8748).getHandlers().put("option:spin", this);
|
||||
SceneryDefinition.forId(20365).getHandlers().put("option:spin", this);
|
||||
SceneryDefinition.forId(21304).getHandlers().put("option:spin", this);
|
||||
SceneryDefinition.forId(25824).getHandlers().put("option:spin", this);
|
||||
SceneryDefinition.forId(26143).getHandlers().put("option:spin", this);
|
||||
SceneryDefinition.forId(34497).getHandlers().put("option:spin", this);
|
||||
SceneryDefinition.forId(36970).getHandlers().put("option:spin", this);
|
||||
SceneryDefinition.forId(37476).getHandlers().put("option:spin", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getDestination(Node node, Node n) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
package content.global.handlers.scenery;
|
||||
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.combat.ImpactHandler.HitsplatType;
|
||||
import core.game.node.entity.impl.Animator.Priority;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.item.ChanceItem;
|
||||
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.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import core.tools.RandomFunction;
|
||||
import core.game.world.GameWorld;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents the thieving guide plugin.
|
||||
* @author 'Vexia
|
||||
* @date 16/11/2013
|
||||
*/
|
||||
@Initializable
|
||||
public class ThievingGuidePlugin extends OptionHandler {
|
||||
|
||||
/**
|
||||
* The coin looots.
|
||||
*/
|
||||
private static final ChanceItem[] COINS = new ChanceItem[] { new ChanceItem(995, 20, 20, 90), new ChanceItem(995, 40, 40, 80) };
|
||||
|
||||
/**
|
||||
* The gem items.
|
||||
*/
|
||||
private static final ChanceItem[] GEMS = new ChanceItem[] { new ChanceItem(1623, 1, 1, 80), new ChanceItem(1621, 1, 1, 60), new ChanceItem(1619, 1, 1, 8), new ChanceItem(1617, 1, 1, 7) };
|
||||
|
||||
/**
|
||||
* Represents the stethoscope item.
|
||||
*/
|
||||
private static final Item SETHOSCOPE = new Item(5560);
|
||||
|
||||
/**
|
||||
* Represents the required level to crack a safe.
|
||||
*/
|
||||
private static final int level = 50;
|
||||
|
||||
/**
|
||||
* Represents the experience gained.
|
||||
*/
|
||||
private static final double experience = 70;
|
||||
|
||||
/**
|
||||
* Represents the animations to use.
|
||||
*/
|
||||
private static final Animation[] animations = new Animation[] { new Animation(2247), new Animation(2248), new Animation(1113), new Animation(2244) };
|
||||
|
||||
/**
|
||||
* Represents the cracked safe.
|
||||
*/
|
||||
private static final int CRACKED_SAFE = 7238;
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
SceneryDefinition.forId(7236).getHandlers().put("option:crack", this);// wall
|
||||
// safe.
|
||||
SceneryDefinition.forId(7227).getHandlers().put("option:disarm", this);// trap
|
||||
SceneryDefinition.forId(7256).getHandlers().put("option:open", this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(final Player player, final Node node, String option) {
|
||||
switch (option) {
|
||||
case "open":
|
||||
player.getDialogueInterpreter().sendDialogues(2266, null, "And where do you think you're going? A little too eager", "I think. Come and talk to me before you go wandering", "around in there.");
|
||||
break;
|
||||
case "crack":
|
||||
if (player.getSkills().getLevel(Skills.THIEVING) < 50) {
|
||||
player.getPacketDispatch().sendMessage("You need to be level " + level + " thief to crack this safe.");
|
||||
return true;
|
||||
}
|
||||
if (player.getInventory().freeSlots() == 0) {
|
||||
player.getPacketDispatch().sendMessage("Not enough inventory space.");
|
||||
return true;
|
||||
}
|
||||
final boolean success = success(player, Skills.THIEVING);
|
||||
player.lock(4);
|
||||
player.getPacketDispatch().sendMessage("You start cracking the safe.");
|
||||
player.animate(animations[success ? 1 : 0]);
|
||||
GameWorld.getPulser().submit(new Pulse(3, player) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
if (success) {
|
||||
handleSuccess(player, (Scenery) node);
|
||||
return true;
|
||||
}
|
||||
final boolean trapped = RandomFunction.random(3) == 1;
|
||||
if (trapped) {
|
||||
player.getPacketDispatch().sendMessage("You slip and trigger a trap!");
|
||||
player.animate(animations[2]);
|
||||
player.getImpactHandler().manualHit(player, RandomFunction.random(2, 6), HitsplatType.NORMAL);
|
||||
GameWorld.getPulser().submit(new Pulse(1) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
player.animate(new Animation(-1, Priority.HIGH));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "search":
|
||||
player.animate(animations[3]);
|
||||
player.getPacketDispatch().sendMessage("You temporarily disarm the trap!");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the success.
|
||||
* @param player the player.
|
||||
* @param object the object.
|
||||
*/
|
||||
public void handleSuccess(final Player player, final Scenery object) {
|
||||
SceneryBuilder.replace(object, object.transform(CRACKED_SAFE), 1);
|
||||
player.getPacketDispatch().sendMessage("You get some loot.");
|
||||
player.getSkills().addExperience(Skills.THIEVING, experience, true);
|
||||
addItem(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item.
|
||||
* @param player the player.
|
||||
*/
|
||||
private void addItem(Player player) {
|
||||
ChanceItem[] l = RandomFunction.random(2) == 1 ? GEMS : COINS;
|
||||
List<ChanceItem> chances = new ArrayList<>(20);
|
||||
for (ChanceItem c : l) {
|
||||
chances.add(c);
|
||||
}
|
||||
Collections.shuffle(chances);
|
||||
int rand = RandomFunction.random(100);
|
||||
Item item = null;
|
||||
int tries = 0;
|
||||
while (item == null) {
|
||||
ChanceItem i = chances.get(0);
|
||||
if (rand <= i.getChanceRate()) {
|
||||
item = i;
|
||||
break;
|
||||
}
|
||||
if (tries > chances.size()) {
|
||||
if (i.getId() == 1617) {
|
||||
item = COINS[0];
|
||||
break;
|
||||
}
|
||||
item = i;
|
||||
break;
|
||||
}
|
||||
tries++;
|
||||
}
|
||||
player.getInventory().add(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to determine the success of a player when thieving.
|
||||
* @param player the player.
|
||||
* @return <code>True</code> if succesfull, <code>False</code> if not.
|
||||
*/
|
||||
public final boolean success(final Player player, final int skill) {
|
||||
double level = player.getSkills().getLevel(skill);
|
||||
double req = 50;
|
||||
int mod = player.getInventory().containsItem(SETHOSCOPE) ? 8 : 17;
|
||||
double successChance = Math.ceil((level * 50 - req * mod) / req / 3 * 4);
|
||||
int roll = RandomFunction.random(99);
|
||||
if (successChance >= roll) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user