Rewrote impling system
Fixed static impling spawns Fixed impling spawn ratio Reworked Puro-Puro, much more authentic Imp defenders now work properly Crop circles now appear Added admin command ::implings to list active implings (excludes implings from Puro-Puro) Fixed bug where you could add to a finished compost bin
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
package content.minigame.puropuro
|
||||
|
||||
import core.api.*
|
||||
import core.game.interaction.*
|
||||
import core.game.world.map.Location
|
||||
import core.game.node.scenery.Scenery
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.TeleportManager.TeleportType
|
||||
|
||||
class CropCircleController : TickListener, InteractionListener, LoginListener {
|
||||
override fun tick () {
|
||||
if (getWorldTicks() < nextCircle)
|
||||
return
|
||||
deconstructOldCircle()
|
||||
|
||||
val (name, loc) = possibleLocations.random()
|
||||
constructCircle(loc)
|
||||
|
||||
sendNews("A crop circle has appeared near $name.")
|
||||
nextCircle = getWorldTicks() + 1500
|
||||
currentLocName = name
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
on (center, IntType.SCENERY, "enter") {player, _ ->
|
||||
if (hasImpBox(player)) {
|
||||
sendDialogue (player, "Something prevents you from entering. You think the portal is offended by your imp box. They are not popular on imp and impling planes.")
|
||||
return@on true
|
||||
}
|
||||
teleport (player, puroLocation, TeleportType.PURO_PURO)
|
||||
setAttribute (player, exitLocation, Location.create(player.location))
|
||||
return@on true
|
||||
}
|
||||
|
||||
on (puroExit, IntType.SCENERY, "leave", "quick-leave") {player, _ ->
|
||||
var exit = getAttribute (player, exitLocation, Location.create(3158, 3300, 0))
|
||||
teleport (player, exit, TeleportType.PURO_PURO)
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
|
||||
override fun login (player: Player) {
|
||||
sendMessage (player, "A crop circle is active near $currentLocName.")
|
||||
}
|
||||
|
||||
private fun constructCircle (location: Location) {
|
||||
activeObjects.add (
|
||||
addScenery (
|
||||
center,
|
||||
location,
|
||||
rotation = 0,
|
||||
type = 10
|
||||
)
|
||||
)
|
||||
for ((index, tile) in location.surroundingTiles.withIndex()) {
|
||||
activeObjects.add (
|
||||
addScenery (
|
||||
surrounding[index % 4],
|
||||
tile,
|
||||
rotation = (index / 4) * 2,
|
||||
type = 10
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun deconstructOldCircle() {
|
||||
for (scenery in activeObjects)
|
||||
removeScenery(scenery)
|
||||
activeObjects.clear()
|
||||
}
|
||||
|
||||
private fun hasImpBox (player: Player) : Boolean {
|
||||
return inInventory(player, 10025) || inInventory(player, 10027) || inInventory(player, 10028)
|
||||
}
|
||||
|
||||
companion object {
|
||||
var currentLocName = ""
|
||||
val exitLocation = "/save:puro-exit"
|
||||
val possibleLocations = arrayOf (
|
||||
Pair ("Doric's Hut", Location.create(2953, 3444, 0)),
|
||||
Pair ("Yanille", Location.create(2583, 3104, 0)),
|
||||
Pair ("Draynor", Location.create(3113, 3274, 0)),
|
||||
Pair ("Rimmington", Location.create(2978, 3216, 0)),
|
||||
Pair ("The Grand Exchange", Location.create(3141, 3461, 0)),
|
||||
Pair ("Northern Lumbridge", Location.create(3160, 3296, 0)),
|
||||
Pair ("Southern Varrock", Location.create(3218, 3348, 0)),
|
||||
Pair ("Northern Ardougne", Location.create(2644, 3350, 0))
|
||||
)
|
||||
val activeObjects = ArrayList<Scenery>()
|
||||
val surrounding = arrayOf (24984, 24985, 24986, 24987)
|
||||
val center = 24991
|
||||
val puroExit = 25014
|
||||
val puroLocation = Location.create(2591, 4320, 0)
|
||||
var nextCircle = 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package content.minigame.puropuro
|
||||
|
||||
import core.api.*
|
||||
import core.tools.*
|
||||
import core.game.node.entity.npc.*
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.item.GroundItemManager
|
||||
import core.game.node.item.Item
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.world.map.RegionManager
|
||||
import core.game.system.task.Pulse
|
||||
import content.global.skill.hunter.bnet.BNetTypes
|
||||
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class ImpDefenderBehavior : NPCBehavior(6074) {
|
||||
override fun onCreation (self: NPC) {
|
||||
self.isWalks = true
|
||||
self.isNeverWalks = false
|
||||
self.walkRadius = 30
|
||||
}
|
||||
|
||||
override fun tick (self: NPC) : Boolean {
|
||||
if (!RandomFunction.roll(10)) return true
|
||||
|
||||
var nextCaptureTick = getAttribute(self, "next-capture-tick", 0)
|
||||
if (getWorldTicks() < nextCaptureTick) return true
|
||||
|
||||
var players = RegionManager.getLocalPlayers(self, 2)
|
||||
for (player in players) {
|
||||
var lowestTierImpling = BNetTypes.getImpling(player)
|
||||
if (lowestTierImpling == null) continue
|
||||
var jarItem = lowestTierImpling.reward
|
||||
setAttribute(self, "capture-target", player)
|
||||
setAttribute(self, "capture-item", jarItem)
|
||||
setAttribute(self, "next-capture-tick", getWorldTicks() + RandomFunction.random(25, 100))
|
||||
submitIndividualPulse(self, TryReleasePulse(self))
|
||||
break
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private class TryReleasePulse(val self: NPC) : Pulse() {
|
||||
companion object {
|
||||
const val catchPlayerLow = 35.0 //14% chance to avoid catch at level 1
|
||||
const val catchPlayerHigh = 280.0 //100% chance to avoid catch at level 90 (level 82 with imp repellent)
|
||||
const val impRepellentBonus = 20.0 //10% bonus if player has imp repellent
|
||||
}
|
||||
|
||||
var counter = 0
|
||||
override fun pulse() : Boolean {
|
||||
val player: Player? = getAttribute(self, "capture-target", null)
|
||||
val jarItem: Item? = getAttribute(self, "capture-item", null)
|
||||
if (player == null || jarItem == null) return true
|
||||
when (counter++) {
|
||||
0 -> {
|
||||
face (self, player)
|
||||
animate (self, 6628)
|
||||
setDelay(animationDuration(getAnimation(6628)))
|
||||
return false
|
||||
}
|
||||
1 -> {
|
||||
var hasRepellent = inInventory(player, Items.IMP_REPELLENT_11262)
|
||||
var baseRoll = RandomFunction.randomDouble(100.0)
|
||||
var playerRoll = RandomFunction.getSkillSuccessChance(
|
||||
catchPlayerLow + if (hasRepellent) impRepellentBonus else 0.0,
|
||||
catchPlayerHigh + if (hasRepellent) impRepellentBonus else 0.0,
|
||||
getStatLevel(player, Skills.THIEVING)
|
||||
)
|
||||
if (playerRoll < baseRoll) {
|
||||
sendChat (self, "Be free!")
|
||||
animate (self, 6629)
|
||||
removeItem (player, jarItem)
|
||||
var loc = ZoneBorders (
|
||||
self.location.x - 2,
|
||||
self.location.y - 2,
|
||||
self.location.x + 2,
|
||||
self.location.y + 2
|
||||
).randomLoc
|
||||
GroundItemManager.create(
|
||||
Item(Items.IMPLING_JAR_11260),
|
||||
loc, player
|
||||
)
|
||||
}
|
||||
resetFace (self)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
package content.minigame.puropuro;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import content.global.skill.hunter.bnet.BNetTypes;
|
||||
import content.global.skill.hunter.bnet.ImplingNode;
|
||||
import core.game.node.entity.npc.AbstractNPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
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.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* Handles the imp defender npc.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class ImpDefenderNPC extends AbstractNPC {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ImpDefenderNPC} {@code Object}.
|
||||
*/
|
||||
public ImpDefenderNPC() {
|
||||
super(0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ImpDefenderNPC} {@code Object}.
|
||||
* @param id the id.
|
||||
* @param location the location.
|
||||
*/
|
||||
public ImpDefenderNPC(int id, Location location) {
|
||||
super(id, location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTickActions() {
|
||||
super.handleTickActions();
|
||||
if (RandomFunction.random(250) <= 3) {
|
||||
stealImp();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to steal an imp.
|
||||
*/
|
||||
private void stealImp() {
|
||||
List<Player> players = RegionManager.getLocalPlayers(this, 3);
|
||||
for (Player player : players) {
|
||||
if (canSteal(player)) {
|
||||
steal(player);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Steals an imp from a player.
|
||||
* @param player the player.
|
||||
*/
|
||||
private void steal(Player player) {
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
ImplingNode node = BNetTypes.getImpling(player);
|
||||
if (node != null) {
|
||||
faceTemporary(player, 1);
|
||||
sendChat("Be free!");
|
||||
player.getInventory().remove(node.getReward());
|
||||
player.setAttribute("imp-steal", GameWorld.getTicks() + 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the imp can steal from the player.
|
||||
* @param player the player.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
private boolean canSteal(Player player) {
|
||||
if (!GameWorld.getSettings().isDevMode() && player.getAttribute("imp-steal", 0) > GameWorld.getTicks()) {
|
||||
return false;
|
||||
}
|
||||
int thievingLevel = player.getSkills().getLevel(Skills.THIEVING);
|
||||
if (thievingLevel >= 60) {
|
||||
return false;
|
||||
}
|
||||
int level = thievingLevel - 10;
|
||||
if (level <= 0) {
|
||||
level = 5;
|
||||
}
|
||||
if (player.getInventory().containsItem(new Item(11262))) {
|
||||
thievingLevel += 15;
|
||||
}
|
||||
int currentLevel = RandomFunction.random(thievingLevel) + 1;
|
||||
double ratio = (double) currentLevel / (new Random().nextInt(level + 5) + 1);
|
||||
return Math.round(ratio * thievingLevel) < level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractNPC construct(int id, Location location, Object... objects) {
|
||||
return new ImpDefenderNPC(id, location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 6074 };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,6 +35,10 @@ import core.plugin.Plugin;
|
||||
import core.plugin.ClassScanner;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
import static core.api.ContentAPIKt.animateScenery;
|
||||
import static core.api.ContentAPIKt.submitWorldPulse;
|
||||
import static core.api.ContentAPIKt.animationDuration;
|
||||
|
||||
/**
|
||||
* Handles the puro puro activity.
|
||||
* @author Vexia
|
||||
@@ -78,7 +82,6 @@ public final class PuroPuroPlugin extends MapZone implements Plugin<Object> {
|
||||
ClassScanner.definePlugin(new WanderingImplingDialogue());
|
||||
ClassScanner.definePlugin(new ElnockInquisitorDialogue());
|
||||
ClassScanner.definePlugin(new PuroOptionHandler());
|
||||
ClassScanner.definePlugin(new ImpDefenderNPC());
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -128,10 +131,7 @@ public final class PuroPuroPlugin extends MapZone implements Plugin<Object> {
|
||||
case 25021:
|
||||
pushThrough(p, (Scenery) target);
|
||||
return true;
|
||||
case 25014:
|
||||
p.getTeleporter().send(Location.create(2427, 4446, 0), TeleportType.PURO_PURO);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.interact(e, target, option);
|
||||
}
|
||||
@@ -213,10 +213,6 @@ public final class PuroPuroPlugin extends MapZone implements Plugin<Object> {
|
||||
WHEAT.add(new WheatSet(1, Location.create(2601, 4293, 0), Location.create(2600, 4293, 0)));
|
||||
WHEAT.add(new WheatSet(0, Location.create(2565, 4310, 0), Location.create(2565, 4311, 0)));
|
||||
WHEAT.add(new WheatSet(1, Location.create(2582, 4346, 0), Location.create(2583, 4346, 0)));
|
||||
WHEAT.add(new WheatSet(0, Location.create(2621, 4328, 0), Location.create(2621, 4329, 0)));
|
||||
WHEAT.add(new WheatSet(1, Location.create(2602, 4349, 0), Location.create(2603, 4349, 0)));
|
||||
WHEAT.add(new WheatSet(0, Location.create(2562, 4334, 0), Location.create(2562, 4333, 0)));
|
||||
WHEAT.add(new WheatSet(1, Location.create(2582, 4290, 0), Location.create(2581, 4290, 0)));
|
||||
WHEAT.add(new WheatSet(0, Location.create(2568, 4348, 0), Location.create(2568, 4347, 0)));
|
||||
WHEAT.add(new WheatSet(0, Location.create(2615, 4347, 0), Location.create(2615, 4348, 0)));
|
||||
WHEAT.add(new WheatSet(0, Location.create(2612, 4345, 0), Location.create(2612, 4344, 0)));
|
||||
@@ -241,7 +237,6 @@ public final class PuroPuroPlugin extends MapZone implements Plugin<Object> {
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
NPCDefinition.forId(6070).getHandlers().put("option:trade", this);
|
||||
SceneryDefinition.forId(24991).getHandlers().put("option:enter", this);
|
||||
ItemDefinition.forId(11273).getHandlers().put("option:toggle-view", this);
|
||||
ItemDefinition.forId(11258).getHandlers().put("option:butterfly-jar", this);
|
||||
ItemDefinition.forId(11258).getHandlers().put("option:impling-jar", this);
|
||||
@@ -258,14 +253,6 @@ public final class PuroPuroPlugin extends MapZone implements Plugin<Object> {
|
||||
case 6070:
|
||||
ElnockInquisitorDialogue.openShop(player);
|
||||
break;
|
||||
case 24991:
|
||||
if (hasImplingBox(player)) {
|
||||
player.getDialogueInterpreter().sendDialogue("Something prevents you from entering. You think the portal is offended by", "your imp boxes. They are not popular on imp and impling planes.");
|
||||
break;
|
||||
}
|
||||
player.sendMessage("Puro Puro is disabled until its rewrite/bugfix update is complete.");
|
||||
//player.getTeleporter().send(Location.create(2591, 4320, 0), TeleportType.PURO_PURO);
|
||||
return true;
|
||||
case 11273:
|
||||
if (!player.getZoneMonitor().isInZone("puro puro")) {
|
||||
player.sendMessage("You can only use this in the Puro Puro Maze.");
|
||||
@@ -367,7 +354,6 @@ public final class PuroPuroPlugin extends MapZone implements Plugin<Object> {
|
||||
|
||||
/**
|
||||
* A wheat set.
|
||||
* @author Vexia
|
||||
*/
|
||||
public static class WheatSet {
|
||||
|
||||
@@ -434,10 +420,36 @@ public final class PuroPuroPlugin extends MapZone implements Plugin<Object> {
|
||||
continue;
|
||||
}
|
||||
if (removed) {
|
||||
submitWorldPulse(new Pulse() {
|
||||
int counter = 0;
|
||||
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
if (counter++ == 0) {
|
||||
animateScenery (object, 6596);
|
||||
setDelay(animationDuration(new Animation(6596)));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
SceneryBuilder.add(object);
|
||||
continue;
|
||||
}
|
||||
SceneryBuilder.remove(object);
|
||||
submitWorldPulse(new Pulse() {
|
||||
int counter = 0;
|
||||
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
if (counter++ == 0) {
|
||||
animateScenery (object, 6599);
|
||||
setDelay(animationDuration(new Animation(6599)));
|
||||
return false;
|
||||
}
|
||||
SceneryBuilder.remove(object);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
removed = !removed;
|
||||
setNextWhilt();
|
||||
|
||||
Reference in New Issue
Block a user