From 5e213db6c54dfb1ca6502147b725ddbba0a965ae Mon Sep 17 00:00:00 2001 From: warriorstar-orion Date: Wed, 10 Apr 2024 14:54:57 -0400 Subject: [PATCH] add "messy" station trait; add party trash to hangover trait (#24485) * add negative station trait: messy station * remains can't be cleaned * Apply suggestions from code review Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> * messy and hangover? you get more mess * pull down max mess size a bit * remove floor tiles properly * autodoc remaining_tiles * actually gonna reduce this further --------- Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> --- code/__HELPERS/trait_helpers.dm | 1 + .../subsystem/non_firing/SSmapping.dm | 5 + code/datums/station_traits/negative_traits.dm | 8 + .../objects/effects/spawners/mess_spawners.dm | 206 ++++++++++++++++++ paradise.dme | 1 + 5 files changed, 221 insertions(+) create mode 100644 code/game/objects/effects/spawners/mess_spawners.dm diff --git a/code/__HELPERS/trait_helpers.dm b/code/__HELPERS/trait_helpers.dm index e008e90a39d..7824018c564 100644 --- a/code/__HELPERS/trait_helpers.dm +++ b/code/__HELPERS/trait_helpers.dm @@ -361,6 +361,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define STATION_TRAIT_RADIOACTIVE_NEBULA "station_trait_radioactive_nebula" #define STATION_TRAIT_FORESTED "station_trait_forested" #define STATION_TRAIT_VENDING_SHORTAGE "station_trait_vending_shortage" +#define STATION_TRAIT_MESSY "station_trait_messy" //***** TURF TRAITS *****// /// Removes slowdown while walking on these tiles. diff --git a/code/controllers/subsystem/non_firing/SSmapping.dm b/code/controllers/subsystem/non_firing/SSmapping.dm index 7a90cc3dd87..c73d53da322 100644 --- a/code/controllers/subsystem/non_firing/SSmapping.dm +++ b/code/controllers/subsystem/non_firing/SSmapping.dm @@ -133,6 +133,11 @@ SUBSYSTEM_DEF(mapping) else world.name = station_name() + if(HAS_TRAIT(SSstation, STATION_TRAIT_MESSY)) + generate_themed_messes(subtypesof(/obj/effect/spawner/themed_mess) - /obj/effect/spawner/themed_mess/party) + if(HAS_TRAIT(SSstation, STATION_TRAIT_HANGOVER)) + generate_themed_messes(list(/obj/effect/spawner/themed_mess/party)) + // Do not confuse with seedRuins() /datum/controller/subsystem/mapping/proc/handleRuins() // load in extra levels of space ruins diff --git a/code/datums/station_traits/negative_traits.dm b/code/datums/station_traits/negative_traits.dm index f8fb95e185c..037bc69cca0 100644 --- a/code/datums/station_traits/negative_traits.dm +++ b/code/datums/station_traits/negative_traits.dm @@ -45,6 +45,14 @@ . = ..() SSshuttle.supply.callTime *= 1.5 // 3 minutes, for those wondering. +/datum/station_trait/messy_station + name = "Messy Station" + trait_type = STATION_TRAIT_NEGATIVE + weight = 5 + show_in_report = TRUE + report_message = "The previous crew has left the station completely trashed." + trait_to_give = STATION_TRAIT_MESSY + // Abstract station trait used for traits that modify a random event in some way (their weight or max occurrences). /datum/station_trait/random_event_weight_modifier name = "Random Event Modifier" diff --git a/code/game/objects/effects/spawners/mess_spawners.dm b/code/game/objects/effects/spawners/mess_spawners.dm new file mode 100644 index 00000000000..164777537c7 --- /dev/null +++ b/code/game/objects/effects/spawners/mess_spawners.dm @@ -0,0 +1,206 @@ +/obj/effect/spawner/themed_mess + name = "mess spawner" + icon = 'icons/effects/spawner_icons.dmi' + icon_state = "questionmark" + + /// The number of tiles to spread to. Each new chosen tile receives this + /// value decremented by one, ensuring the maximum size of the mess is limited + /// by the original spawner's value. + var/remaining_tiles + +/obj/effect/spawner/themed_mess/proc/drop_mess() + return + +/obj/effect/spawner/themed_mess/proc/drop_object() + return + +/obj/effect/spawner/themed_mess/proc/make_next_spawner(turf/T) + new type(T, remaining_tiles - 1) + +/obj/effect/spawner/themed_mess/New(loc, size = 10) + . = ..() + remaining_tiles = size + var/turf/T = get_turf(src) + if(!T) + stack_trace("Spawner placed in nullspace!") + return + randspawn(T) + +/obj/effect/spawner/themed_mess/proc/randspawn(turf/T) + drop_mess(T) + + if(prob(25)) + drop_object(T) + + if(remaining_tiles > 0) + var/dirs = GLOB.alldirs.Copy() + shuffle_inplace(dirs) + for(var/dir in dirs) + var/turf/next = get_step(src, dir) + // Just check for plasteel turf to avoid walls and areas under windows + // findEventArea excludes maintenance anyway so we don't care about missing plating + if(istype(next, /turf/simulated/floor/plasteel) && !(locate(/obj/effect/decal/cleanable) in next)) + make_next_spawner(next) + break + qdel(src) + +/obj/effect/spawner/themed_mess/party + name = "party mess spawner" + +/obj/effect/spawner/themed_mess/party/drop_mess(turf/T) + if(prob(50)) + new /obj/effect/decal/cleanable/vomit(T) + else + new /obj/effect/decal/cleanable/confetti(T) + +/obj/effect/spawner/themed_mess/party/drop_object(turf/T) + if(prob(50)) + new /obj/item/cigbutt(T) // does its own random placement transforms + else if(prob(20)) + new /obj/item/cigbutt/roach(T) + else + var/trash_type = pick( + /obj/item/broken_bottle, + /obj/item/shard, + ) + var/obj/trash = new trash_type(T) + trash.pixel_x = rand(-10, 10) + trash.pixel_y = rand(-10, 10) + trash.transform = turn(transform, rand(0, 360)) + +/obj/effect/spawner/themed_mess/bloody + name = "bloody mess spawner" + var/bloodcolor + +/obj/effect/spawner/themed_mess/bloody/New(loc, size = 10, blood = null) + bloodcolor = blood ? blood : pick( + "#004400", + "#0064c8", + "#1d2cbf", + "#2299fc", + "#a10808", + "#a200ff", + "#a3d4eb", + "#b9ae9c", + "#fb9800") + return ..() + +/obj/effect/spawner/themed_mess/bloody/make_next_spawner(turf/T) + new type(T, remaining_tiles - 1, bloodcolor) + +/obj/effect/spawner/themed_mess/bloody/drop_mess(turf/T) + var/blood_decal_type = pick( + /obj/effect/decal/cleanable/blood, + /obj/effect/decal/cleanable/blood/splatter, + /obj/effect/decal/cleanable/blood/drip, + /obj/effect/decal/cleanable/blood/gibs, + ) + var/obj/effect/decal/cleanable/blood/decal = new blood_decal_type(T) + decal.basecolor = bloodcolor + decal.update_icon() + +/obj/effect/spawner/themed_mess/bloody/drop_object(turf/T) + if(prob(50)) + var/organ_type = pick( + /obj/item/organ/internal/ears, + /obj/item/organ/internal/eyes, + /obj/item/organ/internal/kidneys, + /obj/item/organ/internal/liver, + /obj/item/organ/internal/lungs, + /obj/item/organ/internal/appendix, + ) + var/obj/organ = new organ_type(T) + organ.pixel_x = rand(-10, 10) + organ.pixel_y = rand(-10, 10) + +/obj/effect/spawner/themed_mess/robotic + name = "robotic themed mess" + +/obj/effect/spawner/themed_mess/robotic/drop_mess(turf/T) + var/blood_decal_type = pick( + /obj/effect/decal/cleanable/blood, + /obj/effect/decal/cleanable/blood/splatter, + /obj/effect/decal/cleanable/blood/drip, + /obj/effect/decal/cleanable/blood/gibs, + ) + var/obj/effect/decal/cleanable/blood/decal = new blood_decal_type(T) + decal.basecolor = COLOR_BLOOD_MACHINE + decal.update_icon() + + if(prob(10)) + new /obj/effect/decal/cleanable/blood/gibs/robot(T) + +/obj/effect/spawner/themed_mess/engineering + name = "engineering themed mess" + +/obj/effect/spawner/themed_mess/engineering/drop_mess(turf/T) + var/turf/simulated/floor/floor = T + if(istype(floor)) + if(prob(50)) + floor.burn_tile() + else if(prob(25)) + floor.break_tile() + else if(!istype(floor, /turf/simulated/floor/grass)) // Just because grass isn't *as* easy to replace + floor.remove_tile(null, silent = TRUE, make_tile = TRUE) + +/obj/effect/spawner/themed_mess/engineering/drop_object(turf/T) + var/obj_type = pick( + /obj/effect/decal/cleanable/glass, + /obj/item/stack/cable_coil/cut, + /obj/item/stack/rods, + /obj/item/stack/tile/plasteel, + ) + new obj_type(T) + +/obj/effect/spawner/themed_mess/dirty + name = "dirt themed mess" + +/obj/effect/spawner/themed_mess/dirty/drop_mess(turf/T) + new /obj/effect/decal/cleanable/dirt(T) + +/obj/effect/spawner/themed_mess/dirty/drop_object(turf/T) + var extra_trash = pick( + /obj/effect/decal/cleanable/generic, + /obj/effect/decal/cleanable/insectguts, + /obj/effect/decal/cleanable/shreds, + /obj/effect/decal/cleanable/molten_object, + ) + new extra_trash(T) + +/obj/effect/spawner/themed_mess/cooking + name = "cooking themed mess" + +/obj/effect/spawner/themed_mess/cooking/drop_mess(turf/T) + var mess_type = pick( + /obj/effect/decal/cleanable/egg_smudge, + /obj/effect/decal/cleanable/flour, + /obj/effect/decal/cleanable/blood/oil/cooking, + /obj/effect/decal/cleanable/ants, + ) + new mess_type(T) + +/obj/effect/spawner/themed_mess/cooking/drop_object(turf/T) + var/extra_trash = pick( + /obj/item/trash/plate, + /obj/item/food/snacks/meat, + /obj/item/trash/snack_bowl, + ) + var/obj/trash = new extra_trash(T) + trash.pixel_x = rand(-10, 10) + trash.pixel_y = rand(-10, 10) + trash.transform = turn(transform, rand(0, 360)) + +/proc/generate_themed_messes(themed_mess_types) + var/mess_count = rand(5, 10) + for(var/i in 1 to mess_count) + var/area/target_area = findEventArea() + var/list/turfs = get_area_turfs(target_area) + while(length(turfs)) + var/turf/T = pick_n_take(turfs) + // Just check for plasteel turf to avoid walls and areas under windows + // findEventArea excludes maintenance anyway so we don't care about missing plating + if(!istype(T, /turf/simulated/floor/plasteel)) + continue + var/spawner_type = pick(themed_mess_types) + new spawner_type(T, rand(10, 20)) + break diff --git a/paradise.dme b/paradise.dme index b29f519a52a..50ffe7ecf94 100644 --- a/paradise.dme +++ b/paradise.dme @@ -976,6 +976,7 @@ #include "code\game\objects\effects\spawners\gibspawner.dm" #include "code\game\objects\effects\spawners\grouped_spawner.dm" #include "code\game\objects\effects\spawners\lootdrop.dm" +#include "code\game\objects\effects\spawners\mess_spawners.dm" #include "code\game\objects\effects\spawners\random_barrier.dm" #include "code\game\objects\effects\spawners\random_spawners.dm" #include "code\game\objects\effects\spawners\vaultspawner.dm"