diff --git a/data/area/kandarin/ancient_cavern/ancient_cavern.anims.toml b/data/area/kandarin/ancient_cavern/ancient_cavern.anims.toml new file mode 100644 index 0000000000..843adcfd1b --- /dev/null +++ b/data/area/kandarin/ancient_cavern/ancient_cavern.anims.toml @@ -0,0 +1,20 @@ +[jump_whirlpool] +id = 6723 + +[pass_through_barrier] +id = 10584 + +[brutal_dragon_shoot] +id = 4972 + +[barbarian_unarmed_defend] +id = 3238 + +[barbarian_spirit_attack] +id = 6726 + +[barbarian_spirit_defend] +id = 6728 + +[barbarian_spirit_death] +id = 6727 \ No newline at end of file diff --git a/data/area/kandarin/ancient_cavern/ancient_cavern.areas.toml b/data/area/kandarin/ancient_cavern/ancient_cavern.areas.toml index f162fb3674..b84a9fa55b 100644 --- a/data/area/kandarin/ancient_cavern/ancient_cavern.areas.toml +++ b/data/area/kandarin/ancient_cavern/ancient_cavern.areas.toml @@ -1,3 +1,8 @@ [kuradals_dungeon] x = [1600, 1663] y = [5248, 5311] + +[kuradals_teleport] +x = [1736, 1739] +y = [5311, 5313] +level = 1 diff --git a/data/area/kandarin/ancient_cavern/ancient_cavern.combat.toml b/data/area/kandarin/ancient_cavern/ancient_cavern.combat.toml new file mode 100644 index 0000000000..1f82904323 --- /dev/null +++ b/data/area/kandarin/ancient_cavern/ancient_cavern.combat.toml @@ -0,0 +1,133 @@ +[brutal_green_dragon] +attack_speed = 4 +retreat_range = 8 +defend_anim = "colour_dragon_defend" +defend_sound = "dragon_defend" +death_anim = "colour_dragon_death" +death_sound = "dragon_death" + +[brutal_green_dragon.melee] +chance = 75 +range = 1 +anim = "colour_dragon_attack" +target_hit = { offense = "stab", max = 180 } +target_sound = "dragon_attack" + +[brutal_green_dragon.dragonfire] +chance = 25 +range = 8 +anim = "colour_dragon_breath" +gfx = "dragon_breath_shoot" +target_hit = { offense = "dragonfire", special = true, max = 500 } +target_sound = "dragon_breath" + +[brutal_green_dragon.magic] +chance = 75 +range = 8 +anim = "brutal_dragon_shoot" +projectile = "water_wave" +projectile_origin_x = 2 +projectile_origin_y = 2 +target_hit = { offense = "magic", max = 180 } +target_sound = "dragon_attack" + +[skeleton_barbarian_axe] +attack_speed = 4 +retreat_range = 8 +defend_anim = "barbarian_unarmed_defend" +defend_sound = "barbarian_grunt_defend" +death_anim = "confused_barbarian_death" +death_sound = "confused_barbarian_death" + +[skeleton_barbarian_axe.melee] +range = 1 +anim = "dharoks_greataxe_smash" +target_sound = "dharok_axe_crush" +target_hit = { offense = "crush", max = 150 } + +[lost_barbarian] +attack_speed = 4 +retreat_range = 8 +defend_anim = "unarmed_defend" +defend_sound = "barbarian_grunt_defend" +death_anim = "human_death" +death_sound = "barbarian_grunt_death" + +[lost_barbarian.melee] +range = 1 +anim = "unarmed_punch" +target_sound = "barbarian_grunt_attack" +target_hit = { offense = "crush", max = 150 } + +[skeleton_barbarian] +attack_speed = 4 +retreat_range = 8 +defend_anim = "unarmed_defend" +defend_sound = "skeleton_defend" +death_anim = "human_death" +death_sound = "skeleton_death" + +[skeleton_barbarian.melee] +range = 1 +anim = "unarmed_punch" +target_sound = "skeleton_attack_unarmed" +target_hit = { offense = "crush", max = 150 } + +[barbarian_spirit] +attack_speed = 4 +retreat_range = 8 +defend_anim = "barbarian_spirit_defend" +defend_sound = "ghoul_defend" +death_anim = "barbarian_spirit_death" +death_sound = "ghoul_defend" + +[barbarian_spirit.melee] +range = 1 +anim = "barbarian_spirit_attack" +target_sound = "ghoul_attack" +target_hit = { offense = "crush", max = 180 } + +[mithril_dragon] +attack_speed = 4 +retreat_range = 8 +defend_anim = "metal_dragon_defend" +defend_sound = "dragon_defend" +death_anim = "metal_dragon_death" +death_sound = "dragon_death" + +[mithril_dragon.melee] +chance = 60 +range = 1 +anim = "metal_dragon_attack" +target_hit = { offense = "stab", max = 280 } +target_sound = "dragon_attack" + +[mithril_dragon.dragonfire] +chance = 20 +range = 8 +condition = "ranged_only" +anim = "metal_dragon_breath" +gfx = "dragon_breath_shoot" +target_hit = { offense = "dragonfire", special = true, max = 500 } +target_sound = "dragon_breath" + +[mithril_dragon.magic] +chance = 40 +range = 8 +anim = "metal_dragon_shoot" +projectile = "water_wave" +projectile_origin_x = 2 +projectile_origin_y = 2 +target_hit = { offense = "magic", max = 180 } +target_sound = "dragon_attack" + +[mithril_dragon.range] +chance = 40 +range = 8 +condition = "ranged_only" +anim = "metal_dragon_shoot" +projectile = "ice_arrow" +projectile_origin_x = 2 +projectile_origin_y = 2 +target_hit = { offense = "range", defence = "magic", max = 180 } +target_sound = "dragon_attack" diff --git a/data/area/kandarin/ancient_cavern/ancient_cavern.drops.toml b/data/area/kandarin/ancient_cavern/ancient_cavern.drops.toml index c7b8febc99..bfecf3f253 100644 --- a/data/area/kandarin/ancient_cavern/ancient_cavern.drops.toml +++ b/data/area/kandarin/ancient_cavern/ancient_cavern.drops.toml @@ -43,6 +43,7 @@ drops = [ { id = "strength_mix_2", chance = 5 }, { id = "mithril_grapple", amount = 2, chance = 3 }, { id = "sapphire_ring", chance = 2 }, + { table = "ancient_cavern_pages", chance = 5 }, { table = "gem_drop_table", chance = 2 }, ] @@ -53,6 +54,7 @@ drops = [ { id = "green_dragonhide", amount = 2 }, { table = "brutal_green_dragon_secondary" }, { table = "hard_clue_scroll", roll = 128 }, + { table = "brutal_green_dragon_charms" }, ] [brutal_green_dragon_secondary] @@ -84,8 +86,119 @@ drops = [ { table = "rare_drop_table", chance = 2 }, ] +[brutal_green_dragon_charms] +roll = 1000 +drops = [ + { id = "gold_charm", chance = 143 }, + { id = "green_charm", chance = 356 }, + { id = "crimson_charm", chance = 143 }, + { id = "blue_charm", chance = 28 }, +] + [mangled_bones_drop_table] type = "all" drops = [ { id = "mangled_bones" }, ] + + +[mithril_dragon_drop_table] +type = "all" +drops = [ + { id = "dragon_bones" }, + { id = "mithril_bar", amount = 3 }, + { table = "mithril_dragon_secondary" }, + { table = "mithril_dragon_tertiary" }, + { table = "mithril_dragon_charms" }, +] + +[mithril_dragon_secondary] +roll = 32768 +drops = [ + { id = "rune_battleaxe", chance = 2048 }, + { id = "rune_mace", chance = 2048 }, + { id = "rune_2h_sword", chance = 64 }, + { id = "rune_dart_p", amount = 14, chance = 2048 }, + { id = "rune_javelin", amount = 8, chance = 2048 }, + { id = "adamant_dart_p", amount = 20, chance = 128 }, + { id = "runite_bolts", min = 10, max = 27, chance = 512 }, + { id = "rune_knife", min = 8, max = 18, chance = 512 }, + { id = "rune_arrow", min = 8, max = 42, chance = 512 }, + { id = "rune_full_helm", chance = 512 }, + { id = "dragon_full_helm" }, + { id = "law_rune", min = 4, max = 45, chance = 128 }, + { id = "death_rune", amount = 45, chance = 128 }, + { id = "blood_rune", amount = 27, chance = 2048 }, + { id = "soul_rune", amount = 10, chance = 512 }, + { id = "super_attack_mix_2", chance = 512 }, + { id = "super_strength_mix_2", chance = 512 }, + { id = "super_defence_mix_2", chance = 512 }, + { id = "prayer_mix_2", chance = 512 }, + { id = "coins", min = 283, max = 3000, chance = 2048 }, + { id = "rune_bar", amount = 2, chance = 128 }, + { id = "shark", min = 1, max = 6, chance = 512 }, + { table = "ancient_cavern_pages", chance = 512 }, + { id = "chewed_bones", chance = 512 }, + { table = "rare_drop_table", chance = 256 }, +] + +[mithril_dragon_tertiary] +roll = 10000 +drops = [ + { id = "mithril_dragon_tail_bone", chance = 2500, variable = "fur_n_seek_wish_list", equals = "started", default = "unstarted" }, + { id = "starved_ancient_effigy", chance = 40 }, + { table = "hard_clue_scroll", chance = 40 }, + { table = "elite_clue_scroll", chance = 10 }, + { id = "draconic_visage" }, +] + +[mithril_dragon_charms] +roll = 1000 +drops = [ + { id = "gold_charm", chance = 198 }, + { id = "green_charm", chance = 495 }, + { id = "crimson_charm", chance = 198 }, + { id = "blue_charm", chance = 40 }, +] + + +[ancient_cavern_pages] +roll = 26 +drops = [ + { id = "ancient_page_1" }, + { id = "ancient_page_2" }, + { id = "ancient_page_3" }, + { id = "ancient_page_4" }, + { id = "ancient_page_5" }, + { id = "ancient_page_6" }, + { id = "ancient_page_7" }, + { id = "ancient_page_8" }, + { id = "ancient_page_9" }, + { id = "ancient_page_10" }, + { id = "ancient_page_11" }, + { id = "ancient_page_12" }, + { id = "ancient_page_13" }, + { id = "ancient_page_14" }, + { id = "ancient_page_15" }, + { id = "ancient_page_16" }, + { id = "ancient_page_17" }, + { id = "ancient_page_18" }, + { id = "ancient_page_19" }, + { id = "ancient_page_20" }, + { id = "ancient_page_21" }, + { id = "ancient_page_22" }, + { id = "ancient_page_23" }, + { id = "ancient_page_24" }, + { id = "ancient_page_25" }, + { id = "ancient_page_26" }, +] + +[ancient_cavern_skeleton] +roll = 512 +drops = [ + { id = "skeleton_guard", chance = 22 }, # skeleton_heavy + { id = "guard_dog", chance = 70 }, # skeleton_hero + { id = "bones", chance = 80 }, + { table = "ancient_cavern_pages", chance = 120 }, + { id = "mangled_bones", chance = 180 }, +] \ No newline at end of file diff --git a/data/area/kandarin/ancient_cavern/ancient_cavern.items.toml b/data/area/kandarin/ancient_cavern/ancient_cavern.items.toml index c8b90041ab..d58e1811c8 100644 --- a/data/area/kandarin/ancient_cavern/ancient_cavern.items.toml +++ b/data/area/kandarin/ancient_cavern/ancient_cavern.items.toml @@ -258,27 +258,42 @@ kept = "Vanish" [ferocious_ring_5] id = 15398 slot = "Ring" -examine = "It looks in pretty good condition." +charges = 1 +degrade = "ferocious_ring_4" +degrade_message = "Your ferocious ring has four uses left." weight = 0.004 +examine = "It looks in pretty good condition." [ferocious_ring_4] clone = "ferocious_ring_5" id = 15399 +charges = 1 +degrade = "ferocious_ring_3" +degrade_message = "Your ferocious ring has three uses left." [ferocious_ring_3] id = 15400 slot = "Ring" -examine = "It looks quite worn." +charges = 1 +degrade = "ferocious_ring_2" +degrade_message = "Your ferocious ring has two uses left." weight = 0.004 +examine = "It looks quite worn." [ferocious_ring_2] id = 15401 slot = "Ring" -examine = "It looks pretty worn." +charges = 1 +degrade = "ferocious_ring_1" +degrade_message = "Your ferocious ring has one use left." weight = 0.004 +examine = "It looks pretty worn." [ferocious_ring_1] id = 15402 slot = "Ring" -examine = "It looks like it's going to break soon." +charges = 1 +degrade = "destroy" +degrade_message = "Your ferocious ring crumbles to dust." weight = 0.004 +examine = "It looks like it's going to break soon." diff --git a/data/area/kandarin/ancient_cavern/ancient_cavern.npc-spawns.toml b/data/area/kandarin/ancient_cavern/ancient_cavern.npc-spawns.toml index bab60afdb0..422f74376d 100644 --- a/data/area/kandarin/ancient_cavern/ancient_cavern.npc-spawns.toml +++ b/data/area/kandarin/ancient_cavern/ancient_cavern.npc-spawns.toml @@ -31,14 +31,14 @@ spawns = [ { id = "mithril_dragon", x = 1783, y = 5328, level = 1, members = true }, { id = "confused_barbarian", x = 1767, y = 5345 }, { id = "lost_barbarian", x = 1761, y = 5322 }, - { id = "skeleton_brute_ancient_cavern", x = 1748, y = 5323 }, - { id = "skeleton_warlord_ancient_cavern", x = 1763, y = 5355 }, - { id = "skeleton_warlord_ancient_cavern", x = 1789, y = 5333, level = 1 }, - { id = "skeleton_thug_ancient_cavern", x = 1787, y = 5340 }, + { id = "skeleton_brute", x = 1748, y = 5323 }, + { id = "skeleton_warlord", x = 1763, y = 5355 }, + { id = "skeleton_warlord", x = 1789, y = 5333, level = 1 }, + { id = "skeleton_thug", x = 1787, y = 5340 }, { id = "angry_barbarian", x = 1746, y = 5326 }, { id = "enraged_barbarian_spirit", x = 1751, y = 5331 }, { id = "enraged_barbarian_spirit", x = 1775, y = 5324 }, { id = "berserk_barbarian_spirit", x = 1779, y = 5325 }, { id = "kuradal", x = 1738, y = 5312, level = 1, members = true }, - { id = "gargoyle_ancient_cavern", x = 1733, y = 5312, level = 1, members = true }, +# { id = "gargoyle_ancient_cavern", x = 1733, y = 5312, level = 1, members = true }, ] diff --git a/data/area/kandarin/ancient_cavern/ancient_cavern.npcs.toml b/data/area/kandarin/ancient_cavern/ancient_cavern.npcs.toml index a9b3cdd827..c81dccb13d 100644 --- a/data/area/kandarin/ancient_cavern/ancient_cavern.npcs.toml +++ b/data/area/kandarin/ancient_cavern/ancient_cavern.npcs.toml @@ -5,12 +5,7 @@ att = 268 str = 168 def = 168 mage = 168 -style = "stab" -style = "magic" -style = "dragonfire" -max_hit_melee = 180 -max_hit_magic = 180 -max_hit_dragonfire = 500 +combat_def = "brutal_green_dragon" xp_bonus = 0.5 hunt_mode = "cowardly" slayer_xp = 183.0 @@ -26,8 +21,7 @@ hitpoints = 1240 att = 115 str = 114 def = 110 -style = "crush" -max_hit_melee = 150 +combat_def = "skeleton_barbarian_axe" attack_bonus = 9 respawn_delay = 50 drop_table = "mangled_bones" @@ -39,35 +33,35 @@ hitpoints = 1240 att = 115 str = 114 def = 110 +combat_def = "lost_barbarian" style = "crush" max_hit_melee = 120 respawn_delay = 50 drop_table = "mangled_bones" examine = "His face is expressionless." -[skeleton_brute_ancient_cavern] +[skeleton_brute] id = 6104 hitpoints = 1240 att = 115 str = 114 def = 110 -style = "crush" -max_hit_melee = 150 +combat_def = "skeleton_barbarian" attack_bonus = 9 hunt_mode = "cowardly" slayer_xp = 124.0 categories = ["skeletons"] respawn_delay = 50 +drop_table = "barbarian_spirit" examine = "An ex-barbarian, willing to make you ex too." -[skeleton_warlord_ancient_cavern] +[skeleton_warlord] id = 6105 hitpoints = 1240 att = 115 str = 114 def = 110 -style = "crush" -max_hit_melee = 150 +combat_def = "skeleton_barbarian_axe" attack_bonus = 9 hunt_mode = "cowardly" slayer_xp = 124.0 @@ -76,14 +70,13 @@ respawn_delay = 50 drop_table = "barbarian_spirit" examine = "He's heartless." -[skeleton_thug_ancient_cavern] +[skeleton_thug] id = 6107 hitpoints = 1240 att = 115 str = 114 def = 110 -style = "crush" -max_hit_melee = 150 +combat_def = "skeleton_barbarian" attack_bonus = 9 hunt_mode = "cowardly" slayer_xp = 124.0 @@ -92,14 +85,28 @@ respawn_delay = 50 drop_table = "barbarian_spirit" examine = "Floats like an anvil, hits like a hammer." +[skeleton_hero] +id = 6103 +hitpoints = 1240 +att = 145 +str = 134 +def = 110 +combat_def = "skeleton_barbarian_axe" +max_hit_crush = 180 +attack_bonus = 9 +hunt_mode = "cowardly" +slayer_xp = 124.0 +categories = ["skeletons"] +drop_table = "barbarian_spirit" +examine = "An opponent from the grave. He seems unimpressed by your bone rummaging." + [angry_barbarian] id = 749 hitpoints = 1900 att = 150 str = 140 def = 100 -style = "crush" -max_hit_melee = 180 +combat_def = "barbarian_spirit" attack_bonus = 9 hunt_mode = "cowardly" respawn_delay = 50 @@ -112,8 +119,7 @@ hitpoints = 1900 att = 150 str = 140 def = 100 -style = "crush" -max_hit_melee = 180 +combat_def = "barbarian_spirit" attack_bonus = 9 hunt_mode = "cowardly" respawn_delay = 50 @@ -126,8 +132,7 @@ hitpoints = 1900 att = 150 str = 140 def = 100 -style = "crush" -max_hit_melee = 180 +combat_def = "barbarian_spirit" attack_bonus = 9 hunt_mode = "cowardly" respawn_delay = 50 @@ -137,3 +142,20 @@ examine = "He looks a tad upset." [gargoyle_ancient_cavern] id = 9087 +[mithril_dragon] +id = 5363 +hitpoints = 2540 +att = 268 +str = 268 +def = 268 +mage = 168 +range = 168 +height = 40 +combat_def = "mithril_dragon" +xp_bonus = 7.5 +hunt_mode = "cowardly" +slayer_xp = 273.0 +categories = ["mithril_dragons"] +respawn_delay = 30 +drop_table = "mithril_dragon" +examine = "Experimenting with mithril gone bad!" diff --git a/data/area/kandarin/ancient_cavern/ancient_cavern.objs.toml b/data/area/kandarin/ancient_cavern/ancient_cavern.objs.toml new file mode 100644 index 0000000000..bf014e785f --- /dev/null +++ b/data/area/kandarin/ancient_cavern/ancient_cavern.objs.toml @@ -0,0 +1,27 @@ +[ancient_cavern_whirlpool] +id = 25274 +examine = "Crazy-looking whirlpool." + +[ancient_cavern_steps] +id = 25338 + +[ancient_cavern_stairs] +id = 25336 + +[ancient_cavern_kuradal_steps] +id = 39468 + +[ancient_cavern_kuradal_stairs] +id = 25337 + +[ancient_cavern_stairs_top] +id = 25340 + +[ancient_cavern_stairs_bottom] +id = 25339 + +[ancient_cavern_skeleton] +id = 25362 + +[ancient_cavern_aged_log] +id = 25216 \ No newline at end of file diff --git a/data/area/kandarin/ancient_cavern/ancient_cavern.sounds.toml b/data/area/kandarin/ancient_cavern/ancient_cavern.sounds.toml new file mode 100644 index 0000000000..87aed71d81 --- /dev/null +++ b/data/area/kandarin/ancient_cavern/ancient_cavern.sounds.toml @@ -0,0 +1,20 @@ +[barbarian_grunt_defend] +id = 3383 + +[barbarian_grunt_attack] +id = 3381 + +[barbarian_grunt_death] +id = 3382 + +[dharok_axe_crush] +id = 1316 + +[ghoul_attack] +id = 442 + +[ghoul_defend] +id = 444 + +[ghoul_death] +id = 443 \ No newline at end of file diff --git a/data/area/kandarin/ancient_cavern/ancient_cavern.teles.toml b/data/area/kandarin/ancient_cavern/ancient_cavern.teles.toml new file mode 100644 index 0000000000..3014f49857 --- /dev/null +++ b/data/area/kandarin/ancient_cavern/ancient_cavern.teles.toml @@ -0,0 +1,29 @@ +[ancient_cavern_steps] +option = "Climb-down" +tile = { x = 1769, y = 5365, level = 1 } +to = { x = 1772, y = 5366 } + +[ancient_cavern_stairs] +option = "Climb-up" +tile = { x = 1770, y = 5365 } +to = { x = 1768, y = 5366, level = 1 } + +[ancient_cavern_stairs_bottom] +option = "Climb-up" +tile = { x = 1778, y = 5344 } +to = { x = 1778, y = 5343, level = 1 } + +[ancient_cavern_stairs_top] +option = "Climb-down" +tile = { x = 1778, y = 5344, level = 1 } +to = { x = 1778, y = 5346 } + +[ancient_cavern_kuradal_stairs] +option = "Climb-up" +tile = { x = 1744, y = 5323 } +to = { x = 1744, y = 5321, level = 1 } + +[ancient_cavern_kuradal_steps] +option = "Climb-down" +tile = { x = 1744, y = 5322, level = 1 } +to = { x = 1744, y = 5325 } diff --git a/data/area/kandarin/ancient_cavern/kuradals_dungeon/kuradals_dungeon.objs.toml b/data/area/kandarin/ancient_cavern/kuradals_dungeon/kuradals_dungeon.objs.toml new file mode 100644 index 0000000000..e080a5b474 --- /dev/null +++ b/data/area/kandarin/ancient_cavern/kuradals_dungeon/kuradals_dungeon.objs.toml @@ -0,0 +1,14 @@ +[kuradal_dungeon_cave] +id = 47232 + +[kuradal_dungeon_cave_exit] +id = 47231 + +[kuradal_barrier] +id = 47236 + +[kuradal_dungeon_gap] +id = 47237 + +[kuradal_dungeon_low_wall] +id = 47233 diff --git a/data/area/kandarin/ancient_cavern/kuradals_dungeon/kuradals_dungeon.teles.toml b/data/area/kandarin/ancient_cavern/kuradals_dungeon/kuradals_dungeon.teles.toml new file mode 100644 index 0000000000..96b286a27f --- /dev/null +++ b/data/area/kandarin/ancient_cavern/kuradals_dungeon/kuradals_dungeon.teles.toml @@ -0,0 +1,19 @@ +[kuradal_dungeon_cave] +option = "Enter" +tile = { x = 1733, y = 5311, level = 1 } +to = { x = 1661, y = 5257 } + +[kuradal_dungeon_cave_exit] +option = "Enter" +tile = { x = 1662, y = 5256 } +to = { x = 1735, y = 5313, level = 1 } + +[kuradal_dungeon_gap] +option = "Run-across" +tile = { x = 1641, y = 5261 } +to = { x = 1641, y = 5268 } + +[kuradal_dungeon_gap] +option = "Run-across" +tile = { x = 1641, y = 5267 } +to = { x = 1641, y = 5260 } diff --git a/data/area/kandarin/baxtorian_falls/baxtorian_falls.npcs.toml b/data/area/kandarin/baxtorian_falls/baxtorian_falls.npcs.toml index fdbe1ced8b..65f93d8a50 100644 --- a/data/area/kandarin/baxtorian_falls/baxtorian_falls.npcs.toml +++ b/data/area/kandarin/baxtorian_falls/baxtorian_falls.npcs.toml @@ -56,18 +56,3 @@ attack_bonus = 9 slayer_xp = 124.0 categories = ["skeletons"] examine = "He's less heavy now." - -[skeleton_hero] -id = 6103 -hitpoints = 1240 -att = 145 -str = 134 -def = 110 -style = "crush" -max_hit_melee = 180 -attack_bonus = 9 -hunt_mode = "cowardly" -slayer_xp = 124.0 -categories = ["skeletons"] -drop_table = "barbarian_spirit" -examine = "An opponent from the grave. He seems unimpressed by your bone rummaging." diff --git a/data/area/karamja/brimhaven/dungeon/brimhaven_dungeon.npcs.toml b/data/area/karamja/brimhaven/dungeon/brimhaven_dungeon.npcs.toml index 609c271b8e..23f8fc13eb 100644 --- a/data/area/karamja/brimhaven/dungeon/brimhaven_dungeon.npcs.toml +++ b/data/area/karamja/brimhaven/dungeon/brimhaven_dungeon.npcs.toml @@ -2,24 +2,3 @@ id = 4671 categories = ["red_dragons"] examine = "A big powerful dragon." - -[mithril_dragon] -id = 5363 -hitpoints = 2540 -att = 268 -str = 268 -def = 268 -mage = 168 -range = 168 -style = "stab" -max_hit_melee = 280 -max_hit_magic = 180 -max_hit_range = 220 -max_hit_dragonfire = 500 -xp_bonus = 7.5 -hunt_mode = "cowardly" -slayer_xp = 273.0 -categories = ["mithril_dragons"] -respawn_delay = 30 -examine = "Experimenting with mithril gone bad!" - diff --git a/data/area/kharidian_desert/kalphite_hive/kalphite.combat.toml b/data/area/kharidian_desert/kalphite_hive/kalphite.combat.toml index f21123209f..a60f4c1507 100644 --- a/data/area/kharidian_desert/kalphite_hive/kalphite.combat.toml +++ b/data/area/kharidian_desert/kalphite_hive/kalphite.combat.toml @@ -1,17 +1,3 @@ -[kalphite] -attack_speed = 4 -retreat_range = 15 -defend_anim = "human_defend" -defend_sound = "kalphite_defend" -death_anim = "human_death" -death_sound = "kalphite_death" - -[kalphite.melee] -range = 1 -anim = "human_attack" -target_sound = "kalphite_attack" -target_hit = { offense = "crush", max = 80 } - [kalphite_worker] attack_speed = 4 retreat_range = 8 diff --git a/data/area/wilderness/chaos_tunnels/chaos_tunnels.anims.toml b/data/area/wilderness/chaos_tunnels/chaos_tunnels.anims.toml index 93812b1110..7b7c890cd5 100644 --- a/data/area/wilderness/chaos_tunnels/chaos_tunnels.anims.toml +++ b/data/area/wilderness/chaos_tunnels/chaos_tunnels.anims.toml @@ -39,3 +39,12 @@ id = 5596 [spade_attack] id = 5597 + +[waterfiend_attack] +id = 299 + +[waterfiend_death] +id = 300 + +[waterfiend_defend] +id = 301 diff --git a/data/area/wilderness/chaos_tunnels/chaos_tunnels.combat.toml b/data/area/wilderness/chaos_tunnels/chaos_tunnels.combat.toml index 068d9c23bd..6a5a0a4caa 100644 --- a/data/area/wilderness/chaos_tunnels/chaos_tunnels.combat.toml +++ b/data/area/wilderness/chaos_tunnels/chaos_tunnels.combat.toml @@ -91,3 +91,24 @@ anim = "fire_elemental_attack" target_sound = "fire_elemental_attack" target_hit = { offense = "slash", max = 40 } +[waterfiend] +attack_speed = 4 +retreat_range = 8 +defend_anim = "waterfiend_defend" +defend_sound = "waterfiend_defend" +death_anim = "waterfiend_death" +death_sound = "waterfiend_death" + +[waterfiend.magic] +range = 4 +target_sound = "waterfiend_attack" +projectile = "water_wave" +target_hit = { offense = "magic", max = 120 } +impact_gfx = "water_wave_impact" +miss_sound = "spell_splash" + +[waterfiend.range] +range = 4 +target_sound = "waterfiend_attack" +projectile = "ice_arrow" +target_hit = { offense = "range", defence = "magic", max = 120 } diff --git a/data/area/wilderness/chaos_tunnels/chaos_tunnels.drops.toml b/data/area/wilderness/chaos_tunnels/chaos_tunnels.drops.toml index 66a8b8112b..9323ac7041 100644 --- a/data/area/wilderness/chaos_tunnels/chaos_tunnels.drops.toml +++ b/data/area/wilderness/chaos_tunnels/chaos_tunnels.drops.toml @@ -129,4 +129,109 @@ drops = [ { id = "green_charm", chance = 60 }, { id = "crimson_charm", chance = 243 }, { id = "blue_charm", chance = 8 }, -] \ No newline at end of file +] + +[waterfiend_drop_table] +type = "all" +drops = [ + { id = "water_rune" }, + { table = "waterfiend_secondary" }, + { table = "waterfiend_tertiary" }, + { table = "waterfiend_charms" }, +] + +[waterfiend_secondary] +roll = 512 +drops = [ + { id = "water_rune", amount = 90, chance = 32 }, + { id = "blood_rune", min = 4, max = 12, chance = 8 }, + { id = "death_rune", min = 9, max = 19, chance = 8 }, + { id = "mist_rune", min = 3, max = 10, chance = 8 }, + { id = "mud_rune", min = 3, max = 9, chance = 8 }, + { id = "steam_rune", min = 3, max = 10, chance = 8 }, + { id = "nature_rune", min = 44, max = 100 }, + { id = "belladonna_seed", chance = 8 }, + { id = "cactus_seed", chance = 8 }, + { id = "cadantine_seed", chance = 8 }, + { id = "dwarf_weed_seed", chance = 8 }, + { id = "harralander_seed", chance = 8 }, + { id = "irit_seed", chance = 8 }, + { id = "jangerberry_seed", chance = 8 }, + { id = "kwuarm_seed", chance = 8 }, + { id = "lantadyme_seed", chance = 8 }, + { id = "limpwurt_seed", chance = 8 }, + { id = "marrentill_seed", chance = 8 }, + { id = "bittercap_mushroom_spore", chance = 8 }, + { id = "poison_ivy_seed", chance = 8 }, + { id = "spirit_weed_seed", chance = 8 }, + { id = "strawberry_seed", chance = 8 }, + { id = "tarromin_seed", chance = 8 }, + { id = "toadflax_seed", chance = 8 }, + { id = "whiteberry_seed", chance = 8 }, + { id = "wildblood_seed", chance = 8 }, + { id = "watermelon_seed", min = 1, max = 9, chance = 8 }, + { id = "ranarr_seed", chance = 2 }, + { id = "mithril_arrow", amount = 90, chance = 32 }, + { id = "adamant_chainbody", chance = 8 }, + { id = "blue_dragonhide_vambraces", chance = 8 }, + { id = "mithril_full_helm", chance = 8 }, + { id = "mithril_grapple", chance = 8 }, + { id = "mithril_warhammer", chance = 8 }, + { id = "rune_med_helm", chance = 8 }, + { id = "staff_of_water", chance = 8 }, + { id = "water_battlestaff", chance = 8 }, + { id = "sapphire_bolts", amount = 15, chance = 8 }, + { id = "adamant_platebody", chance = 2 }, + { id = "grimy_guam", min = 1, max = 10, chance = 32 }, + { id = "grimy_marrentill", chance = 32 }, + { id = "grimy_tarromin", chance = 32 }, + { id = "grimy_ranarr", chance = 8 }, + { id = "grimy_irit", chance = 8 }, + { id = "grimy_harralander", chance = 8 }, + { id = "grimy_avantoe", chance = 8 }, + { id = "grimy_kwuarm", chance = 8 }, + { id = "grimy_cadantine", chance = 8 }, + { id = "grimy_dwarf_weed", chance = 8 }, + { id = "grimy_lantadyme", chance = 8 }, + { id = "snape_grass_noted", amount = 20, chance = 8 }, + { id = "mithril_ore_noted", min = 1, max = 5, chance = 8 }, + { id = "mithril_bar", amount = 2, chance = 8 }, + { id = "steel_bar_noted", amount = 3, chance = 2 }, +# { id = "coal_noted", min = 3, max = 6, chance = 8 }, # Ghorrock only +# { id = "gold_ore_noted", min = 3, max = 8, chance = 8 }, + { id = "uncut_sapphire_noted", min = 1, max = 4, chance = 8 }, + { id = "uncut_diamond_noted", chance = 2 }, + { id = "uncut_dragonstone" }, + { id = "coins", min = 97, max = 692, chance = 32 }, + { id = "water_orb_noted", min = 5, max = 10, chance = 32 }, + { id = "oyster", chance = 8 }, + { id = "raw_lobster", min = 5, max = 12, chance = 8 }, + { id = "raw_shark", min = 3, max = 6, chance = 8 }, + { id = "seaweed_noted", min = 10, max = 29, chance = 8 }, + { id = "shark", chance = 8 }, + { id = "water_talisman", chance = 8 }, + { id = "nature_talisman", chance = 2 }, + { id = "vial_of_water_noted", min = 5, max = 10, chance = 8 }, +# { id = "saradomin_brew_1", chance = 8 }, +# { id = "zamorak_brew_1", chance = 8 }, + { id = "fishbowl", chance = 8 }, +# { id = "cannonball", min = 11, max = 27, chance = 2 }, + { table = "rare_drop_table", chance = 8 }, +] + +[waterfiend_tertiary] +roll = 256 +drops = [ + { table = "hard_clue_scroll", chance = 2 }, + { id = "court_summons", chance = 2 }, + { id = "starved_ancient_effigy" }, +] + +[waterfiend_charms] +roll = 1000 +drops = [ + { id = "gold_charm", chance = 99 }, + { id = "green_charm", chance = 50 }, + { id = "crimson_charm", chance = 790 }, + { id = "blue_charm", chance = 20 }, +] diff --git a/data/area/wilderness/chaos_tunnels/chaos_tunnels.npcs.toml b/data/area/wilderness/chaos_tunnels/chaos_tunnels.npcs.toml index c9c7b47002..176e9327bb 100644 --- a/data/area/wilderness/chaos_tunnels/chaos_tunnels.npcs.toml +++ b/data/area/wilderness/chaos_tunnels/chaos_tunnels.npcs.toml @@ -179,9 +179,8 @@ str = 0 def = 128 mage = 105 range = 105 -style = "magic" -style = "magical_ranged" -max_hit_melee = 160 +height = 30 +combat_def = "waterfiend" hunt_mode = "cowardly" slayer_xp = 128.0 categories = ["waterfiends"] diff --git a/data/area/wilderness/chaos_tunnels/chaos_tunnels.sounds.toml b/data/area/wilderness/chaos_tunnels/chaos_tunnels.sounds.toml index 2c2f9b2d83..c7e38a7db5 100644 --- a/data/area/wilderness/chaos_tunnels/chaos_tunnels.sounds.toml +++ b/data/area/wilderness/chaos_tunnels/chaos_tunnels.sounds.toml @@ -15,3 +15,12 @@ id = 415 [dust_devil_defend] id = 416 + +[waterfiend_attack] +id = 3774 + +[waterfiend_defend] +id = 3773 + +[waterfiend_death] +id = 3772 \ No newline at end of file diff --git a/data/entity/npc/monster/draconic/dragon.anims.toml b/data/entity/npc/monster/draconic/dragon.anims.toml index be996c1e3a..a0240a7d64 100644 --- a/data/entity/npc/monster/draconic/dragon.anims.toml +++ b/data/entity/npc/monster/draconic/dragon.anims.toml @@ -44,4 +44,19 @@ id = 14270 id = 14269 [baby_dragon_death] -id = 14271 \ No newline at end of file +id = 14271 + +[metal_dragon_breath] +id = 14246 + +[metal_dragon_attack] +id = 14247 + +[metal_dragon_death] +id = 14248 + +[metal_dragon_defend] +id = 14249 + +[metal_dragon_shoot] +id = 14252 diff --git a/data/entity/npc/monster/draconic/metal_dragon.combat.toml b/data/entity/npc/monster/draconic/metal_dragon.combat.toml index 82ec1384db..e4ebe6d06a 100644 --- a/data/entity/npc/monster/draconic/metal_dragon.combat.toml +++ b/data/entity/npc/monster/draconic/metal_dragon.combat.toml @@ -1,21 +1,22 @@ [bronze_dragon] +attack_speed = 4 retreat_range = 8 -defend_anim = "dragon_defend" +defend_anim = "metal_dragon_defend" defend_sound = "dragon_defend" -death_anim = "dragon_death" +death_anim = "metal_dragon_death" death_sound = "dragon_death" [bronze_dragon.melee] chance = 30 range = 1 -anim = "dragon_attack" +anim = "metal_dragon_attack" target_hit = { offense = "slash", max = 120 } target_sound = "dragon_attack" [bronze_dragon.dragonfire] chance = 30 range = 1 -anim = "dragon_breath" +anim = "metal_dragon_breath" gfx = "dragon_breath_shoot" target_hit = { offense = "dragonfire", special = true, max = 500 } target_sound = "dragon_breath" @@ -23,9 +24,10 @@ target_sound = "dragon_breath" [bronze_dragon.fireball] chance = 30 range = 8 -anim = "dragon_shoot" +anim = "metal_dragon_shoot" projectile = "dragon_breath" -projectile_origin = "centre" +projectile_origin_x = 2 +projectile_origin_y = 2 target_hit = { offense = "dragonfire", special = true, max = 500 } target_sound = "metal_dragon_fireball" diff --git a/data/skill/slayer/chaeldar.enums.toml b/data/skill/slayer/chaeldar.enums.toml index 92c2e5af41..06f4330dba 100644 --- a/data/skill/slayer/chaeldar.enums.toml +++ b/data/skill/slayer/chaeldar.enums.toml @@ -1,4 +1,4 @@ -[vannaka_task_amount] +[chaeldar_task_amount] keyType = "npc" valueType = "string" values = { @@ -38,7 +38,7 @@ values = { warped_terrorbird = "70-130", } -[vannaka_task_weight] +[chaeldar_task_weight] keyType = "npc" valueType = "int" values = { diff --git a/data/skill/slayer/duradel.enums.toml b/data/skill/slayer/duradel.enums.toml index 21b2882060..11c112eafd 100644 --- a/data/skill/slayer/duradel.enums.toml +++ b/data/skill/slayer/duradel.enums.toml @@ -1,4 +1,4 @@ -[vannaka_task_amount] +[duradel_task_amount] keyType = "npc" valueType = "string" values = { @@ -33,7 +33,7 @@ values = { waterfiend = "130-200", } -[vannaka_task_weight] +[duradel_task_weight] keyType = "npc" valueType = "int" values = { @@ -65,5 +65,5 @@ values = { steel_dragon = 7, suqah = 5, # warped_terrorbird = 9, -# waterfiend = 10, + waterfiend = 10, } diff --git a/data/skill/slayer/kuradal.enums.toml b/data/skill/slayer/kuradal.enums.toml index 28f53d5285..14c2356408 100644 --- a/data/skill/slayer/kuradal.enums.toml +++ b/data/skill/slayer/kuradal.enums.toml @@ -1,4 +1,4 @@ -[vannaka_task_amount] +[kuradal_task_amount] keyType = "npc" valueType = "string" values = { @@ -38,7 +38,7 @@ values = { waterfiend = "170-250", } -[vannaka_task_weight] +[kuradal_task_weight] keyType = "npc" valueType = "int" values = { @@ -75,5 +75,5 @@ values = { # tormented_demon = 8, tzhaar_mej = 7, # warped_terrorbird = 8, -# waterfiend = 9, + waterfiend = 9, } diff --git a/data/skill/slayer/sumona.enums.toml b/data/skill/slayer/sumona.enums.toml index d03e7bd9ea..6228f79a30 100644 --- a/data/skill/slayer/sumona.enums.toml +++ b/data/skill/slayer/sumona.enums.toml @@ -1,4 +1,4 @@ -[vannaka_task_amount] +[sumona_task_amount] keyType = "npc" valueType = "string" values = { @@ -38,7 +38,7 @@ values = { warped_terrorbird = "120-185", } -[vannaka_task_weight] +[sumona_task_weight] keyType = "npc" valueType = "int" values = { diff --git a/engine/src/main/kotlin/world/gregs/voidps/engine/data/definition/CombatDefinitions.kt b/engine/src/main/kotlin/world/gregs/voidps/engine/data/definition/CombatDefinitions.kt index 72a387346f..e5e7f96bd3 100644 --- a/engine/src/main/kotlin/world/gregs/voidps/engine/data/definition/CombatDefinitions.kt +++ b/engine/src/main/kotlin/world/gregs/voidps/engine/data/definition/CombatDefinitions.kt @@ -425,6 +425,8 @@ class CombatDefinitions { gfx = original.gfx.ifEmpty { clone.gfx }, sounds = original.sounds.ifEmpty { clone.sounds }, projectileOrigin = if (original.projectileOrigin != CombatAttack.EMPTY.projectileOrigin) original.projectileOrigin else clone.projectileOrigin, + projectileOriginX = if (original.projectileOriginX != CombatAttack.EMPTY.projectileOriginX) original.projectileOriginX else clone.projectileOriginX, + projectileOriginY = if (original.projectileOriginX != CombatAttack.EMPTY.projectileOriginY) original.projectileOriginY else clone.projectileOriginY, projectiles = original.projectiles.ifEmpty { clone.projectiles }, targetAnim = if (original.targetAnim != CombatAttack.EMPTY.targetAnim) original.targetAnim else clone.targetAnim, targetGfx = original.targetGfx.ifEmpty { clone.targetGfx }, diff --git a/game/src/main/kotlin/content/area/kandarin/baxtorian_falls/ancient_cavern/AncientCavern.kt b/game/src/main/kotlin/content/area/kandarin/baxtorian_falls/ancient_cavern/AncientCavern.kt new file mode 100644 index 0000000000..899656ca2d --- /dev/null +++ b/game/src/main/kotlin/content/area/kandarin/baxtorian_falls/ancient_cavern/AncientCavern.kt @@ -0,0 +1,88 @@ +package content.area.kandarin.baxtorian_falls.ancient_cavern + +import content.entity.combat.hit.directHit +import content.entity.player.inv.item.addOrDrop +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.client.instruction.handle.interactPlayer +import world.gregs.voidps.engine.client.message +import world.gregs.voidps.engine.client.ui.open +import world.gregs.voidps.engine.entity.character.move.tele +import world.gregs.voidps.engine.entity.character.npc.NPCs +import world.gregs.voidps.engine.entity.character.player.chat.ChatType +import world.gregs.voidps.engine.entity.character.player.skill.Skill +import world.gregs.voidps.engine.entity.item.drop.DropTables +import world.gregs.voidps.engine.entity.obj.remove +import world.gregs.voidps.engine.timer.toTicks +import world.gregs.voidps.type.Direction +import world.gregs.voidps.type.Tile +import world.gregs.voidps.type.random +import java.util.concurrent.TimeUnit + +class AncientCavern(val drops: DropTables) : Script { + init { + objectApproach("Dive in", "ancient_cavern_whirlpool") { + walkToDelay(Tile(tile.x.coerceIn(2511..2512), 3516)) + face(Direction.SOUTH) + delay(1) + anim("jump_whirlpool") + exactMove(Tile(2512, 3508), startDelay = 15, delay = 255, direction = Direction.SOUTH) + delay(4) + open("fade_out") + delay(4) + message("You dive into the swirling maelstrom of the whirlpool.", type = ChatType.Filter) + tele(1763, 5365, 1) + delay(1) + message("You are swirled beneath the water, the darkness and pressure are overwhelming.", type = ChatType.Filter) + delay(1) + message("Mystical forces guide you into a cavern below the whirlpool.", type = ChatType.Filter) + delay(3) + open("fade_in") + } + + objectOperate("Ride", "ancient_cavern_aged_log") { + message("You jump on the log and dislodge it. You guide your makeshift vessel through the caves to an unknown destination.", type = ChatType.Filter) + open("fade_out") + delay(5) + // TODO: Canoe cutscene would go here + open("fade_in") + tele(2531, 3446) + delay(4) + message("You find yourself on the banks of the river, far below the lake.", type = ChatType.Filter) + } + + objectOperate("Rummage", "ancient_cavern_skeleton") { (target) -> + val table = drops.get("ancient_cavern_skeleton") ?: return@objectOperate + val item = table.roll().single() + message("You rummage in the sharp, slimy pile of bones in search of something useful...") + if (random.nextInt(11) < 8) { + directHit(4 + (levels.get(Skill.Constitution) * (random.nextInt(20) / 100))) + } + target.remove(ticks = TimeUnit.MINUTES.toTicks(2)) + when (item.id) { + "skeleton_guard" -> { + val npc = NPCs.add("skeleton_heavy", tile) + npc.interactPlayer(this, "Attack") + message("... the bones object.") + } + "guard_dog" -> { + val npc = NPCs.add("skeleton_hero", tile) + npc.interactPlayer(this, "Attack") + message("... the bones object.") + } + "nothing" -> message("...but there's nothing remotely valuable.") + else -> if (addOrDrop(item.id, 1)) { + message("...you find something and stow it in your pack.") + } else { + message("...you find something, but it drops to the floor.") + } + } + } + + objectSpawn("ancient_cavern_skeleton") { + val spawn = NPCs.findOrNull(tile.regionLevel) { + (it.id == "skeleton_hero" || it.id == "skeleton_heavy") && it.tile.distanceTo(tile) <= 8 + } ?: return@objectSpawn + NPCs.remove(spawn) + } + } +} diff --git a/game/src/main/kotlin/content/area/kandarin/baxtorian_falls/ancient_cavern/FerociousRing.kt b/game/src/main/kotlin/content/area/kandarin/baxtorian_falls/ancient_cavern/FerociousRing.kt new file mode 100644 index 0000000000..9ddddd0461 --- /dev/null +++ b/game/src/main/kotlin/content/area/kandarin/baxtorian_falls/ancient_cavern/FerociousRing.kt @@ -0,0 +1,54 @@ +package content.area.kandarin.baxtorian_falls.ancient_cavern + +import content.skill.magic.jewellery.itemTeleport +import content.skill.magic.jewellery.jewelleryTeleport +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.client.ui.ItemOption +import world.gregs.voidps.engine.data.definition.Areas +import world.gregs.voidps.engine.entity.character.player.Player +import world.gregs.voidps.engine.entity.character.player.equip.equipped +import world.gregs.voidps.engine.entity.character.player.skill.Skill +import world.gregs.voidps.engine.inv.clear +import world.gregs.voidps.engine.inv.equipment +import world.gregs.voidps.network.login.protocol.visual.update.player.EquipSlot +import world.gregs.voidps.type.Tile + +class FerociousRing : Script { + + init { + levelChanged(Skill.Constitution) { skill, from, to -> + if (to !in 1.. threshold) { + return@levelChanged + } + activateFerociousRing(this) + } + + itemOption("Rub", "ferocious_ring_#", handler = ::teleport) + itemOption("Kuradal", "ferocious_ring_#", "worn_equipment", ::teleport) + } + + private fun teleport(player: Player, option: ItemOption) { + if (player.contains("delay")) { + return + } + jewelleryTeleport(player, option.inventory, option.slot, Areas["kuradals_teleport"]) + } + + private fun activateFerociousRing(player: Player) { + if (!player.equipment.clear(EquipSlot.Ring.index)) { + return + } + itemTeleport(player, Tile(1736, 5313, 1), "jewellery") + } +} diff --git a/game/src/main/kotlin/content/area/kandarin/baxtorian_falls/ancient_cavern/KuradalsDungeon.kt b/game/src/main/kotlin/content/area/kandarin/baxtorian_falls/ancient_cavern/KuradalsDungeon.kt new file mode 100644 index 0000000000..713a070a5e --- /dev/null +++ b/game/src/main/kotlin/content/area/kandarin/baxtorian_falls/ancient_cavern/KuradalsDungeon.kt @@ -0,0 +1,72 @@ +package content.area.kandarin.baxtorian_falls.ancient_cavern + +import content.entity.player.dialogue.* +import content.entity.player.dialogue.type.npc +import content.entity.player.dialogue.type.player +import content.skill.slayer.slayerMaster +import content.skill.slayer.slayerTaskRemaining +import world.gregs.voidps.engine.Script +import world.gregs.voidps.engine.entity.character.player.Teleport +import world.gregs.voidps.engine.entity.character.player.skill.Skill +import world.gregs.voidps.engine.entity.character.player.skill.level.Level.has +import world.gregs.voidps.engine.inv.inventory +import world.gregs.voidps.engine.queue.queue +import world.gregs.voidps.type.Direction +import world.gregs.voidps.type.Tile + +class KuradalsDungeon : Script { + init { + objTeleportTakeOff("Enter", "kuradal_dungeon_cave") { _, _ -> + if (inventory.items.any { it.id == "cannon_barrels" || it.id == "cannon_furnace" || it.id == "cannon_stand" || it.id == "cannon_base" }) { + queue("kuradal_cannon_ban") { + npc("kuradal", "No cannons are allowed in there.") // TODO proper message + } + return@objTeleportTakeOff Teleport.CANCEL + } + if (slayerTaskRemaining <= 0 || slayerMaster != "kuradal") { + queue("kuradal_task_check") { + npc("kuradal", "Sorry, my dungeon is exclusive only to those who need to go in there.") + player("Exclusive?") + npc("kuradal", "Yes, I only allow pupils of Slayer into this dungeon and only if they need to slayer the creatures I've caught inside.") + player("I see. So what creatures do I need to be assigned to kill; what creatures are inside?") + npc("kuradal", "Well, I took a holiday tour of Gielinor and brought back some 'souvenirs'. Of course, as a Slayer master, 'souvenirs' means hellhounds, greater demons, gargoyles, abyssal demons, airut, dark beasts, and blue, iron, and steel dragons.") + player("I'd usually keep it simple with a postcard.") + npc("kuradal", "What was that?") + player("I said that must have been hard.") + } + return@objTeleportTakeOff Teleport.CANCEL + } + Teleport.CONTINUE + } + + objectOperate("Pass", "kuradal_barrier") { (target) -> + if (target.rotation == 2) { // vertical + val x = if (tile.x <= target.tile.x) target.tile.x + 1 else target.tile.x + val y = tile.y.coerceIn(target.tile.y, target.tile.y + 1) + walkOverDelay(tile.copy(y = y)) + anim("pass_through_barrier") + exactMoveDelay(Tile(x, y)) + } else if (target.rotation == 3) { // horizontal + val x = tile.x.coerceIn(target.tile.x, target.tile.x + 1) + val y = if (tile.y >= target.tile.y) target.tile.y - 1 else target.tile.y + walkOverDelay(tile.copy(x = x)) + anim("pass_through_barrier") + exactMoveDelay(Tile(x, y)) + } + } + + objectOperate("Climb-over", "kuradal_dungeon_low_wall") { (target) -> + if (!has(Skill.Agility, 86, message = true)) { + return@objectOperate + } + val end = if (tile.y < target.tile.y) Tile(1633, 5294) else Tile(1633, 5292) + val start = if (tile.y < target.tile.y) Tile(1633, 5292) else Tile(1633, 5294) + val direction = if (tile.y < target.tile.y) Direction.NORTH else Direction.SOUTH + walkOverDelay(start) + face(direction) + delay() + anim("rocks_pile_climb") // TODO proper anim + exactMoveDelay(end, 30, direction = direction) + } + } +} diff --git a/game/src/main/kotlin/content/entity/combat/Target.kt b/game/src/main/kotlin/content/entity/combat/Target.kt index e604945797..88e3ebc54d 100644 --- a/game/src/main/kotlin/content/entity/combat/Target.kt +++ b/game/src/main/kotlin/content/entity/combat/Target.kt @@ -15,6 +15,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap import it.unimi.dsi.fastutil.objects.ObjectArrayList import world.gregs.voidps.engine.client.message import world.gregs.voidps.engine.client.variable.hasClock +import world.gregs.voidps.engine.data.definition.Areas import world.gregs.voidps.engine.data.definition.NPCDefinitions import world.gregs.voidps.engine.entity.character.Character import world.gregs.voidps.engine.entity.character.mode.PauseMode @@ -35,6 +36,10 @@ object Target { if (target.id.startsWith("door_support") && NPCDefinitions.get(target.id).options[1] == "Destroy") { return true } + if (source is Player && target.tile in Areas["kuradals_dungeon"] && !target.categories.contains(source.slayerTask)) { + source.message("You're not down here to kill those.") // https://youtu.be/GU7I1GyaNEU?t=4 + return false + } if (target.id == "mound_feldip_hills" && source is Player && source.slayerTask != "jungle_strykewyrm") { source.message("You need to have strykewyrm assigned as a task in order to fight them.") return false @@ -43,6 +48,10 @@ object Target { source.message("You need to have strykewyrm assigned as a task in order to fight them.") return false } + if (target.id == "mound_ice_strykewyrm" && source is Player && source.slayerTask != "ice_strykewyrm") { + source.message("You need to have strykewyrm assigned as a task in order to fight them.") + return false + } if (target.transform != "") { if (NPCDefinitions.get(target.transform).options[1] != "Attack") { return false diff --git a/game/src/main/kotlin/content/entity/npc/combat/Attack.kt b/game/src/main/kotlin/content/entity/npc/combat/Attack.kt index ab183c4d7c..bcc2a6be67 100644 --- a/game/src/main/kotlin/content/entity/npc/combat/Attack.kt +++ b/game/src/main/kotlin/content/entity/npc/combat/Attack.kt @@ -8,6 +8,7 @@ import content.entity.effect.freeze import content.entity.effect.toxin.poison import content.entity.gfx.areaGfx import content.entity.proj.shoot +import content.entity.proj.shootNearest import net.pearx.kasechange.toPascalCase import org.rsmod.game.pathfinder.LineValidator import world.gregs.voidps.engine.Script @@ -29,7 +30,6 @@ import world.gregs.voidps.engine.entity.character.sound import world.gregs.voidps.engine.entity.item.Item import world.gregs.voidps.engine.map.Overlap import world.gregs.voidps.type.Distance -import world.gregs.voidps.type.Tile import world.gregs.voidps.type.random class Attack( @@ -83,7 +83,7 @@ class Attack( continue } val delay = when (origin) { - CombatDefinition.Origin.Centre -> nearestTile(this, target).shoot(id = projectile.id, target = target, delay = projectile.delay, curve = projectile.curve?.random(random), endHeight = projectile.endHeight) + CombatDefinition.Origin.Centre -> shootNearest(id = projectile.id, target = target, delay = projectile.delay, curve = projectile.curve?.random(random), endHeight = projectile.endHeight) else -> shoot(id = projectile.id, target = target, delay = projectile.delay, curve = projectile.curve?.random(random), endHeight = projectile.endHeight, tileOffsetX = attack.projectileOriginX, tileOffsetY = attack.projectileOriginY) } delays[i] = delay @@ -255,15 +255,4 @@ class Attack( } } } - - /** - * Tile the kbd dragon breath originates from. - * Looks weird imo, but it's the same as OSRS. - */ - private fun nearestTile(source: Character, target: Character): Tile { - val half = source.size / 2 - val centre = source.tile.add(half, half) - val direction = target.tile.delta(centre).toDirection() - return centre.add(direction).add(direction) - } } diff --git a/game/src/main/kotlin/content/entity/proj/ShootProjectile.kt b/game/src/main/kotlin/content/entity/proj/ShootProjectile.kt index 0dc964338d..ee99528f31 100644 --- a/game/src/main/kotlin/content/entity/proj/ShootProjectile.kt +++ b/game/src/main/kotlin/content/entity/proj/ShootProjectile.kt @@ -68,6 +68,30 @@ fun Tile.shoot( sourceTile = this, ) +fun Character.shootNearest( + id: String, + target: Character, + delay: Int? = null, + flightTime: Int? = null, + height: Int? = null, + endHeight: Int? = null, + curve: Int? = null, + offset: Int? = null, +) = projectile( + id = id, + target = target, + flightTime = flightTime, + delay = delay, + startHeight = height, + endHeight = endHeight, + curve = curve, + offset = offset, + sourceHeight = this.height, + targetHeight = target.height, + targetTile = target.tile, + sourceTile = nearestTile(this, target), +) + fun Character.shoot( id: String, target: Character, @@ -96,6 +120,17 @@ fun Character.shoot( sourceTile = tile.add(tileOffsetX, tileOffsetY), ) +/** + * Tile dragon breath originates from. + * Looks weird imo, but it's the same as OSRS. + */ +private fun nearestTile(source: Character, target: Character): Tile { + val half = source.size / 2 + val centre = source.tile.add(half, half) + val direction = target.tile.delta(centre).toDirection() + return centre.add(direction).add(direction) +} + fun Character.shoot( id: String, tile: Tile, diff --git a/game/src/main/kotlin/content/skill/magic/book/SpellBookFilter.kt b/game/src/main/kotlin/content/skill/magic/book/SpellBookFilter.kt index b93d2ee2bb..69d384f255 100644 --- a/game/src/main/kotlin/content/skill/magic/book/SpellBookFilter.kt +++ b/game/src/main/kotlin/content/skill/magic/book/SpellBookFilter.kt @@ -23,7 +23,7 @@ class SpellBookFilter : Script { } interfaceOption(id = "*_spellbook:filter_*") { - filter(it.id) + filter(it.interfaceComponent) } interfaceOption(id = "*_spellbook:sort_*") { diff --git a/types/src/main/kotlin/world/gregs/voidps/type/area/Cuboid.kt b/types/src/main/kotlin/world/gregs/voidps/type/area/Cuboid.kt index 9307fb278a..ef3d41cd7c 100644 --- a/types/src/main/kotlin/world/gregs/voidps/type/area/Cuboid.kt +++ b/types/src/main/kotlin/world/gregs/voidps/type/area/Cuboid.kt @@ -74,7 +74,7 @@ data class Cuboid( override fun random() = Tile(random(minX, maxX), random(minY, maxY), random(minLevel, maxLevel)) companion object { - fun random(first: Int, second: Int) = if (first == second) first else random.nextInt(first, second + 1) + internal fun random(first: Int, second: Int) = if (first == second) first else random.nextInt(first, second + 1) } override fun toString(): String = "Cuboid($minX..$maxX, $minY..$maxY, $minLevel..$maxLevel)"