diff --git a/data/area/misthalin/clan_cup_plaque.ifaces.toml b/data/area/misthalin/clan_cup_plaque.ifaces.toml new file mode 100644 index 0000000000..c1f7f327db --- /dev/null +++ b/data/area/misthalin/clan_cup_plaque.ifaces.toml @@ -0,0 +1,22 @@ +[clan_cup_interface] +id = 205 + +[.combined_winners_button] +id = 49 + +[.skilling_winners_button] +id = 53 + +[.combat_winners_button] +id = 57 + +[.current_winners_button] +id = 61 + +[.sub_text] +id = 64 + +[.main_text] +id = 65 + + diff --git a/data/area/misthalin/lumbridge/freds_farm/ram.anims.toml b/data/area/misthalin/lumbridge/freds_farm/ram.anims.toml index a01ac502bd..02eba0a3e6 100644 --- a/data/area/misthalin/lumbridge/freds_farm/ram.anims.toml +++ b/data/area/misthalin/lumbridge/freds_farm/ram.anims.toml @@ -1,5 +1,6 @@ [ram_death] id = 5336 +ticks = 2 [ram_defend] id = 5337 diff --git a/data/area/misthalin/lumbridge/lumbridge.drops.toml b/data/area/misthalin/lumbridge/lumbridge.drops.toml index 91e3ef39c1..bb5a25335f 100644 --- a/data/area/misthalin/lumbridge/lumbridge.drops.toml +++ b/data/area/misthalin/lumbridge/lumbridge.drops.toml @@ -3,4 +3,31 @@ roll = 128 drops = [ { id = "coins", amount = 9, chance = 123 }, { id = "potato_seed", chance = 5 }, +] + +[lumbridge_guard_drop_table] +type = "all" +drops = [ + { table = "bones" }, + { table = "lumbridge_guard_secondary" }, + { table = "easy_clue_scroll", roll = 128 }, +] + +[lumbridge_guard_secondary] +roll = 128 +drops = [ + { id = "cooked_meat", min = 1, max = 2, chance = 10 }, + { id = "cooked_chicken", min = 1, max = 2, chance = 10 }, + { id = "meat_pie", min = 1, max = 2, chance = 10 }, + { id = "bronze_arrow", amount = 16, chance = 4 }, + { id = "iron_sword" }, + { id = "body_rune", amount = 7, chance = 5 }, + { id = "air_rune", min = 2, max = 7, chance = 3 }, + { id = "mind_rune", min = 13, max = 19, chance = 3 }, + { id = "water_rune", amount = 6, chance = 6 }, + { id = "earth_rune", amount = 4, chance = 3 }, + { id = "staff_of_air" }, + { id = "coins", amount = 50, chance = 10 }, + { id = "copper_ore", chance = 5 }, + { id = "tin_ore", chance = 5 }, ] \ No newline at end of file diff --git a/data/area/misthalin/lumbridge/lumbridge.npc-spawns.toml b/data/area/misthalin/lumbridge/lumbridge.npc-spawns.toml index d0f84f987a..d55aba620c 100644 --- a/data/area/misthalin/lumbridge/lumbridge.npc-spawns.toml +++ b/data/area/misthalin/lumbridge/lumbridge.npc-spawns.toml @@ -1,5 +1,15 @@ spawns = [ -# 12594 + # 12594 + { id = "giant_rat", x = 3192, y = 3203 }, + { id = "giant_rat", x = 3192, y = 3211 }, + { id = "giant_rat", x = 3197, y = 3202 }, + { id = "giant_rat", x = 3193, y = 3203 }, + { id = "giant_rat", x = 3194, y = 3201 }, + { id = "giant_rat", x = 3194, y = 3211 }, + { id = "giant_rat", x = 3192, y = 3208 }, + { id = "giant_rat", x = 3195, y = 3205 }, + { id = "lumbridge_guardsman_attackable", x = 3187, y = 3245 }, + { id = "lumbridge_guardsman_attackable2", x = 3192, y = 3207 }, { id = "butterfly_1", x = 3183, y = 3254 }, { id = "butterfly_1", x = 3182, y = 3251 }, { id = "butterfly_1", x = 3178, y = 3228 }, @@ -49,11 +59,11 @@ spawns = [ { id = "butterfly_3", x = 3233, y= 3216}, { id = "roddeck", x = 3232, y = 3237, direction = "WEST" }, { id = "sigmund_lumbridge", x = 3209, y = 3219, level = 1 }, - { id = "guardsman_deshawn", x = 3206, y = 3214, level = 1 }, - { id = "guardsman_dante", x = 3211, y = 3227, level = 1 }, - { id = "guardsman_brawn", x = 3215, y = 3219, level = 1}, - { id = "guardsman_pazel", x = 3213, y = 3210, level = 1 }, - { id = "guardsman_peale", x = 3208, y = 3227}, + { id = "lumbridge_guardsman_deshawn", x = 3206, y = 3214, level = 1 }, + { id = "lumbridge_guardsman_dante", x = 3211, y = 3227, level = 1 }, + { id = "lumbridge_guardsman_brawn", x = 3215, y = 3219, level = 1}, + { id = "lumbridge_guardsman_pazel", x = 3213, y = 3210, level = 1 }, + { id = "lumbridge_guardsman_peale", x = 3208, y = 3227}, { id = "donie", x = 3219, y = 3247 }, { id = "imp", x = 3223, y = 3223 }, { id = "lumbridge_sage", x = 3238, y = 3219, direction = "WEST" }, @@ -190,6 +200,7 @@ spawns = [ { id = "explorer_jack", x = 3204, y = 3241 }, { id = "doomsayer", x = 3237, y = 3227, direction = "EAST" }, # 12851 + { id = "lumbridge_guardsman_attackable", x = 3253, y = 3238 }, { id = "duck_swim", x = 3235, y = 3265 }, { id = "duck_swim", x = 3233, y = 3267 }, { id = "duck_swim", x = 3233, y = 3270 }, @@ -244,11 +255,10 @@ spawns = [ { id = "farmer_lumbridge", x = 3233, y = 3308 }, { id = "farmer_lumbridge_3", x = 3262, y = 3325 }, { id = "farmer_lumbridge_2", x = 3250, y = 3310 }, - { id = "master_farmer", x = 3203, y = 3254, members = true }, { id = "crow_4", x = 3208, y = 3301, members = true }, { id = "vasquen", x = 3226, y = 3311 }, - { id = "fayeth", x = 3228, y = 3245 }, - { id = "tools_leprechaun", x = 3231, y = 3248 }, + { id = "fayeth", x = 3193, y = 3233 }, + { id = "tools_leprechaun", x = 3196, y = 3228 }, { id = "dwarf_lumbridge", x = 3224, y = 3286, members = true }, { id = "ham_member_lumbridge", x = 3230, y = 3285, members = true }, { id = "seth_groats_lumbridge", x = 3223, y = 3293, members = true }, diff --git a/data/area/misthalin/lumbridge/lumbridge.npcs.toml b/data/area/misthalin/lumbridge/lumbridge.npcs.toml index 47056f2487..3b7a3f1aaf 100644 --- a/data/area/misthalin/lumbridge/lumbridge.npcs.toml +++ b/data/area/misthalin/lumbridge/lumbridge.npcs.toml @@ -123,27 +123,27 @@ wander_radius = 4 collision = "indoors" examine = "Lumbridge Castle's head cook." -[guardsman_dante] +[lumbridge_guardsman_dante] id = 7885 categories = ["human"] wander_radius = 4 collision = "indoors" examine = "He tries to keep order around Lumbridge." -[guardsman_deshawn] -clone = "guardsman_dante" +[lumbridge_guardsman_deshawn] +clone = "lumbridge_guardsman_dante" id = 7886 -[guardsman_brawn] -clone = "guardsman_dante" +[lumbridge_guardsman_brawn] +clone = "lumbridge_guardsman_dante" id = 7887 -[guardsman_pazel] -clone = "guardsman_dante" +[lumbridge_guardsman_pazel] +clone = "lumbridge_guardsman_dante" id = 7889 -[guardsman_peale] -clone = "guardsman_dante" +[lumbridge_guardsman_peale] +clone = "lumbridge_guardsman_dante" id = 7890 [lumbridge_man] @@ -310,3 +310,36 @@ examine = "An old adventurer." [chief_thief_robin_lumbridge_2] id = 7955 + +[lumbridge_guardsman_attackable] +id = 12367 +hitpoints = 100 +attack = 4 +defence = 4 +max_hit_melee = 16 +attack_speed = 5 +combat_anims = "human" +style = "slash" +weapon_style = "sword" +categories = ["human"] +combat_anims = "human" +hunt_mode = "aggressive_npcs" +respawn_delay = 35 +drop_table = "lumbridge_guard" +examine = " He tries to keep order around Lumbridge by killing goblins." + +[lumbridge_guardsman_attackable2] +id = 12368 +hitpoints = 100 +attack = 4 +defence = 4 +max_hit_melee = 16 +attack_speed = 5 +style = "stab" +weapon_style = "sword" +categories = ["human"] +combat_anims = "human" +hunt_mode = "aggressive_npcs" +respawn_delay = 35 +drop_table = "lumbridge_guard" +examine = "He tries to keep order around Lumbridge by killing rats." \ No newline at end of file diff --git a/data/entity/npc/animal/rat/rat.anims.toml b/data/entity/npc/animal/rat/rat.anims.toml index 81b7e5dd59..3119ce94be 100644 --- a/data/entity/npc/animal/rat/rat.anims.toml +++ b/data/entity/npc/animal/rat/rat.anims.toml @@ -6,12 +6,14 @@ id = 2706 [rat_death] id = 2707 +ticks = 2 [giant_rat_attack] id = 14859 [giant_rat_death] id = 14860 +ticks = 4 [giant_rat_defend] id = 14861 diff --git a/data/quest/mini/sheep_shearer/sheep_shearer.items.toml b/data/quest/mini/sheep_shearer/sheep_shearer.items.toml index d3be8594b6..54290f9f1f 100644 --- a/data/quest/mini/sheep_shearer/sheep_shearer.items.toml +++ b/data/quest/mini/sheep_shearer/sheep_shearer.items.toml @@ -23,6 +23,7 @@ id = 1738 id = 15415 limit = 5000 weight = 0.003 +tradeable = false destroy = "You'll have to shear some from another black sheep." spinning = { to = "ball_of_black_wool", level = 1, xp = 2.5 } examine = "This probably came from a black sheep. You can spin it into a ball of black wool at a spinning wheel." @@ -31,5 +32,6 @@ examine = "This probably came from a black sheep. You can spin it into a ball of id = 15416 limit = 5000 weight = 0.012 +tradeable = false destroy = "You'll have to make one from more black wool." examine = "Spun from black wool. You can weave it into black cloth at a loom." diff --git a/game/src/main/kotlin/content/area/misthalin/ClanCupPlaque.kt b/game/src/main/kotlin/content/area/misthalin/ClanCupPlaque.kt new file mode 100644 index 0000000000..b855b6bd28 --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/ClanCupPlaque.kt @@ -0,0 +1,36 @@ +package content.area.misthalin + +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.client.ui.open + +class ClanCupPlaque : Script { + init { + // https://www.youtube.com/watch?v=K-Ptq7ZxeWI + objectOperate("Read", "lumbridge_clan_cup_plaque") { + open("clan_cup_interface") + interfaces.sendText("clan_cup_interface", "current_winners_button", "Current") + interfaces.sendText("clan_cup_interface", "main_text", "Current Winners") + interfaces.sendText("clan_cup_interface", "sub_text", "The victorious winners of the 2010 Jagex Clan Cup

Combat - Runescape Dinasty
Skilling - Divination
Combined - BasedIn2Minutes") + } + interfaceOption("Current-winners", "clan_cup_interface:current_winners_button") { + interfaces.sendText("clan_cup_interface", "current_winners", "Current") + interfaces.sendText("clan_cup_interface", "main_text", "Current Winners") + interfaces.sendText("clan_cup_interface", "sub_text", "The victorious winners of the 2010 Jagex Clan Cup

Combat - Runescape Dinasty
Skilling - Divination
Combined - Basedin2minutes") + } + interfaceOption("Combat-winners", "clan_cup_interface:combat_winners_button") { + interfaces.sendText("clan_cup_interface", "combat_winners", "Combat") + interfaces.sendText("clan_cup_interface", "main_text", "Combat winners") + interfaces.sendText("clan_cup_interface", "sub_text", "2010 - Runescape Dinasty
2009 - The Titans") + } + interfaceOption("Skilling-winners", "clan_cup_interface:skilling_winners_button") { + interfaces.sendText("clan_cup_interface", "skilling_winners", "Skilling") + interfaces.sendText("clan_cup_interface", "main_text", "Skilling Winners") + interfaces.sendText("clan_cup_interface", "sub_text", "2010 - Divination
2009 - Divination") + } + interfaceOption("Combined-winners", "clan_cup_interface:combined_winners_button") { + interfaces.sendText("clan_cup_interface", "combined_winners", "Combined") + interfaces.sendText("clan_cup_interface", "main_text", "Combined Winners") + interfaces.sendText("clan_cup_interface", "sub_text", "2010 - BasedIn2Minutes
2009 - Wicked Fury") + } + } +} diff --git a/game/src/main/kotlin/content/area/misthalin/lumbridge/CowFieldSignpost.kt b/game/src/main/kotlin/content/area/misthalin/lumbridge/CowFieldSignpost.kt new file mode 100644 index 0000000000..31cab267cc --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/lumbridge/CowFieldSignpost.kt @@ -0,0 +1,22 @@ +package content.area.misthalin.lumbridge + +import content.entity.player.dialogue.type.statement +import world.gregs.voidps.engine.Script + +class CowFieldSignpost : Script { + + var cowDeathsToday: Int = 0 + + init { + npcDeath("cow*") { + cowDeathsToday += 1 + } + objectOperate("Read", "lumbridge_signpost_cow") { + if (cowDeathsToday > 0) { + statement("Local cowherders have reported that $cowDeathsToday cows have been slain in this field today by passing adventurers. Farmers throughout the land fear this may be an epidemic.") + } else { + statement("The Lumbridge cow population has been thriving today, without a single cow death to worry about!") + } + } + } +} diff --git a/game/src/main/kotlin/content/area/misthalin/lumbridge/PlayerDeathSignpost.kt b/game/src/main/kotlin/content/area/misthalin/lumbridge/PlayerDeathSignpost.kt new file mode 100644 index 0000000000..41af32e998 --- /dev/null +++ b/game/src/main/kotlin/content/area/misthalin/lumbridge/PlayerDeathSignpost.kt @@ -0,0 +1,22 @@ +package content.area.misthalin.lumbridge + +import content.entity.player.dialogue.type.statement +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.data.Settings + +class PlayerDeathSignpost : Script { + var playerDeathsToday: Int = 0 + + init { + playerDeath { + playerDeathsToday += 1 + } + objectOperate("Read", "lumbridge_signpost_death") { + if (playerDeathsToday > 0) { + statement("So far today, $playerDeathsToday unlucky adventurers have died on ${Settings["server.name"]} and been sent to their respawn location. Be careful out there.") + } else { + statement("So far today, not a single adventurer on ${Settings["server.name"]} has met their end grisly or otherwise. Either the streets are getting safer or adventurers are getting warier.") + } + } + } +} diff --git a/game/src/main/kotlin/content/area/misthalin/lumbridge/castle/LumbridgeGuardsman.kt b/game/src/main/kotlin/content/area/misthalin/lumbridge/castle/LumbridgeGuardsman.kt index dd236fc5d1..2d68d05084 100644 --- a/game/src/main/kotlin/content/area/misthalin/lumbridge/castle/LumbridgeGuardsman.kt +++ b/game/src/main/kotlin/content/area/misthalin/lumbridge/castle/LumbridgeGuardsman.kt @@ -1,16 +1,23 @@ package content.area.misthalin.lumbridge.castle +import content.entity.combat.inCombat import content.entity.player.dialogue.Happy import content.entity.player.dialogue.Neutral import content.entity.player.dialogue.Quiz import content.entity.player.dialogue.type.* import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.client.message import world.gregs.voidps.type.random class LumbridgeGuardsman : Script { init { - npcOperate("Talk-to", "guardsman_*") { + npcOperate("Talk-to", "lumbridge_guardsman_*") { + // From wiki: When you attack them and try to talk to them *Using the Right Click* a message will say "The guard somehow doesn't feel like talking to you." + if (inCombat) { + message("The guard somehow doesn't feel like talking to you.") + return@npcOperate + } when (random.nextInt(0, 5)) { 0 -> player("Howdy.") 1 -> player("Salutations!") diff --git a/game/src/main/kotlin/content/entity/npc/combat/melee/LumbridgeGuardsmanAttackble.kt b/game/src/main/kotlin/content/entity/npc/combat/melee/LumbridgeGuardsmanAttackble.kt new file mode 100644 index 0000000000..0b5c37659d --- /dev/null +++ b/game/src/main/kotlin/content/entity/npc/combat/melee/LumbridgeGuardsmanAttackble.kt @@ -0,0 +1,44 @@ +package content.entity.npc.combat.melee + +import content.entity.combat.killer +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.client.instruction.handle.interactNpc +import world.gregs.voidps.engine.entity.character.npc.NPC +import world.gregs.voidps.engine.entity.character.player.skill.Skill +import world.gregs.voidps.engine.queue.strongQueue + +class LumbridgeGuardsmanAttackble : Script { + init { + huntNPC("aggressive_npcs") { target -> + if (id == "lumbridge_guardsman_attackable2" && target.id.endsWith("rat")) { + interactNpc(target, "Attack") + } + if (id == "lumbridge_guardsman_attackable" && target.id.contains("goblin")) { + interactNpc(target, "Attack") + } + } + npcDeath("goblin*,giant_rat") { + val guard = killer as? NPC ?: return@npcDeath + when { + // Guard attacked rats and giant rats, but only healed when giant rat was killed https://youtu.be/qC_XoAQK6Cs?si=VH9tOmKXu-_Bgjnr&t=137 + id == ("giant_rat") && guard.id == "lumbridge_guardsman_attackable2" -> { + guard.strongQueue("rat_killer") { + guard.delay(2) + guard.anim("eat_drink") + // From wiki: Every time they kill a monster, they eat a piece of food which heals them to full health, and walk over to the square of their death as to collect a drop. + guard.levels.set(Skill.Constitution, guard.levels.getMax(Skill.Constitution)) + guard.walkTo(tile) + } + } + id.contains("goblin") && guard.id == "lumbridge_guardsman_attackable" -> { + guard.strongQueue("goblin_killer") { + guard.delay(2) + guard.anim("eat_drink") + guard.levels.set(Skill.Constitution, guard.levels.getMax(Skill.Constitution)) + guard.walkTo(tile) + } + } + } + } + } +}