From 7bb205f9407f15fc43fb85976356c8133b593618 Mon Sep 17 00:00:00 2001 From: DragonTrance Date: Wed, 24 Feb 2021 17:30:09 -0700 Subject: [PATCH 1/3] nightmares have objectives now --- .../antagonists/nightmare/nightmare.dm | 18 ++- .../nightmare/nightmare_objectives.dm | 110 ++++++++++++++++++ code/modules/mob/living/carbon/human/human.dm | 12 ++ .../human/species_types/shadowpeople.dm | 41 +++++-- tgstation.dme | 1 + 5 files changed, 174 insertions(+), 8 deletions(-) create mode 100644 code/modules/antagonists/nightmare/nightmare_objectives.dm 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" From bbb8c81d8129c28fd997796209dfab2c6cf00548 Mon Sep 17 00:00:00 2001 From: DragonTrance Date: Wed, 24 Feb 2021 18:35:32 -0700 Subject: [PATCH 2/3] light eater no longer eats plasmamen helmets --- .../antagonists/nightmare/nightmare.dm | 1 + .../nightmare/nightmare_objectives.dm | 9 ++------- .../human/species_types/shadowpeople.dm | 20 ++++++++++++++++--- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/code/modules/antagonists/nightmare/nightmare.dm b/code/modules/antagonists/nightmare/nightmare.dm index a8832c5a..847ceeb6 100644 --- a/code/modules/antagonists/nightmare/nightmare.dm +++ b/code/modules/antagonists/nightmare/nightmare.dm @@ -1,6 +1,7 @@ #define LIGHTSTOBREAK_MINIMUM 25 #define LIGHTSTOBREAK_MAXIMUM 75 #define LIGHTSTOBREAK_THRESHOLD 50 +#define LIGHTSTOBREAK_MAX_CHANCE 50 #define LIGHTSTOBREAK_AREA_MIN 1 #define LIGHTSTOBREAK_AREA_MAX 2 diff --git a/code/modules/antagonists/nightmare/nightmare_objectives.dm b/code/modules/antagonists/nightmare/nightmare_objectives.dm index 1fc25248..dbcadc5e 100644 --- a/code/modules/antagonists/nightmare/nightmare_objectives.dm +++ b/code/modules/antagonists/nightmare/nightmare_objectives.dm @@ -33,7 +33,7 @@ area_targets += area2add else target_amount = rand(LIGHTSTOBREAK_MINIMUM, LIGHTSTOBREAK_MAXIMUM) - if(prob(50)) + if(prob(LIGHTSTOBREAK_MAX_CHANCE)) if(target_amount > LIGHTSTOBREAK_THRESHOLD) target_amount = LIGHTSTOBREAK_MAXIMUM else if(target_amount > LIGHTSTOBREAK_THRESHOLD) @@ -73,19 +73,13 @@ 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) @@ -106,5 +100,6 @@ #undef LIGHTSTOBREAK_MINIMUM #undef LIGHTSTOBREAK_MAXIMUM #undef LIGHTSTOBREAK_THRESHOLD +#undef LIGHTSTOBREAK_MAX_CHANCE #undef LIGHTSTOBREAK_AREA_MIN #undef LIGHTSTOBREAK_AREA_MAX 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 1d50d2c4..4a7de3d2 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -186,6 +186,7 @@ if(isopenturf(AM) && !istype(AM, /turf/open/space) && !istype(AM, /turf/open/lava)) var/turf/T = AM if(T.light_power || T.light_range) + to_chat(user, "Your [src] consumes the lights in [AM].") T.set_light(0,0) else if(isopenturf(AM)) return @@ -198,13 +199,13 @@ to_chat(borg, "Your headlamp is fried! You'll need a human to help replace it.") else for(var/obj/item/O in AM) - if(O.light_range && O.light_power) + if(O.light_range && O.light_power && !check_plasmaman(O, AM)) disintegrate(O, user) - if(L.pulling && L.pulling.light_range && isitem(L.pulling)) + if(L.pulling && L.pulling.light_range && isitem(L.pulling) && !check_plasmaman(L.pulling, L)) disintegrate(L.pulling, user) else if(isitem(AM)) var/obj/item/I = AM - if(I.light_range && I.light_power) + if(I.light_range && I.light_power && !check_plasmaman(AM)) disintegrate(I, user) else if(istype(AM, /obj/structure/marker_beacon)) var/obj/structure/marker_beacon/I = AM @@ -247,5 +248,18 @@ if(is_species(user, /datum/species/shadow/nightmare)) handle_objectives(user) +/obj/item/light_eater/proc/check_plasmaman(obj/item/O, mob/living/carbon/human/user) + if(!istype(O, /obj/item/clothing/head/helmet/space/plasmaman)) + return FALSE + var/obj/item/clothing/head/helmet/space/plasmaman/H = O + if(H.on) + H.on = FALSE + H.icon_state = "[initial(H.icon_state)][H.on ? "-light":""]" + H.item_state = H.icon_state + if(user) + user.update_inv_head() + to_chat(user, "Your [H]'s torch extinguishes!") + return TRUE + #undef HEART_SPECIAL_SHADOWIFY #undef HEART_RESPAWN_THRESHHOLD From 4d55d53eafed1ee5f68e4e78a74c6b98a702a214 Mon Sep 17 00:00:00 2001 From: DragonTrance Date: Wed, 24 Feb 2021 20:23:41 -0700 Subject: [PATCH 3/3] typo --- .../mob/living/carbon/human/species_types/shadowpeople.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 4a7de3d2..b1d2f5e1 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -186,7 +186,7 @@ if(isopenturf(AM) && !istype(AM, /turf/open/space) && !istype(AM, /turf/open/lava)) var/turf/T = AM if(T.light_power || T.light_range) - to_chat(user, "Your [src] consumes the lights in [AM].") + to_chat(user, "[src] consumes the lights in [AM].") T.set_light(0,0) else if(isopenturf(AM)) return