diff --git a/_maps/map_files/generic/centcomm.dmm b/_maps/map_files/generic/centcomm.dmm index ae1be9f66b73..b9ddf7c0f50e 100644 --- a/_maps/map_files/generic/centcomm.dmm +++ b/_maps/map_files/generic/centcomm.dmm @@ -7674,6 +7674,10 @@ icon_state = "darkyellow" }, /area/centcom/suppy) +"Bv" = ( +/obj/structure/stone_tile/slab/cracked, +/turf/simulated/floor/plating/lava/smooth/lava_land_surface, +/area/ruin/space/bubblegum_arena) "Bw" = ( /obj/structure/ninjatele{ pixel_x = -28 @@ -8682,6 +8686,10 @@ icon_state = "whiteblue" }, /area/centcom/control) +"Fk" = ( +/obj/structure/stone_tile/slab/burnt, +/turf/simulated/floor/plating/lava/smooth/lava_land_surface, +/area/ruin/space/bubblegum_arena) "Fm" = ( /obj/structure/chair/sofa/corp{ dir = 4 @@ -9375,6 +9383,10 @@ /obj/structure/curtain/open/shower, /turf/simulated/floor/plasteel/freezer, /area/ghost_bar) +"HF" = ( +/obj/effect/landmark/spawner/bubblegum_arena, +/turf/simulated/floor/indestructible/necropolis, +/area/ruin/space/bubblegum_arena) "HH" = ( /obj/effect/decal/warning_stripes/north, /turf/simulated/floor/wood, @@ -9419,6 +9431,9 @@ /obj/item/gun/energy/immolator/multi, /turf/simulated/floor/mineral/plastitanium/red, /area/shuttle/gamma/space) +"HN" = ( +/turf/simulated/floor/indestructible/necropolis, +/area/ruin/space/bubblegum_arena) "HO" = ( /obj/structure/chair/sofa/corp/right, /turf/simulated/floor/transparent/glass, @@ -10630,6 +10645,9 @@ /obj/effect/mapping_helpers/airlock/access/any/security/doors, /turf/simulated/floor/plasteel, /area/shuttle/escape) +"LV" = ( +/turf/simulated/floor/plating/lava/smooth/lava_land_surface, +/area/ruin/space/bubblegum_arena) "LX" = ( /obj/structure/chair/sofa/corp/left{ dir = 8 @@ -12636,6 +12654,9 @@ icon_state = "vault" }, /area/centcom/specops) +"SL" = ( +/turf/simulated/wall/indestructible/necropolis, +/area/ruin/space/bubblegum_arena) "SN" = ( /obj/structure/reagent_dispensers/fueltank/chem{ pixel_x = -32 @@ -13426,6 +13447,12 @@ }, /turf/simulated/floor/transparent/glass, /area/centcom/specops) +"Wg" = ( +/obj/structure/stone_tile/surrounding/burnt, +/obj/structure/stone_tile/center/burnt, +/obj/effect/landmark/spawner/bubblegum, +/turf/simulated/floor/plating/lava/smooth/lava_land_surface, +/area/ruin/space/bubblegum_arena) "Wh" = ( /turf/simulated/floor/plasteel{ dir = 8; @@ -64493,39 +64520,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL aN aN aN @@ -64750,39 +64777,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -65007,39 +65034,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +LV +LV +LV +LV +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +LV +LV +LV +LV +HN +SL aN aN aN @@ -65264,39 +65291,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +LV +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HF +HN +HN +HN +HN +HN +HN +HN +HN +HN +LV +HN +SL aN aN aN @@ -65521,39 +65548,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +LV +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +LV +HN +SL aN aN aN @@ -65778,39 +65805,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +LV +HN +HN +HN +HN +HN +HF +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +LV +HN +SL aN aN aN @@ -66035,39 +66062,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -66292,39 +66319,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -66549,39 +66576,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -66806,39 +66833,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HF +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -67063,39 +67090,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -67320,39 +67347,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -67577,39 +67604,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HF +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -67834,39 +67861,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -68091,39 +68118,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +Fk +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HF +HN +HN +HN +SL aN aN aN @@ -68348,39 +68375,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +Fk +Fk +Fk +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -68605,39 +68632,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +Bv +Bv +Fk +Fk +Fk +HN +HN +HN +HN +HN +HN +HN +HN +HN +HF +HN +HN +HN +SL aN aN aN @@ -68862,39 +68889,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +Bv +Bv +Bv +Wg +Fk +Fk +Fk +HN +HN +HN +HN +HN +HN +HN +HN +HF +HN +HN +HN +SL aN aN aN @@ -69119,39 +69146,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +Bv +Bv +Bv +Bv +Fk +HN +HN +HN +HN +HN +HN +HN +HN +HN +HF +HN +HN +HN +SL aN aN aN @@ -69376,39 +69403,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +Fk +Fk +Bv +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -69633,39 +69660,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +Fk +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -69890,39 +69917,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -70147,39 +70174,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HF +HN +HN +HN +SL aN aN aN @@ -70404,39 +70431,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HF +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -70661,39 +70688,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -70918,39 +70945,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -71175,39 +71202,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -71432,39 +71459,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HF +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -71689,39 +71716,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +LV +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +LV +HN +SL aN aN aN @@ -71946,39 +71973,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +LV +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +LV +HN +SL aN aN aN @@ -72203,39 +72230,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +LV +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HF +HN +HN +HN +HN +HN +HN +HN +HF +HN +HN +HN +HN +HN +HN +LV +HN +SL aN aN aN @@ -72460,39 +72487,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +LV +LV +LV +LV +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +LV +LV +LV +LV +HN +SL aN aN aN @@ -72717,39 +72744,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +HN +SL aN aN aN @@ -72974,39 +73001,39 @@ aN aN aN aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN -aN +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL +SL aN aN aN diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 0b91efc8ca70..2f9617e72037 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -344,7 +344,7 @@ #define COMSIG_MOB_ITEM_ATTACK "mob_item_attack" #define COMPONENT_ITEM_NO_ATTACK (1<<0) ///from base of /mob/living/proc/apply_damage(): (damage, damagetype, def_zone) -#define COMSIG_MOB_APPLY_DAMGE "mob_apply_damage" +#define COMSIG_MOB_APPLY_DAMAGE "mob_apply_damage" ///from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters) #define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack" ///from base of obj/item/attack_qdeleted(): (atom/target, mob/user, proxiumity_flag, click_parameters) @@ -500,6 +500,8 @@ // /mob/living/simple_animal/hostile signals #define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget" #define COMPONENT_HOSTILE_NO_ATTACK (1<<0) +//Called when a /mob/living/simple_animal/hostile fines a new target: (atom/source, give_target) +#define COMSIG_HOSTILE_FOUND_TARGET "comsig_hostile_found_target" // /obj signals diff --git a/code/__DEFINES/misc_defines.dm b/code/__DEFINES/misc_defines.dm index 693598362a8f..61a051fefca9 100644 --- a/code/__DEFINES/misc_defines.dm +++ b/code/__DEFINES/misc_defines.dm @@ -553,6 +553,8 @@ #define CLASSIC_CAVES "Classic Caves" #define DEADLY_DEEPROCK "Deadly Deeprock" +///Sleep check QDEL. Like sleep check death, but checks deleting. Good for non mobs. +#define SLEEP_CHECK_QDEL(X) sleep(X); if(QDELETED(src)) return; // Request console message priority defines #define RQ_NONEW_MESSAGES 0 // RQ_NONEWMESSAGES = no new message diff --git a/code/__DEFINES/sound_defines.dm b/code/__DEFINES/sound_defines.dm index 0aa85d3ccd9c..2a719176b670 100644 --- a/code/__DEFINES/sound_defines.dm +++ b/code/__DEFINES/sound_defines.dm @@ -10,13 +10,14 @@ #define CHANNEL_FIREALARM 1016 //fire alarm alarms #define CHANNEL_ASH_STORM 1015 #define CHANNEL_RADIO_NOISE 1014 // radio headset noise +#define CHANNEL_BOSS_MUSIC 1013 #define USER_VOLUME(M, C) M?.client?.prefs.get_channel_volume(C) //THIS SHOULD ALWAYS BE THE LOWEST ONE! //KEEP IT UPDATED -#define CHANNEL_HIGHEST_AVAILABLE 1013 +#define CHANNEL_HIGHEST_AVAILABLE 1012 #define MAX_INSTRUMENT_CHANNELS (128 * 6) diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index add6fb00ba91..2c188e81e405 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -102,8 +102,11 @@ #define STATUS_EFFECT_CRYO_BEAM /datum/status_effect/cryo_beam //Chills target, freezes reagents in their blood, breaks if sight is lost. +#define STATUS_EFFECT_BUBBLEGUM_CURSE /datum/status_effect/bubblegum_curse //Bleeding. Damage over time. Fog. And, of course, a suprise for people that try to run away. + #define STATUS_BOOKWYRM /datum/status_effect/bookwyrm + //#define STATUS_EFFECT_NECROPOLIS_CURSE /datum/status_effect/necropolis_curse //#define CURSE_BLINDING 1 //makes the edges of the target's screen obscured //#define CURSE_SPAWNING 2 //spawns creatures that attack the target only diff --git a/code/__HELPERS/filters.dm b/code/__HELPERS/filters.dm index b7de92661161..b9a89f4d33aa 100644 --- a/code/__HELPERS/filters.dm +++ b/code/__HELPERS/filters.dm @@ -320,6 +320,6 @@ GLOBAL_LIST_INIT(master_filter_info, list( in_atom.remove_filter("wibbly-[i]") /// Used to create rays on an item. Make sure to removefilter("rays") when done with it -/atom/proc/ray_filter_helper(_priority = 1, _size = 40, _color = "#FFFFFF", _factor = 6, _density = 20) - add_filter(name = "ray", priority = _priority, params = list(type = "rays", size = _size, color = _color , factor = _factor, density = _density)) +/atom/proc/ray_filter_helper(_priority = 1, _size = 40, _color = "#FFFFFF", _factor = 6, _density = 20, _y = 0) + add_filter(name = "ray", priority = _priority, params = list(type = "rays", size = _size, color = _color , factor = _factor, density = _density, y = _y)) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 2c2af7b7691a..2bb8c5ab2f72 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1593,17 +1593,21 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) y = t_center.y + c_dist - 1 x = t_center.x + c_dist + var/list/temp_list_one = list() for(y in t_center.y-c_dist to y) T = locate(x,y,t_center.z) if(T) - L += T + temp_list_one += T + L += reverselist(temp_list_one) y = t_center.y - c_dist x = t_center.x + c_dist - 1 + var/list/temp_list_two = list() for(x in t_center.x-c_dist to x) T = locate(x,y,t_center.z) if(T) - L += T + temp_list_two += T + L += reverselist(temp_list_two) y = t_center.y - c_dist + 1 x = t_center.x - c_dist @@ -2054,6 +2058,8 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) return "Ash Storms" if(CHANNEL_RADIO_NOISE) return "Radio Noise" + if(CHANNEL_BOSS_MUSIC) + return "Boss Music" /proc/slot_bitfield_to_slot(input_slot_flags) // Kill off this garbage ASAP; slot flags and clothing flags should be IDENTICAL. GOSH DARN IT. Doesn't work with ears or pockets, either. switch(input_slot_flags) diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index 49a45597902d..aa4d3b8a42c7 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -104,6 +104,11 @@ icon_state = "payback" show_when_dead = TRUE +/obj/screen/fullscreen/fog + icon = 'icons/mob/screen_fog.dmi' + icon_state = "fog" + color = "#FF0000" + /obj/screen/fullscreen/flash icon = 'icons/mob/screen_gen.dmi' screen_loc = "WEST,SOUTH to EAST,NORTH" diff --git a/code/datums/beam.dm b/code/datums/beam.dm index 15bc2711bbee..d40051220839 100644 --- a/code/datums/beam.dm +++ b/code/datums/beam.dm @@ -131,6 +131,11 @@ ..() A.ex_act(1) +/obj/effect/ebeam/vetus/Destroy() + for(var/mob/living/M in get_turf(src)) + M.electrocute_act(20, "the giant arc", flags = SHOCK_NOGLOVES) //fuck your gloves. + return ..() + /obj/effect/ebeam/disintegration_telegraph alpha = 100 layer = ON_EDGED_TURF_LAYER diff --git a/code/datums/components/boss_music.dm b/code/datums/components/boss_music.dm new file mode 100644 index 000000000000..85af91c4d5e1 --- /dev/null +++ b/code/datums/components/boss_music.dm @@ -0,0 +1,70 @@ +/** + * Attaches to a hostile simplemob and plays that music while they have a target. + */ +/datum/component/boss_music + ///The music track we will play to players. + var/boss_track + ///How long the track is, used to clear players out when the music is supposed to end. + var/track_duration + + ///List of all mobs listening to the boss music currently. Cleared on Destroy or after `track_duration`. + var/list/players_listening_uids = list() + ///List of callback timers, used to clear out mobs listening to boss music after `track_duration`. + var/list/music_callbacks = list() + +/datum/component/boss_music/Initialize(boss_track, track_duration) + . = ..() + if(!ishostile(parent)) + return COMPONENT_INCOMPATIBLE + src.boss_track = boss_track + src.track_duration = track_duration + +/datum/component/boss_music/Destroy(force, silent) + . = ..() + for(var/callback in music_callbacks) + deltimer(callback) + music_callbacks = null + + for(var/player_refs in players_listening_uids) + clear_target(player_refs) + players_listening_uids = null + +/datum/component/boss_music/RegisterWithParent() + . = ..() + RegisterSignal(parent, COMSIG_HOSTILE_FOUND_TARGET, PROC_REF(on_target_found)) + +/datum/component/boss_music/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_HOSTILE_FOUND_TARGET) + return ..() + +///Handles giving the boss music to a new target the fauna has recieved. +///Keeps track of them to not repeatedly overwrite its own track. +/datum/component/boss_music/proc/on_target_found(atom/source, mob/new_target) + SIGNAL_HANDLER + if(QDELETED(source) || !istype(new_target)) + return + + var/target_uid = new_target.UID() + if(target_uid in players_listening_uids) + return + + players_listening_uids += target_uid + RegisterSignal(new_target, COMSIG_MOB_DEATH, PROC_REF(on_mob_death)) + music_callbacks += addtimer(CALLBACK(src, PROC_REF(clear_target), target_uid), track_duration, TIMER_STOPPABLE) + new_target.playsound_local(new_target, boss_track, 200, FALSE, channel = CHANNEL_BOSS_MUSIC, pressure_affected = FALSE, use_reverb = FALSE) + +///Called when a mob listening to boss music dies- ends their music early. +/datum/component/boss_music/proc/on_mob_death(mob/living/source) + SIGNAL_HANDLER + var/target_uid = source.UID() + clear_target(target_uid) + +///Removes `old_target` from the list of players listening, and stops their music if it is still playing. +///This allows them to have music played again if they re-enter combat with this fauna. +/datum/component/boss_music/proc/clear_target(incoming_uid) + players_listening_uids -= incoming_uid + + var/mob/old_target = locateUID(incoming_uid) + if(old_target) + UnregisterSignal(old_target, COMSIG_MOB_DEATH) + old_target.stop_sound_channel(CHANNEL_BOSS_MUSIC) diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 757095315be5..4a56b018a94f 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -985,3 +985,135 @@ owner.reagents.remove_reagent(R.id, 0.75) if(prob(10)) to_chat(owner, "Your blood freezes in your veins, get away!") + +/datum/status_effect/bubblegum_curse + id = "bubblegum curse" + alert_type = /obj/screen/alert/status_effect/bubblegum_curse + duration = -1 //Kill it. There is no other option. + tick_interval = 1 SECONDS + /// The damage the status effect does per tick. + var/damage = 0.75 + var/source_UID + /// Are we starting the process to check if the person has still gotten out of range of bubble / crossed zlvls. + var/coward_checking = FALSE + +/datum/status_effect/bubblegum_curse/on_creation(mob/living/new_owner, mob/living/source) + . = ..() + source_UID = source.UID() + owner.overlay_fullscreen("Bubblegum", /obj/screen/fullscreen/fog, 1) + +/datum/status_effect/bubblegum_curse/tick() + var/mob/living/simple_animal/hostile/megafauna/bubblegum/attacker = locateUID(source_UID) + if(!attacker) + qdel(src) + if(attacker.health <= attacker.maxHealth / 2) + owner.clear_fullscreen("Bubblegum") + owner.overlay_fullscreen("Bubblegum", /obj/screen/fullscreen/fog, 2) + if(!coward_checking) + if(owner.z != attacker.z) + addtimer(CALLBACK(src, PROC_REF(onstation_coward_callback)), 12 SECONDS) + coward_checking = TRUE + else if(get_dist(attacker, owner) >= 25) + addtimer(CALLBACK(src, PROC_REF(runaway_coward_callback)), 12 SECONDS) + coward_checking = TRUE + + owner.apply_damage(damage, BRUTE) + if(ishuman(owner)) + var/mob/living/carbon/human/H = owner + H.bleed(0.33) + if(prob(5)) + to_chat(owner, "[pick("You feel your sins crawling on your back.", "You felt your sins weighing on your neck.", "You feel your blood pulsing inside you.", "YOU'LL NEVER ESCAPE ME", "YOU'LL DIE FOR INSULTING ME LIKE THIS")]") + +/datum/status_effect/bubblegum_curse/on_remove() + owner.clear_fullscreen("Bubblegum") + +/datum/status_effect/bubblegum_curse/proc/onstation_coward_callback() + coward_checking = FALSE + var/mob/living/simple_animal/hostile/megafauna/bubblegum/attacker = locateUID(source_UID) + if(owner.z != attacker.z) + to_chat(owner, "YOU CHALLENGE ME LIKE THIS... AND YOU RUN WITH YOUR FALSE MAGICS?") + else + return + SLEEP_CHECK_QDEL(2 SECONDS) + to_chat(owner, "REALLY?") + SLEEP_CHECK_QDEL(2 SECONDS) + to_chat(owner, "SUCH INSOLENCE!") + SLEEP_CHECK_QDEL(2 SECONDS) + to_chat(owner, "SO PATHETIC...") + SLEEP_CHECK_QDEL(2 SECONDS) + to_chat(owner, "...SO FOOLISH!") + get_over_here() + +/datum/status_effect/bubblegum_curse/proc/runaway_coward_callback() + coward_checking = FALSE + var/mob/living/simple_animal/hostile/megafauna/bubblegum/attacker = locateUID(source_UID) + if(get_dist(attacker, owner) >= 25) + to_chat(owner, "My my, you can run FAST.") + else + return + SLEEP_CHECK_QDEL(2 SECONDS) + to_chat(owner, "I thought you wanted a true fight?") + SLEEP_CHECK_QDEL(2 SECONDS) + to_chat(owner, "Perhaps I was mistaken.") + SLEEP_CHECK_QDEL(2 SECONDS) + to_chat(owner, "You are a coward who does not want a fight...") + SLEEP_CHECK_QDEL(2 SECONDS) + to_chat(owner, "...BUT I WANT YOU DEAD!") + get_over_here() + +/datum/status_effect/bubblegum_curse/proc/get_over_here() + var/mob/living/simple_animal/hostile/megafauna/bubblegum/attacker = locateUID(source_UID) + if(!attacker) + return //Let's not nullspace + var/turf/TA = get_turf(owner) + owner.Immobilize(3 SECONDS) + new /obj/effect/decal/cleanable/blood/bubblegum(TA) + new /obj/effect/temp_visual/bubblegum_hands/rightsmack(TA) + sleep(6) + var/turf/TB = get_turf(owner) + to_chat(owner, "[attacker] rends you!") + playsound(TB, attacker.attack_sound, 100, TRUE, -1) + owner.adjustBruteLoss(10) + new /obj/effect/decal/cleanable/blood/bubblegum(TB) + new /obj/effect/temp_visual/bubblegum_hands/leftsmack(TB) + sleep(6) + var/turf/TC = get_turf(owner) + to_chat(owner, "[attacker] rends you!") + playsound(TC, attacker.attack_sound, 100, TRUE, -1) + owner.adjustBruteLoss(10) + new /obj/effect/decal/cleanable/blood/bubblegum(TC) + new /obj/effect/temp_visual/bubblegum_hands/rightsmack(TC) + sleep(6) + var/turf/TD = get_turf(owner) + to_chat(owner, "[attacker] rends you!") + playsound(TD, attacker.attack_sound, 100, TRUE, -1) + owner.adjustBruteLoss(10) + new /obj/effect/temp_visual/bubblegum_hands/leftpaw(TD) + new /obj/effect/temp_visual/bubblegum_hands/leftthumb(TD) + sleep(8) + to_chat(owner, "[attacker] drags you through the blood!") + playsound(TD, 'sound/misc/enter_blood.ogg', 100, TRUE, -1) + var/turf/targetturf = get_step(attacker, attacker.dir) + owner.forceMove(targetturf) + playsound(targetturf, 'sound/misc/exit_blood.ogg', 100, TRUE, -1) + addtimer(CALLBACK(attacker, TYPE_PROC_REF(/mob/living/simple_animal/hostile/megafauna/bubblegum, FindTarget), list(owner), 1), 2) + +/obj/screen/alert/status_effect/bubblegum_curse + name = "I SEE YOU" + desc = "YOUR SOUL WILL BE MINE FOR YOUR INSOLENCE" + icon_state = "bubblegumjumpscare" + +/obj/screen/alert/status_effect/bubblegum_curse/Initialize(mapload) + . = ..() + START_PROCESSING(SSobj, src) + +/obj/screen/alert/status_effect/bubblegum_curse/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/screen/alert/status_effect/bubblegum_curse/process() + var/new_filter = isnull(get_filter("ray")) + ray_filter_helper(1, 40,"#ce3030", 6, 20) + if(new_filter) + animate(get_filter("ray"), offset = 10, time = 10 SECONDS, loop = -1) + animate(offset = 0, time = 10 SECONDS) diff --git a/code/game/area/areas/ruins/space_areas.dm b/code/game/area/areas/ruins/space_areas.dm index a58edec0be56..5e97afab6814 100644 --- a/code/game/area/areas/ruins/space_areas.dm +++ b/code/game/area/areas/ruins/space_areas.dm @@ -150,6 +150,9 @@ icon_state = "dark" requires_power = FALSE +/area/ruin/space/bubblegum_arena + name = "Bubblegum Arena" + /area/ruin/space/wreck_cargoship name = "Faint Signal" icon_state = "yellow" diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 5be01f245cbf..4d884a51ef8b 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -107,6 +107,18 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/awaystart) //Without this away mission /obj/effect/landmark/spawner/rev name = "revenantspawn" icon_state = "Rev" + +/obj/effect/landmark/spawner/bubblegum_arena + name = "bubblegum_arena_human" + icon_state = "Explorer" + +/obj/effect/landmark/spawner/bubblegum + name = "bubblegum_arena_bubblegum" + icon_state = "bubblegumjumpscare" + +/obj/effect/landmark/spawner/bubblegum_exit + name = "bubblegum_arena_exit" + icon_state = "bubblegumjumpscare" /obj/effect/landmark/spawner/syndie name = "Syndicate-Spawn" diff --git a/code/game/objects/items/devices/radio/radio_objects.dm b/code/game/objects/items/devices/radio/radio_objects.dm index e41bd366e03e..717c3e1e2430 100644 --- a/code/game/objects/items/devices/radio/radio_objects.dm +++ b/code/game/objects/items/devices/radio/radio_objects.dm @@ -61,7 +61,7 @@ GLOBAL_LIST_EMPTY(deadsay_radio_systems) /// How many times this is disabled by EMPs var/disable_timer = 0 /// Areas in which this radio cannot send messages - var/static/list/blacklisted_areas = list(/area/adminconstruction, /area/tdome) + var/static/list/blacklisted_areas = list(/area/adminconstruction, /area/tdome, /area/ruin/space/bubblegum_arena) flags = CONDUCT slot_flags = SLOT_FLAG_BELT diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 7b1065feada2..571c6f285e27 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -976,6 +976,16 @@ new /obj/item/stock_parts/matter_bin(src) new /obj/item/screwdriver(src) +/obj/item/storage/box/hardmode_box + name = "box of HRD-MDE project box" + desc = "Contains everything needed to get yourself killed for a medal." + +/obj/item/storage/box/hardmode_box/populate_contents() + for(var/I in 1 to 7) + new /obj/item/grenade/megafauna_hardmode(src) + new /obj/item/storage/lockbox/medal/hardmode_box(src) + new /obj/item/paper/hardmode(src) + #undef NODESIGN #undef NANOTRASEN #undef SYNDI diff --git a/code/game/objects/items/weapons/storage/lockbox.dm b/code/game/objects/items/weapons/storage/lockbox.dm index 68e090db9ca0..b3257d3587be 100644 --- a/code/game/objects/items/weapons/storage/lockbox.dm +++ b/code/game/objects/items/weapons/storage/lockbox.dm @@ -111,6 +111,37 @@ new /obj/item/clothing/accessory/medal/silver/valor(src) new /obj/item/clothing/accessory/medal/heart(src) +/obj/item/storage/lockbox/medal/hardmode_box + name = "\improper HRD-MDE program medal box" + desc = "A locked box used to store medals of pride. Use a fauna research disk on the box to transmit the data and print a medal." + req_access = list(ACCESS_MINING) //No grubby assistant hands on my hard earned medals + can_hold = list(/obj/item/clothing/accessory, /obj/item/coin) //Whoops almost gave miners boxes that could store 12 legion cores. Scoped to accessory if they want to store neclaces or hope or something in there. Or a coin collection. + var/list/completed_fauna = list() + var/number_of_megafauna = 7 //Increase this if new megafauna are added. + +/obj/item/storage/lockbox/medal/hardmode_box/Initialize(mapload) + . = ..() + number_of_megafauna = length(subtypesof(/obj/item/disk/fauna_research)) + +/obj/item/storage/lockbox/medal/hardmode_box/populate_contents() + return + +/obj/item/storage/lockbox/medal/hardmode_box/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/disk/fauna_research)) + var/obj/item/disk/fauna_research/disky = W + var/obj/item/pride = new disky.output(get_turf(src)) + to_chat(user, "[src] accepts [disky], and prints out [pride]!") + qdel(disky) + if(!is_type_in_list(pride, completed_fauna)) + completed_fauna += pride.type + if(length(completed_fauna) == number_of_megafauna) + to_chat(user, "[src] prints out a very fancy medal!") + var/obj/item/accomplishment = new /obj/item/clothing/accessory/medal/gold/heroism/hardmode_full(get_turf(src)) + user.put_in_hands(accomplishment) + user.put_in_hands(pride) + return + return ..() + /obj/item/storage/lockbox/t4 name = "lockbox (T4)" desc = "Contains three T4 breaching charges." diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index a8885ef65211..b5c6cf8253dc 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -89,6 +89,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts "1016" = 100, // CHANNEL_FIREALARM "1015" = 100, // CHANNEL_ASH_STORM "1014" = 100, // CHANNEL_RADIO_NOISE + "1013" = 100 // CHANNEL_BOSS_MUSIC ) /// The volume mixer save timer handle. Used to debounce the DB call to save, to avoid spamming. var/volume_mixer_saving = null diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm index 22388a01e975..b956d816a0ef 100644 --- a/code/modules/clothing/under/accessories/accessory.dm +++ b/code/modules/clothing/under/accessories/accessory.dm @@ -216,6 +216,7 @@ /obj/item/clothing/accessory/medal/gold/heroism name = "medal of exceptional heroism" desc = "An extremely rare golden medal awarded only by CentComm. To receive such a medal is the highest honor and as such, very few exist." + icon_state = "ion" // SILVER (awarded by Captain) @@ -277,8 +278,73 @@ icon_state = "bronze_heart" item_color = "bronze_heart" +// Plasma, from NT research departments. For now, used by the HRD-MDE project for the moderate 2 fauna, drake and hierophant. +/obj/item/clothing/accessory/medal/plasma + name = "plasma medal" + desc = "An eccentric medal made of plasma." + icon_state = "plasma" + item_color = "plasma" + materials = list(MAT_PLASMA = 1000) +/obj/item/clothing/accessory/medal/plasma/temperature_expose(datum/gas_mixture/air, temperature, volume) + ..() + if(temperature > T0C + 200) + burn_up() + +/obj/item/clothing/accessory/medal/plasma/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay) + . = ..() + burn_up() + +/obj/item/clothing/accessory/medal/plasma/proc/burn_up() + var/turf/simulated/T = get_turf(src) + if(istype(T)) + T.atmos_spawn_air(LINDA_SPAWN_HEAT | LINDA_SPAWN_TOXINS | LINDA_SPAWN_OXYGEN, 10) //Technically twice as much plasma as it should spawn but a little more never hurt anyone. + visible_message("[src] bursts into flame!") + qdel(src) + +// Alloy, for the vetus speculator, or abductors I guess. + +/obj/item/clothing/accessory/medal/alloy + name = "alloy medal" + desc = "An eccentric medal made of some strange alloy." + icon_state = "alloy" + item_color = "alloy" + materials = list(MAT_METAL = 500, MAT_PLASMA = 500) + +// Mostly mining medals past here + +/obj/item/clothing/accessory/medal/gold/bubblegum + name = "bubblegum HRD-MDE award" + desc = "An award which represents magnificant contributions to the HRD-MDE project in the form of analysing Bubblegum, and the related blood space." + +/obj/item/clothing/accessory/medal/gold/heroism/hardmode_full //Kill every hardmode boss. In a shift. Good luck. + name = "medal of incredible dedication" + desc = "An extremely rare golden medal awarded only by CentComm. This medal was issued for miners who went above and beyond for the HRD-MDE project. Engraved on it is the phrase 'mori quam foedari'..." + +/obj/item/clothing/accessory/medal/silver/colossus + name = "colossus HRD-MDE award" + desc = "An award which represents major contributions to the HRD-MDE project in the form of analysing a colossus." + +/obj/item/clothing/accessory/medal/silver/legion + name = "legion HRD-MDE award" + desc = "An award which represents major contributions to the HRD-MDE project in the form of analysing the Legion." + +/obj/item/clothing/accessory/medal/blood_drunk + name = "blood drunk HRD-MDE award" + desc = "A award which represents minor contributions to the HRD-MDE project in the form of analysing the blood drunk miner." + +/obj/item/clothing/accessory/medal/plasma/hierophant + name = "hierophant HRD-MDE award" + desc = "An award which represents moderate contributions to the HRD-MDE project in the form of analysing the Hierophant." + +/obj/item/clothing/accessory/medal/plasma/ash_drake + name = "ash drake HRD-MDE award" + desc = "An award which represents moderate contributions to the HRD-MDE project in the form of analysing an ash drake." + +/obj/item/clothing/accessory/medal/alloy/vetus + name = "vetus speculator HRD-MDE award" + desc = "An award which represents major contributions to the HRD-MDE project in the form of analysing the Vetus Speculator." /* Holobadges are worn on the belt or neck, and can be used to show that the holder is an authorized diff --git a/code/modules/mining/equipment/hardmode_grenade.dm b/code/modules/mining/equipment/hardmode_grenade.dm new file mode 100644 index 000000000000..32eee7eb2630 --- /dev/null +++ b/code/modules/mining/equipment/hardmode_grenade.dm @@ -0,0 +1,79 @@ +/obj/item/grenade/megafauna_hardmode + name = "\improper HRD-MDE Scanning Grenade" + desc = "An advanced grenade that releases nanomachines, which enter nearby megafauna. This will enrage them greatly, but allows nanotrasen to fully research their abilities." + icon = 'icons/obj/grenade.dmi' + icon_state = "enrager" + item_state = "grenade" + +/obj/item/grenade/megafauna_hardmode/prime() + update_mob() + playsound(loc, 'sound/effects/empulse.ogg', 50, TRUE) + for(var/mob/living/simple_animal/hostile/megafauna/M in range(7, src)) + M.enrage() + visible_message("[M] begins to wake up as the nanomachines enter them, it looks pissed!") + qdel(src) + +/obj/item/paper/hardmode + name = "HRD-MDE Scanner Guide" + icon_state = "paper" + info = {"Welcome to the NT HRD-MDE Project
+
+ This guide will cover the basics on the Hi-tech Research and Development, Mining Department Experiment project.
+
+ These grenades when used, will disperse a cloud of nanomachines into nearbye fauna, allowing a detailed examination of their body structure when alive. We will use this data to develope new products to sell, and we need your help!
+
+ We need to see these fauna working at their full potential with the nanomachines in them, so you will have to fight them. As a warning, these nanomachines have been known to irratate and annoy animals in testing, as well injecting a cocktail of drugs into them to get their organs outputting at maximum potential.
+
+ We operate on a limited budget, but we do provide payment for participating in this project: 0.1% of profits from any products made from this research, and medals showing off your pride for NT and promoting their research. +

+ By participating in this experiment you waive all rights for compensation of death on the job. +"} + + +/obj/item/disk/fauna_research + name = "empty HRD-MDE project disk" + desc = "A disk used by the HRD-MDE project. Seems empty?" + icon_state = "holodisk" + var/obj/item/clothing/accessory/medal/output + +/obj/item/disk/fauna_research/Initialize(mapload) + . = ..() + for(var/obj/structure/closet/C in get_turf(src)) + forceMove(C) + return + +/obj/item/disk/fauna_research/blood_drunk_miner + name = "blood drunk HRD-MDE project disk" + desc = "A disk used by the HRD-MDE project. Contains data on the dash and resistance of the blood drunk miner." + output = /obj/item/clothing/accessory/medal/blood_drunk + +/obj/item/disk/fauna_research/hierophant + name = "\improper Hierophant HRD-MDE project disk" + desc = "A disk used by the HRD-MDE project. Contains data on the energy manipulation and material composition of the Hierophant." + output = /obj/item/clothing/accessory/medal/plasma/hierophant + +/obj/item/disk/fauna_research/ash_drake + name = "ash drake HRD-MDE project disk" + desc = "A disk used by the HRD-MDE project. Contains data on the fire production methods and rapid regeneration of the ash drakes." + output = /obj/item/clothing/accessory/medal/plasma/ash_drake + +/obj/item/disk/fauna_research/vetus + name = "\improper Vetus Speculator HRD-MDE project disk" + desc = "A disk used by the HRD-MDE project. Contains data on the anomaly manipulation and computing processes of the Vetus Speculator." + output = /obj/item/clothing/accessory/medal/alloy/vetus + +/obj/item/disk/fauna_research/colossus + name = "colossus HRD-MDE project disk" + desc = "A disk used by the HRD-MDE project. Contains data on the powerful voice and A-T field of the colossi." + output = /obj/item/clothing/accessory/medal/silver/colossus + +/obj/item/disk/fauna_research/legion + name = "\improper Legion HRD-MDE project disk" + desc = "A disk used by the HRD-MDE project. Contains data on the endless regeneration and disintegration laser of the Legion." + output = /obj/item/clothing/accessory/medal/silver/legion + +/obj/item/disk/fauna_research/bubblegum + name = "\improper Bubblegum HRD-MDE project disk" + desc = "A disk used by the HRD-MDE project. Contains data on the bloodcrawling and \[REDACTED\] of Bubblegum." //I hate this so much + output = /obj/item/clothing/accessory/medal/gold/bubblegum + diff --git a/code/modules/mining/lavaland/loot/bubblegum_loot.dm b/code/modules/mining/lavaland/loot/bubblegum_loot.dm index 91c3d797f52b..b217e2a7d332 100644 --- a/code/modules/mining/lavaland/loot/bubblegum_loot.dm +++ b/code/modules/mining/lavaland/loot/bubblegum_loot.dm @@ -13,6 +13,76 @@ . = ..() new /obj/item/crusher_trophy/demon_claws(src) +/obj/structure/closet/crate/necropolis/bubblegum/bait/populate_contents() + return + +/obj/structure/closet/crate/necropolis/bubblegum/bait/open(by_hand) + . = ..() + for(var/obj/effect/bubblegum_trigger/B in contents) + B.targets_to_fuck_up += usr + B.activate() + +/obj/effect/bubblegum_trigger + var/list/targets_to_fuck_up = list() + +/obj/effect/bubblegum_trigger/Initialize(mapload, target_list) + . = ..() + addtimer(CALLBACK(src, PROC_REF(activate)), 15 SECONDS) //We try to auto engage the fun 15 seconds after death, or when manually opened, whichever comes first. If for some strange reason the target list is empty, we'll trigger when opened + targets_to_fuck_up = target_list + +/obj/effect/bubblegum_trigger/proc/activate() + if(!length(targets_to_fuck_up)) + return + var/spawn_locs = list() + for(var/obj/effect/landmark/spawner/bubblegum_arena/R in GLOB.landmarks_list) + spawn_locs += get_turf(R) + for(var/mob/living/M in targets_to_fuck_up) + var/turf/T = get_turf(M) + M.Immobilize(1 SECONDS) + to_chat(M, "NO! I REFUSE TO LET YOU THINK YOU HAVE WON. I SHALL END YOUR INSIGNIFICANT LIFE!") + new /obj/effect/temp_visual/bubblegum_hands/leftpaw(T) + new /obj/effect/temp_visual/bubblegum_hands/leftthumb(T) + sleep(8) + playsound(T, 'sound/misc/enter_blood.ogg', 100, TRUE, -1) + var/turf/target_turf = pick(spawn_locs) + M.forceMove(target_turf) + playsound(target_turf, 'sound/misc/exit_blood.ogg', 100, TRUE, -1) + for(var/obj/effect/landmark/spawner/bubblegum/B in GLOB.landmarks_list) + new /mob/living/simple_animal/hostile/megafauna/bubblegum/round_2(get_turf(B)) + + +/obj/effect/bubblegum_exit/Initialize(mapload, target_list) + . = ..() + addtimer(CALLBACK(src, PROC_REF(activate)), 10 SECONDS) + +/obj/effect/bubblegum_exit/proc/activate() + var/spawn_exit = list() + for(var/obj/effect/landmark/spawner/bubblegum_exit/E in GLOB.landmarks_list) + for(var/turf/T in range(4, E)) + if(T.density) + continue + spawn_exit += get_turf(T) + var/area/probably_bubblearena = get_area(src) + for(var/mob/living/M in probably_bubblearena) + var/turf/T = get_turf(M) + M.Immobilize(1 SECONDS) + to_chat(M, "Now... get out of my home.") + new /obj/effect/temp_visual/bubblegum_hands/leftpaw(T) + new /obj/effect/temp_visual/bubblegum_hands/leftthumb(T) + sleep(8) + playsound(T, 'sound/misc/enter_blood.ogg', 100, TRUE, -1) + var/turf/target_turf = pick(spawn_exit) + M.forceMove(target_turf) + playsound(target_turf, 'sound/misc/exit_blood.ogg', 100, TRUE, -1) + for(var/obj/O in probably_bubblearena) //Mobs are out, lets get items / limbs / brains. Lets also exclude blood.. + if(iseffect(O)) + continue + if(istype(O, /obj/structure/stone_tile)) //Taking the tiles from the arena is funny, but a bit stupid + continue + var/turf/target_turf = pick(spawn_exit) + O.forceMove(target_turf) + + // Mayhem /obj/item/mayhem diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm index 43539bc563e8..19321fad7a7d 100644 --- a/code/modules/mining/machine_vending.dm +++ b/code/modules/mining/machine_vending.dm @@ -91,6 +91,7 @@ EQUIPMENT("Soap", /obj/item/soap/nanotrasen, 200), EQUIPMENT("Space Cash", /obj/item/stack/spacecash/c200, 2000), EQUIPMENT("Whiskey", /obj/item/reagent_containers/food/drinks/bottle/whiskey, 100), + EQUIPMENT("HRD-MDE Project Box", /obj/item/storage/box/hardmode_box, 5000) //I want miners have to pay a lot to get this, but be set once they do. ) prize_list["Extra"] = list() // Used in child vendors diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index fc18091e6e08..ed47d4a0bed3 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -9,6 +9,7 @@ standard 0 if fail */ /mob/living/proc/apply_damage(damage = 0, damagetype = BRUTE, def_zone, blocked = 0, sharp = FALSE, used_weapon, spread_damage = FALSE) + SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMAGE, damage, damagetype, def_zone) var/hit_percent = (100 - blocked) / 100 if(!damage || (hit_percent <= 0)) return FALSE diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 988454694eb9..a429d1c22950 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -235,6 +235,7 @@ return FALSE /mob/living/simple_animal/hostile/proc/GiveTarget(new_target)//Step 4, give us our selected target + SEND_SIGNAL(src, COMSIG_HOSTILE_FOUND_TARGET, new_target) target = new_target LosePatience() if(target != null) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/ancient_robot.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/ancient_robot.dm index 92b16aa46d2d..b11bf9f1d407 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/ancient_robot.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/ancient_robot.dm @@ -1,4 +1,4 @@ -#define BODY_SHIELD_COOLDOWN_TIME 5 SECONDS +#define BODY_SHIELD_COOLDOWN_TIME enraged ? 3 SECONDS : 5 SECONDS #define EXTRA_PLAYER_ANGER_NORMAL_CAP 6 #define EXTRA_PLAYER_ANGER_STATION_CAP 3 #define BLUESPACE 1 @@ -167,6 +167,28 @@ Difficulty: Hard var/crate_type = pick(loot) var/obj/structure/closet/crate/C = new crate_type(loc) new core_type(C) + if(!enraged) + return + for(var/mob/living/M in urange(40, src)) //Bigger range, ran once per shift, as people run away from vetus as it blows up. + if(M.client) + new /obj/item/disk/fauna_research/vetus(C) + +/mob/living/simple_animal/hostile/megafauna/ancient_robot/enrage() + . = ..() + armour_penetration_percentage = 66 + TL.armour_penetration_percentage = 66 + TR.armour_penetration_percentage = 66 + BL.armour_penetration_percentage = 66 + BR.armour_penetration_percentage = 66 + +/mob/living/simple_animal/hostile/megafauna/ancient_robot/unrage() + . = ..() + armour_penetration_percentage = 50 + TL.armour_penetration_percentage = 50 + TR.armour_penetration_percentage = 50 + BL.armour_penetration_percentage = 50 + BR.armour_penetration_percentage = 50 + /mob/living/simple_animal/hostile/megafauna/ancient_robot/OpenFire() if(charging) @@ -178,6 +200,9 @@ Difficulty: Hard anger_modifier = clamp(((maxHealth - health) / 50), 0, 20) ranged_cooldown = world.time + (ranged_cooldown_time * ((10 - extra_player_anger) / 10)) + if(enraged && prob(20)) //This attack is free, and can be combined with other attacks, so chance is low. + single_laser() + if(prob(30 + (anger_modifier / 2))) //Less scaling as the weaker attack / first calculated. triple_charge() @@ -189,6 +214,33 @@ Difficulty: Hard calculate_extra_player_anger() +/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/single_laser() + say(pick("KTMGMK JOYIU OTLKXTU", "ROQK G OTZKXTGR JOYQ", "HO-JOXKIZOUTGR RGYKXY KTMGMKJ")) + new /obj/effect/vetus_laser(get_turf(src)) + +/obj/effect/vetus_laser + icon = 'icons/obj/tesla_engine/energy_ball.dmi' + icon_state = "energy_ball" + pixel_x = -32 + pixel_y = -32 + +/obj/effect/vetus_laser/Initialize(mapload) + . = ..() + var/newcolor = rgb(241, 137, 172) + add_atom_colour(newcolor, TEMPORARY_COLOUR_PRIORITY) + beam_it_up() + +/obj/effect/vetus_laser/ex_act(severity) + return + +/obj/effect/vetus_laser/proc/beam_it_up() + var/turf/beam_me_up_scotty = get_turf(src) + for(var/turf/T in spiral_range_turfs(9, src, 9)) + T.Beam(beam_me_up_scotty, icon_state = "sm_arc_dbz_referance", time = 0.1, beam_type = /obj/effect/ebeam/vetus) + SLEEP_CHECK_QDEL(1) + qdel(src) + + /mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/triple_charge() if(mode == BLUESPACE) charge(delay = 24) //An extra charge, to make up for the longer time between teleports @@ -201,10 +253,10 @@ Difficulty: Hard charge(delay = 3) SetRecoveryTime(15) -/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/charge(atom/chargeat = target, delay = 5, chargepast = 2) //add limb charge as well +/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/charge(atom/chargeat = target, delay = 5, chargepast = 2) if(!chargeat) return - if(mode == BLUESPACE) + if(mode == BLUESPACE || (enraged && prob(13))) new /obj/effect/temp_visual/bsg_kaboom(get_turf(src)) src.visible_message("[src] teleports somewhere nearby!") do_teleport(src, target, 7, sound_in = 'sound/effects/phasein.ogg', safe_turf_pick = TRUE) //Teleport within 7 tiles of the target @@ -253,7 +305,7 @@ Difficulty: Hard playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, TRUE) shake_camera(L, 4, 3) shake_camera(src, 2, 3) - if(mode == GRAV) + if(mode == GRAV || enraged) var/atom/throw_target = get_edge_target_turf(L, get_dir(src, get_step_away(L, src))) L.throw_at(throw_target, 3, 2) ..() @@ -303,7 +355,7 @@ Difficulty: Hard H.apply_status_effect(STATUS_EFFECT_BLUESPACESLOWDOWN) if(GRAV) visible_message("Debris from the battlefield begin to get compressed into rocks!") - var/list/turfs = new/list() + var/list/turfs = list() var/rocks = 0 for(var/turf/T in view(4, target)) if(T.density) @@ -311,14 +363,17 @@ Difficulty: Hard if(T in range (2, target)) continue turfs += T - while(rocks < 3 && length(turfs)) + var/amount = enraged ? 5 : 3 + while(rocks < amount && length(turfs)) var/turf/spot = pick_n_take(turfs) + if(!spot) + return new /obj/effect/temp_visual/rock(spot) addtimer(CALLBACK(src, PROC_REF(throw_rock), spot, target), 2 SECONDS) rocks++ if(PYRO) visible_message("The ground begins to heat up around you!") - var/list/turfs = new/list() + var/list/turfs = list() var/volcanos = 0 for(var/turf/T in view(4, target)) if(T.density) @@ -326,10 +381,13 @@ Difficulty: Hard if(T in range(1, target)) continue turfs += T - while(volcanos < 3 && length(turfs)) + var/amount = enraged ? 5 : 3 + while(volcanos < amount && length(turfs)) var/turf/spot = pick_n_take(turfs) + if(!spot) + return for(var/turf/around in range(1, spot)) - new /obj/effect/temp_visual/lava_warning(around) + new /obj/effect/temp_visual/lava_warning(around, enraged ? 18 SECONDS : 6 SECONDS) volcanos++ if(FLUX) for(var/mob/living/carbon/human/H in view(7, src)) @@ -345,7 +403,7 @@ Difficulty: Hard if(VORTEX) visible_message("[src] begins vibrate rapidly. It's causing an earthquake!") for(var/turf/turf in range(9,get_turf(target))) - if(prob(15)) + if(prob(enraged ? 40 : 15)) new /obj/effect/temp_visual/target/ancient(turf) if(CRYO) visible_message("[src]'s shell opens slightly, as sensors begin locking on to everyone around it!") @@ -356,31 +414,33 @@ Difficulty: Hard say(pick("JKVRUEOTM XGC VUCKX", "KXXUX OT GTUSGRE IUTZGOTSKTZ", "YZGHOROZE OT OTYZGHOROZE OT YZGHOROZE OT OTYZGH-")) var/list/turfs = list() var/anomalies = 0 - for(var/turf/T in view(5, src)) + for(var/turf/T in view(enraged ? 7 : 5, src)) if(T.density) continue turfs += T - while(anomalies < 3 && length(turfs)) + var/amount = enraged ? 5 : 3 + while(anomalies < amount && length(turfs)) var/turf/spot = pick(turfs) turfs -= spot + var/time_to_use = enraged ? 25 SECONDS : 15 SECONDS switch(mode) if(BLUESPACE) - var/obj/effect/anomaly/bluespace/A = new(spot, 150, FALSE) + var/obj/effect/anomaly/bluespace/A = new(spot, time_to_use, FALSE) A.mass_teleporting = FALSE if(GRAV) - var/obj/effect/anomaly/grav/A = new(spot, 150, FALSE, FALSE) + var/obj/effect/anomaly/grav/A = new(spot, time_to_use, FALSE, FALSE) A.knockdown = TRUE if(PYRO) - var/obj/effect/anomaly/pyro/A = new(spot, 150, FALSE) + var/obj/effect/anomaly/pyro/A = new(spot, time_to_use, FALSE) A.produces_slime = FALSE if(FLUX) - var/obj/effect/anomaly/flux/A = new(spot, 150, FALSE) + var/obj/effect/anomaly/flux/A = new(spot, time_to_use, FALSE) A.explosive = FALSE A.knockdown = TRUE if(VORTEX) - new /obj/effect/anomaly/bhole(spot, 150, FALSE) + new /obj/effect/anomaly/bhole(spot, time_to_use, FALSE) if(CRYO) - new /obj/effect/anomaly/cryo(spot, 150, FALSE) + new /obj/effect/anomaly/cryo(spot, time_to_use, FALSE) anomalies++ return @@ -404,7 +464,9 @@ Difficulty: Hard anger++ if(health <= health / 2) anger += 2 - cap = (is_station_level(loc.z) ? EXTRA_PLAYER_ANGER_STATION_CAP : EXTRA_PLAYER_ANGER_NORMAL_CAP) + if(enraged) + anger += 2 + cap = (is_station_level(loc.z) ? EXTRA_PLAYER_ANGER_STATION_CAP : EXTRA_PLAYER_ANGER_NORMAL_CAP) + enraged extra_player_anger = clamp(anger,1,cap) - 1 /mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/self_destruct() @@ -515,7 +577,7 @@ Difficulty: Hard if(charging) if(mode == PYRO) var/turf/C = get_turf(src) - new /obj/effect/temp_visual/lava_warning(C) + new /obj/effect/temp_visual/lava_warning(C, enraged ? 18 SECONDS : 6 SECONDS) for(var/turf/T in range (1,src)) new /obj/effect/hotspot(T) T.hotspot_expose(700,50,1) @@ -526,7 +588,7 @@ Difficulty: Hard T.ex_act(3) if(mode == CRYO) var/turf/simulated/S = get_turf(src) - S.MakeSlippery(TURF_WET_ICE, rand(10, 20 SECONDS)) + S.MakeSlippery(TURF_WET_ICE, enraged ? rand(25, 35 SECONDS) : rand(10, 20 SECONDS)) for(var/turf/T in range (1, src)) new /obj/effect/snowcloud(T) for(var/mob/living/carbon/C in T.contents) @@ -539,6 +601,9 @@ Difficulty: Hard /mob/living/simple_animal/hostile/megafauna/ancient_robot/mob_negates_gravity() //No more being thrown around like a spastic child by grav anomalies return TRUE +/mob/living/simple_animal/hostile/megafauna/ancient_robot/electrocute_act(shock_damage, source, siemens_coeff, flags) + return + /mob/living/simple_animal/hostile/ancient_robot_leg name = "leg" desc = "Legs with a mounted turret, for shooting and crushing small miners like you." @@ -695,6 +760,9 @@ Difficulty: Hard /mob/living/simple_animal/hostile/ancient_robot_leg/mob_negates_gravity() return TRUE +/mob/living/simple_animal/hostile/ancient_robot_leg/electrocute_act(shock_damage, source, siemens_coeff, flags) + return + /obj/item/projectile/bullet/ancient_robot_bullet damage = 8 damage_type = BRUTE @@ -767,7 +835,7 @@ Difficulty: Hard var/turf/T = get_turf(src) playsound(T,'sound/magic/fleshtostone.ogg', 80, TRUE) new /obj/effect/temp_visual/fireball/rock(T) - sleep(duration) + SLEEP_CHECK_QDEL(duration) if(ismineralturf(T)) var/turf/simulated/mineral/M = T M.gets_drilled() diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm index d96248ec52ea..fe55c7f6b1e2 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm @@ -46,15 +46,17 @@ Difficulty: Medium blood_volume = BLOOD_VOLUME_NORMAL internal_gps = /obj/item/gps/internal/miner medal_type = BOSS_MEDAL_MINER - var/obj/item/melee/energy/cleaving_saw/miner/miner_saw + var/obj/item/melee/energy/cleaving_saw/miner_saw var/time_until_next_transform = 0 var/dashing = FALSE - var/dash_cooldown = 15 + var/dash_cooldown = 0 + var/dash_cooldown_to_use = 1.5 SECONDS var/guidance = FALSE var/transform_stop_attack = FALSE // stops the blood drunk miner from attacking after transforming his weapon until the next attack chain deathmessage = "falls to the ground, decaying into glowing particles." death_sound = "bodyfall" footstep_type = FOOTSTEP_MOB_HEAVY + enraged_loot = /obj/item/disk/fauna_research/blood_drunk_miner attack_action_types = list(/datum/action/innate/megafauna_attack/dash, /datum/action/innate/megafauna_attack/kinetic_accelerator, /datum/action/innate/megafauna_attack/transform_weapon) @@ -67,7 +69,7 @@ Difficulty: Medium /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/Initialize(mapload) . = ..() - miner_saw = new(src) + miner_saw = new /obj/item/melee/energy/cleaving_saw/miner(src) /datum/action/innate/megafauna_attack/dash name = "Dash To Target" @@ -123,10 +125,14 @@ Difficulty: Medium icon_state = "ka_tracer" range = MINER_DASH_RANGE +/obj/item/projectile/kinetic/miner/enraged + damage = 35 + /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/adjustHealth(amount, updating_health = TRUE) - var/adjustment_amount = amount * 0.1 - if(world.time + adjustment_amount > next_move) - changeNext_move(adjustment_amount) //attacking it interrupts it attacking, but only briefly + if(!enraged) + var/adjustment_amount = amount * 0.1 + if(world.time + adjustment_amount > next_move) + changeNext_move(adjustment_amount) //attacking it interrupts it attacking, but only briefly . = ..() /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/death() @@ -170,7 +176,7 @@ Difficulty: Medium changeNext_move(CLICK_CD_MELEE) miner_saw.melee_attack_chain(src, target) if(guidance) - adjustHealth(-2) + adjustHealth(enraged ? -10 : -2) if(prob(50)) transform_weapon() //Still follows the normal rules for cooldown between swaps. return TRUE @@ -186,6 +192,24 @@ Difficulty: Medium if(. && target && !targets_the_same) wander = TRUE +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/enrage() + . = ..() + miner_saw = new /obj/item/melee/energy/cleaving_saw(src) //Real saw for real men. + dash_cooldown_to_use = 0.5 SECONDS //Becomes a teleporting shit. + ranged_cooldown_time = 5 //They got some cooldown mods. + projectiletype = /obj/item/projectile/kinetic/miner/enraged + maxHealth = 1800 + health = 1800 //Bit more of a challenge. + +/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/unrage() + . = ..() + miner_saw = new /obj/item/melee/energy/cleaving_saw/miner(src) + dash_cooldown_to_use = initial(dash_cooldown_to_use) + ranged_cooldown_time = initial(ranged_cooldown_time) + projectiletype = initial(projectiletype) + maxHealth = initial(maxHealth) + health = initial(health) + /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/dash_attack() INVOKE_ASYNC(src, PROC_REF(dash), target) shoot_ka() @@ -232,7 +256,7 @@ Difficulty: Medium accessable_turfs -= t if(!LAZYLEN(accessable_turfs)) return - dash_cooldown = world.time + initial(dash_cooldown) + dash_cooldown = world.time + dash_cooldown_to_use target_turf = pick(accessable_turfs) var/turf/step_back_turf = get_step(target_turf, get_cardinal_dir(target_turf, own_turf)) var/turf/step_forward_turf = get_step(own_turf, get_cardinal_dir(own_turf, target_turf)) @@ -291,7 +315,7 @@ Difficulty: Medium /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/hunter/AttackingTarget() . = ..() - if(. && prob(12)) + if(. && prob(enraged ? 40 : 12)) INVOKE_ASYNC(src, PROC_REF(dash)) #undef MINER_DASH_RANGE diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm index f91b6ac6b128..8a3d90563ffa 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm @@ -1,4 +1,4 @@ -#define BUBBLEGUM_SMASH (health <= maxHealth * 0.5) // angery +#define BUBBLEGUM_SMASH (health <= maxHealth * 0.5 || second_life) // angery #define BUBBLEGUM_CAN_ENRAGE (enrage_till + (enrage_time * 2) <= world.time) #define BUBBLEGUM_IS_ENRAGED (enrage_till > world.time) @@ -59,6 +59,8 @@ Difficulty: Hard var/enrage_till = 0 var/enrage_time = 70 var/revving_charge = FALSE + /// Is it on its enraged exclusive second life? + var/second_life = FALSE internal_gps = /obj/item/gps/internal/bubblegum medal_type = BOSS_MEDAL_BUBBLEGUM score_type = BUBBLEGUM_SCORE @@ -111,7 +113,48 @@ Difficulty: Hard chosen_message = "You are now warping to blood around your clicked position." chosen_attack_num = 4 -/mob/living/simple_animal/hostile/megafauna/bubblegum/OpenFire() +/mob/living/simple_animal/hostile/megafauna/bubblegum/enrage() + . = ..() + maxHealth = 2000 //Less health, as a phase 2 + health = 2000 + rapid_melee = 12 //Don't stand still + vision_range = 18 + loot = list(/obj/effect/decal/cleanable/blood/gibs/bubblegum) //You'll get it in phase 2. + crusher_loot = list(/obj/effect/decal/cleanable/blood/gibs/bubblegum) + RegisterSignal(src, COMSIG_HOSTILE_FOUND_TARGET, PROC_REF(i_see_you)) + for(var/mob/living/carbon/human/H in range(18)) //suprise motherfucker bubblegum wakes up fast + to_chat(H, "You DARE to insult my body with these constructs? I curse you as you curse ME!") + FindTarget(list(H), 1) //From down town with the pile driver + +/mob/living/simple_animal/hostile/megafauna/bubblegum/unrage() + return //They are pissed. Also whoever enraged them is stuck fighting them so, kinda a M.A.D situation. + +/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/i_see_you(source, target) + if(!ishuman(target)) + return + var/mob/living/carbon/human/H = target + H.apply_status_effect(STATUS_EFFECT_BUBBLEGUM_CURSE, src) + if(second_life) + H.clear_fullscreen("bubblegum") + H.overlay_fullscreen("bubblegum", /obj/screen/fullscreen/fog, 2) + + +/mob/living/simple_animal/hostile/megafauna/bubblegum/death(gibbed) + if(enraged && !second_life) + var/obj/structure/closet/crate/necropolis/bubblegum/bait/jebait = new /obj/structure/closet/crate/necropolis/bubblegum/bait(get_turf(src)) + var/obj/effect/bubblegum_trigger/great_chest_ahead = new /obj/effect/bubblegum_trigger(jebait, ListTargets()) + new /obj/effect/landmark/spawner/bubblegum_exit(get_turf(src)) + great_chest_ahead.forceMove(jebait) + if(second_life) + var/area/A = get_area(src) + for(var/mob/M in A) + to_chat(M, "YOU FUCK... I... I'll... get you later. Enjoy the last few days of your life...") + new /obj/effect/bubblegum_exit(get_turf(src)) + return ..() + +/mob/living/simple_animal/hostile/megafauna/bubblegum/OpenFire(atom/A) + if(second_life) + Shoot(A) if(charging) return @@ -137,6 +180,9 @@ Difficulty: Hard if(!BUBBLEGUM_SMASH) triple_charge() else + if(prob(25) && enraged) + hit_up_narsi() + return if(prob(50 + anger_modifier)) hallucination_charge() else @@ -208,7 +254,7 @@ Difficulty: Hard /mob/living/simple_animal/hostile/megafauna/bubblegum/proc/try_bloodattack() var/list/targets = get_mobs_on_blood() if(targets.len) - INVOKE_ASYNC(src, PROC_REF(bloodattack), targets, prob(50)) + INVOKE_ASYNC(src, PROC_REF(bloodattack), targets, prob(enraged ? 75 : 50)) return TRUE return FALSE @@ -255,7 +301,7 @@ Difficulty: Hard to_chat(L, "[src] rends you!") playsound(T, attack_sound, 100, TRUE, -1) var/limb_to_hit = L.get_organ(pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)) - L.apply_damage(10, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, MELEE, null, null, armour_penetration_flat, armour_penetration_percentage)) + L.apply_damage(second_life ? 20 : 10, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, MELEE, null, null, armour_penetration_flat, armour_penetration_percentage)) SLEEP_CHECK_DEATH(3) /mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodgrab(turf/T, handedness) @@ -318,6 +364,27 @@ Difficulty: Hard return TRUE return FALSE + +/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/hit_up_narsi() + SetRecoveryTime(20) + visible_message("[pick("[SSticker.cultdat.entity_name], I call on YOU for one of MY favours you owe me!", "[SSticker.cultdat.entity_title1], I call on you for some support...", "Let us see how you like the minions of [SSticker.cultdat.entity_title2]!", "Oh, [SSticker.cultdat.entity_title3] join me in RENDING THIS WHELP APART!")]") + var/list/turfs = list() + var/constructs = 0 + for(var/turf/T in view(6, target)) + if(T.density) + continue + if(T in range(2, target)) + continue + turfs += T + var/amount = enraged ? 4 : 3 + while(constructs < amount && length(turfs)) + var/turf/spot = pick_n_take(turfs) + if(!spot) + return + var/mob/living/simple_animal/hostile/construct/wraith/hostile/summon = new /mob/living/simple_animal/hostile/construct/wraith/hostile(spot) + summon.faction = faction.Copy() + constructs++ + /mob/living/simple_animal/hostile/megafauna/bubblegum/proc/be_aggressive() if(BUBBLEGUM_IS_ENRAGED) return TRUE @@ -340,8 +407,10 @@ Difficulty: Hard if(!BUBBLEGUM_CAN_ENRAGE) return FALSE enrage_till = world.time + enrage_time + if(enraged) + adjustHealth(-75) update_approach() - change_move_delay(5) + change_move_delay(enraged ? 3 : 4) //3 if enraged, 4 otherwise var/newcolor = rgb(149, 10, 10) add_atom_colour(newcolor, TEMPORARY_COLOUR_PRIORITY) var/datum/callback/cb = CALLBACK(src, PROC_REF(blood_enrage_end)) @@ -554,3 +623,26 @@ Difficulty: Hard /mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/try_bloodattack() return + +/mob/living/simple_animal/hostile/megafauna/bubblegum/round_2 + desc = "Oh they are PISSED. And quite injured too..." + health = 750 + maxHealth = 750 + armour_penetration_percentage = 75 + second_life = TRUE + enraged = TRUE + rapid_melee = 12 + projectiletype = /obj/item/projectile/magic/arcane_barrage/blood + projectilesound = 'sound/effects/splat.ogg' + deathmessage = null + death_sound = 'sound/hallucinations/veryfar_noise.ogg' + ranged = TRUE + ranged_cooldown_time = 10 + enraged_loot = /obj/item/disk/fauna_research/bubblegum + +/mob/living/simple_animal/hostile/megafauna/bubblegum/round_2/Initialize(mapload) + . = ..() + RegisterSignal(src, COMSIG_HOSTILE_FOUND_TARGET, PROC_REF(i_see_you)) + for(var/mob/living/carbon/human/H in range(20)) + to_chat(H, "I WILL END YOU HERE AND NOW!") + FindTarget(list(H), 1) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 02d7f2664d90..dc527b96fdf3 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -54,6 +54,7 @@ Difficulty: Very Hard loot = list(/obj/structure/closet/crate/necropolis/colossus) deathmessage = "disintegrates, leaving a glowing core in its wake." death_sound = 'sound/misc/demon_dies.ogg' + enraged_loot = /obj/item/disk/fauna_research/colossus attack_action_types = list(/datum/action/innate/megafauna_attack/spiral_attack, /datum/action/innate/megafauna_attack/aoe_attack, /datum/action/innate/megafauna_attack/shotgun, @@ -61,6 +62,15 @@ Difficulty: Very Hard /// Have we used our final attack yet? var/final_available = TRUE +/mob/living/simple_animal/hostile/megafauna/colossus/Initialize(mapload) + . = ..() + return INITIALIZE_HINT_LATELOAD + +/mob/living/simple_animal/hostile/megafauna/colossus/LateInitialize() + . = ..() + for(var/mob/living/simple_animal/hostile/megafauna/hierophant/H in GLOB.mob_list) + H.RegisterSignal(src, COMSIG_MOB_APPLY_DAMAGE, TYPE_PROC_REF(/mob/living/simple_animal/hostile/megafauna/hierophant, easy_anti_cheese)) + /datum/action/innate/megafauna_attack/spiral_attack name = "Spiral Shots" icon_icon = 'icons/mob/actions/actions.dmi' @@ -93,6 +103,14 @@ Difficulty: Very Hard . = ..(("[uppertext(message)]"), sanitize = FALSE, ignore_speech_problems = TRUE, ignore_atmospherics = TRUE) +/mob/living/simple_animal/hostile/megafauna/colossus/enrage() + . = ..() + move_to_delay = 5 + +/mob/living/simple_animal/hostile/megafauna/colossus/unrage() + . = ..() + move_to_delay = initial(move_to_delay) + /mob/living/simple_animal/hostile/megafauna/colossus/OpenFire() anger_modifier = clamp(((maxHealth - health)/50),0,20) ranged_cooldown = world.time + 120 @@ -109,7 +127,7 @@ Difficulty: Very Hard alternating_dir_shots() return - if(enrage(target)) + if(target_trying_to_cheese_us(target)) if(move_to_delay == initial(move_to_delay)) say("You can't dodge") ranged_cooldown = world.time + 30 @@ -120,9 +138,10 @@ Difficulty: Very Hard else move_to_delay = initial(move_to_delay) - if(health <= maxHealth / 10 && final_available) //One time use final attack - final_available = FALSE + if(health <= maxHealth / (enraged ? 10 : 9) && final_available) //One time use final attack. Want to make it not get skipped as much on base colossus, but a little easier to skip on enraged as it can be used multiple times final_attack() + if(!enraged) + final_available = FALSE else if(prob(20 + anger_modifier)) //Major attack select_spiral_attack() else if(prob(20)) @@ -133,23 +152,28 @@ Difficulty: Very Hard else alternating_dir_shots() -/mob/living/simple_animal/hostile/megafauna/colossus/proc/enrage(mob/living/L) - if(ishuman(L)) - var/mob/living/carbon/human/H = L - if(H.mind && H.mind.martial_art && prob(H.mind.martial_art.deflection_chance)) - return TRUE - -/mob/living/simple_animal/hostile/megafauna/colossus/proc/alternating_dir_shots() - ranged_cooldown = world.time + 40 - telegraph(DIR_SHOTS) - SLEEP_CHECK_DEATH(1.5 SECONDS) +/mob/living/simple_animal/hostile/megafauna/colossus/proc/target_trying_to_cheese_us(mob/living/L) + if(!ishuman(L)) + return + var/mob/living/carbon/human/H = L + if(H.mind && H.mind.martial_art && prob(H.mind.martial_art.deflection_chance)) + return TRUE + +/mob/living/simple_animal/hostile/megafauna/colossus/proc/alternating_dir_shots(telegraphing = TRUE) + var/rage = enraged ? 5 : 10 + if(telegraphing) + ranged_cooldown = world.time + 4 SECONDS + telegraph(DIR_SHOTS) + SLEEP_CHECK_DEATH(1.5 SECONDS) dir_shots(GLOB.diagonals) - SLEEP_CHECK_DEATH(10) + SLEEP_CHECK_DEATH(rage) dir_shots(GLOB.cardinal) - SLEEP_CHECK_DEATH(10) + SLEEP_CHECK_DEATH(rage) dir_shots(GLOB.diagonals) - SLEEP_CHECK_DEATH(10) + SLEEP_CHECK_DEATH(rage) dir_shots(GLOB.cardinal) + if(telegraphing) + alternating_dir_shots(FALSE) /mob/living/simple_animal/hostile/megafauna/colossus/proc/select_spiral_attack() if(health < maxHealth/3) @@ -204,14 +228,14 @@ Difficulty: Very Hard var/turf/U = get_turf(src) playsound(U, 'sound/magic/clockwork/invoke_general.ogg', 300, TRUE, 5) for(var/T in RANGE_TURFS(12, U) - U) - if(prob(5)) + if(prob(enraged ? 10 : 5)) shoot_projectile(T) /mob/living/simple_animal/hostile/megafauna/colossus/proc/blast(set_angle, do_sleep = TRUE) ranged_cooldown = world.time + 20 if(do_sleep) telegraph(BLAST) - SLEEP_CHECK_DEATH(1.5 SECONDS) + SLEEP_CHECK_DEATH(enraged ? 0.1 SECONDS : 1.5 SECONDS) var/turf/target_turf = get_turf(target) playsound(src, 'sound/magic/clockwork/invoke_general.ogg', 200, TRUE, 2) newtonian_move(get_dir(target_turf, src)) @@ -306,10 +330,7 @@ Difficulty: Very Hard /mob/living/simple_animal/hostile/megafauna/colossus/float(on) //we don't want this guy to float, messes up his animations if(throwing) return - if(on && !floating) - floating = TRUE - else if(!on && floating) - floating = FALSE + floating = on /obj/item/projectile/colossus name ="death bolt" diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index 849341d9f15b..68d3e7b8cffa 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -61,6 +61,7 @@ Difficulty: Medium deathmessage = "collapses into a pile of bones, its flesh sloughing away." death_sound = 'sound/misc/demon_dies.ogg' footstep_type = FOOTSTEP_MOB_HEAVY + enraged_loot = /obj/item/disk/fauna_research/ash_drake attack_action_types = list(/datum/action/innate/megafauna_attack/fire_cone, /datum/action/innate/megafauna_attack/fire_cone_meteors, /datum/action/innate/megafauna_attack/mass_fire, @@ -104,7 +105,7 @@ Difficulty: Medium if(swooping) return - anger_modifier = clamp(((maxHealth - health)/50),0,20) + anger_modifier = clamp(max((maxHealth - health) / 50, enraged ? 15 : 0), 0, 20) ranged_cooldown = world.time + ranged_cooldown_time if(client) @@ -124,6 +125,8 @@ Difficulty: Medium else if(prob(10+anger_modifier)) shoot_fire_attack() + else if(enraged && prob(20)) + arena_escape_enrage() else fire_cone() @@ -138,7 +141,7 @@ Difficulty: Medium return target.visible_message("Fire rains from the sky!") for(var/turf/turf in range(9,get_turf(target))) - if(prob(11)) + if(prob(enraged ? 44 : 11)) new /obj/effect/temp_visual/target(turf) /mob/living/simple_animal/hostile/megafauna/dragon/proc/lava_pools(amount, delay = 0.8) @@ -148,15 +151,15 @@ Difficulty: Medium while(amount > 0) if(QDELETED(target)) break - var/turf/T = pick(RANGE_TURFS(1, target)) - new /obj/effect/temp_visual/lava_warning(T, 60) // longer reset time for the lava + var/turf/T = pick(RANGE_TURFS(enraged ? 2 : 1, target)) + new /obj/effect/temp_visual/lava_warning(T, enraged ? 18 SECONDS : 6 SECONDS) // longer reset time for the lava amount-- SLEEP_CHECK_DEATH(delay) /mob/living/simple_animal/hostile/megafauna/dragon/proc/lava_swoop(amount = 30) if(health < maxHealth * 0.5) - return swoop_attack(lava_arena = TRUE, swoop_cooldown = 60) - INVOKE_ASYNC(src, PROC_REF(lava_pools), amount) + return swoop_attack(lava_arena = TRUE, swoop_cooldown = enraged ? 2 SECONDS : 6 SECONDS) + INVOKE_ASYNC(src, PROC_REF(lava_pools), enraged ? 60 : amount) swoop_attack(FALSE, target, 1000) // longer cooldown until it gets reset below SLEEP_CHECK_DEATH(0) fire_cone() @@ -169,6 +172,8 @@ Difficulty: Medium /mob/living/simple_animal/hostile/megafauna/dragon/proc/mass_fire(spiral_count = 12, range = 15, times = 3) SLEEP_CHECK_DEATH(0) + if(prob(50) && enraged) + INVOKE_ASYNC(src, PROC_REF(fire_rain)) for(var/i = 1 to times) SetRecoveryTime(50) playsound(get_turf(src),'sound/magic/fireball.ogg', 200, TRUE) @@ -185,12 +190,12 @@ Difficulty: Medium target.visible_message("[src] encases you in an arena of fire!") var/amount = 3 var/turf/center = get_turf(target) - var/list/walled = RANGE_TURFS(3, center) - RANGE_TURFS(2, center) + var/list/walled = RANGE_TURFS(enraged ? 4 : 3, center) - RANGE_TURFS(enraged ? 3 : 2, center) var/list/drakewalls = list() for(var/turf/T in walled) drakewalls += new /obj/effect/temp_visual/drakewall(T) // no people with lava immunity can just run away from the attack for free var/list/indestructible_turfs = list() - for(var/turf/T in RANGE_TURFS(2, center)) + for(var/turf/T in RANGE_TURFS(enraged ? 3 : 2, center)) if(istype(T, /turf/simulated/floor/indestructible)) continue if(!istype(T, /turf/simulated/wall/indestructible)) @@ -199,14 +204,14 @@ Difficulty: Medium indestructible_turfs += T SLEEP_CHECK_DEATH(10) // give them a bit of time to realize what attack is actually happening - var/list/turfs = RANGE_TURFS(2, center) + var/list/turfs = RANGE_TURFS(enraged ? 3 : 2, center) while(amount > 0) var/list/empty = indestructible_turfs.Copy() // can't place safe turfs on turfs that weren't changed to be open var/any_attack = 0 for(var/turf/T in turfs) for(var/mob/living/L in T.contents) if(L.client) - empty += pick(((RANGE_TURFS(2, L) - RANGE_TURFS(1, L)) & turfs) - empty) // picks a turf within 2 of the creature not outside or in the shield + empty += pick(((RANGE_TURFS(enraged ? 3 : 2, L) - RANGE_TURFS(enraged ? 2 : 1, L)) & turfs) - empty) // picks a turf within 2 of the creature not outside or in the shield any_attack = 1 for(var/obj/mecha/M in T.contents) empty += pick(((RANGE_TURFS(2, M) - RANGE_TURFS(1, M)) & turfs) - empty) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index 42c8456c6e91..d2a79230e927 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -39,7 +39,7 @@ Difficulty: Hard desc = "A massive metal club that hangs in the air as though waiting. It'll make you dance to its beat." health = 2500 maxHealth = 2500 - attacktext = "clubs" + attacktext = "slams into" attack_sound = 'sound/weapons/sonic_jackhammer.ogg' icon_state = "hierophant" icon_living = "hierophant" @@ -47,7 +47,7 @@ Difficulty: Hard icon = 'icons/mob/lavaland/hierophant_new.dmi' faction = list("boss") //asteroid mobs? get that shit out of my beautiful square house speak_emote = list("preaches") - armour_penetration_percentage = 50 + armour_penetration_percentage = 100 //It does 15 damage / only attacks when enraged melee_damage_lower = 15 melee_damage_upper = 15 speed = 10 @@ -63,6 +63,7 @@ Difficulty: Hard score_type = HIEROPHANT_SCORE del_on_death = TRUE death_sound = 'sound/magic/repulse.ogg' + enraged_loot = /obj/item/disk/fauna_research/hierophant attack_action_types = list(/datum/action/innate/megafauna_attack/blink, /datum/action/innate/megafauna_attack/chaser_swarm, /datum/action/innate/megafauna_attack/cross_blasts, @@ -81,10 +82,13 @@ Difficulty: Hard var/list/kill_phrases = list("Wsyvgi sj irivkc xettih. Vitemvmrk...", "Irivkc wsyvgi jsyrh. Vitemvmrk...", "Jyip jsyrh. Egxmzexmrk vitemv gcgpiw...", "Kix fiex. Liepmrk...") var/list/target_phrases = list("Xevkix psgexih.", "Iriqc jsyrh.", "Eguymvih xevkix.") var/list/stored_nearby = list() // stores people nearby the hierophant when it enters the death animation + ///If the hiero has changed colour, stop the rays animation. + var/colour_shifting = FALSE /mob/living/simple_animal/hostile/megafauna/hierophant/Initialize(mapload) . = ..() spawned_beacon = new(loc) + AddComponent(/datum/component/boss_music, 'sound/lavaland/hiero_boss.ogg', 145 SECONDS) /datum/action/innate/megafauna_attack/blink name = "Blink To Target" @@ -114,6 +118,14 @@ Difficulty: Hard chosen_message = "You are now repeatedly blinking at your target." chosen_attack_num = 4 +/mob/living/simple_animal/hostile/megafauna/hierophant/enrage() + . = ..() + move_to_delay = 5 + +/mob/living/simple_animal/hostile/megafauna/hierophant/unrage() + . = ..() + move_to_delay = initial(move_to_delay) + /mob/living/simple_animal/hostile/megafauna/hierophant/OpenFire() if(blinking) return @@ -194,12 +206,26 @@ Difficulty: Hard else //just release a burst of power INVOKE_ASYNC(src, PROC_REF(burst), get_turf(src)) +/mob/living/simple_animal/hostile/megafauna/hierophant/proc/easy_anti_cheese(mob/living/simple_animal/S) + if(enraged || get_dist(S, src) > 20) + return + for(var/mob/living/L in urange(20, src)) + if(L.client) + enrage() + arena_trap(L, TRUE) + FindTarget(list(L), 1) + for(var/mob/living/simple_animal/hostile/megafauna/colossus/C in GLOB.mob_list) + UnregisterSignal(C, COMSIG_MOB_APPLY_DAMAGE) + break + /mob/living/simple_animal/hostile/megafauna/hierophant/proc/blink_spam(blink_counter, target_slowness, cross_counter) ranged_cooldown = world.time + max(5, major_attack_cooldown - anger_modifier * 0.75) - if(health < maxHealth * 0.5 && blink_counter > 1) + if(((health < maxHealth * 0.5) || enraged) && blink_counter > 1) visible_message("\"Mx ampp rsx iwgeti.\"") var/oldcolor = color animate(src, color = "#660099", time = 6) + colour_shifting = TRUE + remove_filter("rays") SLEEP_CHECK_DEATH(6) while(!QDELETED(target) && blink_counter) if(loc == target.loc || loc == target) //we're on the same tile as them after about a second we can stop now @@ -210,6 +236,7 @@ Difficulty: Hard blinking = TRUE SLEEP_CHECK_DEATH(4 + target_slowness) animate(src, color = oldcolor, time = 8) + colour_shifting = FALSE addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_atom_colour)), 8) SLEEP_CHECK_DEATH(8) blinking = FALSE @@ -222,6 +249,8 @@ Difficulty: Hard blinking = TRUE var/oldcolor = color animate(src, color = "#660099", time = 6) + colour_shifting = TRUE + remove_filter("rays") SLEEP_CHECK_DEATH(6) while(!QDELETED(target) && cross_counter) cross_counter-- @@ -231,6 +260,7 @@ Difficulty: Hard INVOKE_ASYNC(src, PROC_REF(blasts), target, GLOB.diagonals) SLEEP_CHECK_DEATH(6 + target_slowness) animate(src, color = oldcolor, time = 8) + colour_shifting = FALSE addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_atom_colour)), 8) SLEEP_CHECK_DEATH(8) blinking = FALSE @@ -242,6 +272,8 @@ Difficulty: Hard blinking = TRUE var/oldcolor = color animate(src, color = "#660099", time = 6) + colour_shifting = TRUE + remove_filter("rays") SLEEP_CHECK_DEATH(6) var/list/targets = ListTargets() var/list/cardinal_copy = GLOB.cardinal.Copy() @@ -259,6 +291,7 @@ Difficulty: Hard SLEEP_CHECK_DEATH(8 + target_slowness) chaser_cooldown = world.time + initial(chaser_cooldown) animate(src, color = oldcolor, time = 8) + colour_shifting = FALSE addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_atom_colour)), 8) SLEEP_CHECK_DEATH(8) blinking = FALSE @@ -273,7 +306,7 @@ Difficulty: Hard new /obj/effect/temp_visual/hierophant/telegraph/diagonal(T, src) else new /obj/effect/temp_visual/hierophant/telegraph(T, src) - playsound(T,'sound/effects/bin_close.ogg', 200, TRUE) + playsound(T,'sound/effects/bin_close.ogg', 75, TRUE) SLEEP_CHECK_DEATH(2) new /obj/effect/temp_visual/hierophant/blast(T, src, FALSE) for(var/d in directions) @@ -288,19 +321,20 @@ Difficulty: Hard previousturf = J J = get_step(previousturf, set_dir) -/mob/living/simple_animal/hostile/megafauna/hierophant/proc/arena_trap(mob/victim) //trap a target in an arena +/mob/living/simple_animal/hostile/megafauna/hierophant/proc/arena_trap(mob/victim, forced = FALSE) //trap a target in an arena var/turf/T = get_turf(victim) if(!istype(victim) || victim.stat == DEAD || !T || arena_cooldown > world.time) return if((istype(get_area(T), /area/ruin/unpowered/hierophant) || istype(get_area(src), /area/ruin/unpowered/hierophant)) && victim != src) - return + if(!forced) + return arena_cooldown = world.time + initial(arena_cooldown) for(var/d in GLOB.cardinal) INVOKE_ASYNC(src, PROC_REF(arena_squares), T, d) for(var/t in RANGE_EDGE_TURFS(11, T)) new /obj/effect/temp_visual/hierophant/wall(t, src) new /obj/effect/temp_visual/hierophant/blast(t, src, FALSE) - if(get_dist(src, T) >= 11) //hey you're out of range I need to get closer to you! + if(get_dist(src, T) >= 11 || forced) //hey you're out of range I need to get closer to you! INVOKE_ASYNC(src, PROC_REF(blink), T) /mob/living/simple_animal/hostile/megafauna/hierophant/proc/arena_squares(turf/T, set_dir) //make a fancy effect extending from the arena target @@ -322,8 +356,8 @@ Difficulty: Hard var/turf/source = get_turf(src) new /obj/effect/temp_visual/hierophant/telegraph(T, src) new /obj/effect/temp_visual/hierophant/telegraph(source, src) - playsound(T,'sound/magic/wand_teleport.ogg', 200, TRUE) - playsound(source,'sound/machines/airlock_open.ogg', 200, TRUE) + playsound(T,'sound/magic/wand_teleport.ogg', 80, TRUE) + playsound(source,'sound/machines/airlock_open.ogg', 80, TRUE) blinking = TRUE SLEEP_CHECK_DEATH(2) //short delay before we start... new /obj/effect/temp_visual/hierophant/telegraph/teleport(T, src) @@ -355,14 +389,14 @@ Difficulty: Hard if(!T) return new /obj/effect/temp_visual/hierophant/telegraph(T, src) - playsound(T,'sound/effects/bin_close.ogg', 200, TRUE) + playsound(T,'sound/effects/bin_close.ogg', 75, TRUE) SLEEP_CHECK_DEATH(2) for(var/t in RANGE_TURFS(1, T)) new /obj/effect/temp_visual/hierophant/blast(t, src, FALSE) //expanding square /proc/hierophant_burst(mob/caster, turf/original, burst_range, spread_speed = 0.5) - playsound(original,'sound/machines/airlock_open.ogg', 200, TRUE) + playsound(original,'sound/machines/airlock_open.ogg', 75, TRUE) var/last_dist = 0 for(var/t in spiral_range_turfs(burst_range, original)) var/turf/T = t @@ -377,8 +411,25 @@ Difficulty: Hard /mob/living/simple_animal/hostile/megafauna/hierophant/proc/burst(turf/original, spread_speed) hierophant_burst(src, original, burst_range, spread_speed) +/mob/living/simple_animal/hostile/megafauna/hierophant/float(on) //we don't want this guy to float, messes up his animations + if(throwing) + return + floating = on + +/mob/living/simple_animal/hostile/megafauna/hierophant/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) + if(!enraged) //We do not want it to animate attacking as that breaks the cool animation. If it is not enraged, it can do it. However this only happens if admin controlled + ..() + /mob/living/simple_animal/hostile/megafauna/hierophant/Life() . = ..() + if(enraged && !colour_shifting) + var/new_filter = isnull(get_filter("ray")) + ray_filter_helper(1, 40, "#660099", 6, 20, 16) + if(new_filter) + animate(get_filter("ray"), offset = 10, y = 8, time = 10 SECONDS, loop = -1) + animate(offset = 0, time = 10 SECONDS) + else + remove_filter("ray") if(. && spawned_beacon && !QDELETED(spawned_beacon) && !client) if(target || loc == spawned_beacon.loc) timeout_time = initial(timeout_time) @@ -399,6 +450,8 @@ Difficulty: Hard if(health > 0 || stat == DEAD) return else + for(var/mob/living/simple_animal/hostile/megafauna/colossus/C in GLOB.mob_list) + UnregisterSignal(C, COMSIG_MOB_APPLY_DAMAGE) set_stat(DEAD) blinking = TRUE //we do a fancy animation, release a huge burst(), and leave our staff. visible_message("\"Mrmxmexmrk wipj-hiwxvygx wiuyirgi...\"") @@ -448,6 +501,11 @@ Difficulty: Hard if(target && isliving(target)) var/mob/living/L = target if(L.stat != DEAD) + if(enraged) + ..() + if(L.move_resist < INFINITY) + var/atom/throw_target = get_edge_target_turf(L, get_dir(src, get_step_away(L, src))) + L.throw_at(throw_target, 1, 2) //Yeet them away. Makes crusher harder / stops endless backstab if(ranged_cooldown <= world.time) calculate_rage() ranged_cooldown = world.time + max(5, ranged_cooldown_time - anger_modifier * 0.75) @@ -474,7 +532,7 @@ Difficulty: Hard if(!stat && .) var/obj/effect/temp_visual/hierophant/squares/HS = new(oldLoc) HS.setDir(movement_dir) - playsound(src, 'sound/mecha/mechmove04.ogg', 150, TRUE, -4) + playsound(src, 'sound/mecha/mechmove04.ogg', 65, TRUE, -4) if(target) arena_trap(target) @@ -485,7 +543,7 @@ Difficulty: Hard /mob/living/simple_animal/hostile/megafauna/hierophant/proc/calculate_rage() //how angry we are overall did_reset = FALSE //oh hey we're doing SOMETHING, clearly we might need to heal if we recall - anger_modifier = clamp(((maxHealth - health) / 42),0,50) + anger_modifier = clamp((max((maxHealth - health) / 42, enraged ? 40 : 0)),0,50) burst_range = initial(burst_range) + round(anger_modifier * 0.08) beam_range = initial(beam_range) + round(anger_modifier * 0.12) @@ -666,7 +724,7 @@ Difficulty: Hard var/turf/T = get_turf(src) if(!T) return - playsound(T,'sound/magic/blind.ogg', 125, TRUE, -5) //make a sound + playsound(T,'sound/magic/blind.ogg', 65, TRUE, -5) //make a sound sleep(6) //wait a little bursting = TRUE do_damage(T) //do damage and mark us as bursting diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm index 7ee14ad12dbb..75a4d1cc5e91 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm @@ -45,6 +45,7 @@ Difficulty: Medium score_type = LEGION_SCORE loot = list(/obj/item/storm_staff) crusher_loot = list(/obj/item/storm_staff, /obj/item/crusher_trophy/empowered_legion_skull) + enraged_loot = /obj/item/disk/fauna_research/legion vision_range = 13 elimination = TRUE appearance_flags = 0 @@ -56,6 +57,36 @@ Difficulty: Medium . = ..() transform *= 2 +/mob/living/simple_animal/hostile/megafauna/legion/enrage() + health = 1250 + maxHealth = 1250 + transform /= 1.5 + loot = list(/datum/nothing) + crusher_loot = list(/datum/nothing) + var/mob/living/simple_animal/hostile/megafauna/legion/legiontwo = new /mob/living/simple_animal/hostile/megafauna/legion(get_turf(src)) + legiontwo.transform /= 1.5 + legiontwo.loot = list(/datum/nothing) + legiontwo.crusher_loot = list(/datum/nothing) + legiontwo.health = 1250 + legiontwo.maxHealth = 1250 + +/mob/living/simple_animal/hostile/megafauna/legion/unrage() + . = ..() + for(var/mob/living/simple_animal/hostile/megafauna/legion/other in GLOB.mob_list) + if(other != src) + other.loot = initial(loot) + other.crusher_loot = initial(crusher_loot) + other.maxHealth = 2500 + other.health = 2500 + qdel(src) //Suprise, it's the one on lavaland that regrows to full. + +/mob/living/simple_animal/hostile/megafauna/legion/death(gibbed) + for(var/mob/living/simple_animal/hostile/megafauna/legion/other in GLOB.mob_list) + if(other != src) + other.loot = initial(loot) + other.crusher_loot = initial(crusher_loot) + . = ..() + /mob/living/simple_animal/hostile/megafauna/legion/AttackingTarget() . = ..() if(. && ishuman(target)) @@ -98,7 +129,11 @@ Difficulty: Medium "You summon a big [A]!") ranged_cooldown = world.time + 5 SECONDS else - var/mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril/A = new(loc) + var/mob/living/simple_animal/hostile/asteroid/hivelord/legion/A + if(enraged) + A = new /mob/living/simple_animal/hostile/asteroid/hivelord/legion/advanced/tendril(loc) + else + A = new /mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril(loc) A.GiveTarget(target) A.friends = friends A.faction = faction @@ -159,11 +194,15 @@ Difficulty: Medium return if(.) var/matrix/M = new - resize = 1 + (health / maxHealth) + resize = (enraged ? 0.33 : 1) + (health / maxHealth) M.Scale(resize, resize) transform = M - if(amount > 0 && prob(33)) - var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new(loc) + if(amount > 0 && (enraged || prob(33))) + var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/A + if(enraged) + A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/advanced(loc) + else + A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion(loc) A.GiveTarget(target) A.friends = friends A.faction = faction diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index fdc8f6cc87a5..9e244ae95ea3 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -40,6 +40,10 @@ var/nest_range = 10 var/chosen_attack = 1 // chosen attack num var/list/attack_action_types = list() + /// Has someone enabled hard mode? + var/enraged = FALSE + /// Path of the hardmode loot disk, if applicable. + var/enraged_loot /mob/living/simple_animal/hostile/megafauna/Initialize(mapload) . = ..() @@ -74,6 +78,10 @@ var/datum/status_effect/crusher_damage/C = has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING) if(C && crusher_loot && C.total_damage >= maxHealth * 0.6) spawn_crusher_loot() + if(enraged && length(loot) && enraged_loot) //Don't drop a disk if the boss drops no loot. Important for legion. + for(var/mob/living/M in urange(20, src)) //Yes big range, but for bubblegum arena + if(M.client) + loot += enraged_loot //Disk for each miner / borg. if(!elimination) //used so the achievment only occurs for the last legion to die. SSblackbox.record_feedback("tally", "megafauna_kills", 1, "[initial(name)]") return ..() @@ -89,10 +97,15 @@ var/mob/living/L = target if(L.stat != DEAD) if(!client && ranged && ranged_cooldown <= world.time) - OpenFire() + OpenFire(L) else devour(L) +/mob/living/simple_animal/hostile/megafauna/onTransitZ(old_z, new_z) + . = ..() + if(!istype(get_area(src), /area/shuttle)) //I'll be funny and make non teleported enrage mobs not lose enrage. Harder to pull off, and also funny when it happens accidently. Or if one gets on the escape shuttle. + unrage() + /mob/living/simple_animal/hostile/megafauna/onShuttleMove(turf/oldT, turf/T1, rotation, mob/caller) var/turf/oldloc = loc . = ..() @@ -130,6 +143,15 @@ recovery_time = world.time + buffer_time ranged_cooldown = world.time + buffer_time +/// This proc is called by the HRD-MDE grenade to enrage the megafauna. This should increase the megafaunas attack speed if possible, give it new moves, or disable weak moves. This should be reverseable, and reverses on zlvl change. +/mob/living/simple_animal/hostile/megafauna/proc/enrage() + if(enraged || ((health / maxHealth) * 100 <= 80)) + return + enraged = TRUE + +/mob/living/simple_animal/hostile/megafauna/proc/unrage() + enraged = FALSE + /mob/living/simple_animal/hostile/megafauna/DestroySurroundings() . = ..() for(var/turf/simulated/floor/chasm/C in circlerangeturfs(src, 1)) diff --git a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm index 04c2a1f032d2..4c89d2b6bd94 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm @@ -273,6 +273,9 @@ stat_attack = DEAD can_infest_dead = TRUE +/mob/living/simple_animal/hostile/asteroid/hivelord/legion/advanced/tendril + fromtendril = TRUE + //Legion that spawns Legions /mob/living/simple_animal/hostile/asteroid/big_legion name = "big legion" diff --git a/icons/effects/bubblegum.dmi b/icons/effects/bubblegum.dmi index a53dd7d563aa..76c0c0caf9fc 100644 Binary files a/icons/effects/bubblegum.dmi and b/icons/effects/bubblegum.dmi differ diff --git a/icons/effects/spawner_icons.dmi b/icons/effects/spawner_icons.dmi index cd78697ca168..a01678d2301d 100644 Binary files a/icons/effects/spawner_icons.dmi and b/icons/effects/spawner_icons.dmi differ diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi index f4369f4acac2..b3a990bc54c1 100644 Binary files a/icons/mob/screen_alert.dmi and b/icons/mob/screen_alert.dmi differ diff --git a/icons/mob/screen_fog.dmi b/icons/mob/screen_fog.dmi new file mode 100644 index 000000000000..762578101579 Binary files /dev/null and b/icons/mob/screen_fog.dmi differ diff --git a/icons/mob/ties.dmi b/icons/mob/ties.dmi index fd40d8db0618..2b6f4974624d 100644 Binary files a/icons/mob/ties.dmi and b/icons/mob/ties.dmi differ diff --git a/icons/obj/clothing/ties.dmi b/icons/obj/clothing/ties.dmi index d9a988e02d23..d48bd8258eec 100644 Binary files a/icons/obj/clothing/ties.dmi and b/icons/obj/clothing/ties.dmi differ diff --git a/icons/obj/clothing/ties_overlay.dmi b/icons/obj/clothing/ties_overlay.dmi index 727aaa911639..68fbd505ae75 100644 Binary files a/icons/obj/clothing/ties_overlay.dmi and b/icons/obj/clothing/ties_overlay.dmi differ diff --git a/icons/obj/grenade.dmi b/icons/obj/grenade.dmi index 5d619868eadc..e175f79dc9f8 100644 Binary files a/icons/obj/grenade.dmi and b/icons/obj/grenade.dmi differ diff --git a/icons/obj/module.dmi b/icons/obj/module.dmi index a1dad69342b2..fe9c40361f11 100644 Binary files a/icons/obj/module.dmi and b/icons/obj/module.dmi differ diff --git a/paradise.dme b/paradise.dme index 805bd67a0a37..28009db6d493 100644 --- a/paradise.dme +++ b/paradise.dme @@ -364,6 +364,7 @@ #include "code\datums\cache\powermonitor.dm" #include "code\datums\components\_component.dm" #include "code\datums\components\boomerang.dm" +#include "code\datums\components\boss_music.dm" #include "code\datums\components\caltrop.dm" #include "code\datums\components\deadchat_control.dm" #include "code\datums\components\decal.dm" @@ -1938,6 +1939,7 @@ #include "code\modules\mining\satchel_ore_boxdm.dm" #include "code\modules\mining\shelters.dm" #include "code\modules\mining\equipment\explorer_gear.dm" +#include "code\modules\mining\equipment\hardmode_grenade.dm" #include "code\modules\mining\equipment\kinetic_crusher.dm" #include "code\modules\mining\equipment\lazarus_injector.dm" #include "code\modules\mining\equipment\marker_beacons.dm" diff --git a/sound/lavaland/hiero_boss.ogg b/sound/lavaland/hiero_boss.ogg new file mode 100644 index 000000000000..23412b5346d1 Binary files /dev/null and b/sound/lavaland/hiero_boss.ogg differ