diff --git a/code/modules/antagonists/nightmare/nightmare.dm b/code/modules/antagonists/nightmare/nightmare.dm
index 41a3f181..a8832c5a 100644
--- a/code/modules/antagonists/nightmare/nightmare.dm
+++ b/code/modules/antagonists/nightmare/nightmare.dm
@@ -1,4 +1,20 @@
+#define LIGHTSTOBREAK_MINIMUM 25
+#define LIGHTSTOBREAK_MAXIMUM 75
+#define LIGHTSTOBREAK_THRESHOLD 50
+#define LIGHTSTOBREAK_AREA_MIN 1
+#define LIGHTSTOBREAK_AREA_MAX 2
+
/datum/antagonist/nightmare
name = "Nightmare"
show_in_antagpanel = FALSE
- show_name_in_check_antagonists = TRUE
\ No newline at end of file
+ show_name_in_check_antagonists = TRUE
+
+/datum/antagonist/nightmare/on_gain()
+ owner.objectives += forge_objective()
+ owner.objectives += new /datum/objective/survive
+
+/datum/antagonist/nightmare/proc/forge_objective()
+ var/datum/objective/break_lights/O = new
+ O.mode = prob(50) ? TRUE : FALSE
+ antag_memory = "Objectives:
1. [O.apply_rules()]
2. Stay alive until the end."
+ return O
diff --git a/code/modules/antagonists/nightmare/nightmare_objectives.dm b/code/modules/antagonists/nightmare/nightmare_objectives.dm
new file mode 100644
index 00000000..1fc25248
--- /dev/null
+++ b/code/modules/antagonists/nightmare/nightmare_objectives.dm
@@ -0,0 +1,110 @@
+/datum/objective/break_lights
+ var/mode = FALSE //If true, break all lights in determined area
+ var/list/area_targets = list() //Which areas we have to keep lights broken
+ target_amount = LIGHTSTOBREAK_AREA_MIN
+ var/lightsbroken = 0
+
+ var/safe_areas = list(
+ /area/space,
+ /area/maintenance/solars,
+ /area/maintenance/central, //HOP/Conference room APC
+ /area/ai_monitored,
+ /area/shuttle,
+ /area/engine/engine_smes,
+ /area/security/prison, //If you get unlucky, you'll have to break the lights in armory
+ /area/security/execution)
+
+/datum/objective/break_lights/proc/apply_rules()
+ if(mode)
+ var/list/valid_areas = list()
+ for(var/obj/machinery/power/apc/C in GLOB.apcs_list)
+ if(C.cell && is_station_level(C.z))
+ var/is_safearea = 1
+ for(var/A in safe_areas)
+ if(istype(C.area, A))
+ is_safearea = 0
+ break
+ if(is_safearea)
+ valid_areas += C.area
+ var/I = rand(LIGHTSTOBREAK_AREA_MIN, LIGHTSTOBREAK_AREA_MAX)
+ for(var/N in 1 to I)
+ var/area2add = pick(valid_areas)
+ if(!locate(area2add) in area_targets)
+ area_targets += area2add
+ else
+ target_amount = rand(LIGHTSTOBREAK_MINIMUM, LIGHTSTOBREAK_MAXIMUM)
+ if(prob(50))
+ if(target_amount > LIGHTSTOBREAK_THRESHOLD)
+ target_amount = LIGHTSTOBREAK_MAXIMUM
+ else if(target_amount > LIGHTSTOBREAK_THRESHOLD)
+ target_amount = LIGHTSTOBREAK_THRESHOLD
+ explanation_text = update_explanation_text()
+ return explanation_text
+
+/datum/objective/break_lights/update_explanation_text()
+ ..()
+ if(mode)
+ if(!area_targets.len)
+ return "Uh oh! Something broke! Report this."
+ . += "There must not be any light sources in the "
+ if(area_targets.len == 1)
+ var/area/A = area_targets[1]
+ . += "[A.name]"
+ else if(area_targets.len == 2)
+ var/area/A = area_targets[1]
+ var/area/B = area_targets[2]
+ . += "[A.name] and [B.name]"
+ else //Won't get here because of define values, but during development you can get here. leaving this here for future purposes
+ var/i = 1
+ for(var/area/A in area_targets)
+ if(i != area_targets.len) . += "[A.name], "
+ else . += "and [A.name]"
+
+ . += " before the end."
+ else
+ . += "Break at least [target_amount] lights with your light eater."
+
+/datum/objective/break_lights/check_completion()
+ if(completed)
+ return TRUE //An attempt to stop this from being called twice
+ if(!mode)
+ if(lightsbroken >= target_amount)
+ completed = TRUE
+ else
+ var/list/valid_turfs = list()
+ for(var/area/target in area_targets)
+ var/I = 0
+ var/list/cached_area = get_area_turfs(target.type)
+ for(var/turf/A in cached_area)
+ if(!is_station_level(A.z))
+ continue
+ valid_turfs += A
+ I++
+ var/E = 0
+ var/D = 0
+ for(var/turf/T in valid_turfs)
+ D++
+ for(var/atom/C in T.contents)
+ E++
+ /*if(!C?.visibility) //Doesn't compile, add this another time
+ continue*/
+ if(C.light_range > 0)
+ if(C.light_power <= SHADOW_SPECIES_LIGHT_THRESHOLD*2) //Give some leniency for not destroying that unbreakable requests console
+ completed = TRUE
+ else
+ completed = FALSE
+ break
+ if(!completed)
+ break
+
+ return completed
+
+/datum/objective/break_lights/area
+ mode = TRUE
+
+
+#undef LIGHTSTOBREAK_MINIMUM
+#undef LIGHTSTOBREAK_MAXIMUM
+#undef LIGHTSTOBREAK_THRESHOLD
+#undef LIGHTSTOBREAK_AREA_MIN
+#undef LIGHTSTOBREAK_AREA_MAX
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index b8b62a8b..343cf07c 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -82,6 +82,18 @@
if(changeling)
sList2 += "Chemical Storage: " + "[changeling.chem_charges]/[changeling.chem_storage]"
sList2 += "Absorbed DNA: "+ "[changeling.absorbedcount]"
+ var/datum/antagonist/nightmare/nightmare = mind.has_antag_datum(/datum/antagonist/nightmare)
+ if(nightmare)
+ for(var/datum/objective/O in mind.objectives)
+ if(istype(O, /datum/objective/break_lights))
+ var/datum/objective/break_lights/BL = O
+ if(BL.mode) //Keeping lights out of areas
+ var/T = "Target Area(s): "
+ for(var/area/I in BL.area_targets)
+ T += "[initial(I.name)], "
+ sList2 += T
+ else //Break number of lights
+ sList2 += "Lights Broken: " + "[BL.lightsbroken]/[BL.target_amount]"
if (sList2 != null)
stat(null, "[sList2.Join("\n\n")]")
diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
index 3c716fa1..1d50d2c4 100644
--- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
@@ -183,9 +183,13 @@
. = ..()
if(!proximity)
return
- if(isopenturf(AM)) //So you can actually melee with it
+ if(isopenturf(AM) && !istype(AM, /turf/open/space) && !istype(AM, /turf/open/lava))
+ var/turf/T = AM
+ if(T.light_power || T.light_range)
+ T.set_light(0,0)
+ else if(isopenturf(AM))
return
- if(isliving(AM))
+ else if(isliving(AM))
var/mob/living/L = AM
if(iscyborg(AM))
var/mob/living/silicon/robot/borg = AM
@@ -195,19 +199,39 @@
else
for(var/obj/item/O in AM)
if(O.light_range && O.light_power)
- disintegrate(O)
+ disintegrate(O, user)
if(L.pulling && L.pulling.light_range && isitem(L.pulling))
- disintegrate(L.pulling)
+ disintegrate(L.pulling, user)
else if(isitem(AM))
var/obj/item/I = AM
if(I.light_range && I.light_power)
- disintegrate(I)
+ disintegrate(I, user)
else if(istype(AM, /obj/structure/marker_beacon))
var/obj/structure/marker_beacon/I = AM
- disintegrate(I)
+ disintegrate(I, user)
//why the fuck is the marker beacon a structure? who. what. why.
+ else if(istype(AM, /obj/machinery/light))
+ var/obj/machinery/light/L = AM
+ if(L.status == 2) //Assume we just broke the light
+ handle_objectives(user)
+ L.status = 1 //No tube
+ L.update(FALSE)
-/obj/item/light_eater/proc/disintegrate(obj/item/O)
+/obj/item/light_eater/proc/handle_objectives(mob/living/carbon/human/H)
+ if(!H.mind)
+ return
+
+ if(!H.mind.objectives)
+ return
+
+ for(var/O in H.mind.objectives)
+ if(!istype(O, /datum/objective/break_lights))
+ continue
+ var/datum/objective/break_lights/BL = O
+ if(!BL.mode)
+ BL.lightsbroken++
+
+/obj/item/light_eater/proc/disintegrate(obj/item/O, user)
if(istype(O, /obj/item/pda))
var/obj/item/pda/PDA = O
PDA.set_light(0)
@@ -220,5 +244,8 @@
O.burn()
playsound(src, 'sound/items/welder.ogg', 50, 1)
+ if(is_species(user, /datum/species/shadow/nightmare))
+ handle_objectives(user)
+
#undef HEART_SPECIAL_SHADOWIFY
#undef HEART_RESPAWN_THRESHHOLD
diff --git a/tgstation.dme b/tgstation.dme
index fd4992bd..9562ec48 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1375,6 +1375,7 @@
#include "code\modules\antagonists\morph\morph.dm"
#include "code\modules\antagonists\morph\morph_antag.dm"
#include "code\modules\antagonists\nightmare\nightmare.dm"
+#include "code\modules\antagonists\nightmare\nightmare_objectives.dm"
#include "code\modules\antagonists\ninja\ninja.dm"
#include "code\modules\antagonists\nukeop\clownop.dm"
#include "code\modules\antagonists\nukeop\nukeop.dm"