Implemented the Big Chompy Bird Hunting quest
Implemented the toad inflation Distraction & Diversion
This commit is contained in:
@@ -546,7 +546,7 @@
|
||||
{
|
||||
"itemId": "2866",
|
||||
"name": "Ogre arrow",
|
||||
"start_graphic": "243,96",
|
||||
"start_graphic": "243,60",
|
||||
"darkbow_graphic": "",
|
||||
"projectile": "242,40,36,41,46,5,0",
|
||||
"poison_damage": "0"
|
||||
|
||||
@@ -305,7 +305,7 @@
|
||||
},
|
||||
{
|
||||
"item_id": "1573",
|
||||
"loc_data": "{1,2740,3637,0,5898270}-{1,2736,3638,0,5898270}-{1,2735,3636,0,5898270}-{1,2743,3636,0,5898270}-{1,2739,3634,0,5898270}-{1,2743,3640,0,5898270}-{1,2741,3639,0,5898270}-{1,2736,3641,0,5898270}-{1,2738,3641,0,5898270}-{1,2734,3640,0,5898270}-{1,2738,3636,0,5898270}"
|
||||
"loc_data": "{1,2559,2975,0,327690}-{1,2560,2974,0,327690}-{1,2561,2973,0,327690}-{1,2561,2976,0,327690}-{1,2740,3637,0,5898270}-{1,2736,3638,0,5898270}-{1,2735,3636,0,5898270}-{1,2743,3636,0,5898270}-{1,2739,3634,0,5898270}-{1,2743,3640,0,5898270}-{1,2741,3639,0,5898270}-{1,2736,3641,0,5898270}-{1,2738,3641,0,5898270}-{1,2734,3640,0,5898270}-{1,2738,3636,0,5898270}"
|
||||
},
|
||||
{
|
||||
"item_id": "1590",
|
||||
@@ -425,7 +425,7 @@
|
||||
},
|
||||
{
|
||||
"item_id": "1982",
|
||||
"loc_data": "{1,3085,3261,0,11141270}-{1,3039,3706,0,1310735}"
|
||||
"loc_data": "{1,3085,3261,0,11141270}-{1,3039,3706,0,1310735}-{1,2584,2966,0,327690}"
|
||||
},
|
||||
{
|
||||
"item_id": "1985",
|
||||
@@ -598,5 +598,9 @@
|
||||
{
|
||||
"item_id": "22",
|
||||
"loc_data": "{1,2574,9633,0,100}"
|
||||
},
|
||||
{
|
||||
"item_id": "2128",
|
||||
"loc_data": "{1,2648,2963,0,327690}-{1,2647,2956,0,327690}-{1,2638,2949,0,327690}"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -221277,5 +221277,16 @@
|
||||
"examine": "Moley, moley, moley!",
|
||||
"name": "Baby Mole",
|
||||
"id": "3343"
|
||||
},
|
||||
{
|
||||
"examine": "He hungry.",
|
||||
"combat_style": "1",
|
||||
"start_gfx": "243",
|
||||
"name": "Rantz",
|
||||
"start_height": "100",
|
||||
"range_animation": "3460",
|
||||
"id": "1010",
|
||||
"projectile": "242",
|
||||
"prj_height": "50"
|
||||
}
|
||||
]
|
||||
@@ -377,7 +377,7 @@
|
||||
},
|
||||
{
|
||||
"npc_id": "115",
|
||||
"loc_data": "{2572,3028,0,1,2}-{2550,3046,0,1,4}-{2572,3034,0,1,3}-{2576,3026,0,1,4}-{2534,2975,0,1,1}-{2518,2974,0,1,1}-{2573,2987,0,1,1}-{2592,2967,0,1,3}-{2589,2961,0,0,2}-{2575,2989,0,1,0}-{2574,2992,0,1,4}-{2521,2974,0,1,4}-{2500,3092,0,1,6}-{2524,3375,0,1,3}-{2524,3374,0,1,3}-{2529,3374,0,1,3}-{2532,3375,0,1,1}-{2532,3373,0,1,1}-{2527,3376,0,1,6}-{2525,3373,0,1,7}-{2525,3373,0,1,5}-{2511,3086,0,1,1}-{2511,3084,0,1,3}-{2503,3114,0,1,6}-{2509,3120,0,1,4}-{2506,3107,0,1,4}-{2500,3112,0,1,4}-{2521,3045,0,1,6}-{2517,3043,0,1,5}-{2500,3095,0,1,3}-{2497,3090,0,1,4}-{2502,3099,0,1,4}-{2504,3097,0,1,4}-{2503,3134,0,1,3}-{2554,3196,0,1,7}-{2519,3039,0,1,4}-{2722,9701,0,1,1}-{2720,9715,0,1,1}-{2721,9669,0,1,1}-{2722,9707,0,1,1}-{2723,9716,0,1,1}-{2717,9669,0,1,1}"
|
||||
"loc_data": "{2583,2967,0,1,0}-{2572,3028,0,1,2}-{2550,3046,0,1,4}-{2572,3034,0,1,3}-{2576,3026,0,1,4}-{2534,2975,0,1,1}-{2518,2974,0,1,1}-{2573,2987,0,1,1}-{2592,2967,0,1,3}-{2589,2961,0,0,2}-{2575,2989,0,1,0}-{2574,2992,0,1,4}-{2521,2974,0,1,4}-{2500,3092,0,1,6}-{2524,3375,0,1,3}-{2524,3374,0,1,3}-{2529,3374,0,1,3}-{2532,3375,0,1,1}-{2532,3373,0,1,1}-{2527,3376,0,1,6}-{2525,3373,0,1,7}-{2525,3373,0,1,5}-{2511,3086,0,1,1}-{2511,3084,0,1,3}-{2503,3114,0,1,6}-{2509,3120,0,1,4}-{2506,3107,0,1,4}-{2500,3112,0,1,4}-{2521,3045,0,1,6}-{2517,3043,0,1,5}-{2500,3095,0,1,3}-{2497,3090,0,1,4}-{2502,3099,0,1,4}-{2504,3097,0,1,4}-{2503,3134,0,1,3}-{2554,3196,0,1,7}-{2519,3039,0,1,4}-{2722,9701,0,1,1}-{2720,9715,0,1,1}-{2721,9669,0,1,1}-{2722,9707,0,1,1}-{2723,9716,0,1,1}-{2717,9669,0,1,1}"
|
||||
},
|
||||
{
|
||||
"npc_id": "116",
|
||||
@@ -2427,9 +2427,13 @@
|
||||
"npc_id": "1005",
|
||||
"loc_data": "{3057,3905,0,1,3}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1010",
|
||||
"loc_data": "{2629,2979,0,1,0}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1013",
|
||||
"loc_data": "{2544,2988,0,0,0}-{2532,2983,0,0,0}-{2549,2983,0,0,0}-{2545,2983,0,0,0}-{2528,2986,0,0,0}-{2550,2979,0,0,0}-{2522,2978,0,0,0}-{2523,2976,0,0,0}-{2526,2974,0,0,0}-{2593,2971,0,0,0}-{2594,2971,0,0,0}-{2596,2961,0,0,0}-{2598,2971,0,0,0}-{2599,2960,0,0,0}-{2598,2960,0,0,0}-{2603,2966,0,0,0}-{2603,2970,0,0,0}-{2598,2960,0,0,0}-{2596,2963,0,0,0}-{2595,2964,0,0,0}-{2594,2964,0,0,0}-{2601,2964,0,0,0}-{2598,2969,0,0,0}-{2604,2971,0,0,0}-{2601,2972,0,0,0}-{2544,2904,0,0,0}-{2548,2990,0,0,0}-{2552,2988,0,0,0}-{2548,2979,0,0,0}-{2547,2991,0,0,0}-{2525,2975,0,0,0}-{2464,2912,0,0,0}"
|
||||
"loc_data": "{2544,2988,0,1,0}-{2532,2983,0,1,0}-{2549,2983,0,1,0}-{2545,2983,0,1,0}-{2528,2986,0,1,0}-{2550,2979,0,1,0}-{2522,2978,0,1,0}-{2523,2976,0,1,0}-{2526,2974,0,1,0}-{2593,2971,0,1,0}-{2594,2971,0,1,0}-{2596,2961,0,1,0}-{2598,2971,0,1,0}-{2599,2960,0,1,0}-{2598,2960,0,1,0}-{2603,2966,0,1,0}-{2603,2970,0,1,0}-{2598,2960,0,1,0}-{2596,2963,0,1,0}-{2595,2964,0,1,0}-{2594,2964,0,1,0}-{2601,2964,0,1,0}-{2598,2969,0,1,0}-{2604,2971,0,1,0}-{2601,2972,0,1,0}-{2544,2904,0,1,0}-{2548,2990,0,1,0}-{2552,2988,0,1,0}-{2548,2979,0,1,0}-{2547,2991,0,1,0}-{2525,2975,0,1,0}-{2464,2912,0,1,0}-{2392,3057,0,1,0}-{2395,3056,0,1,0}-{2395,3052,0,1,0}-{2397,3048,0,1,0}-{2400,3050,0,1,0}-{2400,3053,0,1,0}-{2391,3052,0,1,0}-{2393,3047,0,1,0}-{2399,3046,0,1,0}-{2402,3044,0,1,0}-{2399,3040,0,1,0}-{2395,3042,0,1,0}-{2391,3045,0,1,0}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1017",
|
||||
@@ -11014,5 +11018,13 @@
|
||||
{
|
||||
"npc_id": "1078",
|
||||
"loc_data": "{2905,3540,1,1,0}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1011",
|
||||
"loc_data": "{2642,9394,0,1,0}"
|
||||
},
|
||||
{
|
||||
"npc_id": "1012",
|
||||
"loc_data": "{2650,9393,0,1,0}"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -341,6 +341,21 @@ public abstract class DialoguePlugin implements Plugin<Player> {
|
||||
interpreter.activeTopics.add(topic);
|
||||
validTopics.add(topic.getText());
|
||||
}
|
||||
|
||||
if (validTopics.size() == 1) {
|
||||
Topic topic = interpreter.activeTopics.get(0);
|
||||
|
||||
if(topic.getToStage() instanceof DialogueFile) {
|
||||
DialogueFile topicFile = (DialogueFile) topic.getToStage();
|
||||
interpreter.getDialogue().loadFile(topicFile);
|
||||
} else if(topic.getToStage() instanceof Integer) {
|
||||
stage = (Integer) topic.getToStage();
|
||||
}
|
||||
|
||||
player(topic.getText());
|
||||
interpreter.activeTopics.clear();
|
||||
}
|
||||
|
||||
options(validTopics.toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -667,7 +667,7 @@ public class NPC extends Entity {
|
||||
* Transforms this NPC.
|
||||
* @param id The new NPC id.
|
||||
*/
|
||||
public void transform(int id) {
|
||||
public NPC transform(int id) {
|
||||
this.id = id;
|
||||
this.definition = NPCDefinition.forId(id);
|
||||
super.name = definition.getName();
|
||||
@@ -680,6 +680,7 @@ public class NPC extends Entity {
|
||||
getUpdateMasks().unregisterSynced(NPCSwitchId.getOrdinal());
|
||||
}
|
||||
getUpdateMasks().register(new NPCSwitchId(id), id != originalId);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -266,6 +266,7 @@ public class Fletching {
|
||||
}
|
||||
private enum Items{
|
||||
STANDARD(1511,FletchingItems.ARROW_SHAFT, FletchingItems.SHORT_BOW, FletchingItems.LONG_BOW, FletchingItems.WOODEN_STOCK),
|
||||
ACHEY(2862, FletchingItems.OGRE_ARROW_SHAFT),
|
||||
OAK(1521, FletchingItems.OAK_SHORTBOW, FletchingItems.OAK_LONGBOW, FletchingItems.OAK_STOCK),
|
||||
WILLOW(1519, FletchingItems.WILLOW_SHORTBOW, FletchingItems.WILLOW_LONGBOW, FletchingItems.WILLOW_STOCK),
|
||||
MAPLE(1517, FletchingItems.MAPLE_SHORTOW, FletchingItems.MAPLE_LONGBOW, FletchingItems.MAPLE_STOCK),
|
||||
@@ -300,6 +301,9 @@ public class Fletching {
|
||||
SHORT_BOW(50, 5, 5, 1),
|
||||
LONG_BOW(48, 10, 10, 1),
|
||||
WOODEN_STOCK(9440, 6, 9, 1),
|
||||
|
||||
//Achey logs
|
||||
OGRE_ARROW_SHAFT(2864, 6.4, 5, 4),
|
||||
|
||||
//Oak logs
|
||||
OAK_SHORTBOW(54, 16.5, 20, 1),
|
||||
|
||||
@@ -23,7 +23,7 @@ import core.plugin.Plugin;
|
||||
public class FletchingPlugin extends UseWithHandler {
|
||||
|
||||
public FletchingPlugin() {
|
||||
super(819,820,821,822,823,824,11232,9375,9376,9377,9382,9378,9379,9380,9381,13279,1511,1521,1519,1517,1515,1513,6332,6333, Items.MAHOGANY_LOGS_6332);
|
||||
super(819,820,821,822,823,824,11232,9375,9376,9377,9382,9378,9379,9380,9381,13279,1511,1521,1519,1517,1515,1513,2862,6332,6333, Items.MAHOGANY_LOGS_6332);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package core.game.node.entity.skill.fletching;
|
||||
|
||||
import core.tools.RandomFunction;
|
||||
import core.game.node.entity.player.link.diary.DiaryType;
|
||||
import core.game.world.map.zone.ZoneBorders;
|
||||
import core.game.node.entity.skill.SkillPulse;
|
||||
@@ -55,6 +56,12 @@ public final class FletchingPulse extends SkillPulse<Item> {
|
||||
if (amount > player.getInventory().getAmount(node)) {
|
||||
amount = player.getInventory().getAmount(node);
|
||||
}
|
||||
if (fletch == Fletching.FletchingItems.OGRE_ARROW_SHAFT) {
|
||||
if (player.getQuestRepository().getQuest("Big Chompy Bird Hunting").getStage(player) == 0) {
|
||||
player.getPacketDispatch().sendMessage("You must have started Big Chompy Bird Hunting to make those.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -74,7 +81,10 @@ public final class FletchingPulse extends SkillPulse<Item> {
|
||||
}
|
||||
if (player.getInventory().remove(node)) {
|
||||
final Item item = new Item(fletch.id,fletch.amount);
|
||||
player.getInventory().add(item);
|
||||
if ( fletch == Fletching.FletchingItems.OGRE_ARROW_SHAFT ) {
|
||||
item.setAmount(RandomFunction.random(3,6));
|
||||
}
|
||||
player.getInventory().add(item);
|
||||
player.getSkills().addExperience(Skills.FLETCHING, fletch.experience, true);
|
||||
String message = getMessage();
|
||||
player.getPacketDispatch().sendMessage(message);
|
||||
|
||||
+1
-1
@@ -202,7 +202,7 @@ public class WoodcuttingSkillPulse extends Pulse {
|
||||
//OSRS: https://oldschool.runescape.wiki/w/Woodcutting scroll down to the mechanics section
|
||||
//RS3 : https://runescape.wiki/w/Woodcutting scroll down to the mechanics section, and expand the tree felling chances table
|
||||
if (resource.getRespawnRate() != 0) {
|
||||
if (RandomFunction.roll(8) || resource.identifier == 1 || resource.identifier == 2) {
|
||||
if (RandomFunction.roll(8) || resource.identifier == 1 || resource.identifier == 2 || resource.identifier == 6) {
|
||||
if (resource.isFarming()) {
|
||||
FarmingPatch fPatch = FarmingPatch.forObject(node.asScenery());
|
||||
if(fPatch != null) {
|
||||
|
||||
@@ -202,9 +202,9 @@ public final class DarkZone extends MapZone implements EventHook<UseWithEvent>{
|
||||
public void process(@NotNull Entity entity, @NotNull UseWithEvent event) {
|
||||
boolean isTinderbox = getItemName(event.getUsed()).equals("Tinderbox") || getItemName(event.getWith()).equals("Tinderbox");
|
||||
|
||||
if (isTinderbox && entity instanceof Player) runTask(entity, 2, () -> {
|
||||
if (isTinderbox && entity instanceof Player) runTask(entity, 2, 1, () -> {
|
||||
checkDarkArea(entity.asPlayer());
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import Cutscene
|
||||
import com.moandjiezana.toml.Toml
|
||||
import core.cache.def.impl.ItemDefinition
|
||||
import core.cache.def.impl.SceneryDefinition
|
||||
import core.cache.def.impl.VarbitDefinition
|
||||
import core.game.component.Component
|
||||
import core.game.container.impl.EquipmentContainer
|
||||
import core.game.content.dialogue.FacialExpression
|
||||
@@ -16,6 +17,7 @@ import core.game.node.entity.impl.ForceMovement
|
||||
import core.game.node.entity.impl.Projectile
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.HintIconManager
|
||||
import core.game.node.entity.player.link.TeleportManager
|
||||
import core.game.node.entity.player.link.audio.Audio
|
||||
import core.game.node.entity.player.link.emote.Emotes
|
||||
@@ -498,6 +500,18 @@ fun produceGroundItem(player: Player, item: Int) {
|
||||
GroundItemManager.create(Item(item), player)
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a ground item with the given ID and amount at the given location
|
||||
* @param owner the owner of the ground item, use null for none.
|
||||
* @param id the id of the item.
|
||||
* @param amount the amount of the item.
|
||||
* @param location the location of the item.
|
||||
* @return the created ground item.
|
||||
*/
|
||||
fun produceGroundItem(owner: Player?, id: Int, amount: Int, location: Location) : GroundItem {
|
||||
return GroundItemManager.create(Item(id, amount), location, owner)
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns a projectile
|
||||
*/
|
||||
@@ -620,6 +634,15 @@ fun sendDialogue(player: Player, message: String) {
|
||||
player.dialogueInterpreter.sendDialogue(*splitLines(message))
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the player's dialogue box
|
||||
* @param player the player to send the dialogue to
|
||||
* @param lines the lines of dialogue to send. No automatic splitting.
|
||||
*/
|
||||
fun sendDialogueLines(player: Player, vararg message: String) {
|
||||
player.dialogueInterpreter.sendDialogue(*message)
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays an animation on the entity
|
||||
* @param entity the entity to animate
|
||||
@@ -846,6 +869,21 @@ fun setVarbit(player: Player, varpIndex: Int, offset: Int, value: Int, save: Boo
|
||||
if (save) player.varpManager.flagSave(varpIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given varbit for the given player.
|
||||
* @param player the player to set the varbit for.
|
||||
* @param varbitId the ID of the varbit to set.
|
||||
* @param value the value to set the varbit to.
|
||||
* @param save whether or not we should save this setting (default false)
|
||||
*/
|
||||
fun setVarbit(player: Player, varbitId: Int, value: Int, save: Boolean = false) {
|
||||
player.varpManager.setVarbit(varbitId, value)
|
||||
if (save) {
|
||||
val def = VarbitDefinition.forId(varbitId)
|
||||
player.varpManager.flagSave(def.varpId)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all bits for a given varp index
|
||||
* @param player the player to clear for
|
||||
@@ -1284,11 +1322,12 @@ fun submitIndividualPulse(entity: Entity, pulse: Pulse) {
|
||||
/**
|
||||
* Similar to submitIndividualPulse, but for non-repeating tasks, with a cleaner syntax.
|
||||
*/
|
||||
fun runTask(entity: Entity, delay: Int = 0, task: () -> Unit) {
|
||||
fun runTask(entity: Entity, delay: Int = 0, repeatTimes: Int = 1, task: () -> Unit) {
|
||||
var cycles = repeatTimes
|
||||
entity.pulseManager.run(object : Pulse(delay) {
|
||||
override fun pulse(): Boolean {
|
||||
task.invoke()
|
||||
return true
|
||||
return --cycles == 0
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1706,4 +1745,99 @@ fun getSlayerTaskFlags(player : Player) : Int {
|
||||
*/
|
||||
fun hasSlayerTask(player : Player) : Boolean {
|
||||
return SlayerManager.getInstance(player).hasTask()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Skill Dialogue builder.
|
||||
* @param player the player to send the dialogue for.
|
||||
* Use like:
|
||||
* sendSkillDialogue(player) {
|
||||
* withItems(Items.EXAMPLE_0, Items.EXAMPLE_1)
|
||||
* create { id, amount ->
|
||||
* doSomethingWith(id, amount)
|
||||
* }
|
||||
* calculateMaxAmount { id ->
|
||||
* return someAmount
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
fun sendSkillDialogue(player: Player, init: SkillDialogueBuilder.() -> Unit) {
|
||||
val builder = SkillDialogueBuilder()
|
||||
builder.player = player
|
||||
builder.init()
|
||||
|
||||
if (builder.items.size !in 1..5) {
|
||||
throw IllegalStateException("Invalid number of items passed to skill dialogue (min 1, max 5): ${builder.items.size}")
|
||||
}
|
||||
|
||||
val type = when (builder.items.size) {
|
||||
1 -> SkillDialogueHandler.SkillDialogue.ONE_OPTION
|
||||
2 -> SkillDialogueHandler.SkillDialogue.TWO_OPTION
|
||||
3 -> SkillDialogueHandler.SkillDialogue.THREE_OPTION
|
||||
4 -> SkillDialogueHandler.SkillDialogue.FOUR_OPTION
|
||||
5 -> SkillDialogueHandler.SkillDialogue.FIVE_OPTION
|
||||
else -> null
|
||||
}
|
||||
|
||||
object : SkillDialogueHandler(player, type, *builder.items) {
|
||||
override fun create(amount: Int, index: Int) {
|
||||
builder.creationCallback(builder.items[index].id, amount)
|
||||
}
|
||||
|
||||
override fun getAll(index: Int): Int {
|
||||
return builder.totalAmountCallback(builder.items[index].id)
|
||||
}
|
||||
}.open()
|
||||
}
|
||||
|
||||
class SkillDialogueBuilder {
|
||||
internal lateinit var player: Player
|
||||
internal var items: Array<Item> = arrayOf<Item>()
|
||||
internal var creationCallback: (itemId: Int, amount: Int) -> Unit = {_,_ -> }
|
||||
internal var totalAmountCallback: (itemId: Int) -> Int = {id -> amountInInventory(player, id)}
|
||||
|
||||
fun withItems(vararg item: Item) {
|
||||
items = arrayOf(*item)
|
||||
}
|
||||
|
||||
fun withItems(vararg item: Int) {
|
||||
items = item.map { Item(it) }.toTypedArray()
|
||||
}
|
||||
|
||||
fun create(method: (itemId: Int, amount: Int) -> Unit) {
|
||||
creationCallback = method
|
||||
}
|
||||
|
||||
fun calculateMaxAmount(method: (itemId: Int) -> Int) {
|
||||
totalAmountCallback = method
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a hint icon with the given height at the given location
|
||||
* @param player the player to register the hint icon for
|
||||
* @param height the height of the hint icon
|
||||
* @param location the location of the hint icon
|
||||
*/
|
||||
fun registerHintIcon(player: Player, location: Location, height: Int) {
|
||||
setAttribute(player, "hinticon", HintIconManager.registerHintIcon(player, location, 1, -1, player.hintIconManager.freeSlot(), height, 3))
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a hint icon for the given Node.
|
||||
* @param player the player to show a hint icon to.
|
||||
* @param node the Node to register a hint icon for.
|
||||
*/
|
||||
fun registerHintIcon(player: Player, node: Node) {
|
||||
setAttribute(player, "hinticon", HintIconManager.registerHintIcon(player, node))
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the active ContentAPI-originated hint icon
|
||||
* @param player the player to clear the active hint icon for
|
||||
*/
|
||||
fun clearHintIcon(player: Player) {
|
||||
val slot = getAttribute(player, "hinticon", -1)
|
||||
player.removeAttribute("hinticon")
|
||||
HintIconManager.removeHintIcon(player, slot)
|
||||
}
|
||||
|
||||
@@ -142,6 +142,17 @@ abstract class DialogueFile {
|
||||
topic -> interpreter!!.activeTopics.add(topic)
|
||||
validTopics.add(topic.text)
|
||||
}
|
||||
options(*validTopics.toTypedArray())
|
||||
if (validTopics.size == 1) {
|
||||
val topic = topics[0]
|
||||
if(topic.toStage is DialogueFile) {
|
||||
val topicFile = topic.toStage as DialogueFile
|
||||
interpreter!!.dialogue.loadFile(topicFile)
|
||||
} else if(topic.toStage is Int) {
|
||||
stage = topic.toStage as Int
|
||||
}
|
||||
player(topic.text)
|
||||
interpreter!!.activeTopics.clear()
|
||||
}
|
||||
else options(*validTopics.toTypedArray())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
package rs09.game.content.quest.members.chompybird
|
||||
|
||||
import api.*
|
||||
|
||||
import org.rs09.consts.NPCs
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.Graphics
|
||||
|
||||
import rs09.game.interaction.InteractionListener
|
||||
import rs09.game.system.command.Privilege
|
||||
import core.plugin.Initializable
|
||||
import core.game.node.entity.npc.AbstractNPC
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.world.map.RegionManager
|
||||
import core.game.world.map.Location
|
||||
import core.tools.RandomFunction
|
||||
|
||||
@Initializable
|
||||
class BloatedToadNPC : AbstractNPC {
|
||||
constructor() : super(NPCs.BLOATED_TOAD_1014, null, true) {}
|
||||
private constructor(id: Int, location: Location) : super(id, location) {}
|
||||
|
||||
var ticksToLive = 100
|
||||
var chompySpawned = false
|
||||
|
||||
override fun construct(id: Int, location: Location, vararg objects: Any?): AbstractNPC {
|
||||
val npc = BloatedToadNPC(id, location)
|
||||
npc.isWalks = false
|
||||
npc.isNeverWalks = true
|
||||
npc.isRespawn = false
|
||||
return npc
|
||||
}
|
||||
|
||||
override fun getIds() : IntArray {
|
||||
return intArrayOf(NPCs.BLOATED_TOAD_1014)
|
||||
}
|
||||
|
||||
override fun handleTickActions() {
|
||||
super.handleTickActions()
|
||||
|
||||
if (ticksToLive-- <= 0) {
|
||||
val toDamage = RegionManager.getLocalEntitys(this.location, 2)
|
||||
|
||||
for (entity in toDamage) {
|
||||
if (entity == this) continue
|
||||
impact(entity, RandomFunction.random(1, 3))
|
||||
}
|
||||
|
||||
sendGraphics(Graphics.TOAD_DETONATION_240, this.location)
|
||||
|
||||
clear()
|
||||
}
|
||||
|
||||
if (!chompySpawned && RandomFunction.random(20) == 5) { //Arbitrary random number matching (ryan: updated this from 1/5 to 1/20 because 1/5 was debug stuff.)
|
||||
val chompy = NPC.create(NPCs.CHOMPY_BIRD_1550, this.location)
|
||||
val spawn = getPathableRandomLocalCoordinate(chompy, 4, this.location, 3)
|
||||
if (spawn == null || spawn == this.location) return
|
||||
|
||||
val owner = getAttribute<Player?>("owner", null) ?: return
|
||||
|
||||
chompy.isRespawn = false
|
||||
chompy.location = spawn
|
||||
chompy.setAttribute("owner", owner)
|
||||
chompy.setAttribute("toad", this)
|
||||
chompy.walkingQueue.update()
|
||||
|
||||
chompy.init()
|
||||
sendChat(chompy, "Squawk!")
|
||||
clearHintIcon(owner)
|
||||
registerHintIcon(owner, chompy)
|
||||
chompySpawned = true
|
||||
ticksToLive = 100
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class BloatedToadListeners : InteractionListener, StartupListener, Commands {
|
||||
lateinit var borders: ZoneBorders
|
||||
val extraBorders = ArrayList<ZoneBorders>()
|
||||
|
||||
override fun startup() {
|
||||
borders = ZoneBorders(2368, 2944, 2687, 3071)
|
||||
borders.addException(ZoneBorders.forRegion(10287))
|
||||
borders.addException(ZoneBorders.forRegion(10031))
|
||||
borders.addException(ZoneBorders.forRegion(9775))
|
||||
}
|
||||
|
||||
override fun defineCommands() {
|
||||
define("toadzone", Privilege.MODERATOR, "", "Toad inflation.") {player, _ ->
|
||||
val swloc = player.location.transform(-15,-15,0)
|
||||
val neloc = player.location.transform(15,15,0)
|
||||
val newBorders = ZoneBorders(swloc.x, swloc.y, neloc.x, neloc.y)
|
||||
extraBorders.add(newBorders)
|
||||
for (i in 0 until 10) {
|
||||
val npc = NPC(NPCs.SWAMP_TOAD_1013, newBorders.randomLoc)
|
||||
npc.isRespawn = true
|
||||
npc.isWalks = true
|
||||
npc.isNeverWalks = false
|
||||
npc.init()
|
||||
}
|
||||
}
|
||||
|
||||
define("toadbomb", Privilege.ADMIN, "", "Toad detoadation.") {player, _ ->
|
||||
val swloc = player.location.transform(-5,-5,0)
|
||||
val neloc = player.location.transform(5,5,0)
|
||||
for (x in swloc.x until neloc.x) {
|
||||
for (y in swloc.y until neloc.y) {
|
||||
val npc = BloatedToadNPC().construct(NPCs.BLOATED_TOAD_1014, Location.create(x, y, swloc.z))
|
||||
npc.isNeverWalks = true
|
||||
npc.isWalks = false
|
||||
(npc as BloatedToadNPC).ticksToLive = 5
|
||||
npc.init()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
on(Items.BLOATED_TOAD_2875, ITEM, "drop") {player, used ->
|
||||
val quest = player.questRepository.getQuest("Big Chompy Bird Hunting")
|
||||
val inExtraBorder = extraBorders.filter { it.insideBorder(player) }.count() > 0
|
||||
|
||||
if (!borders.insideBorder(player) && !inExtraBorder) {
|
||||
sendPlayerDialogue(player, "I probably wouldn't catch many chompies here.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
if (quest.getStage(player) < 30) {
|
||||
sendPlayerDialogue(player, "I don't know what you want from me.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
if (quest.getStage(player) in 30..40) {
|
||||
if (player.location == Location.create(2635, 2966, 0) || player.location == Location.create(2636, 2966, 0)){
|
||||
quest.setStage(player, 40)
|
||||
} else {
|
||||
sendPlayerDialogue(player, "I should probably put this where Rantz told me.")
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
|
||||
if (removeItem(player, used.asItem())) {
|
||||
val toad = core.game.node.entity.npc.NPC.create(NPCs.BLOATED_TOAD_1014, player.location)
|
||||
setAttribute(toad, "owner", player)
|
||||
toad.init()
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
package rs09.game.content.quest.members.chompybird
|
||||
|
||||
import api.*
|
||||
|
||||
import org.rs09.consts.Vars
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.Animations
|
||||
import org.rs09.consts.Graphics
|
||||
import org.rs09.consts.NPCs
|
||||
|
||||
import core.plugin.Initializable
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import core.game.node.item.Item
|
||||
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.world.update.flag.context.Graphics as Gfx
|
||||
|
||||
import rs09.game.interaction.InteractionListener
|
||||
import rs09.game.content.dialogue.SkillDialogueHandler
|
||||
import rs09.game.content.dialogue.SkillDialogueHandler.SkillDialogue
|
||||
|
||||
import kotlin.math.min
|
||||
import java.util.Random
|
||||
|
||||
@Initializable
|
||||
class ChompyBird : Quest("Big Chompy Bird Hunting", 35, 34, 2, Vars.VARP_QUEST_CHOMPY, 0, 1, 65), InteractionListener {
|
||||
companion object {
|
||||
val CAVE_ENTRANCE = Location.create(2646, 9378, 0)
|
||||
val CAVE_EXIT = Location.create(2630, 2997, 0)
|
||||
val TOAD_LOCATION = Location.create(2636, 2966, 0)
|
||||
val ATTR_ING_RANTZ = "/save:chompybird:rantz-ingredient"
|
||||
val ATTR_ING_BUGS = "/save:chompybird:bugs-ingredient"
|
||||
val ATTR_ING_FYCIE = "/save:chompybird:fycie-ingredient"
|
||||
val ATTR_BUGS_ASKED = "/save:chompybird:bugs-asked"
|
||||
val ATTR_FYCIE_ASKED = "/save:chompybird:fycie-asked"
|
||||
}
|
||||
|
||||
override fun drawJournal(player: Player, stage: Int) {
|
||||
super.drawJournal(player, stage)
|
||||
|
||||
var ln = 11
|
||||
|
||||
if (stage == 0) {
|
||||
line(player, "To start this quest I will need:", ln++, false)
|
||||
line(player, "Level 5 !!Fletching??", ln++, getStatLevel(player, Skills.FLETCHING) >= 5)
|
||||
line(player, "Level 30 !!Cooking??", ln++, getStatLevel(player, Skills.COOKING) >= 30)
|
||||
line(player, "Level 30 !!Ranged??", ln++, getStatLevel(player, Skills.RANGE) >= 30)
|
||||
line(player, "Ability to defend against !!level 64 wolves?? and !!level 70 ogres<n>??for short periods of time.", ln++, false)
|
||||
} else {
|
||||
if (stage == 10) {
|
||||
line(player, "Rantz needs me to make 'stabbers'. To do this I need:", ln++, false)
|
||||
line(player, "- !!Achey Logs??", ln++, false)
|
||||
line(player, "- !!Wolf Bones??", ln++, false)
|
||||
line(player, "- !!Feathers??", ln++, false)
|
||||
line(player, "I then must turn the !!achey logs?? into !!ogre shafts??,", ln++, false)
|
||||
line(player, "attach !!feathers?? to these !!shafts??, and then tip them", ln++, false)
|
||||
line(player, "with !!wolf bones?? chiseled into !!tips??.", ln++, false)
|
||||
line(player, "At least, that's what I think he was getting at.", ln++, false)
|
||||
} else if (stage > 10) {
|
||||
line(player, "I created 'stabbers' for Rantz.", ln++, true)
|
||||
}
|
||||
|
||||
if (stage == 20) {
|
||||
line(player, "Rantz needs me to obtain a bloated swamp toad.", ln++, false)
|
||||
line(player, "To do this, I need to take !!billows?? from the !!locked", ln++, false)
|
||||
line(player, "!!chest?? in his cave, and then head to the !!swamp to", ln++, false)
|
||||
line(player, "!!the south??. There, I should !!use the billows?? on the", ln++, false)
|
||||
line(player, "!!swamp bubbles?? to fill them with swamp gas. Then I can", ln++, false)
|
||||
line(player, "use the !!billows?? to fill the !!swamp toads?? with gas.", ln++, false)
|
||||
} else if (stage > 20) {
|
||||
line(player, "I learned how to collect swamp gas and conduct toad inflation.", ln++, true)
|
||||
}
|
||||
|
||||
if (stage == 30) {
|
||||
line(player, "Rantz needs me to place the swamp toad to bait out a 'chompy'.", ln++, false)
|
||||
} else if (stage > 30) {
|
||||
line(player, "I learned how to use the toads to bait chompies.", ln++, true)
|
||||
}
|
||||
|
||||
if (stage == 40) {
|
||||
line(player, "I should return to Rantz and let him know.", ln++, false)
|
||||
}
|
||||
|
||||
if (stage == 50) {
|
||||
line(player, "Rantz keeps missing the birds. Perhaps I should try.", ln++, false)
|
||||
} else if (stage > 50) {
|
||||
line(player, "Rantz gave me his bow so that I could try to catch a chompy.", ln++, true)
|
||||
}
|
||||
|
||||
if (stage == 60) {
|
||||
line(player, "I should use what I've learned to try to bait and kill a chompy bird.", ln++, false)
|
||||
}
|
||||
|
||||
if (stage == 70) {
|
||||
line(player, "I managed to hunt and kill a chompy bird, and now Rantz wants", ln++, false)
|
||||
line(player, "me to cook the bird for him! And to make it even worse, he and", ln++, false)
|
||||
line(player, "his children want special ingredients! Those are listed below:", ln++, false)
|
||||
line(player, "- Rantz wants: !!${getItemName(getAttribute(player, ATTR_ING_RANTZ, -1))}??", ln++, false)
|
||||
line(player, "- ${if(getAttribute(player, ATTR_BUGS_ASKED, false)) "Bugs wants: !!${getItemName(getAttribute(player, ATTR_ING_BUGS, -1))}??" else "I still need to ask !!Bugs??."}", ln++, false)
|
||||
line(player, "- ${if(getAttribute(player, ATTR_FYCIE_ASKED, false)) "Fycie wants: !!${getItemName(getAttribute(player, ATTR_ING_FYCIE, -1))}??" else "I still need to ask !!Fycie??."}", ln++, false)
|
||||
} else if (stage > 70) {
|
||||
line(player, "I seasoned and cooked the chompy bird for Rantz and his kids.", ln++, true)
|
||||
line(player, "!!QUEST COMPLETE!??", ln++, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun finish(player: Player?) {
|
||||
super.finish(player)
|
||||
player ?: return
|
||||
|
||||
var ln = 10
|
||||
player.packetDispatch.sendItemZoomOnInterface(Items.OGRE_BOW_2883, 230, 277, 5)
|
||||
drawReward(player, "2 Quest Points, 262 Fletching", ln++)
|
||||
drawReward(player, "XP, 1470 Cooking XP, 735", ln++)
|
||||
drawReward(player, "Ranged XP", ln++)
|
||||
drawReward(player, "Ogre Bow", ln++)
|
||||
drawReward(player, "Ability to make Ogre Arrows", ln++)
|
||||
rewardXP(player, Skills.FLETCHING, 262.0)
|
||||
rewardXP(player, Skills.COOKING, 1470.0)
|
||||
rewardXP(player, Skills.RANGE, 735.0)
|
||||
removeItem(player, Items.SEASONED_CHOMPY_2882)
|
||||
removeAttribute(player, ATTR_ING_BUGS)
|
||||
removeAttribute(player, ATTR_BUGS_ASKED)
|
||||
removeAttribute(player, ATTR_ING_RANTZ)
|
||||
removeAttribute(player, ATTR_ING_FYCIE)
|
||||
removeAttribute(player, ATTR_FYCIE_ASKED)
|
||||
}
|
||||
|
||||
override fun newInstance(`object`: Any?): Quest { return this }
|
||||
|
||||
override fun defineListeners() {
|
||||
val filledBellows = intArrayOf(Items.OGRE_BELLOWS_3_2872, Items.OGRE_BELLOWS_2_2873, Items.OGRE_BELLOWS_1_2874)
|
||||
|
||||
on(3379, SCENERY, "enter") {player, _ ->
|
||||
teleport(player, CAVE_ENTRANCE)
|
||||
sendMessage(player, "You walk through the cave entrance into a dimly lit cave.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(intArrayOf(32068, 32069), SCENERY, "pass-through") {player, _ ->
|
||||
teleport(player, CAVE_EXIT)
|
||||
sendMessage(player, "You walk back out of the darkness of the cave into daylight.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(3377, SCENERY, "unlock") {player, node ->
|
||||
if (freeSlots(player) == 0) {
|
||||
sendMessage(player, "You don't have enough space to do that.")
|
||||
return@on true
|
||||
}
|
||||
if (amountInInventory(player, Items.OGRE_BELLOWS_2871) > 0) {
|
||||
sendDialogue(player, "I don't need another set of bellows.")
|
||||
return@on true
|
||||
}
|
||||
sendMessage(player, "You strain to lift the rock off the chest.")
|
||||
sendChat(player, "Humph!")
|
||||
runTask(player, 2) {
|
||||
if (Random().nextBoolean()) {
|
||||
sendMessage(player, "But it's just too heavy for you.")
|
||||
sendMessage(player, "The experience has left you feeling temporarily weakened.")
|
||||
sendChat(player, "ARRRGH")
|
||||
adjustLevel(player, Skills.STRENGTH, -1)
|
||||
} else {
|
||||
replaceScenery(node.asScenery(), node.id + 1, 5)
|
||||
sendChat(player, "I guess this is what an ogre would call a locked chest.")
|
||||
sendItemDialogue(player, Items.OGRE_BELLOWS_2871, "You take the bellows from the chest.")
|
||||
addItem(player, Items.OGRE_BELLOWS_2871)
|
||||
}
|
||||
}
|
||||
|
||||
return@on true
|
||||
}
|
||||
|
||||
onUseWith(SCENERY, Items.RAW_CHOMPY_2876, 3375) {player, used, _ ->
|
||||
val rantzIngredient = getAttribute(player, ATTR_ING_RANTZ, -1)
|
||||
val bugsIngredient = getAttribute(player, ATTR_ING_BUGS, -1)
|
||||
val fycieIngredient = getAttribute(player, ATTR_ING_FYCIE, -1)
|
||||
|
||||
if (rantzIngredient == -1) {
|
||||
sendDialogue(player, "I don't have a reason to do this yet.")
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
if (
|
||||
amountInInventory(player, rantzIngredient) > 0
|
||||
&& amountInInventory(player, bugsIngredient) > 0
|
||||
&& amountInInventory(player, fycieIngredient) > 0
|
||||
) {
|
||||
lock(player, 5)
|
||||
setVarbit(player, Vars.VARBIT_QUEST_CHOMPY_SPITROAST, 1)
|
||||
animate(player, Animations.HUMAN_COOKING_RANGE_896)
|
||||
sendMessage(player, "You carefully place the chompy bird on the spit-roast.")
|
||||
sendMessage(player, "You add the other ingredients and cook the food.")
|
||||
runTask(player, 4) {
|
||||
setVarbit(player, Vars.VARBIT_QUEST_CHOMPY_SPITROAST, 0)
|
||||
sendItemDialogue(
|
||||
player,
|
||||
Items.SEASONED_CHOMPY_2882,
|
||||
"You use the ${getItemName(rantzIngredient).lowercase()}, ${getItemName(bugsIngredient).lowercase()} and the ${getItemName(fycieIngredient)} with the chompy bird to make a seasoned chompy."
|
||||
)
|
||||
if (
|
||||
removeItem(player, used.asItem())
|
||||
&& removeItem(player, rantzIngredient)
|
||||
&& removeItem(player, bugsIngredient)
|
||||
&& removeItem(player, fycieIngredient)
|
||||
) addItem(player, Items.SEASONED_CHOMPY_2882)
|
||||
sendMessage(player, "Eventually the chompy is cooked")
|
||||
sendMessage(player, "It has been deliciously seasoned to taste wonderful for ogres.")
|
||||
}
|
||||
} else {
|
||||
sendDialogue(player, "I don't have all the ingredients I need yet.")
|
||||
player.debug("Required Items: $rantzIngredient, $bugsIngredient, $fycieIngredient")
|
||||
}
|
||||
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
onUseWith(SCENERY, Items.OGRE_BELLOWS_2871, 684) {player, used, _ ->
|
||||
if (removeItem(player, used.asItem())) {
|
||||
lock(player, 2)
|
||||
visualize(player, Animations.HUMAN_USING_BELLOWS_1026, Gfx(Graphics.USING_BELLOWS, 80))
|
||||
addItem(player, Items.OGRE_BELLOWS_3_2872)
|
||||
sendMessage(player, "You fill the bellows with swamp gas.")
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
onUseWith(NPC, filledBellows, NPCs.SWAMP_TOAD_1013) {player, used, with ->
|
||||
val hasTooManyToads = amountInInventory(player, Items.BLOATED_TOAD_2875) >= 3
|
||||
|
||||
if (hasTooManyToads) {
|
||||
sendMessage(player, "One of your toads manages to escape.")
|
||||
removeItem(player, Items.BLOATED_TOAD_2875)
|
||||
}
|
||||
|
||||
sendChat(player, "Come here toady!")
|
||||
sendMessage(player, "You manage to catch the toad and inflate it with swamp gas.")
|
||||
visualize(player, Animations.HUMAN_USING_BELLOWS_1026, Gfx(Graphics.USING_BELLOWS, 80))
|
||||
animate(with.asNpc(), Animations.TOAD_INFLATION_1019)
|
||||
runTask(player, 2) {
|
||||
if (removeItem(player, used.asItem())) {
|
||||
if (filledBellows.isLast(used.id)) {
|
||||
addItem(player, Items.OGRE_BELLOWS_2871)
|
||||
} else {
|
||||
addItem(player, filledBellows.getNext(used.id))
|
||||
}
|
||||
addItem(player, Items.BLOATED_TOAD_2875)
|
||||
runTask(player) { with.asNpc().clear() }
|
||||
}
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
onUseWith(ITEM, Items.OGRE_ARROW_SHAFT_2864, Items.FEATHER_314) {player, used, with ->
|
||||
val shaftAmount = amountInInventory(player, used.id)
|
||||
val featherAmount = amountInInventory(player, with.id)
|
||||
var maxAmount = min(shaftAmount, featherAmount)
|
||||
|
||||
submitIndividualPulse(player, object : Pulse(3) {
|
||||
override fun pulse() : Boolean {
|
||||
val iterAmount = min(maxAmount, 6)
|
||||
if (removeItem(player, Item(Items.OGRE_ARROW_SHAFT_2864, iterAmount)) && removeItem(player, Item(Items.FEATHER_314, iterAmount)))
|
||||
{
|
||||
addItem(player, Items.FLIGHTED_OGRE_ARROW_2865, iterAmount)
|
||||
rewardXP(player, Skills.FLETCHING, 0.9 * iterAmount)
|
||||
maxAmount -= iterAmount
|
||||
}
|
||||
return maxAmount == 0
|
||||
}
|
||||
})
|
||||
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
onUseWith(ITEM, Items.WOLF_BONES_2859, Items.CHISEL_1755) {player, used, with ->
|
||||
val maxAmount = amountInInventory(player, used.id)
|
||||
|
||||
if (getStage(player) == 0) {
|
||||
sendMessage(player, "You must have started Big Chompy Bird Hunting to make these.")
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
if (getStatLevel(player, Skills.FLETCHING) < 5) {
|
||||
sendMessage(player, "You need a Fletching level of 5 to make these.")
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
fun process() {
|
||||
if (removeItem(player, Item(used.id))) {
|
||||
addItem(player, Items.WOLFBONE_ARROWTIPS_2861, 4)
|
||||
rewardXP(player, Skills.FLETCHING, 2.5)
|
||||
}
|
||||
}
|
||||
|
||||
sendSkillDialogue(player) {
|
||||
create { id, amount ->
|
||||
var actualAmount = min(amount, maxAmount)
|
||||
runTask(
|
||||
player,
|
||||
delay = 2,
|
||||
repeatTimes = actualAmount,
|
||||
task = ::process
|
||||
)
|
||||
}
|
||||
withItems(Item(Items.WOLFBONE_ARROWTIPS_2861, 5))
|
||||
}
|
||||
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
onUseWith(ITEM, Items.WOLFBONE_ARROWTIPS_2861, Items.FLIGHTED_OGRE_ARROW_2865) {player, used, with ->
|
||||
fun getMaxAmount(_unused: Int = 0): Int {
|
||||
val tips = amountInInventory(player, Items.WOLFBONE_ARROWTIPS_2861)
|
||||
val shafts = amountInInventory(player, Items.FLIGHTED_OGRE_ARROW_2865)
|
||||
return min(tips, shafts)
|
||||
}
|
||||
|
||||
fun process() {
|
||||
val amountThisIter = min(6, getMaxAmount())
|
||||
if (removeItem(player, Item(used.id, amountThisIter)) && removeItem(player, Item(with.id, amountThisIter))) {
|
||||
addItem(player, Items.OGRE_ARROW_2866, amountThisIter)
|
||||
rewardXP(player, Skills.FLETCHING, 6.0)
|
||||
}
|
||||
}
|
||||
|
||||
sendSkillDialogue(player) {
|
||||
create { id, amount ->
|
||||
runTask(
|
||||
player,
|
||||
delay = 2,
|
||||
repeatTimes = min(amount, getMaxAmount() / 6 + 1),
|
||||
task = ::process
|
||||
)
|
||||
}
|
||||
calculateMaxAmount(::getMaxAmount)
|
||||
withItems(Item(Items.OGRE_ARROW_2866, 5))
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+461
@@ -0,0 +1,461 @@
|
||||
package rs09.game.content.quest.members.chompybird
|
||||
|
||||
import api.*
|
||||
|
||||
import org.rs09.consts.NPCs
|
||||
import org.rs09.consts.Items
|
||||
|
||||
import rs09.tools.END_DIALOGUE
|
||||
import rs09.game.content.dialogue.DialogueFile
|
||||
import rs09.game.content.dialogue.Topic
|
||||
import rs09.game.content.dialogue.IfTopic
|
||||
import core.game.content.dialogue.DialoguePlugin
|
||||
import core.game.content.dialogue.FacialExpression
|
||||
|
||||
import core.tools.RandomFunction
|
||||
import core.plugin.Initializable
|
||||
import core.game.node.item.Item
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.quest.Quest
|
||||
|
||||
@Initializable
|
||||
class RantzDialogue(player: Player? = null) : DialoguePlugin(player) {
|
||||
override fun getIds() : IntArray {
|
||||
return intArrayOf(NPCs.RANTZ_1010)
|
||||
}
|
||||
|
||||
override fun newInstance(player: Player?) : DialoguePlugin {
|
||||
return RantzDialogue(player)
|
||||
}
|
||||
|
||||
override fun open(vararg args: Any?) : Boolean {
|
||||
npc = args[0] as NPC
|
||||
|
||||
val chompyBird = player.questRepository.getQuest("Big Chompy Bird Hunting")
|
||||
val chompyStage = chompyBird.getStage(player)
|
||||
|
||||
val hasOgreBow = inInventory(player, Items.OGRE_BOW_2883) || inEquipment(player, Items.OGRE_BOW_2883) || inBank(player, Items.OGRE_BOW_2883)
|
||||
|
||||
if (stage in 60 until 100 && !hasOgreBow) {
|
||||
stage = 201
|
||||
player.dialogueInterpreter.handle(0,0)
|
||||
return true
|
||||
}
|
||||
|
||||
when (chompyStage) {
|
||||
in 0 until 100 -> loadFile(RantzChompyBirdDialogue(chompyBird))
|
||||
}
|
||||
|
||||
player.dialogueInterpreter.handle(0,0)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun handle(componentId: Int, buttonId: Int) : Boolean {
|
||||
when(stage) {
|
||||
0 -> npcl(FacialExpression.OLD_NORMAL, "Creature done good, cooking da chompy. Maybe you wants a free hatsie? Rantz got lots of hatsies for chompy shooters.").also { stage++ }
|
||||
1 -> options("What are these 'hatsies'?", "Okay, show me your 'hatsies'.", "No thanks.").also { stage++ }
|
||||
2 -> when(buttonId) {
|
||||
1 -> playerl(FacialExpression.FRIENDLY, "What are these 'hatsies'?").also { stage = 3 }
|
||||
2 -> playerl(FacialExpression.FRIENDLY, "Okay, show me your 'hatsies'.").also { stage = 100 }
|
||||
3 -> playerl(FacialExpression.FRIENDLY, "No thanks.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
3 -> npcl(FacialExpression.OLD_NORMAL, "Creature stupid? Hatsies to wear on head, make you look good. Huh huh huh.").also { stage++ }
|
||||
4 -> playerl(FacialExpression.FRIENDLY, "Ah, I see, you're offering me hats.").also { stage++ }
|
||||
5 -> npcl(FacialExpression.OLD_NORMAL, "Dat's what Rantz said. You want hatsies or not?").also { stage = 1 }
|
||||
|
||||
100 -> {
|
||||
val hasBow = inInventory(player, Items.OGRE_BOW_2883) || inEquipment(player, Items.OGRE_BOW_2883)
|
||||
|
||||
if (!hasBow) {
|
||||
npcl(FacialExpression.OLD_NORMAL, "Stupid creature. Me need bow to see how many chompy creature kill. Bring bow.")
|
||||
stage = 200
|
||||
return true
|
||||
}
|
||||
|
||||
val hats = ChompyHat.getApplicableHats(player)
|
||||
if (hats.isEmpty()) {
|
||||
npcl(FacialExpression.OLD_NORMAL, "Sorry, creature, no hatsies for you. Come back when kill more chompy.")
|
||||
} else {
|
||||
val spaces = freeSlots(player)
|
||||
if (spaces < hats.size) {
|
||||
for (i in 0 until spaces) addItem(player, hats[i])
|
||||
npcl(FacialExpression.OLD_NORMAL, "There all hats you can fit, creature. Come back when have more room for hatsies.")
|
||||
} else {
|
||||
for (hat in hats) addItem(player, hat)
|
||||
npcl(FacialExpression.OLD_NORMAL, "There all hats, creature. Come back when kill more chompy. Unless you kill all chompy already.")
|
||||
}
|
||||
}
|
||||
stage = END_DIALOGUE
|
||||
}
|
||||
|
||||
200 -> showTopics(
|
||||
IfTopic("About that...", 201, !inBank(player, Items.OGRE_BOW_2883)),
|
||||
Topic("Okay.", END_DIALOGUE)
|
||||
)
|
||||
|
||||
201 -> npcl(FacialExpression.OLD_NORMAL, "Yes, creature?").also { stage++ }
|
||||
202 -> playerl(FacialExpression.HALF_GUILTY, "I lost my bow.").also { stage++ }
|
||||
203 -> npcl(FacialExpression.OLD_NORMAL, "Haha! Stupid creature! That okay, me can sell new one.").also { stage++ }
|
||||
204 -> playerl(FacialExpression.FRIENDLY, "Really? How much?").also { stage++ }
|
||||
205 -> npcl(FacialExpression.OLD_NORMAL, "Hmm.. let me think...").also { stage++ }
|
||||
206 -> {
|
||||
val cost = RandomFunction.random(500,550)
|
||||
setAttribute(player, "/save:chompybird:new-bow-cost", cost)
|
||||
npcl(FacialExpression.OLD_NORMAL, "Me think $cost shiny coins be ok.")
|
||||
stage++
|
||||
}
|
||||
|
||||
207 -> showTopics(
|
||||
IfTopic(
|
||||
"Okay.", 208,
|
||||
amountInInventory(player, Items.COINS_995) >= getAttribute(player, "chompybird:new-bow-cost", 500)
|
||||
),
|
||||
Topic("No thank you...", END_DIALOGUE)
|
||||
)
|
||||
|
||||
208 -> {
|
||||
if (removeItem(player, Item(Items.COINS_995, getAttribute(player, "chompybird:new-bow-cost", 500)))) {
|
||||
addItemOrDrop(player, Items.OGRE_BOW_2883)
|
||||
npcl(FacialExpression.OLD_NORMAL, "There you go, creature, now hunt chompy.")
|
||||
} else {
|
||||
playerl(FacialExpression.FRIENDLY, "Actually, I can't afford it right now.")
|
||||
}
|
||||
stage = END_DIALOGUE
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@Initializable
|
||||
class BugsDialogue(player: Player? = null) : DialoguePlugin(player) {
|
||||
override fun getIds() : IntArray {
|
||||
return intArrayOf(NPCs.BUGS_1012)
|
||||
}
|
||||
|
||||
override fun newInstance(player: Player?) : DialoguePlugin {
|
||||
return BugsDialogue(player)
|
||||
}
|
||||
|
||||
override fun open(vararg args: Any?) : Boolean {
|
||||
npc = args[0] as NPC
|
||||
|
||||
val chompyBird = player.questRepository.getQuest("Big Chompy Bird Hunting")
|
||||
val chompyStage = chompyBird.getStage(player)
|
||||
|
||||
when (chompyStage) {
|
||||
in 0 until 100 -> loadFile(BugsChompyBirdDialogue(chompyBird))
|
||||
}
|
||||
|
||||
player.dialogueInterpreter.handle(0,0)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun handle(componentId: Int, buttonId: Int) : Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@Initializable
|
||||
class FycieDialogue(player: Player? = null) : DialoguePlugin(player) {
|
||||
override fun getIds() : IntArray {
|
||||
return intArrayOf(NPCs.FYCIE_1011)
|
||||
}
|
||||
|
||||
override fun newInstance(player: Player?) : DialoguePlugin {
|
||||
return FycieDialogue(player)
|
||||
}
|
||||
|
||||
override fun open(vararg args: Any?) : Boolean {
|
||||
npc = args[0] as NPC
|
||||
|
||||
val chompyBird = player.questRepository.getQuest("Big Chompy Bird Hunting")
|
||||
val chompyStage = chompyBird.getStage(player)
|
||||
|
||||
when (chompyStage) {
|
||||
in 0 until 100 -> loadFile(FycieChompyBirdDialogue(chompyBird))
|
||||
}
|
||||
|
||||
player.dialogueInterpreter.handle(0,0)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun handle(componentId: Int, buttonId: Int) : Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
class BugsChompyBirdDialogue(val quest: Quest) : DialogueFile() {
|
||||
override fun handle(componentId: Int, buttonId: Int) {
|
||||
when (quest.getStage(player)) {
|
||||
in 0 until 20 -> npcl(FacialExpression.OLD_NORMAL, "You's better talk to Dad, him chasey sneaky da chompy.").also { stage = END_DIALOGUE }
|
||||
in 20 until 70 -> handleBellowsDialogue(player, buttonId)
|
||||
in 70 until 90 -> handleIngredientDialogue(player, buttonId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleBellowsDialogue(player: Player?, buttonId: Int) {
|
||||
when(stage) {
|
||||
0 -> playerl("Rantz said that you play with the fatsy toadies, what are they?").also { stage++ }
|
||||
1 -> npcl(FacialExpression.OLD_NORMAL, "Oh, we sometimes use da blower on da toadies but Dad don't let us get in da locked box no more. He he it was good fun making da toadies fat on da swamp gas.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleIngredientDialogue(player: Player?, buttonId: Int) {
|
||||
val bugsIngredient = getAttribute(player!!, ChompyBird.ATTR_ING_BUGS, -1)
|
||||
when(stage) {
|
||||
0 -> npcl(FacialExpression.OLD_NORMAL, "Dad say's you's making da chompy for us! Slurp! Me's has to have ${getItemName(bugsIngredient)} wiv mine! Chompy is our favourite yummms!").also { stage = END_DIALOGUE }
|
||||
}
|
||||
setAttribute(player!!, ChompyBird.ATTR_BUGS_ASKED, true)
|
||||
}
|
||||
}
|
||||
|
||||
class FycieChompyBirdDialogue(val quest: Quest) : DialogueFile() {
|
||||
override fun handle(componentId: Int, buttonId: Int) {
|
||||
when (quest.getStage(player)) {
|
||||
in 0 until 70 -> npcl(FacialExpression.OLD_NORMAL, "You's better talk to Dad, We not talk to wierdly 'umans.").also { stage = END_DIALOGUE }
|
||||
in 70 until 90 -> handleIngredientDialogue(player, buttonId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleIngredientDialogue(player: Player?, buttonId: Int) {
|
||||
val fycieIngredient = getAttribute(player!!, ChompyBird.ATTR_ING_FYCIE, -1)
|
||||
when(stage) {
|
||||
0 -> npcl(FacialExpression.OLD_NORMAL, "Dad say's you's roasting da chompy for us! Slurp! Me's wants ${getItemName(fycieIngredient)} wiv mine! Yummy can't wait to eats it.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
setAttribute(player!!, ChompyBird.ATTR_FYCIE_ASKED, true)
|
||||
}
|
||||
}
|
||||
|
||||
class RantzChompyBirdDialogue(val quest: Quest) : DialogueFile() {
|
||||
override fun handle(componentId: Int, buttonId: Int) {
|
||||
when (quest.getStage(player)) {
|
||||
0 -> handleQuestStartDialogue(player, buttonId)
|
||||
in 20 until 30 -> handleToadsiesDialogue(player, buttonId)
|
||||
in 30 until 40 -> handlePlaceToadsiesDialogue(player, buttonId)
|
||||
in 40 until 50 -> handlePlacedBaitDialogue(player, buttonId)
|
||||
in 50 until 60 -> handleRantzSucksDialogue(player, buttonId)
|
||||
in 60 until 70 -> handleWaitingForChompyDialogue(player, buttonId)
|
||||
in 70 until 80 -> handleWaitingForCookedChompy(player, buttonId)
|
||||
else -> handleImpatienceDialogue(player, buttonId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleQuestStartDialogue(player: Player?, buttonId: Int) {
|
||||
when(stage) {
|
||||
0 -> npcl(FacialExpression.OLD_NORMAL, "Hey you creature! Make some stabbers! I wanna hunt da chompy?").also { stage++ }
|
||||
1 -> options("What are 'stabbers'?", "What's a 'chompy'?", "Ok, I’ll make you some 'stabbers'.", "Er, make your own 'stabbers'!").also { stage++ }
|
||||
2 -> when(buttonId) {
|
||||
1 -> playerl("What are 'stabbers'?").also { stage = 3 }
|
||||
2 -> playerl("What's a 'chompy'?").also { stage = 7 }
|
||||
3 -> playerl("Ok, I'll make you some 'stabbers'.").also { stage = 10 }
|
||||
4 -> playerl("Er, make your own 'stabbers'!").also { stage = END_DIALOGUE }
|
||||
}
|
||||
3 -> npcl(FacialExpression.OLD_NORMAL, "For da stabbie chucker, I's wanna hunt da chompy! Creature knows what Rantz wants... ...flyin' to stabbie da chompy!").also { stage++ }
|
||||
4 -> npcl(FacialExpression.OLD_NORMAL, "The ogre shows you a huge but crude bow and then starts to nod energetically in an effort to help you understand.").also { stage++ }
|
||||
5 -> playerl("I think I understand. You want me to make some arrows for you?").also { stage++ }
|
||||
6 -> npcl(FacialExpression.OLD_NORMAL, "Yeah, is what Rantz sayed, make da stabbers for da stabby chucker!").also { stage = 1 }
|
||||
7 -> npcl(FacialExpression.OLD_NORMAL, "Da chompy is der bestest yummies for Rantz, Fycie and Bugs! We's looking for da yummies all da time. Da chompy is a big flapper, Rantz want's stabbers to sneaky, sneaky, stick da chompy.").also { stage++ }
|
||||
8 -> playerl("Ah, so 'da chompy' is some kind of bird?").also { stage++ }
|
||||
9 -> npcl(FacialExpression.OLD_NORMAL, "Yeah, is what Rantz sayed, Da chompy is da big flapper and is bestest yummies. But Rantz needs stabbers to stick da chompy... Will creatures make dem stabbers for us?").also {stage = 1 }
|
||||
10 -> npcl(FacialExpression.OLD_NORMAL, "Good you creature, you need sticksies from achey tree and stabbies from dog bones.").also { stage = END_DIALOGUE; quest.start(player) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleImpatienceDialogue(player: Player?, buttonId: Int) {
|
||||
val hasArrows = amountInInventory(player!!, Items.OGRE_ARROW_2866) > 0
|
||||
|
||||
when(stage) {
|
||||
0 -> npcl(FacialExpression.OLD_NORMAL, "Hey you creature... Have you made me da stabbers? I wanna stick da chompy?").also { stage++ }
|
||||
|
||||
1 -> {
|
||||
if (!hasArrows) {
|
||||
playerl("Er not exactly?").also { stage++ }
|
||||
} else {
|
||||
playerl(FacialExpression.ANNOYED, "Well, yes actually, as you asked so nicely. Here you go! Here's your 'stabbers'.")
|
||||
stage = 100
|
||||
}
|
||||
}
|
||||
|
||||
2 -> npcl(FacialExpression.OLD_NORMAL, "You do stabbers quick!...quick!.. Or Rantz make stabbers for Rantz and then practice for chompy sticking on creature!").also { stage++ }
|
||||
3 -> options("How do I make the 'stabbers' again?", "Ok, I'll make the 'stabbers' for you.").also { stage++ }
|
||||
4 -> when(buttonId) {
|
||||
1 -> playerl("How do I make the 'stabbers' again?").also { stage = 5 }
|
||||
2 -> playerl("Ok, I'll make the 'stabbers' for you.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
5 -> npcl(FacialExpression.OLD_NORMAL, "Grrr creature... you's no good stabber maker! You's make da stabbie bit from da dog bones, and get da sticksies from da Achey tree... simple see! Oh and da flufgies from da flappers as well!").also { stage++ }
|
||||
6 -> playerl("Oh, so I need logs from the achey tree, bones from a canine... and feather?").also { stage++ }
|
||||
7 -> npcl(FacialExpression.OLD_NORMAL, "Is just what Rantz sayed!").also { stage++ }
|
||||
8 -> npcl(FacialExpression.OLD_NORMAL, "The hulking ogre nods excitedly.").also { stage = END_DIALOGUE }
|
||||
|
||||
100 -> {
|
||||
sendItemDialogue(player!!, Item(Items.OGRE_ARROW_2866, 20), "Rantz takes six ogre arrows off you.")
|
||||
removeItem(player!!, Item(Items.OGRE_ARROW_2866, 6))
|
||||
stage++
|
||||
}
|
||||
|
||||
101 -> {
|
||||
npcl(FacialExpression.OLD_NORMAL, "Ahh, der creature has dem...goodly, goodly. Now us can stick der chompy bird...")
|
||||
stage = 4 //Skips to "How do we make the chompsys come?" in the dialogue below
|
||||
quest.setStage(player, 20)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleToadsiesDialogue(player: Player?, buttonId: Int) {
|
||||
val hasToads = amountInInventory(player!!, Items.BLOATED_TOAD_2875) > 0
|
||||
|
||||
when(stage) {
|
||||
0 -> npcl(FacialExpression.OLD_NORMAL, "Hey you creature you still here?").also { stage++ }
|
||||
1 -> npcl(FacialExpression.OLD_NORMAL, "Da chompy still not coming! We need da fatsy toady to get da chompy, do you got it? Do you got da fatsy toady? Then we can sneaky, sneaky stick da chompy.").also { stage++ }
|
||||
2 -> {
|
||||
if (hasToads) {
|
||||
playerl("Yes, I have a 'fatsy toady' for you, here look!")
|
||||
stage = 100
|
||||
} else {
|
||||
playerl("No I haven't got the 'fatsy toady' yet!").also { stage++ }
|
||||
}
|
||||
}
|
||||
3 -> npcl(FacialExpression.OLD_NORMAL, "Dat's a pidy... but maybe Rantz can help da creature?").also { stage++ }
|
||||
4 -> options("How do we make the chompys come?", "What are 'fatsy toadies'?", "Where do we put the fatsy toadies?", "What do you mean 'sneaky..sneaky.. stick da chompy?'", "Ok, thanks.").also { stage++ }
|
||||
5 -> when(buttonId) {
|
||||
1 -> playerl("How do we make the chompys come?").also { stage = 6 }
|
||||
2 -> playerl("What are 'fatsy toadies'?").also { stage = 8 }
|
||||
3 -> playerl("Where do we put the fatsy toadies?").also { stage = 9 }
|
||||
4 -> playerl("What do you mean 'sneaky..sneaky.. stick da chompy?'").also { stage = 12 }
|
||||
5 -> playerl("Ok, thanks.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
6 -> npcl(FacialExpression.OLD_NORMAL, "Chompys love da fatsy toadies. Toadies get big on der swamp gas and der chomys are licking der lips for em as me is licking lips for da chompy. Da chompys don't like da smaller toadies from nearby swampy.").also { stage++ }
|
||||
7 -> npcl(FacialExpression.OLD_NORMAL, "Dey's fussie eaters like Rantz. Fycie an Bugs play with toadies and blower dey's all times making fatsy toadies.").also { stage = 4 }
|
||||
8 -> npcl(FacialExpression.OLD_NORMAL, "Fatsy toadies are da chompy burds bestest yumms. But da toadies here are too small for da chompy. You've godda make da toadies big and round!").also { stage = 4 }
|
||||
9 -> npcl(FacialExpression.OLD_NORMAL, "Over der!").also { stage++ }
|
||||
10 -> npcl(FacialExpression.OLD_NORMAL, "The ogre points to a small clearing to da south.").also { stage++ }
|
||||
11 -> npcl(FacialExpression.OLD_NORMAL, "Ok creature? You got dat? Over here by der no tree's place.").also { stage = 4 }
|
||||
12 -> npcl(FacialExpression.OLD_NORMAL, "Duh! You creature is a bit stoopid yes? Us needs to sneaky, sneaky.. and stick da chompy! Den we can eat da chompy!").also { stage = 4 }
|
||||
|
||||
100 -> sendItemDialogue(player!!, Items.BLOATED_TOAD_2875, "You show the bloated toad to Rantz. He nods with approval.").also { stage++ }
|
||||
101 -> npcl(FacialExpression.OLD_NORMAL, "Dat's a good fatsy toady, now we's need to put it for da chompy to come.").also { stage++ }
|
||||
102 -> {
|
||||
playerl("Where do I put the 'fatsy toadies'?").also { stage++ }
|
||||
quest.setStage(player, 30)
|
||||
stage = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handlePlaceToadsiesDialogue(player: Player?, buttonId: Int) {
|
||||
npcl(FacialExpression.OLD_NORMAL, "Over 'dere creature, put da toadies over der! ~ The ogre points to a clearing to the south. ~")
|
||||
clearHintIcon(player!!)
|
||||
registerHintIcon(player!!, ChompyBird.TOAD_LOCATION, 5) //TODO: ADD OFFSETS WHEN WE UNFUCK ARIOS'S MISTAKES, YEET
|
||||
stage = END_DIALOGUE
|
||||
}
|
||||
|
||||
private fun handlePlacedBaitDialogue(player: Player?, buttonId: Int) {
|
||||
when(stage) {
|
||||
0 -> playerl("There you go, I've placed the bait.").also { stage++ }
|
||||
1 -> npcl(FacialExpression.OLD_NORMAL, "Goodz me now waits for da chompy! It shouldn't be long now. Sneaky...sneaky...").also { stage++ }
|
||||
2 -> playerl("Yes, I know...stick da chompy!").also { stage++ }
|
||||
3 -> npcl(FacialExpression.OLD_NORMAL, "Hey.. you's creature, is da fatsy toady still dere? Go get more fatsy toadies if dey all gone!").also { stage++ }
|
||||
4 -> playerl("What? I have to get more bait if there's none there? Does this Chompy Bird even exist I wonder?").also { stage = END_DIALOGUE }
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleRantzSucksDialogue(player: Player?, buttonId: Int) {
|
||||
when(stage) {
|
||||
0 -> playerl("Hey there, you keep missing the chompy bird.").also { stage++ }
|
||||
1 -> npcl(FacialExpression.OLD_NORMAL, "I knows, I keeps missing... because your stabbers are worserer at flying than a dead dog.").also { stage++ }
|
||||
2 -> options("Oh, keep trying then... you might hit one through pure luck.", "Come on, let me have a go...").also { stage++ }
|
||||
3 -> when(buttonId) {
|
||||
1 -> playerl("Oh, keep trying then... you might hit one through pure luck.").also { stage = END_DIALOGUE }
|
||||
2 -> playerl("Come on, let me have a go...").also { stage = 4 }
|
||||
}
|
||||
4 -> npcl(FacialExpression.OLD_NORMAL, "No, is Rantz stabby thrower... you too weedy...").also { stage++ }
|
||||
5 -> options("I'm actually quite strong... please let me try.", "Oh suit yourself, you'll just have to go hungry.").also { stage++ }
|
||||
6 -> when(buttonId) {
|
||||
1 -> playerl("I'm actually quite strong... please let me try.").also { stage = 7 }
|
||||
2 -> playerl("Oh suit yourself, you'll just have to go hungry.").also { stage = END_DIALOGUE }
|
||||
}
|
||||
7 -> npcl(FacialExpression.OLD_NORMAL, "Oh, ok... I lend you other stabby thrower... but creature don't better cry when it hurts itself.").also { stage++ }
|
||||
8 -> {
|
||||
sendItemDialogue(player!!, Items.OGRE_BOW_2883, "Rantz hands over an ogre bow. It's huge! You can barely drawn back the string!")
|
||||
addItemOrDrop(player!!, Items.OGRE_BOW_2883)
|
||||
stage = END_DIALOGUE
|
||||
quest.setStage(player, 60)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleWaitingForChompyDialogue(player: Player?, buttonId: Int) {
|
||||
val hasChompyBird = amountInInventory(player!!, Items.RAW_CHOMPY_2876) > 0
|
||||
|
||||
assignRandomIngredients(player ?: return)
|
||||
val rantzIngredient = getAttribute(player, ChompyBird.ATTR_ING_RANTZ, -1)
|
||||
|
||||
when(stage) {
|
||||
0 -> npcl(FacialExpression.OLD_NORMAL, "Hey You! Got da chompy yet?").also { stage++ }
|
||||
1 -> {
|
||||
if (hasChompyBird) {
|
||||
playerl("Yep, here's your chompy Bird!")
|
||||
stage = 100
|
||||
} else {
|
||||
playerl("Not yet!").also { stage++ }
|
||||
}
|
||||
}
|
||||
2 -> npcl(FacialExpression.OLD_NORMAL, "Well hurry up and get some, we is hungry!").also { stage = END_DIALOGUE }
|
||||
|
||||
100 -> sendItemDialogue(player!!, Items.RAW_CHOMPY_2876, "You show Rantz the freshly plucked chompy carcass.").also { stage++ }
|
||||
101 -> npcl(FacialExpression.OLD_NORMAL, "Dat's a great chompy, you musta got a lucky shot wiv da stabbie chucker.").also { stage++ }
|
||||
102 -> npcl(FacialExpression.OLD_NORMAL, "Okay's now you's needs to cook da chompy! Slurp! You's can cook it's over der! ~Rantz points to a nearby spit roast.~").also { stage++ }
|
||||
103 -> npcl(FacialExpression.OLD_NORMAL, "But's we's particular about our chompy yumms. Me's wants ${getItemName(rantzIngredient)} wiv mine! Fycie and Bugs want something wiv der's as well, go and ask 'em wat dey want.").also { stage++ }
|
||||
104 -> playerl("What! Now I've got the chompy bird, you expect me to cook it as well?").also { stage++ }
|
||||
105 -> npcl(FacialExpression.OLD_NORMAL, "Yep, da spit's over der! Last time Rantz did yummies, got very bad, did bad things to food.. and belly.").also { stage++ }
|
||||
106 -> {
|
||||
playerl("HUH!").also { stage = END_DIALOGUE }
|
||||
quest.setStage(player, 70)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleWaitingForCookedChompy(player: Player?, buttonId: Int) {
|
||||
val hasCookedChompy = amountInInventory(player!!, Items.SEASONED_CHOMPY_2882) > 0
|
||||
|
||||
when (stage) {
|
||||
0 -> npcl(FacialExpression.OLD_NORMAL, "Hey You! Cook da chompy yet?").also { stage++ }
|
||||
1 -> {
|
||||
if (hasCookedChompy) {
|
||||
playerl("Yep, here you go, here's your cooked chompy bird.")
|
||||
stage = 100
|
||||
} else {
|
||||
playerl("Not yet!").also { stage++ }
|
||||
}
|
||||
}
|
||||
2 -> npcl(FacialExpression.OLD_NORMAL, "Well hurry up, we is hungry!").also { stage = END_DIALOGUE }
|
||||
|
||||
100 -> sendItemDialogue(player!!, Items.SEASONED_CHOMPY_2882, "You hand over the cooked chompy bird to Rantz.").also { stage++ }
|
||||
101 -> npcl(FacialExpression.OLD_NORMAL, "Hey hey! We got da delicious chompy bird Yay! This looks really tasty as well!").also { stage++ }
|
||||
102 -> npcl(FacialExpression.OLD_NORMAL, "Tank's very much for da chompy... Fycie an Bugs like very much da chompy yumms!").also { stage++ }
|
||||
103 -> sendDialogue(player, "~The family of ogres sit down together~").also { stage++ }
|
||||
104 -> sendDialogue(player, "~and enjoy your well cooked chompy bird.~").also { stage++ }
|
||||
105 -> playerl("It's my pleasure!").also { stage = END_DIALOGUE; quest.finish(player) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignRandomIngredients(player: Player) {
|
||||
val possibleIngredients = arrayListOf(
|
||||
Items.ONION_1957,
|
||||
Items.DOOGLE_LEAVES_1573,
|
||||
Items.EQUA_LEAVES_2128,
|
||||
Items.TOMATO_1982,
|
||||
Items.POTATO_1942,
|
||||
Items.CABBAGE_1965
|
||||
)
|
||||
|
||||
setAttribute(player, ChompyBird.ATTR_ING_RANTZ, possibleIngredients.random().also { possibleIngredients.remove(it) })
|
||||
setAttribute(player, ChompyBird.ATTR_ING_BUGS, possibleIngredients.random().also { possibleIngredients.remove(it) })
|
||||
setAttribute(player, ChompyBird.ATTR_ING_FYCIE, possibleIngredients.random().also { possibleIngredients.remove(it) })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
package rs09.game.content.quest.members.chompybird
|
||||
|
||||
import api.*
|
||||
|
||||
import org.rs09.consts.NPCs
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.Animations
|
||||
|
||||
import core.plugin.Initializable
|
||||
import core.tools.RandomFunction
|
||||
import core.game.system.task.Pulse
|
||||
|
||||
import core.game.node.Node
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.npc.AbstractNPC
|
||||
import core.game.node.entity.combat.BattleState
|
||||
import core.game.node.entity.combat.CombatStyle
|
||||
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.path.Pathfinder
|
||||
import core.game.interaction.MovementPulse
|
||||
import rs09.game.interaction.InteractionListener
|
||||
import core.game.world.update.flag.context.Animation
|
||||
|
||||
@Initializable
|
||||
class ChompyBirdNPC : AbstractNPC, InteractionListener {
|
||||
constructor() : super(NPCs.CHOMPY_BIRD_1550, null, true)
|
||||
private constructor(id: Int, location: Location) : super(id, location) {}
|
||||
|
||||
var timeToLive = 100
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
val toad = getAttribute<NPC?>("toad", null)
|
||||
animate(Animation(Animations.CHOMPY_SPAWN_6766))
|
||||
|
||||
if (toad != null) {
|
||||
submitIndividualPulse(this, object : MovementPulse(this, toad, Pathfinder.SMART) {
|
||||
var bufferTicks = 7
|
||||
override fun pulse() : Boolean {
|
||||
if (bufferTicks-- == 0) {
|
||||
setAttribute("toad_eaten", true)
|
||||
toad.clear()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override fun construct(id: Int, location: Location, vararg objects: Any?): AbstractNPC {
|
||||
val npc = ChompyBirdNPC(id, location)
|
||||
npc.isRespawn = false
|
||||
return npc
|
||||
}
|
||||
|
||||
override fun getIds() : IntArray {
|
||||
return intArrayOf(NPCs.CHOMPY_BIRD_1550)
|
||||
}
|
||||
|
||||
override fun isAttackable(entity: Entity, style: CombatStyle, message: Boolean) : Boolean {
|
||||
if (entity !is Player) return true
|
||||
|
||||
var attackable = super.isAttackable(entity, style, message)
|
||||
val hasOgreBow = inEquipment(entity, Items.OGRE_BOW_2883)
|
||||
|
||||
if (!hasOgreBow) {
|
||||
sendMessage(entity, "You need an ogre bow to hunt chompy birds.")
|
||||
}
|
||||
|
||||
return attackable && hasOgreBow
|
||||
}
|
||||
|
||||
override fun attack(node: Node) {}
|
||||
|
||||
override fun checkImpact(state: BattleState) {
|
||||
super.checkImpact(state)
|
||||
if (getAttribute("toad_eaten", false) || state.attacker.id == NPCs.RANTZ_1010) {
|
||||
impactHandler.disabledTicks = 10
|
||||
locks.lockInteractions(10)
|
||||
sendChat("Squawk!")
|
||||
submitWorldPulse(object : Pulse(2) {
|
||||
var counter = 0
|
||||
override fun pulse() : Boolean {
|
||||
when (counter++) {
|
||||
1 -> animate(Animation(Animations.CHOMPY_FLY_AWAY_6767))
|
||||
2 -> clear()
|
||||
3 -> return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
} else {
|
||||
sendChat("Screech!")
|
||||
}
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
if (this.inCombat() && this.skills.lifepoints > 0) {
|
||||
val newLoc = this.location.transform(
|
||||
RandomFunction.random(-2,2),
|
||||
RandomFunction.random(-2,2),
|
||||
0
|
||||
)
|
||||
submitIndividualPulse(this, object : MovementPulse(this, newLoc, Pathfinder.DUMB) {
|
||||
override fun pulse() : Boolean { return true }
|
||||
})
|
||||
}
|
||||
super.tick()
|
||||
}
|
||||
|
||||
override fun handleTickActions() {
|
||||
if (id == NPCs.CHOMPY_BIRD_1550) {
|
||||
if (getAttribute("toad_eaten", false)) {
|
||||
super.handleTickActions()
|
||||
}
|
||||
if (timeToLive-- <= 0) {
|
||||
animate(Animation(Animations.CHOMPY_FLY_AWAY_6767))
|
||||
runTask(this, 2) { clear() }
|
||||
timeToLive = 100
|
||||
}
|
||||
} else {
|
||||
if (timeToLive-- <= 0)
|
||||
clear()
|
||||
}
|
||||
}
|
||||
|
||||
override fun finalizeDeath(killer: Entity) {
|
||||
properties.teleportLocation = null
|
||||
val newSelf = transform(NPCs.CHOMPY_BIRD_1016)
|
||||
newSelf.isNeverWalks = true
|
||||
newSelf.isWalks = false
|
||||
newSelf.walkRadius = 0
|
||||
timeToLive = 200
|
||||
|
||||
this.pulseManager.clear()
|
||||
this.walkingQueue.reset()
|
||||
|
||||
if (killer is Player) {
|
||||
sendMessage(killer, "You scratch a notch on your bow for the chompy bird kill.")
|
||||
val old = killer.getAttribute("chompy-kills", 0)
|
||||
killer.setAttribute("/save:chompy-kills", old + 1)
|
||||
ChompyHat.checkForNewRank(killer)
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
on(NPCs.CHOMPY_BIRD_1016, NPC, "pluck") { player, node ->
|
||||
val bird = node.asNpc()
|
||||
|
||||
if (!bird.getAttribute("plucked", false)) {
|
||||
addItem(player, Items.FEATHER_314, RandomFunction.random(25, 32))
|
||||
produceGroundItem(player, Items.BONES_526, 1, bird.location)
|
||||
produceGroundItem(player, Items.RAW_CHOMPY_2876, 1, bird.location)
|
||||
bird.clear()
|
||||
}
|
||||
|
||||
bird.setAttribute("plucked", true)
|
||||
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(Items.OGRE_BOW_2883, ITEM, "check kills") { player, _ ->
|
||||
val amount = player.getAttribute("chompy-kills", 0)
|
||||
sendDialogue(player, "You have killed $amount chompy birds.")
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package rs09.game.content.quest.members.chompybird
|
||||
|
||||
import api.*
|
||||
import rs09.tools.stringtools.colorize
|
||||
|
||||
import org.rs09.consts.Items
|
||||
|
||||
import rs09.game.interaction.InteractionListener
|
||||
import core.game.node.entity.player.Player
|
||||
|
||||
import java.util.*
|
||||
|
||||
enum class ChompyHat(val id: Int, val kills: Int, val rankName: String) {
|
||||
O_BOWMAN(Items.CHOMPY_BIRD_HAT_2978, 30, "an Ogre Bowman"),
|
||||
BOWMAN(Items.CHOMPY_BIRD_HAT_2979, 40, "a Bowman"),
|
||||
O_YEOMAN(Items.CHOMPY_BIRD_HAT_2980, 50, "an Ogre Yeoman"),
|
||||
YEOMAN(Items.CHOMPY_BIRD_HAT_2981, 70, "a Yeoman"),
|
||||
O_MARKSMAN(Items.CHOMPY_BIRD_HAT_2982, 95, "an Ogre Marksman"),
|
||||
MARKSMAN(Items.CHOMPY_BIRD_HAT_2983, 125, "a Marksman"),
|
||||
O_WOODSMAN(Items.CHOMPY_BIRD_HAT_2984, 170, "an Ogre Woodsman"),
|
||||
WOODSMAN(Items.CHOMPY_BIRD_HAT_2985, 225, "a Woodsman"),
|
||||
O_FORESTER(Items.CHOMPY_BIRD_HAT_2986, 300, "an Ogre Forester"),
|
||||
FORESTER(Items.CHOMPY_BIRD_HAT_2987, 400, "a Forester"),
|
||||
O_BOWMASTER(Items.CHOMPY_BIRD_HAT_2988, 550, "an Ogre Bowmaster"),
|
||||
BOWMASTER(Items.CHOMPY_BIRD_HAT_2989, 700, "a Bowmaster"),
|
||||
O_EXPERT(Items.CHOMPY_BIRD_HAT_2990, 1000, "an Ogre Expert"),
|
||||
EXPERT(Items.CHOMPY_BIRD_HAT_2991, 1300, "an Expert"),
|
||||
O_DA(Items.CHOMPY_BIRD_HAT_2992, 1700, "an Ogre Dragon Archer"),
|
||||
DA(Items.CHOMPY_BIRD_HAT_2993, 2250, "a Dragon Archer"),
|
||||
EO_DA(Items.CHOMPY_BIRD_HAT_2994, 3000, "an Expert Ogre Dragon Archer"),
|
||||
E_DA(Items.CHOMPY_BIRD_HAT_2995, 4000, "an Expert Dragon Archer");
|
||||
|
||||
companion object {
|
||||
val killMap = values().map { it.kills to it }.toMap()
|
||||
|
||||
fun checkForNewRank(player: Player) {
|
||||
val kills = getAttribute(player, "chompy-kills", 0)
|
||||
val newRank = killMap[kills] ?: return
|
||||
|
||||
sendDialogueLines(player,
|
||||
colorize("%B*** Congratulations! $kills Chompies! ***"),
|
||||
colorize("%R~ You're ${newRank.rankName} ~")
|
||||
)
|
||||
}
|
||||
|
||||
fun getApplicableHats(player: Player) : List<Int> {
|
||||
val kills = getAttribute(player, "chompy-kills", 0)
|
||||
val hats = ArrayList<Int>()
|
||||
for (hat in values()) {
|
||||
if (hat.kills > kills) break
|
||||
if (inInventory(player, hat.id) || inEquipment(player, hat.id) || inBank(player, hat.id)) continue
|
||||
hats.add(hat.id)
|
||||
}
|
||||
return hats
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ChompyEquipListener : InteractionListener {
|
||||
override fun defineListeners() {
|
||||
ChompyHat.values().forEach { hat ->
|
||||
onEquip(hat.id) {player, node ->
|
||||
val kills = getAttribute(player, "chompy-kills", 0)
|
||||
if (kills < hat.kills) {
|
||||
sendItemDialogue(player, node.id, "You haven't earned this!")
|
||||
removeItem(player, node.asItem())
|
||||
return@onEquip false
|
||||
}
|
||||
return@onEquip true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package rs09.game.content.quest.members.chompybird
|
||||
|
||||
import api.*
|
||||
|
||||
import org.rs09.consts.NPCs
|
||||
|
||||
import core.plugin.Initializable
|
||||
import core.game.node.entity.npc.AbstractNPC
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.world.map.Location
|
||||
|
||||
@Initializable
|
||||
class RantzNPC : AbstractNPC {
|
||||
constructor() : super(NPCs.RANTZ_1010, null, true)
|
||||
private constructor(id: Int, location: Location) : super(id, location)
|
||||
|
||||
override fun construct(id: Int, location: Location, vararg objects: Any?) : AbstractNPC {
|
||||
return RantzNPC(id, location)
|
||||
}
|
||||
|
||||
override fun getIds() : IntArray {
|
||||
return intArrayOf(NPCs.RANTZ_1010)
|
||||
}
|
||||
|
||||
override fun handleTickActions() {
|
||||
super.handleTickActions()
|
||||
val chompy = findLocalNPC(this, NPCs.CHOMPY_BIRD_1550) as? ChompyBirdNPC ?: return
|
||||
|
||||
val owner = getAttribute<Player?>(chompy, "owner", null) ?: return
|
||||
val quest = owner.questRepository.getQuest("Big Chompy Bird Hunting")
|
||||
|
||||
if (quest.getStage(owner) !in 40..50 || chompy.getAttribute("attacked", false)) return
|
||||
|
||||
sendChat("Hey, dere's da chompy, I's gonna shoot it.")
|
||||
sendMessage(owner, "Rantz: Hey, dere's da chompy, I's gonna shoot it.")
|
||||
sendMessage(owner, "Rantz keeps missing the chompy bird.")
|
||||
sendMessage(owner, "Rantz: Grrr...de'ese arrows are rubbish.")
|
||||
|
||||
attack(chompy)
|
||||
chompy.setAttribute("attacked", true)
|
||||
quest.setStage(owner, 50)
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -16,7 +16,7 @@ class GatheringSkillOptionListeners : InteractionListener {
|
||||
val ETCETERIA_REGION = 10300
|
||||
|
||||
override fun defineListeners() {
|
||||
on(SCENERY,"chop-down","chop down","cut down"){ player, node ->
|
||||
on(SCENERY,"chop-down","chop down","cut down","chop"){ player, node ->
|
||||
if(player.location.regionId == ETCETERIA_REGION){
|
||||
player.dialogueInterpreter.open(KjallakOnChopDialogue(), NPC(NPCs.CARPENTER_KJALLAK_3916))
|
||||
return@on true
|
||||
@@ -45,4 +45,4 @@ class GatheringSkillOptionListeners : InteractionListener {
|
||||
player.pulseManager.run(FishingPulse(player, npc, op))
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ class RangedConfigLoader {
|
||||
if (effect != null) {
|
||||
ammo.effect = effect
|
||||
}
|
||||
Ammunition.getAmmunition().putIfAbsent(Integer.parseInt(e["itemId"].toString()),ammo)
|
||||
Ammunition.getAmmunition().put(Integer.parseInt(e["itemId"].toString()),ammo)
|
||||
count++
|
||||
}
|
||||
SystemLogger.logWarn("Parsed $count ammo configs...")
|
||||
@@ -77,4 +77,4 @@ class RangedConfigLoader {
|
||||
}
|
||||
SystemLogger.logInfo("Parsed $count ranged weapon configs...")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user