Made the Sheep Shearer wool collected count persist between logins

Reorganised, expanded, and corrected the Sheep Shearer quest dialogue
This commit is contained in:
zsrv
2023-05-26 09:12:09 +00:00
committed by Ryan
parent f7941f80ab
commit 6dcec3c42f
8 changed files with 469 additions and 652 deletions
@@ -0,0 +1,119 @@
package content.global.handlers.npc
import content.region.misthalin.lumbridge.quest.sheepshearer.SheepShearer.Companion.ATTR_IS_PENGUIN_SHEEP_SHEARED
import core.api.*
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.combat.DeathTask
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.node.entity.player.link.audio.Audio
import core.game.system.task.Pulse
import core.game.world.GameWorld
import core.game.world.update.flag.context.Animation
import core.tools.RandomFunction
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import org.rs09.consts.Sounds
private val sheepIds = intArrayOf(
NPCs.SHEEP_42,
NPCs.SHEEP_43,
NPCs.GOLDEN_SHEEP_1271,
NPCs.GOLDEN_SHEEP_1272,
NPCs.SHEEP_1529,
NPCs.SHEEP_1762,
NPCs.SHEEP_1763,
NPCs.SHEEP_1764,
NPCs.SHEEP_1765,
NPCs.SICK_LOOKING_SHEEP_1_2377,
NPCs.SICK_LOOKING_SHEEP_2_2378,
NPCs.SICK_LOOKING_SHEEP_3_2379,
NPCs.SICK_LOOKING_SHEEP_4_2380,
NPCs.SHEEP_3310,
NPCs.SHEEP_3311,
NPCs.SHEEP_3579,
NPCs.SHEEP_5148,
NPCs.SHEEP_5149,
NPCs.SHEEP_5150,
NPCs.SHEEP_5151,
NPCs.SHEEP_5152,
NPCs.SHEEP_5153,
NPCs.SHEEP_5154,
NPCs.SHEEP_5155,
NPCs.SHEEP_5156,
NPCs.SHEEP_5157,
NPCs.SHEEP_5158,
NPCs.SHEEP_5159,
NPCs.SHEEP_5160,
NPCs.SHEEP_5161,
NPCs.SHEEP_5162,
NPCs.SHEEP_5163,
NPCs.SHEEP_5164,
NPCs.SHEEP_5165,
NPCs.GOLDEN_SHEEP_5172,
NPCs.GOLDEN_SHEEP_5173
)
class SheepBehavior : NPCBehavior(*sheepIds), InteractionListener {
override fun tick(self: NPC): Boolean {
if (self.properties.combatPulse.isAttacking || DeathTask.isDead(self)) {
return true
}
if (RandomFunction.random(35) == 5) {
sendChat(self, "Baa!")
}
return true
}
override fun defineListeners() {
on(IntType.NPC, "shear") { player, node ->
val sheep = node as NPC
if (sheep.id == NPCs.SHEEP_3579) {
if (player.questRepository.getQuest("Sheep Shearer").isStarted(player)) {
setAttribute(player, ATTR_IS_PENGUIN_SHEEP_SHEARED, true)
}
animate(player, Animation(893))
playAudio(player, Audio(Sounds.PENGUINSHEEP_ESCAPE_686), false)
sendMessage(player, "The... whatever it is... manages to get away from you!")
animate(sheep, Animation(3570))
sheep.moveStep()
return@on true
}
if (!inInventory(player, Items.SHEARS_1735)) {
sendMessage(player, "You need shears to shear a sheep.")
return@on true
}
if (hasOption(sheep, "attack")) {
sendMessage(player, "That one looks a little too violent to shear...")
return@on true
}
if (freeSlots(player) == 0) {
sendMessage(player, "You don't have enough space in your inventory to carry any wool you would shear.")
return@on true
}
lock(sheep, 3)
stopWalk(sheep)
animate(player, Animation(893))
val random = RandomFunction.random(1, 5)
if (random != 4) {
sheep.locks.lockMovement(2)
sheep.transform(NPCs.SHEEP_5153)
playAudio(player, Audio(Sounds.SHEAR_SHEEP_761), false)
sendMessage(player, "You get some wool.")
addItem(player, Items.WOOL_1737) // 5160
GameWorld.Pulser.submit(object : Pulse(80, sheep) {
override fun pulse(): Boolean {
sheep.reTransform()
return true
}
})
} else {
sendMessage(player, "The sheep manages to get away from you!")
sheep.moveStep()
}
return@on true
}
}
}
@@ -1,59 +0,0 @@
package content.global.handlers.npc;
import core.game.node.entity.combat.DeathTask;
import core.game.node.entity.npc.AbstractNPC;
import core.game.world.map.Location;
import core.plugin.Initializable;
import core.tools.RandomFunction;
/**
* Handles the sheep npc's.
* @author 'Vexia
*/
@Initializable
public class SheepNPC extends AbstractNPC {
/**
* The NPC ids of NPCs using this plugin.
*/
private static final int[] ID = { 42, 43, 1271, 1272, 1529, 1762, 1763, 1764, 1765, 2377, 2378, 2379, 2380, 3310, 3311, 3579, 5148, 5149, 5150, 5151, 5152, 5153, 5154, 5155, 5156, 5157, 5158, 5159, 5160, 5161, 5162, 5163, 5164, 5165, 5172, 5173 };
/**
* Constructs a new {@code AlKharidWarriorPlugin} {@code Object}.
*/
public SheepNPC() {
super(0, null);
}
/**
* Constructs a new {@code AlKharidWarriorPlugin} {@code Object}.
* @param id The NPC id.
* @param location The location.
*/
private SheepNPC(int id, Location location) {
super(id, location);
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new SheepNPC(id, location);
}
@Override
public void tick() {
if (getProperties().getCombatPulse().isAttacking() || DeathTask.isDead(this)) {
super.tick();
return;
}
if (RandomFunction.random(35) == 5) {
sendChat("Baa!");
}
super.tick();
}
@Override
public int[] getIds() {
return ID;
}
}
@@ -1,374 +0,0 @@
package content.region.misthalin.lumbridge.dialogue;
import core.game.dialogue.DialoguePlugin;
import core.game.dialogue.FacialExpression;
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.plugin.Initializable;
import content.region.misthalin.lumbridge.quest.sheepshearer.SheepShearer;
/**
* Represents the dialogue plugin used for fred the farmer npc.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class FredTheFarmer extends DialoguePlugin {
/**
* Represents the quest instance.
*/
private Quest quest;
/**
* Constructs a new {@code FredTheFarmer} {@code Object}.
*/
public FredTheFarmer() {
/**
* empty.
*/
}
/**
* Constructs a new {@code FredTheFarmer} {@code Object}.
* @param player the player.
*/
public FredTheFarmer(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new FredTheFarmer(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
quest = player.getQuestRepository().getQuest("Sheep Shearer");
if (player.getQuestRepository().getQuest("Sheep Shearer").getStage(player) == 10 || player.getQuestRepository().getQuest("Sheep Shearer").getStage(player) == 90) {
if (SheepShearer.getWoolGiven(player) == 20 && player.getQuestRepository().getQuest("Sheep Shearer").getStage(player) == 90) {
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "That's the last of them.");
stage = 999;
return true;
}
if (player.getInventory().contains(1737, 1) || player.getInventory().contains(1759, 1)) {
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "What are you doing on my land?");
stage = 5000;
return true;
}
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "How are you doing getting those balls of wool?");
stage = 4000;
return true;
}
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "What are you doing on my land? You're not the one", "who keeps leaving all my gates open and letting out all", "my sheep are you?");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
quest = player.getQuestRepository().getQuest("Sheep Shearer");
switch (stage) {
case 0:
if (!player.getQuestRepository().isComplete("Sheep Shearer")) {
interpreter.sendOptions("Select an Option", "I'm looking for a quest.", "I'm looking for something to kill.", "I'm lost.");
stage = 1;
} else {
interpreter.sendOptions("Select an Option", "I'm looking for something to kill.", "I'm lost.");
stage = 346;
}
break;
case 346:
switch (buttonId) {
case 1:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I'm looking for something to kill.");
stage = 20;
break;
case 2:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I'm lost.");
stage = 30;
break;
}
break;
case 1:
switch (buttonId) {
case 1:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I'm looking for a quest.");
stage = 10;
break;
case 2:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I'm looking for something to kill.");
stage = 20;
break;
case 3:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I'm lost.");
stage = 30;
break;
}
break;
case 30:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "How can you be lost? Just follow the road east and", "south. You'll end up in Lumbridge fairly quickly.");
stage = 31;
break;
case 31:
end();
break;
case 10:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "You're after a quest, you say? Actually I could do with", "a bit of help.");
stage = 11;
break;
case 11:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "My sheep are getting mighty woolly. I'd be much", "obliged if you could shear them. And while you're at it", "spin the wool for me too.");
stage = 12;
break;
case 12:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Yes, that's it. Bring me 20 balls of wool. And I'm sure", "I could sort out somesort of payment. Of course,", "there's a small matter of The Thing.");
stage = 13;
break;
case 13:
interpreter.sendOptions("Select an Option", "Yes okay. I can do that.", "That doesn't sound a very exiting quest.", "What do you mean, The Thing?");
stage = 14;
break;
case 14:
switch (buttonId) {
case 1:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Yes okay. I can do that.");
stage = 670;
break;
case 2:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "That doesn't sound a very exiting quest.");
stage = 560;
break;
case 3:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "What do you mean, The Thing?");
stage = 456;
break;
}
break;
case 670:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Good! Now one more thing, do you actually know how", "to shear a sheep?");
stage = 678;
break;
case 678:
interpreter.sendOptions("Select an Option", "Of course!", "No, I don't know actually.");
stage = 679;
break;
case 679:
switch (buttonId) {
case 1:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Of course!");
stage = 954;
break;
case 2:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Err. No, I don't know actually.");
stage = 750;
break;
}
break;
case 954:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Do you know how to spin wool?");
stage = 754;
break;
case 750:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Just use a set of shears on a sheep to shear it.");
stage = 751;
break;
case 751:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "That's all I have to do?");
stage = 752;
break;
case 752:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Well once you've collected some wool you'll need to spin", "it into balls.");
stage = 753;
break;
case 753:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Do you know how to spin wool?");
stage = 754;
break;
case 754:
interpreter.sendOptions("Select an Option", "I don't know how to spin wool, sorry.", "I'm something of an expert actually!");
stage = 755;
break;
case 755:
switch (buttonId) {
case 1:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I don't know how to spin wool, sorry.");
stage = 756;
break;
case 2:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I'm something of an expert actually!");
stage = 850;
break;
}
break;
case 850:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Well you can stop grinning and get to work then.");
stage = 851;
break;
case 851:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "I'm not paying you by the hour!");
stage = 852;
break;
case 852:
end();
quest.start(player);
break;
case 756:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Don't worry, it's quite simple!");
stage = 757;
break;
case 757:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "The nearest Spinning Wheel can be found on the first", "floor of Lumbridge Castle.");
stage = 758;
break;
case 758:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "To get to the Lumbridge Castle just follow the road east.");
stage = 759;
break;
case 759:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Thank you!");
stage = 760;
break;
case 760:
end();
quest.start(player);
break;
case 671:
end();
break;
case 560:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Well what do you expect if you ask a farmer for a", "quest?");
stage = 21;
break;
case 456:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Well now, no one has ever seen The Thing. That's", "why we call it The Thing, 'cos we don't know what it is.");
stage = 457;
break;
case 457:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Someone say it's a black hearted shapeshifter, hungering for", "the souls of hard working decent folk like me. Others", "say it's just a sheep.");
stage = 21;
break;
case 20:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "What, on my land? Leave my livestock alone you", "scoundrel!");
stage = 21;
break;
case 21:
end();
break;
case 4000:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "How many more do I need to give you?");
stage = 4001;
break;
case 4001:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "You need to collect " + SheepShearer.getWoolLeft(player) + " more balls of wool.");
stage = 4002;
break;
case 4002:
if (!player.getInventory().contains(1759, 1)) {
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I haven't got any at the moment.");
stage = 4003;
break;
}
break;
case 4003:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Well at least you haven't been eaten.");
stage = 21;
break;
case 4004:
break;
case 5000:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I'm back!");
stage = 50001;
break;
case 50001:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "How are you doing getting those balls of wool?");
stage = 50002;
break;
case 50002:
if (player.getInventory().contains(1759, 1)) {
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I have some.");
stage = 50010;
break;
}
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "How many more do I need to give you?");
stage = 50003;
break;
case 50003:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "You need to collect " + SheepShearer.getWoolLeft(player) + " more balls of wool.");
stage = 50004;
break;
case 50004:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Well I've got some wool. I've not managed to make it", "into a ball though.");
stage = 50005;
break;
case 50005:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Well go find a spinning wheel then. You can find one", "on the first floor of the Lumbridge Castle, just walk east on", "the road outside my house and you'll find Lumbridge.");
stage = 50006;
break;
case 50006:
end();
break;
case 50010:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Give 'em here then.");
stage = 5011;
break;
case 5011:
int removeAmount = SheepShearer.getWoolRemove(player);
if (SheepShearer.addWool(player)) {
if (SheepShearer.getWoolGiven(player) == 20) {
player.getQuestRepository().getQuest("Sheep Shearer").setStage(player, 90);
}
interpreter.sendDialogue("You give fred " + removeAmount + " balls of wool");
stage = 5012;
}
break;
case 5012:
if (SheepShearer.getWoolGiven(player) == 20) {
player.getQuestRepository().getQuest("Sheep Shearer").setStage(player, 90);
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "That's the last of them.");
stage = 999;
break;// enough
}
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "That's all I've got so far.");
stage = 5013;
break;
case 5013:
if (SheepShearer.getWoolGiven(player) == 20) {
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "That's the last of them.");
stage = 999;
break;// enough
}
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "I need " + SheepShearer.getWoolCollect(player) + " before I can pay you.");
stage = 5014;
break;
case 999:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "I guess I'd better pay you then.");
stage = 1000;
break;
case 1000:
end();
Quest quest11 = player.getQuestRepository().getQuest("Sheep Shearer");
quest11.finish(player);
player.removeAttribute("sheep-shearer:wool");
break;
case 5014:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Ok, I'll work on it.");
stage = 5015;
break;
case 5015:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 758 };
}
}
@@ -0,0 +1,47 @@
package content.region.misthalin.lumbridge.dialogue
import content.region.misthalin.lumbridge.quest.sheepshearer.SSFredTheFarmerDialogue
import core.api.*
import core.game.dialogue.DialoguePlugin
import core.game.dialogue.FacialExpression
import core.game.dialogue.IfTopic
import core.game.dialogue.Topic
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.plugin.Initializable
import core.tools.END_DIALOGUE
import core.tools.START_DIALOGUE
@Initializable
class FredTheFarmerDialogue(player: Player? = null) : DialoguePlugin(player) {
override fun getIds(): IntArray {
return intArrayOf(758)
}
override fun open(vararg args: Any): Boolean {
npc = args[0] as NPC
if (questStage(player, "Sheep Shearer") in 1..99) {
openDialogue(player, SSFredTheFarmerDialogue(questStage(player, "Sheep Shearer")), npc)
} else {
npc(FacialExpression.ANGRY, "What are you doing on my land? You're not the one", "who keeps leaving all my gates open and letting out all", "my sheep are you?").also { stage = START_DIALOGUE }
}
return true
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when (stage) {
START_DIALOGUE -> showTopics(
IfTopic(FacialExpression.NEUTRAL, "I'm looking for a quest.", 1000, questStage(player!!, "Sheep Shearer") == 0),
Topic(FacialExpression.HALF_GUILTY, "I'm looking for something to kill.", 100),
Topic(FacialExpression.HALF_GUILTY, "I'm lost.", 200)
)
100 -> npc(FacialExpression.HALF_GUILTY, "What, on my land? Leave my livestock alone you", "scoundrel!").also { stage = END_DIALOGUE }
200 -> npc(FacialExpression.HALF_GUILTY, "How can you be lost? Just follow the road east and", "south. You'll end up in Lumbridge fairly quickly.").also { stage = END_DIALOGUE }
1000 -> openDialogue(player, SSFredTheFarmerDialogue(questStage(player, "Sheep Shearer")), npc)
}
return true
}
}
@@ -0,0 +1,182 @@
package content.region.misthalin.lumbridge.quest.sheepshearer
import core.api.*
import core.game.dialogue.DialogueFile
import core.game.dialogue.FacialExpression
import core.tools.END_DIALOGUE
import core.tools.START_DIALOGUE
import org.rs09.consts.Items
class SSFredTheFarmerDialogue(val questStage: Int) : DialogueFile() {
companion object {
const val STAGE_BEGIN_QUEST = 1000
const val STAGE_PENGUIN_SHEEP_SHEARED = 3000
const val STAGE_CANT_SPIN_WOOL = 20000
const val STAGE_CAN_SPIN_WOOL = 20100
const val STAGE_DELIVER_BALLS_OF_WOOL = 30000
const val STAGE_FINISH_QUEST = 30301
}
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
START_DIALOGUE -> if (questStage == 10) {
if (getAttribute(player!!, SheepShearer.ATTR_IS_PENGUIN_SHEEP_SHEARED, false)) {
npc(FacialExpression.ANGRY, "What are you doing on my land?").also { stage = STAGE_PENGUIN_SHEEP_SHEARED }
} else {
npc(FacialExpression.NEUTRAL, "How are you doing getting those balls of wool?").also { stage = STAGE_DELIVER_BALLS_OF_WOOL }
}
} else if (questStage == 90) {
// Player delivered all balls of wool but exited the dialogue before the quest was recorded as complete
npc(FacialExpression.SAD, "I guess I'd better pay you then.").also { stage = STAGE_FINISH_QUEST }
} else {
npc(FacialExpression.NEUTRAL, "You're after a quest, you say? Actually I could do with", "a bit of help.").also { stage = STAGE_BEGIN_QUEST }
}
STAGE_BEGIN_QUEST -> npc(FacialExpression.NEUTRAL, "My sheep are getting mighty woolly. I'd be much", "obliged if you could shear them. And while you're at it", "spin the wool for me too.").also { stage++ }
1001 -> npc(FacialExpression.HAPPY, "Yes, that's it. Bring me 20 balls of wool. And I'm sure", "I could sort out some sort of payment. Of course,", "there's the small matter of The Thing.").also { stage++ }
1002 -> options("Yes okay. I can do that.", "That doesn't sound a very exciting quest.", "What do you mean, The Thing?").also { stage++ }
1003 -> when (buttonID) {
1 -> player(FacialExpression.HAPPY, "Yes okay. I can do that.").also { stage = 2000 }
2 -> player(FacialExpression.HALF_GUILTY, "That doesn't sound a very exciting quest.").also { stage = 1100 }
3 -> player(FacialExpression.ASKING, "What do you mean, The Thing?").also { stage = 1200 }
}
// TODO: There might be more dialogue here
1100 -> npc(FacialExpression.HALF_GUILTY, "Well what do you expect if you ask a farmer for a", "quest?").also { stage = END_DIALOGUE }
1200 -> npc(FacialExpression.SUSPICIOUS, "Well now, no one has ever seen The Thing. That's", "why we call it The Thing, 'cos we don't know what it is.").also { stage++ }
1201 -> npc(FacialExpression.SCARED, "Some say it's a black hearted shapeshifter, hungering for", "the souls of hard working decent folk like me. Others", "say it's just a sheep.").also { stage++ }
1202 -> npc(FacialExpression.ANGRY, "Well I don't have all day to stand around and gossip.", "Are you going to shear my sheep or what!").also { stage++ }
1203 -> options("Yes okay. I can do that.", "Erm I'm a bit worried about this Thing.").also { stage++ }
1204 -> when (buttonID) {
1 -> player(FacialExpression.HAPPY, "Yes okay. I can do that.").also { stage = 2000 }
2 -> player(FacialExpression.HALF_GUILTY, "Erm I'm a bit worried about this Thing.").also { stage = 1300 }
}
1300 -> npc(FacialExpression.HALF_GUILTY, "I'm sure it's nothing to worry about. Just because", "my last shearer was seen bolting out of the field", "screaming for his life doesn't mean anything.").also { stage++ }
1301 -> player(FacialExpression.HALF_GUILTY, "I'm not convinced.").also { stage = END_DIALOGUE }
2000 -> {
// NOTE: In a July 2009 video, this only happens when the dialogue ends
startQuest(player!!, "Sheep Shearer")
npc(FacialExpression.NEUTRAL, "Good! Now one more thing, do you actually know how", "to shear a sheep?").also { stage++ }
}
2001 -> options("Of course!", "Err. No, I don't know actually.").also { stage++ }
2002 -> when (buttonID) {
1 -> player(FacialExpression.HAPPY, "Of course!").also { stage = 2100 }
2 -> player(FacialExpression.NEUTRAL, "Err. No, I don't know actually.").also { stage = 2200 }
}
2100 -> npc(FacialExpression.NEUTRAL, "And you know how to spin wool into balls?").also { stage++ }
2101 -> options("I'm something of an expert actually!", "I don't know how to spin wool, sorry.").also { stage++ }
2102 -> when (buttonID) {
1 -> player(FacialExpression.HAPPY, "I'm something of an expert actually!").also { stage = STAGE_CAN_SPIN_WOOL }
2 -> player(FacialExpression.NEUTRAL, "I don't know how to spin wool, sorry.").also { stage = STAGE_CANT_SPIN_WOOL }
}
2200 -> {
if (inInventory(player!!, Items.SHEARS_1735)) {
npc(FacialExpression.HAPPY, "Well, you're halfway there already! You have a set of", "shears in your inventory. Just use those on a Sheep to", "shear it.").also { stage = 2300 }
} else {
npc(FacialExpression.NEUTRAL, "Well, first things first, you need a pair of shears, there's", "a pair in the house on the table.").also { stage = 2400 }
}
}
2300 -> player(FacialExpression.NEUTRAL, "That's all I have to do?").also { stage++ }
2301 -> npc(FacialExpression.NEUTRAL, "Well once you've collected some wool you'll need to spin", "it into balls.").also { stage++ }
2302 -> npc(FacialExpression.ASKING, "Do you know how to spin wool?").also { stage++ }
2303 -> options("I don't know how to spin wool, sorry.", "I'm something of an expert actually!").also { stage++ }
2304 -> when (buttonID) {
1 -> player(FacialExpression.NEUTRAL, "I don't know how to spin wool, sorry.").also { stage = STAGE_CANT_SPIN_WOOL }
2 -> player(FacialExpression.HAPPY, "I'm something of an expert actually!").also { stage = STAGE_CAN_SPIN_WOOL }
}
2400 -> npc(FacialExpression.NEUTRAL, "Or you could buy your own pair from the General", "Store in Lumbridge.").also { stage++ }
2401 -> npc(FacialExpression.NEUTRAL, "To get to Lumbridge travel east on the road outside.").also { stage++ }
// TODO: Add "General Stores are marked on the map by this symbol." message with the general store map icon here
2402 -> npc(FacialExpression.NEUTRAL, "Once you get some shears use them on the sheep in", "my field.").also { stage++ }
2403 -> player(FacialExpression.HAPPY, "Sounds easy!").also { stage++ }
2404 -> npc(FacialExpression.LAUGH, "That's what they all say!").also { stage++ }
2405 -> npc(FacialExpression.NEUTRAL, "Some of the sheep don't like it and will run away from", "you. Persistence is the key.").also { stage++ }
2406 -> npc(FacialExpression.NEUTRAL, "Once you've collected some wool you can spin it into", "balls.").also { stage++ }
2407 -> npc(FacialExpression.NEUTRAL, "Do you know how to spin wool?").also { stage++ }
2408 -> options("I don't know how to spin wool, sorry.", "I'm something of an expert actually!").also { stage++ }
2409 -> when (buttonID) {
1 -> player(FacialExpression.NEUTRAL, "I don't know how to spin wool, sorry.").also { stage = STAGE_CANT_SPIN_WOOL }
2 -> player(FacialExpression.HAPPY, "I'm something of an expert actually!").also { stage = STAGE_CAN_SPIN_WOOL }
}
STAGE_PENGUIN_SHEEP_SHEARED -> options("I'm back!", "Fred! Fred! I've seen The Thing!").also { stage++ }
3001 -> when (buttonID) {
1 -> player(FacialExpression.HAPPY, "I'm back!").also { stage = 3100 }
2 -> player(FacialExpression.AMAZED, "Fred! Fred! I've seen The Thing!").also { stage = 3200 }
}
3100 -> npc(FacialExpression.NEUTRAL, "How are you doing getting those balls of wool?").also { stage = STAGE_DELIVER_BALLS_OF_WOOL }
3200 -> npc(FacialExpression.SCARED, "You ... you actually saw it?").also { stage++ }
3201 -> npc(FacialExpression.SCARED, "Run for the hills! ${player!!.username} grab as many chickens as", "you can! We have to ...").also { stage++ }
3202 -> player(FacialExpression.AMAZED, "Fred!").also { stage++ }
3203 -> npc(FacialExpression.SCARED, "... flee! Oh, woe is me! The shapeshifter is coming!", "We're all ...").also { stage++ }
3204 -> player(FacialExpression.ANGRY, "FRED!").also { stage++ }
3205 -> npc(FacialExpression.HALF_CRYING, "... doomed. What!").also { stage++ }
3206 -> player(FacialExpression.NEUTRAL, "It's not a shapeshifter or any other kind of monster!").also { stage++ }
3207 -> npc(FacialExpression.ASKING, "Well then what is it boy?").also { stage++ }
3208 -> player(FacialExpression.THINKING, "Well ... it's just two Penguins; Penguins disguised as a", "sheep.").also { stage++ }
3209 -> npc(FacialExpression.THINKING, "...").also { stage++ }
3210 -> npc(FacialExpression.AMAZED, "Have you been out in the sun too long?").also { stage = END_DIALOGUE }
// Common dialogue - doesn't know how to spin wool
STAGE_CANT_SPIN_WOOL -> npc(FacialExpression.NEUTRAL, "Don't worry, it's quite simple!").also { stage++ }
20001 -> npc(FacialExpression.NEUTRAL, "The nearest Spinning Wheel can be found on the first", "floor of Lumbridge Castle.").also { stage++ }
20002 -> npc(FacialExpression.NEUTRAL, "To get to Lumbridge Castle just follow the road east.").also { stage++ }
// TODO: Add "This icon denotes a Spinning Wheel on the world map." message with the spinning wheel map icon here
20003 -> player(FacialExpression.HAPPY, "Thank you!").also { stage = END_DIALOGUE }
// Common dialogue - knows how to spin wool
STAGE_CAN_SPIN_WOOL -> npc(FacialExpression.NEUTRAL, "Well you can stop grinning and get to work then.").also { stage++ }
20101 -> npc(FacialExpression.ANGRY, "I'm not paying you by the hour!").also { stage = END_DIALOGUE }
// Common dialogue - deliver balls of wool
STAGE_DELIVER_BALLS_OF_WOOL -> {
if (inInventory(player!!, Items.BALL_OF_WOOL_1759)) {
player(FacialExpression.HAPPY, "I have some.").also { stage = 30100 }
} else {
player(FacialExpression.ASKING, "How many more do I need to give you?").also { stage = 31000 }
}
}
30100 -> npc(FacialExpression.NEUTRAL, "Give 'em here then.").also { stage++ }
30101 -> {
val ballsOfWoolDelivered = SheepShearer.deliverBallsOfWool(player!!)
if (SheepShearer.getBallsOfWoolRequired(player!!) == 0) {
setQuestStage(player!!, "Sheep Shearer", 90)
player(FacialExpression.HAPPY, "That's the last of them.").also { stage = 30300 }
} else {
sendDialogue(player!!, "You give Fred $ballsOfWoolDelivered balls of wool").also { stage = 30200 }
}
}
30200 -> player(FacialExpression.NEUTRAL, "That's all I've got so far.").also { stage++ }
30201 -> npc(FacialExpression.NEUTRAL, "I need ${SheepShearer.getBallsOfWoolRequired(player!!)} more before I can pay you.").also { stage++ }
30202 -> player(FacialExpression.NEUTRAL, "Ok I'll work on it.").also { stage = END_DIALOGUE }
30300 -> npc(FacialExpression.SAD, "I guess I'd better pay you then.").also { stage++ }
STAGE_FINISH_QUEST -> finishQuest(player!!, "Sheep Shearer").also { stage = END_DIALOGUE }
31000 -> npc(FacialExpression.NEUTRAL, "You need to collect ${SheepShearer.getBallsOfWoolRequired(player!!)} more balls of wool.").also { stage++ }
31001 -> {
if (inInventory(player!!, Items.WOOL_1737)) {
player(FacialExpression.NEUTRAL, "Well I've got some wool. I've not managed to make it", "into a ball though.").also { stage = 31100 }
} else {
player(FacialExpression.HALF_GUILTY, "I haven't got any at the moment.").also { stage = 31200 }
}
}
31100 -> npc(FacialExpression.NEUTRAL, "Well go find a spinning wheel then. You can find one", "on the first floor of Lumbridge Castle, just walk east on", "the road outside my house and you'll find Lumbridge.").also { stage = END_DIALOGUE }
// TODO: There might be more dialogue here
31200 -> npc(FacialExpression.HALF_GUILTY, "Ah well at least you haven't been eaten.").also { stage = END_DIALOGUE }
}
}
}
@@ -1,84 +0,0 @@
package content.region.misthalin.lumbridge.quest.sheepshearer;
import core.cache.def.impl.NPCDefinition;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.npc.NPC;
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.plugin.Plugin;
import core.plugin.Initializable;
import core.tools.RandomFunction;
import org.rs09.consts.Sounds;
/**
* Represents the plugin used to shear a sheep.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class SheepShearPlugin extends OptionHandler {
/**
* Represents the animation to use.
*/
private static final Animation ANIMATION = new Animation(893);
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
NPCDefinition.setOptionHandler("shear", this);
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
final NPC sheep = (NPC) node;
if (sheep.getId() == 3579) {
player.animate(ANIMATION);
player.getAudioManager().send(Sounds.PENGUINSHEEP_ESCAPE_686);
player.getPacketDispatch().sendMessage("The... whatever it is... manages to get away from you!");
sheep.animate(Animation.create(3570));
sheep.moveStep();
return true;
}
if (!player.getInventory().contains(1735, 1)) {
player.getPacketDispatch().sendMessage("You need shears to shear a sheep.");
return true;
}
if (sheep.getDefinition().hasAction("attack")) {
player.getPacketDispatch().sendMessage("That one looks a little too violent to shear...");
return true;
}
if (player.getInventory().freeSlots() == 0) {
player.getPacketDispatch().sendMessage("You don't have enough space in your inventory to carry any wool you would shear.");
return true;
}
sheep.lock(3);
sheep.getWalkingQueue().reset();
player.animate(ANIMATION);
int random = RandomFunction.random(1, 5);
if (random != 4) {
sheep.getLocks().lockMovement(2);
sheep.transform(5153);
player.getAudioManager().send(Sounds.SHEAR_SHEEP_761);
player.getPacketDispatch().sendMessage("You get some wool.");
player.getInventory().add(new Item(1737, 1));// 5160
GameWorld.getPulser().submit(new Pulse(80, sheep) {
@Override
public boolean pulse() {
sheep.reTransform();
return true;
}
});
} else {
player.getPacketDispatch().sendMessage("The sheep manages to get away from you!");
sheep.moveStep();
}
return true;
}
}
@@ -1,135 +0,0 @@
package content.region.misthalin.lumbridge.quest.sheepshearer;
import core.plugin.Initializable;
import core.game.node.entity.skill.Skills;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.quest.Quest;
import core.game.node.item.GroundItemManager;
import core.game.node.item.Item;
/**
* Represents the sheep shearer quest.
* @author 'Veixa
*/
@Initializable
public class SheepShearer extends Quest {
/**
* Constructs a new {@code SheepShearer} {@code Object}.
*/
public SheepShearer() {
super("Sheep Shearer", 28, 27, 1, 179, 0, 20, 21);
}
/**
* Represents the wool item.
*/
public static final Item WOOL = new Item(1759);
@Override
public void finish(Player player) {
super.finish(player);
player.getPacketDispatch().sendString("1 Quest Point", 277, 8 + 2);
player.getPacketDispatch().sendString("150 Crafting XP", 277, 9 + 2);
player.getPacketDispatch().sendString("60 coins", 277, 10 + 2);
player.getPacketDispatch().sendItemZoomOnInterface(1735, 240, 277, 3 + 2);
player.getSkills().addExperience(Skills.CRAFTING, 150);
player.getInterfaceManager().closeChatbox();
if (player.getInventory().freeSlots() == 0) {
GroundItemManager.create(new Item(995, 60), player.getLocation());
} else {
player.getInventory().add(new Item(995, 60));
}
}
@Override
public void drawJournal(Player player, int stage) {
super.drawJournal(player, stage);
if (stage < 10) {
player.getPacketDispatch().sendString("<col=08088A>I can start this quest by speaking to <col=8A0808>Farmer Fred</col> <col=08088A>at his", 275, 4+ 7);
player.getPacketDispatch().sendString("<col=8A0808>farm</col> <col=08088A>just a little way <col=8A0808>North West of Lumbridge", 275, 5+ 7);
return;
}
if (stage == 10 || stage == 90) {
player.getPacketDispatch().sendString("<str>I can start this quest by speaking to Farmer Fred at his", 275, 4+ 7);
player.getPacketDispatch().sendString("<str>farm just a little way North West of Lumbridge</str>", 275, 5+ 7);
int wool = getWoolCollect(player);
if (wool == 0) {
player.getPacketDispatch().sendString("<col=08088A>I have enough <col=8A0808>balls of wool</col> <col=08088A>to give <col=8A0808>Fred</col> <col=08088A> and get my</col> <col=8A0808>reward", 275, 7+ 7);
player.getPacketDispatch().sendString("<col=8A0808>money!", 275, 8+ 7);
}
if (wool != 0) {
player.getPacketDispatch().sendString("<col=08088A>I need to collect " + wool + " <col=8A0808>more balls of wool.", 275, 7+ 7);
}
}
if (stage == 100) {
player.getPacketDispatch().sendString("<str>I brought Farmer Fred 20 balls of wool, and he paid me for", 275, 4+ 7);
player.getPacketDispatch().sendString("<str>it!</str>", 275, 5+ 7);
player.getPacketDispatch().sendString("<col=FF0000>QUEST COMPLETE!</col>", 275, 7+ 7);
}
}
/**
* Method used to get the wool given.
* @param player the player.
* @return the wool given.
*/
public static int getWoolGiven(final Player player) {
return player.getAttribute("sheep-shearer:wool", 0);
}
/**
* Method used to get the wool left to give.
* @param player the player.
* @return the wool.
*/
public static int getWoolLeft(final Player player) {
int left = 20 - getWoolGiven(player);
return left;
}
/**
* Method used to add wool to the current amount given.
* @param player the player.
* @return <code>True</code> if added.
*/
public static boolean addWool(final Player player) {
final int removeAmount = getWoolRemove(player);
if (player.getInventory().remove(new Item(1759, removeAmount))) {
player.setAttribute("sheep-shearer:wool", getWoolGiven(player) + removeAmount);
return true;
}
return false;
}
/**
* Method used to get the wool to remove.
* @param player the player.
* @return the amount that can be removed from the inventory.
*/
public static int getWoolRemove(final Player player) {
int woolAmount = player.getInventory().getAmount(WOOL);
int remove = getWoolLeft(player) - (getWoolLeft(player) - woolAmount);
int realRemove = remove > 20 ? remove - (remove - getWoolLeft(player)) : remove;
if (realRemove > getWoolLeft(player)) {
realRemove = getWoolLeft(player);
}
return realRemove;
}
/**
* Method used to get the wool left to collect.
* @param player the player.
* @return the wool.
*/
public static int getWoolCollect(final Player player) {
return 20 - (getWoolGiven(player) + getWoolRemove(player));
}
@Override
public Quest newInstance(Object object) {
// TODO Auto-generated method stub
return this;
}
}
@@ -0,0 +1,121 @@
package content.region.misthalin.lumbridge.quest.sheepshearer
import core.api.*
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.quest.Quest
import core.game.node.entity.skill.Skills
import core.game.node.item.Item
import core.plugin.Initializable
import org.rs09.consts.Items
import kotlin.math.min
@Initializable
class SheepShearer : Quest("Sheep Shearer", 28, 27, 1, 179, 0, 20, 21) {
companion object {
val ATTR_NUM_BALLS_OF_WOOL_DELIVERED = "/save:sheep-shearer:num-balls-of-wool-delivered"
val ATTR_IS_PENGUIN_SHEEP_SHEARED = "/save:sheep-shearer:is-penguin-sheep-sheared"
/**
* Gets the number of balls of wool that have been delivered to Fred the Farmer.
* @param player the player to check
* @return the number of balls of wool that have been delivered
*/
fun getBallsOfWoolDelivered(player: Player): Int {
return getAttribute(player, ATTR_NUM_BALLS_OF_WOOL_DELIVERED, 0)
}
/**
* Gets the number of balls of wool remaining to be delivered to Fred the Farmer.
* @param player the player to check
* @return the number of balls of wool remaining to be delivered
*/
fun getBallsOfWoolRequired(player: Player): Int {
return 20 - getBallsOfWoolDelivered(player)
}
/**
* Gets the number of balls of wool that can be removed from the player's inventory,
* up to the amount still required by Fred the Farmer.
* @param player the player whose inventory should be checked
* @return the number of balls of wool that can be removed from the player's inventory
* and delivered to Fred the Farmer
*/
fun getBallsOfWoolToRemove(player: Player): Int {
return min(getBallsOfWoolRequired(player), amountInInventory(player, Items.BALL_OF_WOOL_1759))
}
/**
* Gets the number of balls of wool that still need to be collected by the player.
*
* This takes into account the number of balls of wool already delivered to Fred the
* Farmer, and the number of balls of wool in the player's inventory.
* @param player the player to check
* @return the number of balls of wool that still needs to be collected by the player
*/
fun getBallsOfWoolToCollect(player: Player): Int {
return getBallsOfWoolRequired(player) - getBallsOfWoolToRemove(player)
}
/**
* Delivers all balls of wool in the player's inventory, up to the amount still required
* by Fred the Farmer.
* @param player the player delivering balls of wool to Fred the Farmer
* @return the number of balls of wool removed from the player's inventory and delivered to Fred the Farmer
*/
fun deliverBallsOfWool(player: Player): Int {
val removeAmount = getBallsOfWoolToRemove(player)
if (removeItem(player, Item(Items.BALL_OF_WOOL_1759, removeAmount))) {
setAttribute(player, ATTR_NUM_BALLS_OF_WOOL_DELIVERED, getBallsOfWoolDelivered(player) + removeAmount)
return removeAmount
}
return 0
}
}
override fun newInstance(`object`: Any?): Quest {
return this
}
override fun drawJournal(player: Player, stage: Int) {
super.drawJournal(player, stage)
var ln = 11
if (stage == 0) {
line(player, "I can start this quest by speaking to !!Farmer Fred?? at his", ln++)
line(player, "!!farm?? just a little way !!North West of Lumbridge??", ln++)
} else if (stage == 10 || stage == 90) {
line(player, "<col=000000>I asked Farmer Fred, near Lumbridge, for a quest. Fred</col>", ln++, true)
line(player, "<col=000000>said he'd pay me for shearing his sheep for him!</col>", ln++, true)
ln++
val ballsOfWoolToCollect = getBallsOfWoolToCollect(player)
if (ballsOfWoolToCollect == 0) {
line(player, "I have enough !!balls of wool?? to give !!Fred?? and get my !!reward??", ln++)
line(player, "!!money!??", ln++)
} else {
line(player, "I need to collect $ballsOfWoolToCollect more !!balls of wool.??", ln++)
}
} else if (stage == 100) {
line(player, "<col=000000>I brought Farmer Fred 20 balls of wool, and he paid me for</col>", ln++, true)
line(player, "<col=000000>it!</col>", ln++, true)
ln++
line(player, "<col=FF0000>QUEST COMPLETE!</col>", ln++)
}
}
override fun finish(player: Player?) {
super.finish(player)
player ?: return
var ln = 10
player.packetDispatch.sendItemZoomOnInterface(Items.SHEARS_1735, 240, 277, 5)
drawReward(player, "1 Quest Point", ln++)
drawReward(player, "150 Crafting XP", ln++)
drawReward(player, "60 coins", ln++)
rewardXP(player, Skills.CRAFTING, 150.0)
addItemOrDrop(player, Items.COINS_995, 60)
removeAttribute(player, ATTR_NUM_BALLS_OF_WOOL_DELIVERED)
removeAttribute(player, ATTR_IS_PENGUIN_SHEEP_SHEARED)
}
}