diff --git a/data/json/field_type.json b/data/json/field_type.json index beaef5740d70b..442e711f86674 100644 --- a/data/json/field_type.json +++ b/data/json/field_type.json @@ -161,14 +161,16 @@ "intensity_levels": [ { "name": "starlit webs", - "transparent": false, + "sym": "}", + "color": "white", + "transparent": true, "effects": [ { "effect_id": "webbed", "intensity": 1, "min_duration": "1 m", "immune_in_vehicle": true, "is_environmental": false } ] }, { "name": "starlit webs", - "transparent": false, + "transparent": true, "effects": [ { "effect_id": "webbed", "intensity": 2, "min_duration": "1 m", "immune_in_vehicle": true, "is_environmental": false } ] @@ -182,7 +184,7 @@ } ], "description_affix": "covered_in", - "immune_mtypes": [ "mon_void_spider", "mon_void_spider_spiderling" ], + "immune_mtypes": [ "mon_void_spider", "mon_void_spider_spiderling", "mon_void_spider_maw", "mon_void_spider_limb" ], "decrease_intensity_on_contact": true, "priority": 2, "phase": "solid", diff --git a/data/json/furniture_and_terrain/terrain-nether.json b/data/json/furniture_and_terrain/terrain-nether.json index 0c3a2613f23fd..7a6eb6e9084fb 100644 --- a/data/json/furniture_and_terrain/terrain-nether.json +++ b/data/json/furniture_and_terrain/terrain-nether.json @@ -23,11 +23,12 @@ { "type": "terrain", "id": "t_nether_glass_floor_basalt", - "name": "black glass", - "description": "An endless expanse of black glass. It perfectly reflects the darkness around it.", - "symbol": " ", - "color": "black", - "move_cost": 2, + "name": "basalt floor", + "looks_like": "t_rock_floor", + "description": "Flat hexagonal stone plates tile perfectly across the ground, each an exact copy of the next.", + "symbol": ".", + "color": "dark_gray", + "move_cost": 1, "flags": [ "TRANSPARENT", "FLAT", "ROAD" ] }, { @@ -46,7 +47,7 @@ "type": "terrain", "id": "t_nether_basalt", "name": "perfect basalt wall", - "description": "Hexagonal columns of basalt spring from the dark floor. Each a perfect copy of the next.", + "description": "Hexagonal columns of basalt spring from the dark floor, each an exact copy of the next.", "symbol": "#", "color": "dark_gray", "move_cost": 0, diff --git a/data/json/items/armor/hats.json b/data/json/items/armor/hats.json index 7e7160aefd3c2..2ec4dd96f030b 100644 --- a/data/json/items/armor/hats.json +++ b/data/json/items/armor/hats.json @@ -1691,6 +1691,14 @@ } ] }, + { + "id": "golden_hat", + "type": "ITEM", + "copy-from": "wizard_hat_costume", + "name": "golden hat", + "material": [ "leather" ], + "description": "An incredibly tall hat made from leather covered in gold leaf. Its crown in divided into several segments, with patterns describing the phases of the moon, the seasons and the movements of strange constellations." + }, { "id": "hijab", "type": "ITEM", diff --git a/data/json/items/melee/swords_and_blades.json b/data/json/items/melee/swords_and_blades.json index a2aa27782d4f4..8037b538192be 100644 --- a/data/json/items/melee/swords_and_blades.json +++ b/data/json/items/melee/swords_and_blades.json @@ -2747,7 +2747,7 @@ { "id": "jade_nagamaki", "type": "ITEM", - "subtypes": [ "TOOL" ], + "subtypes": [ "TOOL", "ARTIFACT" ], "copy-from": "qt_katana", "name": { "str_sp": "jade nagamaki" }, "description": "A master smith painstakingly flaked its flowing blade from meteoric sea-green stone. The hilt's cordage is speckled by gold flakes from the tumultuous waters where the blade was whet, and the chosen tsuba depicts an all-devouring snake.", @@ -2759,6 +2759,7 @@ "flags": [ "SPEAR", "REACH_ATTACK", "UNBREAKABLE_MELEE", "SHEATH_SWORD", "NONCONDUCTIVE" ], "techniques": [ "WBLOCK_1", "WIDE", "SPIN" ], "to_hit": { "grip": "weapon", "length": "long", "surface": "line", "balance": "uneven" }, + "passive_effects": [ { "has": "WIELD", "values": [ { "value": "MELEE_STAMINA_CONSUMPTION", "multiply": -0.67 } ] } ], "melee_damage": { "bash": 10, "cut": 32 } }, { diff --git a/data/json/mapgen/map_extras/spider.json b/data/json/mapgen/map_extras/spider.json index 01d444efd396c..9442b10c8f135 100644 --- a/data/json/mapgen/map_extras/spider.json +++ b/data/json/mapgen/map_extras/spider.json @@ -44,7 +44,7 @@ "monsters": { "X": { "monster": "GROUP_SPIDER", "chance": 1, "density": 0.5 } }, "nested": { "X": { "chunks": [ "spider_webs" ] }, - "x": { "chunks": [ "spider_webs" ] }, + "x": { "chunks": [ [ "spider_webs", 800 ], [ "void_spider_webs", 1 ] ] }, "o": { "chunks": [ [ "spider_webs", 2 ], [ "spider_webs_weak", 2 ], [ "null", 1 ] ] }, ",": { "chunks": [ "spider_webs", "spider_webs_weak", "null" ] }, ".": { "chunks": [ [ "spider_webs_weak", 1 ], [ "null", 2 ] ] } diff --git a/data/json/mapgen/map_extras/wilderness.json b/data/json/mapgen/map_extras/wilderness.json index 16e9b129cd914..8990154d28804 100644 --- a/data/json/mapgen/map_extras/wilderness.json +++ b/data/json/mapgen/map_extras/wilderness.json @@ -675,7 +675,9 @@ "]": [ [ "t_water_sh", 8 ], "t_dirt", "t_grass" ], "~": "t_water_dp" }, - "place_nested": [ { "chunks": [ [ "null", 30 ], [ "mx_pond_forest_fruit_patch", 1 ] ], "x": 16, "y": 16 } ], + "place_nested": [ + { "chunks": [ [ "null", 3000 ], [ "mx_pond_forest_fruit_patch", 1000 ], [ "void_spider_webs", 1 ] ], "x": 16, "y": 16 } + ], "place_monsters": [ { "monster": "GROUP_SAFE", "x": [ 0, 23 ], "y": [ 0, 23 ], "chance": 5, "density": 0.5 }, { "monster": "GROUP_FISH", "x": [ 0, 23 ], "y": [ 0, 23 ], "chance": 1, "repeat": [ 1, 2 ], "density": 0.5 }, diff --git a/data/json/mapgen/standing_stones.json b/data/json/mapgen/standing_stones.json index b0e3228913b87..481dc0a969416 100644 --- a/data/json/mapgen/standing_stones.json +++ b/data/json/mapgen/standing_stones.json @@ -43,7 +43,7 @@ " ..........ss...O..... ", " ........ossssss....... ", " ..sssssssss..... ", - " ..Ossss#sOsss.o..... ", + " ..Ossss#!Osss.o..... ", " ......sssssssss.....o. ", " .o.....ossssssO....... ", " .......ss..ss....... ", @@ -62,13 +62,15 @@ ".": [ "t_region_soil", "t_region_groundcover" ], "O": "t_region_soil", "o": "t_region_soil", - "s": "t_region_soil" + "s": "t_region_soil", + "!": "t_region_soil" }, "furniture": { "#": "f_brazier", "O": "f_boulder_large", "o": "f_boulder_small" }, "place_items": [ { "item": "standing_stones_accident", "x": [ 9, 14 ], "y": [ 13, 15 ], "chance": 50, "repeat": [ 3, 6 ] }, { "item": "standing_stones_libation", "x": 11, "y": 11, "chance": 100 } ], + "nested": { "!": { "chunks": [ [ "void_spider_webs", 1 ], [ "null", 19 ] ] } }, "items": { "#": { "item": "fireplace_fill", "repeat": [ 1, 3 ] } } } }, @@ -90,7 +92,7 @@ " ..........ss...O..... ", " ........ossssss....... ", " ..sssssssss..... ", - " ..OssssssOsss.o..... ", + " ..Osssss!Osss.o..... ", " ......sssssssss.....o. ", " .o.....ossssssO....... ", " .......ss..ss....... ", @@ -104,8 +106,16 @@ " " ], "flags": [ "ERASE_ALL_BEFORE_PLACING_TERRAIN" ], - "terrain": { "#": "t_dirt", ".": [ "t_dirt", "t_highland_groundcover" ], "O": "t_dirt", "o": "t_dirt", "s": "t_dirt" }, - "furniture": { "O": "f_boulder_large", "o": "f_boulder_small" } + "terrain": { + "#": "t_dirt", + ".": [ "t_dirt", "t_highland_groundcover" ], + "O": "t_dirt", + "o": "t_dirt", + "s": "t_dirt", + "!": "t_dirt" + }, + "furniture": { "O": "f_boulder_large", "o": "f_boulder_small" }, + "nested": { "!": { "chunks": [ [ "void_spider_webs", 1 ] ] } } } } ] diff --git a/data/json/mapgen/void_spider.json b/data/json/mapgen/void_spider.json index 47135b4d55aa7..edac33e320416 100644 --- a/data/json/mapgen/void_spider.json +++ b/data/json/mapgen/void_spider.json @@ -64,6 +64,7 @@ "entries": [ { "item": "longrifle_flintlock", "variant": "leadworks_longrifle_flintlock", "prob": 10 }, { "item": "helmet_kettle", "variant": "morion", "prob": 10 }, + { "item": "golden_hat", "prob": 10 }, { "item": "towel", "prob": 10 }, { "item": "tattered_garment", "prob": 10 }, { @@ -87,83 +88,6 @@ { "item": "cape_sci_fi", "prob": 10 } ] }, - { - "type": "mapgen", - "om_terrain": [ "void_spider_lair_entrance" ], - "object": { - "fill_ter": "t_rock_floor_no_roof", - "rows": [ - "# X X X X #", - "# -x---x- -x---x- #", - "# X X X X #", - "# X X X X #", - "# -x---x- -x---x- #", - "# X X X X #", - "# X X X X #", - "# -x---x- -x---x- #", - "# X X X X #", - "# X X X X #", - "## -x---x- -x---x- #", - "### X X X X #", - "### X X X X ##", - "#####---x- ##---x-###", - "##### X ##### X ###", - "######,,X ##############", - "#####---x,##############", - "###|X,,,X,|#############", - "||||X,,,X,||############", - "|||,,,,,,,,|||##########", - "|||,,,,,X,,,,||#########", - "||,,X ,,X,,,,,|#########", - "|,,-x---,,,,,,|||#######", - "|,,,X,,,,,,,,,,,|#######" - ], - "palettes": [ "subway_underground" ], - "terrain": { "#": "t_rock", "|": "t_nether_basalt", ",": "t_nether_glass_floor" }, - "place_fields": [ { "field": "fd_void_web", "x": [ 0, 16 ], "y": [ 18, 23 ], "intensity": 1, "repeat": [ 12, 24 ] } ] - } - }, - { - "type": "mapgen", - "update_mapgen_id": "void_spider_lair_entrance_shift", - "object": { "place_nested": [ { "chunks": [ "void_spider_lair_entrance_shift" ], "x": 0, "y": 0 } ] } - }, - { - "type": "mapgen", - "nested_mapgen_id": "void_spider_lair_entrance_shift", - "object": { - "mapgensize": [ 24, 24 ], - "rows": [ - "## -x---x- -x---x- #", - "### X X X X #", - "### X X X X ##", - "#####---x- ##---x-###", - "##### X ##### X ###", - "######,,X ##############", - "########################", - "########################", - "########################", - "########################", - "########################", - "########################", - "########################", - "########################", - "########################", - "########################", - "##BBBBBBBBBB############", - "BBB||||||||BBB##########", - "B|||, , ||BBB#########", - "B||,,,,,,,,|||BB########", - "B|| , ||B########", - "B| ,, , ,|BBB######", - "B| ,,,,, |||B######", - "B| , |BBBBBBB" - ], - "palettes": [ "subway_underground" ], - "flags": [ "ERASE_ALL_BEFORE_PLACING_TERRAIN" ], - "terrain": { "#": "t_rock", "|": "t_nether_basalt", ",": "t_nether_glass_floor", "B": "t_nether_glass_wall" } - } - }, { "type": "mapgen", "update_mapgen_id": "void_spider_lair_corpses", @@ -175,34 +99,35 @@ "object": { "mapgensize": [ 24, 24 ], "rows": [ - " ", - " ", - " ", - " , ", - " ,b, ", - " ,,, , ", - " ,,b,, ", - " ,,, # # ", - " , , ##,,,## ", - " ,b,, ,,,,A,,, ", - " , ##,,,## ", - " # # ", - " ,, # ", - " ,,,,,, , ", - " ,b,,, ,,, ", - " , ,,b,,, ", - " ,,,,# ", - " ,,,, ", - " ,,b,,, ", - " , ", - " ", - " ", - " ", - " " + " ,,,,,,,,, , ", + " ,,,,,, ,,, ", + " ,,,,,,,,,,, ", + ", ,, ,,,, ,o,,, ", + ", ,,,,,,,ooo ,bo ", + ", ,,,ooo, ,,o ", + ", ,,,,,b,,o ,,,,,,, ,,", + ",,, ,,,,,o,,,,o#,,,#o,,", + ", ,,,,,,,,,,, ##,,,##,,", + ",,, ,,bo,, ,,,,,,,A,,,,,", + ", ,,,,o,, oo ##,,,##,,", + " ,, ,,,, ooo#,,,#o,,", + ",,,,,,,,, # ,,,, ,", + ", ,,,o,,, , ,,, ,", + ", ,bo,, ,,,,, ,,", + " , , ,,bo,, , ", + " ,oo,# ,,,", + " ,o,, ,,,,,", + " ,, ,,b,o, ,,,,,,", + " , , ,,, ,,,,, ,,", + " ,, ,,,,,,,,,,,,o,, ", + " ,,,,,,,,,,,,,,,,, ", + " ,,,,o,,,,,, ", + " ,,,,,,,,,,,,,,,,, " ], "flags": [ "ERASE_ALL_BEFORE_PLACING_TERRAIN" ], "terrain": { "#": "t_rock", + "o": "t_nether_glass_floor", "|": "t_nether_basalt", ",": "t_nether_glass_floor", "B": "t_nether_glass_wall", @@ -210,6 +135,7 @@ "b": "t_nether_glass_floor_clairvoyance" }, "items": { + "o": { "item": "void_spider_nest", "chance": 100 }, "A": { "item": "void_spider_corpse_mayor_loot", "chance": 100 }, "b": { "item": "void_spider_corpse_minor_loot", "chance": 100 } } @@ -220,6 +146,20 @@ "update_mapgen_id": "void_spider_lair_eggs", "object": { "place_nested": [ { "chunks": [ "void_spider_lair_eggs" ], "x": 0, "y": 0 } ] } }, + { + "type": "mapgen", + "nested_mapgen_id": "void_spider_webs", + "object": { + "mapgensize": [ 2, 2 ], + "rows": [ + "W ", + " W" + ], + "flags": [ "ERASE_ALL_BEFORE_PLACING_TERRAIN" ], + "fields": { "W": { "field": "fd_void_web", "intensity": 2, "age": 1 } }, + "traps": { "W": "tr_void_spider_entry" } + } + }, { "type": "mapgen", "nested_mapgen_id": "void_spider_lair_eggs", @@ -258,36 +198,36 @@ }, { "type": "mapgen", - "om_terrain": [ [ "void_spider_lair_a1", "void_spider_lair_a2" ] ], + "om_terrain": [ "void_spider_lair" ], "object": { "fill_ter": "t_nether_glass_floor", "rows": [ - "BBBBBBBBBBBBBBBBBBBBBBBBB| ||BBBBBB", - "B####|||||||||||||||#####||| |||###B", - "B##||| ||||#####| |||| |||##B", - "B##| ||||| |||###|| |||##| |||B", - "B##|| ||##|||| |||||| |####|| |B", - "B###| ||####||| || |||###|| |B", - "B###|| |||||| |####||| |B", - "B####|| | ||| |######|| |B", - "B#####||| |||#||| ||#####|| |B", - "B#######| ||#####| |||##|| |B", - "B#######|| |#####|| |#||| |B", - "B########| ||######| || ||B", - "B########| ||#######| ||#B", - "B#######|| |||||#######|| |##B", - "B####||| ||########|||| ||##B", - "B####| ||##########| ||####B", - "B##||| |||| ||#########||| ||#####B", - "B#|| ||##|| |########|| ||||#####B", - "B#| ||####| ||###||||| |########B", - "B#|| ||#####| ||||| ||||########B", - "B###| ||######|| |||||||###########B", - "B####|||########|| |||||||||################B", - "B###############||||||#########################B", - "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" + "||| ||||||......|||", + "|| |||| .... ||", + "| || .. |", + ". || || .", + ".. |||| |||| ..", + "...|||||| ||||||...", + "...|||||| ||||||...", + ".. |||| |||| ..", + ". || || .", + "| .. || |", + "|| .... |||| ||", + "|||......|||||| |||", + "|||......|||||| |||", + "|| .... |||| ||", + "| .. || |", + " || || ", + " |||| |||| ", + " |||||| |||||| ", + " |||||| |||||| ", + " |||| |||| ", + " || || ", + "| || .. |", + "|| |||| .... ||", + "||| ||||||......|||" ], - "terrain": { "#": "t_nether_basalt", "|": "t_nether_basalt", "B": "t_nether_glass_wall" }, + "terrain": { ".": "t_nether_glass_floor_basalt", "|": "t_nether_basalt" }, "place_fields": [ { "field": "fd_void_web", "x": [ 0, 23 ], "y": [ 0, 23 ], "intensity": [ 2, 3 ], "repeat": [ 140, 184 ] }, { "field": "fd_void_web", "x": [ 24, 47 ], "y": [ 0, 23 ], "intensity": [ 2, 3 ], "repeat": [ 140, 184 ] } diff --git a/data/json/monster_special_attacks/void_spider_mechanics.json b/data/json/monster_special_attacks/void_spider_mechanics.json index 3d68d8b12bcf9..5c1b163290b9e 100644 --- a/data/json/monster_special_attacks/void_spider_mechanics.json +++ b/data/json/monster_special_attacks/void_spider_mechanics.json @@ -14,21 +14,126 @@ "use_action": { "type": "effect_on_conditions", "description": "Touch the effigy.", - "effect_on_conditions": [ - { - "id": "VOID_SPIDER_TEST_MAP", - "effect": [ - { "u_message": "The world warps." }, - { - "u_location_variable": { "global_val": "spider_map" }, - "target_params": { "om_terrain": "void_spider_lair_entrance", "z": -5, "min_distance": 1 } - }, - { "u_teleport": { "global_val": "spider_map" }, "force": true } - ] - } - ] + "effect_on_conditions": [ "EOC_VOID_SPIDER_RESET_VARS", "EOC_SPIDER_DIMENSION_TELEPORT" ] } }, + { + "type": "trap", + "id": "tr_void_spider_entry", + "name": "", + "color": "green", + "symbol": "#", + "visibility": 99, + "always_invisible": true, + "avoidance": 99, + "difficulty": 99, + "trap_radius": 0, + "flags": [ "UNDODGEABLE" ], + "action": "eocs", + "eocs": [ "EOC_SPIDER_DIMENSION_TELEPORT" ] + }, + { + "type": "effect_on_condition", + "id": "EOC_SPIDER_DIMENSION_TELEPORT", + "condition": { "math": [ "void_spider_killed != 1" ] }, + "global": true, + "effect": [ + { + "u_travel_to_dimension": "spider_dimension", + "npc_travel_radius": 0, + "region_type": "spider_dimension", + "npc_travel_filter": "none", + "fail_message": "Nothing happens.", + "success_message": "The abyss opens up around you." + }, + { + "u_location_variable": { "context_val": "spider_map" }, + "target_params": { "om_terrain": "void_spider_lair", "z": -1 }, + "terrain": "t_nether_glass_floor_basalt", + "target_max_radius": 26 + }, + { "u_teleport": { "context_val": "spider_map" } }, + { "run_eocs": "EOC_IN_VOID_SPIDER_LAIR", "time_in_future": "1 seconds" } + ] + }, + { + "type": "SPELL", + "id": "void_spider_gore", + "name": { "str": "Great Gore Heap", "//~": "NO_I18N" }, + "description": { "str": "Calls foul chunks of gore and acid from the great heap.", "//~": "NO_I18N" }, + "extra_effects": [ + { "id": "void_spider_acid" }, + { "id": "void_spider_gore_repeat" }, + { "id": "void_spider_acid" }, + { "id": "void_spider_gore_repeat" } + ], + "valid_targets": [ "ground", "self", "ally" ], + "effect": "attack", + "shape": "blast", + "damage_type": "bash", + "min_damage": 1, + "max_damage": 1, + "flags": [ "LOUD", "RANDOM_TARGET", "RANDOM_DAMAGE", "RANDOM_AOE", "NO_EXPLOSION_SFX", "SILENT" ], + "base_casting_time": 100, + "min_aoe": 2, + "max_aoe": 4, + "min_range": 20, + "max_range": 20 + }, + { + "type": "SPELL", + "id": "void_spider_gore_repeat", + "name": { "str": "Gore Heap - gore", "//~": "NO_I18N" }, + "description": { "str": "A single bit of gore from the heap.", "//~": "NO_I18N" }, + "valid_targets": [ "ground" ], + "effect": "attack", + "shape": "blast", + "message": "", + "damage_type": "bash", + "min_damage": 1, + "max_damage": 5, + "flags": [ "LOUD", "RANDOM_TARGET", "RANDOM_DAMAGE", "RANDOM_AOE" ], + "base_casting_time": 100, + "min_aoe": 1, + "max_aoe": 2, + "min_range": 10, + "max_range": 30, + "field_id": "fd_gibs_flesh", + "field_chance": 2, + "min_field_intensity": 1, + "max_field_intensity": 3 + }, + { + "type": "SPELL", + "id": "void_spider_acid", + "name": { "str": "Gore Heap - acid", "//~": "NO_I18N" }, + "description": { "str": "A single bit of acid from the heap.", "//~": "NO_I18N" }, + "valid_targets": [ "hostile", "ground", "self", "ally" ], + "effect": "attack", + "shape": "blast", + "message": "", + "damage_type": "bash", + "min_damage": 1, + "max_damage": 3, + "flags": [ "LOUD", "RANDOM_TARGET", "RANDOM_DAMAGE", "RANDOM_AOE" ], + "base_casting_time": 100, + "min_aoe": 1, + "max_aoe": 1, + "min_range": 10, + "max_range": 30, + "field_id": "fd_acid", + "field_chance": 2, + "min_field_intensity": 1, + "max_field_intensity": 3 + }, + { + "type": "monster_attack", + "id": "void_spider_control", + "attack_type": "eoc", + "cooldown": 1, + "range": 35, + "eoc": [ "EOC_VOID_SPIDER_CONTROL" ] + }, { "type": "monster_attack", "attack_type": "melee", @@ -39,23 +144,13 @@ "hitsize_min": 4, "effects": [ { "id": "venom_blind", "duration": 120 } ], "hit_dmg_u": "%1$s's immaterial limbs crawl over you and sink their fangs in your %2$s!", - "hit_dmg_npc": "%1$s buries its beak in !", + "hit_dmg_npc": "%1$s's immaterial limbs sink into !", "miss_msg_u": "%1$s's hanging limbs try to bite you, but you dodge!", "miss_msg_npc": "%1$s's hanging limbs try to bite , but they dodge!", "no_dmg_msg_u": "%1$s's hanging limbs try to bite your %2$s, but fails to penetrate your armor!", "no_dmg_msg_npc": "%1$s's hanging limbs try to bite , but fails to penetrate their armor!", "condition": { "or": [ { "npc_has_effect": "WEBBED" }, { "npc_has_effect": "GRABBED" } ] } }, - { - "type": "ter_furn_transform", - "id": "cavern_emptiness", - "terrain": [ { "result": [ "t_nether_glass_floor_basalt" ], "valid_terrain": [ "t_nether_basalt" ] } ] - }, - { - "type": "ter_furn_transform", - "id": "cavern_emptiness_revert", - "terrain": [ { "result": [ "t_nether_basalt" ], "valid_terrain": [ "t_nether_glass_floor_basalt" ] } ] - }, { "id": "void_spider_empty", "name": { "str": "Void spider emptiness", "//~": "NO_I18N" }, @@ -66,35 +161,13 @@ "effect": "ter_transform", "effect_str": "cavern_emptiness", "shape": "blast", - "min_aoe": 5, - "max_aoe": 5 - }, - { - "id": "void_spider_empty_revert", - "name": { "str": "Void spider revert emptiness", "//~": "NO_I18N" }, - "description": { "str": "Constantly empties the area around the spider.", "//~": "NO_I18N" }, - "valid_targets": [ "ally", "hostile", "ground" ], - "type": "SPELL", - "effect": "ter_transform", - "effect_str": "cavern_emptiness_revert", - "flags": [ "SILENT", "NO_EXPLOSION_SFX" ], - "shape": "blast", - "min_aoe": 35, - "max_aoe": 35 + "min_aoe": 12, + "max_aoe": 12 }, { - "id": "void_spider_control", - "type": "SPELL", - "name": { "str": "Void spider control", "//~": "NO_I18N" }, - "description": { "str": "Void spiders control themselves using this one.", "//~": "NO_I18N" }, - "valid_targets": [ "self" ], - "flags": [ "SILENT", "NO_EXPLOSION_SFX" ], - "shape": "blast", - "min_range": 1, - "max_range": 1, - "message": "", - "effect": "effect_on_condition", - "effect_str": "EOC_VOID_SPIDER_CONTROL" + "type": "ter_furn_transform", + "id": "cavern_emptiness", + "terrain": [ { "result": [ "t_nether_glass_floor_basalt" ], "valid_terrain": [ "t_nether_basalt" ] } ] }, { "type": "SPELL", @@ -115,67 +188,12 @@ "effect": "summon", "effect_str": "mon_void_spider" }, - { - "type": "SPELL", - "id": "mon_void_weaver_death", - "name": { "str": "Void Weaver Death", "//~": "NO_I18N" }, - "description": { "str": "Ends the fight.", "//~": "NO_I18N" }, - "valid_targets": [ "self", "hostile", "ally" ], - "max_level": 1, - "flags": [ "SILENT", "NO_HANDS", "NO_LEGS" ], - "base_casting_time": 75, - "min_range": 15, - "max_range": 15, - "min_aoe": 30, - "max_aoe": 30, - "shape": "blast", - "effect": "effect_on_condition", - "effect_str": "EOC_VOID_SPIDER_ON_DEATH" - }, - { - "type": "effect_on_condition", - "id": "EOC_ENTER_VOID_SPIDER_LAIR", - "eoc_type": "EVENT", - "required_event": "avatar_enters_omt", - "condition": { "or": [ { "u_at_om_location": "void_spider_lair_a1" }, { "u_at_om_location": "void_spider_lair_a2" } ] }, - "effect": [ - { - "run_eocs": [ - { - "id": "seal_void_spider_lair", - "condition": { "math": [ "spider_lair_sealed != 1" ] }, - "effect": [ - { "mapgen_update": "void_spider_lair_entrance_shift", "om_terrain": "void_spider_lair_entrance" }, - { "math": [ "spider_lair_sealed = 1" ] }, - { "run_eocs": "EOC_IN_VOID_SPIDER_LAIR", "time_in_future": "1 seconds" }, - { "run_eocs": "EOC_VOID_SPIDER_EMPTY_REVERT", "time_in_future": "25 seconds" } - ] - } - ] - } - ] - }, { "type": "effect_on_condition", "id": "EOC_IN_VOID_SPIDER_LAIR", - "condition": { - "or": [ - { "u_at_om_location": "void_spider_lair_entrance" }, - { "u_at_om_location": "void_spider_lair_a1" }, - { "u_at_om_location": "void_spider_lair_a2" } - ] - }, - "deactivate_condition": { - "not": { - "or": [ - { "u_at_om_location": "void_spider_lair_entrance" }, - { "u_at_om_location": "void_spider_lair_a1" }, - { "u_at_om_location": "void_spider_lair_a2" } - ] - } - }, + "condition": { "or": [ { "u_at_om_location": "void_spider_lair" } ] }, + "deactivate_condition": { "not": { "or": [ { "u_at_om_location": "void_spider_lair" } ] } }, "effect": [ - { "place_override": { "global_val": "place_name", "default": "strange cavern" }, "length": "10 seconds" }, { "run_eocs": "EOC_IN_VOID_SPIDER_LAIR", "time_in_future": "1 seconds" }, { "run_eocs": [ @@ -241,8 +259,12 @@ "id": "void_spider_life_remaining", "condition": { "and": [ { "math": [ "u_hp('ALL') < 350" ] }, { "math": [ "u_void_spider_nest_disturbed != 1" ] } ] }, "effect": [ + { "math": [ "u_hp('ALL') += 150" ] }, + { "u_lose_effect": "maimed_armor" }, { "u_make_sound": "the spider mimic an anguished scream", "volume": 60, "type": "speech" }, { "run_eocs": [ "EOC_VOID_SPIDER_DISTURBED_NEST" ] }, + { "npc_location_variable": { "context_val": "disturbed_loc" }, "min_radius": 40, "max_radius": 50 }, + { "u_teleport": { "context_val": "disturbed_loc" } }, { "math": [ "u_void_spider_nest_disturbed = 1" ] } ] }, @@ -254,23 +276,69 @@ "real_count": { "math": [ "(u_hp('ALL') / 300)" ] }, "min_radius": 1, "max_radius": 1, - "lifespan": [ "1 seconds", "3 seconds" ] + "lifespan": [ "2 seconds", "3 seconds" ] }, { - "//": "6 of these at the start, looses one for every 100 hp lost, monster starts at 600 hp", + "//": "6 of these at the start, looses one for every 150 hp lost, monster starts at 900 hp", "u_spawn_monster": "mon_void_spider_limb", - "real_count": { "math": [ "u_hp('ALL') / 100" ] }, + "real_count": { "math": [ "u_hp('ALL') / 150" ] }, "min_radius": 2, "max_radius": 2, - "lifespan": [ "1 seconds", "3 seconds" ] + "lifespan": [ "2 seconds", "3 seconds" ] } ] } ] }, + { "u_location_variable": { "context_val": "my_loc" } }, + { "npc_location_variable": { "context_val": "t_loc" } }, + { "math": [ "_distance = distance('u', 'npc')" ] }, + { + "switch": { "math": [ "_distance" ] }, + "cases": [ + { "case": 0, "effect": [ { "u_attack": "void_spider_bite" } ] }, + { + "case": 15, + "effect": [ { "run_eocs": [ "EOC_VOID_SPIDER_GORE" ], "variables": { "tar": { "context_val": "t_loc" } } } ] + } + ] + }, { "u_cast_spell": { "id": "void_spider_empty", "hit_self": true } } ] }, + { + "type": "effect_on_condition", + "id": "EOC_HURT_WEAVER", + "condition": "has_alpha", + "effect": [ + { + "if": "u_is_avatar", + "then": [ + { "message": "The limb shatters like a pane of glass!", "type": "good" }, + { + "npc_run_monster_eocs": [ { "id": "_EOC_HURT_WEAVER", "effect": { "u_deal_damage": "pure", "amount": 20, "bodypart": "torso" } } ], + "monster_range": 36 + } + ] + } + ] + }, + { + "type": "effect_on_condition", + "id": "EOC_VOID_SPIDER_GORE", + "condition": { "math": [ "spider_gore < 10" ] }, + "effect": [ + { "u_message": "Foul heaps of rotten flesh rain down from the Weaver's maw!", "type": "bad" }, + { "u_cast_spell": { "id": "void_spider_gore" }, "loc": { "context_val": "tar" } }, + { "math": [ "spider_gore++" ] }, + { + "run_eocs": "EOC_VOID_SPIDER_GORE", + "time_in_future": "1 seconds", + "variables": { "tar": { "context_val": "t_loc" } } + } + ], + "false_effect": [ { "math": [ "spider_gore = 0" ] } ] + }, { "type": "effect_on_condition", "id": "EOC_VOID_SPIDER_DISTURBED_NEST", @@ -283,8 +351,12 @@ "real_count": [ 1, 3 ], "min_radius": 6, "max_radius": 12, - "lifespan": [ "10 seconds", "25 seconds" ] + "lifespan": [ "5 seconds", "25 seconds" ] }, + { "u_location_variable": { "global_val": "void_spider_eggs" } }, + { "u_location_variable": { "global_val": "void_spider_corpses" } }, + { "location_variable_adjust": { "global_val": "void_spider_eggs" }, "overmap_tile": true, "x_adjust": 1 }, + { "location_variable_adjust": { "global_val": "void_spider_corpses" }, "overmap_tile": true, "y_adjust": 1 }, { "run_eocs": [ { @@ -301,7 +373,11 @@ "id": "EOC_VOID_SPIDER_SPAWN_EGGS", "condition": { "and": [ { "one_in_chance": 3 }, { "math": [ "void_spider_nest_eggs_spawned != 1" ] } ] }, "effect": [ - { "mapgen_update": "void_spider_lair_eggs", "om_terrain": "void_spider_lair_a2" }, + { + "mapgen_update": "void_spider_lair_eggs", + "om_terrain": "void_spider_lair", + "target_var": { "global_val": "void_spider_eggs" } + }, { "math": [ "void_spider_nest_eggs_spawned = 1" ] } ] }, @@ -309,7 +385,11 @@ "id": "EOC_VOID_SPIDER_SPAWN_CORPSES", "condition": { "and": [ { "one_in_chance": 6 }, { "math": [ "void_spider_nest_corpses_spawned != 1" ] } ] }, "effect": [ - { "mapgen_update": "void_spider_lair_corpses", "om_terrain": "void_spider_lair_a1" }, + { + "mapgen_update": "void_spider_lair_corpses", + "om_terrain": "void_spider_lair", + "target_var": { "global_val": "void_spider_corpses" } + }, { "math": [ "void_spider_nest_corpses_spawned = 1" ] } ] } @@ -323,41 +403,32 @@ "id": "EOC_VOID_SPIDER_CAST_CHAOS_SWAP", "global": true, "effect": [ - { "u_location_variable": { "global_val": "void_spider_chaos_point_player" }, "min_radius": 5, "max_radius": 12 }, + { "u_location_variable": { "global_val": "void_spider_chaos_point_player" }, "min_radius": 25, "max_radius": 30 }, { "u_teleport": { "global_val": "void_spider_chaos_point_player" } }, { "u_message": "The cavern shifts under unseen pressure." } ] }, - { - "type": "effect_on_condition", - "id": "EOC_VOID_SPIDER_EMPTY_REVERT", - "global": true, - "condition": { - "or": [ - { "u_at_om_location": "void_spider_lair_entrance" }, - { "u_at_om_location": "void_spider_lair_a1" }, - { "u_at_om_location": "void_spider_lair_a2" } - ] - }, - "effect": [ - { "u_cast_spell": { "id": "void_spider_empty_revert", "hit_self": true } }, - { "run_eocs": "EOC_VOID_SPIDER_EMPTY_REVERT", "time_in_future": "25 seconds" } - ] - }, { "type": "effect_on_condition", "id": "EOC_VOID_SPIDER_ON_DEATH", "effect": [ { "run_eocs": "EOC_VOID_SPIDER_KILLED", "time_in_future": "0 seconds" }, - { "run_eocs": "EOC_VOID_SPIDER_RESET_VARS", "time_in_future": "2 hours" }, { "run_eocs": "EOC_DISSOLVE_VOID_SPIDER_LAIR", "time_in_future": "20 minutes" } ] }, { "type": "effect_on_condition", "id": "EOC_DISSOLVE_VOID_SPIDER_LAIR", + "global": true, "effect": [ { "u_message": "The cavern folds itself beyond perception.", "popup": true }, + { + "u_travel_to_dimension": "", + "npc_travel_radius": 0, + "npc_travel_filter": "none", + "fail_message": "Nothing seems to change.", + "success_message": "The emptiness seems to expand into endlessness." + }, { "u_location_variable": { "global_val": "nether_glass" }, "target_params": { "om_terrain": "nether_glass_deep", "z": -10, "min_distance": 1 } @@ -379,9 +450,8 @@ "type": "effect_on_condition", "id": "EOC_VOID_SPIDER_RESET_VARS", "global": true, - "//": "Reset in case someone finds a second lair under some extraneous circumstances.", + "//": "Reset vars for debugging.", "effect": [ - { "math": [ "spider_lair_sealed = 0" ] }, { "math": [ "void_spider_killed = 0" ] }, { "math": [ "void_spider_nest_eggs_spawned = 0" ] }, { "math": [ "void_spider_nest_corpses_spawned = 0" ] } diff --git a/data/json/monster_weakpoints/netherium_weakpoints.json b/data/json/monster_weakpoints/netherium_weakpoints.json index a7c5876605396..93af2978977d3 100644 --- a/data/json/monster_weakpoints/netherium_weakpoints.json +++ b/data/json/monster_weakpoints/netherium_weakpoints.json @@ -35,6 +35,83 @@ } ] }, + { + "type": "weakpoint_set", + "id": "wps_void_spider", + "weakpoints": [ + { + "id": "weak_point", + "name": "a band of vulnerable flesh.", + "coverage": 20, + "condition": { "not": { "npc_has_any_effect": [ "maimed_armor" ] } }, + "difficulty": { "melee": 3, "ranged": 4 }, + "coverage_mult": { "ranged": 0.5 }, + "armor_mult": { "all": 0.03 }, + "effects": [ + { + "effect": "maimed_armor", + "permanent": true, + "duration": 86400, + "chance": 2, + "message": "Foul vapor starts seeping from the %s body!", + "damage_required": [ 1, 5 ] + }, + { + "effect": "maimed_armor", + "permanent": true, + "duration": 86400, + "chance": 5, + "message": "Foul vapor starts seeping from the %s body!", + "damage_required": [ 5, 9 ] + }, + { + "effect": "maimed_armor", + "permanent": true, + "duration": 86400, + "chance": 20, + "message": "Foul vapor starts seeping from the %s body!", + "damage_required": [ 10, 100 ] + } + ] + }, + { + "id": "heavy_armor", + "name": "a segment full of fangs", + "is_good": false, + "armor_mult": { "all": 1.5 }, + "coverage_mult": { "melee": 0.15 }, + "difficulty": { "melee": 5, "ranged": 8 }, + "condition": { "not": { "npc_has_any_effect": [ "maimed_armor", "afs_android_crawling" ] } }, + "coverage": 30, + "effects": [ + { + "effect": "maimed_armor", + "permanent": true, + "duration": 86400, + "chance": 10, + "message": "Foul vapor starts seeping from the %s body!", + "damage_required": [ 1, 5 ] + }, + { + "effect": "maimed_armor", + "permanent": true, + "duration": 86400, + "chance": 30, + "message": "Foul vapor starts seeping from the %s body!", + "damage_required": [ 5, 100 ] + } + ] + }, + { + "id": "internal_exposed", + "name": "its exposed internals", + "armor_mult": { "all": 0.01 }, + "damage_mult": { "all": 1.5 }, + "condition": { "npc_has_any_effect": [ "maimed_armor" ] }, + "coverage": 45 + } + ] + }, { "type": "weakpoint_set", "id": "wps_nether_huntsman", diff --git a/data/json/monsters/nether.json b/data/json/monsters/nether.json index d535abd44fe01..ffde5eb55e7db 100644 --- a/data/json/monsters/nether.json +++ b/data/json/monsters/nether.json @@ -233,41 +233,28 @@ { "id": "mon_void_spider", "type": "MONSTER", - "name": { "str": "void weaver" }, - "description": "Articulated limbs slip into the outlines of shadow, each a conduit for the kaleidoscopic maw from which they emerge.", + "name": { "str": "unformed weaver" }, + "description": "It stalks thin slices of reality like gossamer threads, each a narrow conduit between worlds unknown and its kaleidoscopic maw.", "default_faction": "nether", "volume": "1800 L", "weight": "750000 g", - "hp": 600, + "hp": 900, "symbol": "S", - "speed": 87, + "speed": 80, "morale": 50, "aggression": 100, "grab_strength": 2, "melee_dice": 4, "melee_dice_sides": 4, "melee_skill": 8, - "regenerates": 1, - "path_settings": { "avoid_traps": true, "avoid_sharp": true, "max_dist": 50 }, - "special_attacks": [ - [ "void_spider_bite", 1 ], - { - "type": "spell", - "spell_data": { "id": "void_spider_control", "min_level": 1, "hit_self": true }, - "monster_message": "", - "cooldown": 2 - } - ], + "vision_night": 40, + "special_attacks": [ { "id": "void_spider_control", "cooldown": 2 } ], "dodge": 8, - "armor": { "bash": 20, "cut": 24, "bullet": 30, "electric": 3, "stab": 18, "acid": 15 }, + "armor": { "bash": 1000, "cut": 1000, "bullet": 1000, "electric": 30, "stab": 1000, "acid": 100 }, "families": [ "prof_wp_netherium_abomination" ], - "weakpoint_sets": [ "wps_arthropod_spider" ], + "weakpoint_sets": [ "wps_void_spider" ], "bleed_rate": 10, - "death_function": { - "corpse_type": "NO_CORPSE", - "message": "The %s dissolves into inert shadows.", - "effect": { "id": "mon_void_weaver_death", "hit_self": true } - }, + "death_function": { "corpse_type": "NO_CORPSE", "message": "The %s dissolves into inert shadows.", "eoc": "EOC_VOID_SPIDER_ON_DEATH" }, "flags": [ "SEES", "HEARS", @@ -276,14 +263,13 @@ "SMELLS", "DESTROYS", "WARM", - "CAMOUFLAGE", "FIREPROOF", "NIGHT_INVISIBILITY", "ALWAYS_SEES_YOU", + "ALWAYS_VISIBLE", "NO_BREATHE", "PRIORITIZE_TARGETS", "ARTHROPOD_BLOOD", - "PATH_AVOID_DANGER", "HARDTOSHOOT" ] }, @@ -291,7 +277,7 @@ "id": "mon_void_spider_maw", "type": "MONSTER", "name": { "str": "hanging maw" }, - "description": "An explosion of glistening fangs, itself but a small reflection of the greater horror.", + "description": "An explosion of glistening fangs, itself a small fragment of a greater horror.", "default_faction": "nether", "copy-from": "mon_void_spider", "symbol": "w", @@ -303,42 +289,34 @@ "melee_damage": [ { "damage_type": "bash", "amount": 5, "armor_penetration": 28 } ], "armor": { "bash": 10, "cut": 12, "bullet": 15, "electric": 3, "stab": 18, "acid": 15 }, "special_attacks": [ [ "void_spider_bite", 1 ] ], - "death_function": { - "effect": { "id": "hurt_void_spider", "hit_self": true }, - "corpse_type": "NO_CORPSE", - "message": "The %s shatters like pane of glass." - }, + "death_function": { "eoc": "EOC_HURT_WEAVER", "corpse_type": "NO_CORPSE", "message": "" }, "delete": { "flags": [ "ALWAYS_SEES_YOU" ] }, - "extend": { "flags": [ "SILENT_DISAPPEAR" ] } + "extend": { "flags": [ "QUIETDEATH" ] } }, { "id": "mon_void_spider_limb", "type": "MONSTER", "name": { "str": "hanging limb" }, - "description": "A limb of shadow, itself but a small reflection of a greater horror.", + "description": "Strands of shadow snap from their ordained positions, briefly reaching out before recoiling back into the darkness.", "default_faction": "nether", "copy-from": "mon_void_spider", "symbol": "/", - "hp": 20, + "hp": 15, "proportional": { "speed": 1.2, "dodge": 0.25, "vision_day": 2 }, "melee_dice": 3, "melee_dice_sides": 2, "melee_skill": 3, "special_attacks": [ ], + "death_function": { "eoc": "EOC_HURT_WEAVER", "corpse_type": "NO_CORPSE", "message": "" }, "armor": { "bash": 5, "cut": 6, "bullet": 6, "electric": 3, "stab": 7, "acid": 15 }, - "death_function": { - "effect": { "id": "hurt_void_spider", "hit_self": true }, - "corpse_type": "NO_CORPSE", - "message": "The %s shatters like pane of glass." - }, "delete": { "flags": [ "ALWAYS_SEES_YOU" ] }, - "extend": { "flags": [ "SILENT_DISAPPEAR" ] } + "extend": { "flags": [ "QUIETDEATH" ] } }, { "id": "mon_void_spider_spiderling", "type": "MONSTER", "name": { "str": "weaver juvenile" }, - "description": "The distressed movements of the juvenile reveal conjoined layers of flailing legs and fangs. It is no spider as you know it.", + "description": "The distressed movements of the juvenile reveal conjoined layers of flailing legs and fangs.", "default_faction": "nether", "copy-from": "mon_void_spider", "color": "red", diff --git a/data/json/obsoletion_and_migration_0.I/obsolete_overmap_special.json b/data/json/obsoletion_and_migration_0.I/obsolete_overmap_special.json index 976831187d666..5aa907266dc90 100644 --- a/data/json/obsoletion_and_migration_0.I/obsolete_overmap_special.json +++ b/data/json/obsoletion_and_migration_0.I/obsolete_overmap_special.json @@ -14,6 +14,10 @@ "id": "Railroad Station", "//": "Moved to railroad mod in 0.G, but no migration, remove when 0.I stable" }, + { + "type": "overmap_special_migration", + "id": "void_spider_lair" + }, { "type": "overmap_special_migration", "id": "house_05ab", diff --git a/data/json/obsoletion_and_migration_0.I/obsolete_overmap_terrain.json b/data/json/obsoletion_and_migration_0.I/obsolete_overmap_terrain.json index 82af69ddce9f2..81f275e29a03d 100644 --- a/data/json/obsoletion_and_migration_0.I/obsolete_overmap_terrain.json +++ b/data/json/obsoletion_and_migration_0.I/obsolete_overmap_terrain.json @@ -566,5 +566,10 @@ "outpost_cross_roof_east": "outpost_roof_east", "outpost_cross_roof_west": "outpost_roof_west" } + }, + { + "type": "oter_id_migration", + "//": "migrated in 0.I", + "oter_ids": { "void_spider_lair_entrance": "deep_rock", "void_spider_lair_a1": "deep_rock", "void_spider_lair_a2": "deep_rock" } } ] diff --git a/data/json/overmap/overmap_special/specials.json b/data/json/overmap/overmap_special/specials.json index c52df76599145..fc77b3f24b216 100644 --- a/data/json/overmap/overmap_special/specials.json +++ b/data/json/overmap/overmap_special/specials.json @@ -3588,23 +3588,6 @@ "occurrences": [ 50, 100 ], "flags": [ "LAB", "MAN_MADE", "OVERMAP_UNIQUE" ] }, - { - "type": "overmap_special", - "id": "void_spider_lair", - "overmaps": [ - { "point": [ 0, 0, -4 ], "overmap": "microlab_sub_connector_north" }, - { "point": [ 0, 1, -4 ], "overmap": "sub_ramp_above_north" }, - { "point": [ 0, 1, -5 ], "overmap": "sub_ramp_below_north" }, - { "point": [ 0, 2, -5 ], "overmap": "void_spider_lair_entrance_north" }, - { "point": [ -1, 3, -5 ], "overmap": "void_spider_lair_a1_north" }, - { "point": [ 0, 3, -5 ], "overmap": "void_spider_lair_a2_north" } - ], - "locations": [ "land" ], - "city_distance": [ 1, -1 ], - "occurrences": [ 2, 2 ], - "rotate": false, - "flags": [ "OVERMAP_UNIQUE" ] - }, { "type": "overmap_special", "id": "4x4_microlab_rodent", diff --git a/data/json/overmap/overmap_terrain/overmap_terrain_nether.json b/data/json/overmap/overmap_terrain/overmap_terrain_nether.json index e35b009c4873e..bda466cc223c3 100644 --- a/data/json/overmap/overmap_terrain/overmap_terrain_nether.json +++ b/data/json/overmap/overmap_terrain/overmap_terrain_nether.json @@ -11,12 +11,12 @@ }, { "type": "overmap_terrain", - "id": [ "void_spider_lair_entrance", "void_spider_lair_a1", "void_spider_lair_a2" ], + "id": "void_spider_lair", "vision_levels": "always_full", - "name": "abyss", + "name": "abyssal cavern", "sym": " ", "color": "black", "see_cost": "opaque", - "flags": [ "RISK_EXTREME" ] + "flags": [ "RISK_EXTREME", "NO_ROTATE" ] } ] diff --git a/data/json/region_settings/region_settings/dimensions/spider_dimension.json b/data/json/region_settings/region_settings/dimensions/spider_dimension.json new file mode 100644 index 0000000000000..50b40767160fc --- /dev/null +++ b/data/json/region_settings/region_settings/dimensions/spider_dimension.json @@ -0,0 +1,55 @@ +[ + { + "type": "region_settings", + "id": "spider_dimension", + "rivers": null, + "lakes": null, + "ocean": null, + "ravines": null, + "forests": null, + "forest_trails": null, + "highways": null, + "cities": null, + "forest_composition": "no_forests", + "map_extras": "no_map_extras", + "terrain_furniture": "default", + "weather": "default", + "place_roads": false, + "place_specials": false, + "neighbor_connections": false, + "default_oter": [ + "nether_glass_deep_north", + "nether_glass_deep_north", + "nether_glass_deep_north", + "nether_glass_deep_north", + "nether_glass_deep_north", + "nether_glass_deep_north", + "nether_glass_deep_north", + "nether_glass_deep_north", + "nether_glass_deep_north", + "nether_glass_deep_north", + "nether_glass_deep_north", + "void_spider_lair", + "nether_glass_deep_north", + "nether_glass_deep_north", + "nether_glass_deep_north", + "nether_glass_deep_north", + "nether_glass_deep_north", + "nether_glass_deep_north", + "nether_glass_deep_north", + "nether_glass_deep_north", + "nether_glass_deep_north" + ], + "default_groundcover": [ [ "t_nether_glass_floor", 1 ] ], + "feature_flag_settings": { "blacklist": [ ], "whitelist": [ "NETHER_ABYSS" ] }, + "//": "ignored", + "connections": { + "intra_city_road_connection": "local_road", + "inter_city_road_connection": "local_road", + "trail_connection": "forest_trail", + "sewer_connection": "sewer_tunnel", + "subway_connection": "subway_tunnel", + "rail_connection": "local_railroad" + } + } +] diff --git a/data/mods/MindOverMatter/effectoncondition/conditions_for_eocs.json b/data/mods/MindOverMatter/effectoncondition/conditions_for_eocs.json index 445478d452857..02b01d0b1ac67 100644 --- a/data/mods/MindOverMatter/effectoncondition/conditions_for_eocs.json +++ b/data/mods/MindOverMatter/effectoncondition/conditions_for_eocs.json @@ -131,9 +131,7 @@ { "u_near_om_location": "nether_glass_deep", "range": 2 }, { "u_near_om_location": "nether_glass", "range": 2 }, { "u_at_om_location": "microlab_portal_elevator_nether_glass" }, - { "u_near_om_location": "void_spider_lair_entrance", "range": 2 }, - { "u_near_om_location": "void_spider_lair_a1", "range": 2 }, - { "u_near_om_location": "void_spider_lair_a2", "range": 2 }, + { "u_near_om_location": "void_spider_lair", "range": 2 }, { "and": [ { "math": [ "u_val('pos_z') == 6" ] }, { "not": "u_is_outside" }, { "u_is_on_terrain": "t_floor_warped" } ] } diff --git a/data/mods/TEST_DATA/overmap_terrain_coverage_test/overmap_terrain_coverage_whitelist.json b/data/mods/TEST_DATA/overmap_terrain_coverage_test/overmap_terrain_coverage_whitelist.json index 47ea051aa3d11..9770e722fdfc0 100644 --- a/data/mods/TEST_DATA/overmap_terrain_coverage_test/overmap_terrain_coverage_whitelist.json +++ b/data/mods/TEST_DATA/overmap_terrain_coverage_test/overmap_terrain_coverage_whitelist.json @@ -56,7 +56,8 @@ "pottery_cottage_field_2nd", "pottery_cottage_field_roof", "pottery_cottage_field", - "pottery_cottage_basement" + "pottery_cottage_basement", + "void_spider_lair" ] } ] diff --git a/doc/JSON/MONSTERS.md b/doc/JSON/MONSTERS.md index 74a2392672736..7f7aa1a24730a 100644 --- a/doc/JSON/MONSTERS.md +++ b/doc/JSON/MONSTERS.md @@ -531,7 +531,7 @@ How the monster behaves on death. "corpse_type": "NORMAL", // can be: BROKEN, NO_CORPSE, NORMAL (default) "message": "The %s dies!", // substitute %s for the monster's name. "effect": { "id": "death_boomer", "hit_self": true }, // the spell that gets called when the monster dies. follows the syntax of fake_spell. - "eoc": "debug_eoc_message", // eoc that would be run when monster dies. Alpha talker is monster, beta talker is player (always). + "eoc": "debug_eoc_message", // eoc that would be run when monster dies. Alpha talker is the killer (if it exists), beta talker is the monster. Check for "has_alpha" if you plan to use it. } ``` diff --git a/doc/JSON/MONSTER_SPECIAL_ATTACKS.md b/doc/JSON/MONSTER_SPECIAL_ATTACKS.md index ea2934416646f..7fbe88b40c05e 100644 --- a/doc/JSON/MONSTER_SPECIAL_ATTACKS.md +++ b/doc/JSON/MONSTER_SPECIAL_ATTACKS.md @@ -322,3 +322,15 @@ A special defense attack, triggered when the monster is attacked. It should con - ```ACIDSPLASH``` Splashes acid on the attacker. - ```NONE``` No special attack to the attacker. - ```ZAPBACK``` Shocks attacker on hit. + +## EOC attack + +Triggers the specified `effect_on_condition` with the monster as `alpha_talker` and its target as `beta_talker`, the attack requires vision of the target. + +| Field | Description | +| --- | ---------------------------------------------------------------------------------------------------------- | +| `range` | (Required) Float, maximal range of the jump. Respects circular distance setting! | +| `cooldown` | Disregard target location entirely when leaping, leading to completely random jumps. | +| `eoc` | (Required) Array of ids, the effect on condition . See `NPCs.md` | +| `condition` | Object, dialogue conditions enabling the attack. See `NPCs.md` for the possible conditions, `u` refers to the monster. | +| `allow_no_target` | Default `false`. If true the script will always run, the beta talker will be discarded. | diff --git a/src/mattack_actors.cpp b/src/mattack_actors.cpp index 3c802e4b96fd9..d17a2bceab453 100644 --- a/src/mattack_actors.cpp +++ b/src/mattack_actors.cpp @@ -276,6 +276,66 @@ bool leap_actor::call( monster &z ) const return true; } +std::unique_ptr mon_eoc_actor::clone() const +{ + return std::make_unique( *this ); +} + +void mon_eoc_actor::load_internal( const JsonObject &obj, const std::string & ) +{ + + optional( obj, was_loaded, "range", range, 1 ); + optional( obj, was_loaded, "eoc", eoc ); + allow_no_target = obj.get_bool( "allow_no_target", false ); + + if( obj.has_member( "condition" ) ) { + read_condition( obj, "condition", condition, false ); + has_condition = true; + } + +} + +bool mon_eoc_actor::call( monster &mon ) const +{ + map &here = get_map(); + Creature *target = ( allow_no_target ) ? nullptr : mon.attack_target(); + + if( !mon.can_act() ) { + return false; + } + + + if( !mon.attack_target() && !allow_no_target ) { + // this is an attack. there is no reason to attack if there isn't a real target. + // Unless we don't need one + return false; + } + if( has_condition ) { + dialogue d( get_talker_for( &mon ), + allow_no_target ? nullptr : get_talker_for( target ) ); + if( !condition( d ) ) { + add_msg_debug( debugmode::DF_MATTACK, "Attack conditionals failed" ); + return false; + } + } + + if( range > 1 && !allow_no_target ) { + if( !mon.sees( here, *target ) || + rl_dist( mon.pos_bub(), target->pos_bub() ) > range ) { + return false; + } + } + + { + for( const effect_on_condition_id &eoc : eoc ) { + dialogue d( get_talker_for( mon ), + allow_no_target ? nullptr : get_talker_for( target ) ); + eoc->activate( d ); + } + return true; + } +} + std::unique_ptr mon_spellcasting_actor::clone() const { return std::make_unique( *this ); diff --git a/src/mattack_actors.h b/src/mattack_actors.h index 88f3c0e709392..39b47046b61fd 100644 --- a/src/mattack_actors.h +++ b/src/mattack_actors.h @@ -80,6 +80,22 @@ class mon_spellcasting_actor : public mattack_actor std::unique_ptr clone() const override; }; +class mon_eoc_actor : public mattack_actor +{ + public: + int range = 1; + bool allow_no_target = false; + std::vector eoc; + + mon_eoc_actor() = default; + ~mon_eoc_actor() override = default; + + void load_internal( const JsonObject &obj, const std::string &src ) override; + bool call( monster & ) const override; + std::unique_ptr clone() const override; + +}; + struct grab { // Intensity of grab effect applied, defaults to the monster's defined grab_strength unless specified int grab_strength; diff --git a/src/monstergenerator.cpp b/src/monstergenerator.cpp index dbc51ca5bdadd..af34302903550 100644 --- a/src/monstergenerator.cpp +++ b/src/monstergenerator.cpp @@ -1326,6 +1326,8 @@ mtype_special_attack MonsterGenerator::create_actor( const JsonObject &obj, new_attack = std::make_unique(); } else if( attack_type == "spell" ) { new_attack = std::make_unique(); + } else if( attack_type == "eoc" ) { + new_attack = std::make_unique(); } else if( attack_type == "invalid" ) { new_attack = std::make_unique(); } else {