diff --git a/code/game/objects/effects/anomalies/anomalies_dimensional.dm b/code/game/objects/effects/anomalies/anomalies_dimensional.dm index 2d9b8ec71b4..9aea9dfea6a 100644 --- a/code/game/objects/effects/anomalies/anomalies_dimensional.dm +++ b/code/game/objects/effects/anomalies/anomalies_dimensional.dm @@ -8,7 +8,7 @@ /// Range of effect, if left alone anomaly will convert a 2(range)+1 squared area. var/range = 3 /// List of turfs this anomaly will try to transform before relocating - var/list/turf/target_turfs = new() + var/list/turf/target_turfs = list() /// Current anomaly 'theme', dictates what tiles to create. var/datum/dimension_theme/theme /// Effect displaying on the anomaly to represent the theme. @@ -38,7 +38,7 @@ var/turf/affected_turf = target_turfs[1] new /obj/effect/temp_visual/transmute_tile_flash(affected_turf) theme.apply_theme(affected_turf) - target_turfs.Remove(affected_turf) + target_turfs -= affected_turf /** * Prepare a new area for transformation into a new theme. @@ -50,11 +50,10 @@ theme = new new_theme_path() apply_theme_icon() - target_turfs = new() - var/list/turfs = spiral_range_turfs(range, src) - for (var/turf/turf in turfs) + target_turfs = list() + for (var/turf/turf as anything in spiral_range_turfs(range, src)) if (theme.can_convert(turf)) - target_turfs.Add(turf) + target_turfs += turf /** * Applies an overlay icon based on the current theme. diff --git a/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm b/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm index d1500e8bd89..16408ea9ce6 100644 --- a/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm +++ b/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm @@ -3,6 +3,8 @@ * Datum which describes a theme and replaces turfs and objects in specified locations to match that theme */ /datum/dimension_theme + /// Human readable name of the theme + var/name = "Unnamed Theme" /// An icon to display to represent the theme var/icon/icon /// Icon state to use to represent the theme @@ -16,11 +18,16 @@ /// Typepath of turf to replace walls with. var/turf/replace_walls = /turf/closed/wall/material /// List of weighted lists for object replacement. Key is an original typepath, value is a weighted list of typepaths to replace it with. - var/list/replace_objs = list(\ - /obj/structure/chair = list(/obj/structure/chair/greyscale = 1), \ - /obj/machinery/door/airlock = list(/obj/machinery/door/airlock/material = 1, /obj/machinery/door/airlock/material/glass = 1), \ - /obj/structure/table = list(/obj/structure/table/greyscale = 1), \ - /obj/structure/toilet = list(/obj/structure/toilet/greyscale = 1),) + var/list/replace_objs = list( + /obj/structure/chair = list(/obj/structure/chair/greyscale = 1), + /obj/machinery/door/airlock = list(/obj/machinery/door/airlock/material = 1, /obj/machinery/door/airlock/material/glass = 1), + /obj/structure/table = list(/obj/structure/table/greyscale = 1), + /obj/structure/toilet = list(/obj/structure/toilet/greyscale = 1), + ) + /// List of random spawns to place in completely open turfs + var/list/random_spawns + /// Prob of placing a random spawn in a completely open turf + var/random_spawn_chance = 0 /// Typepath of full-size windows which will replace existing ones /// These need to be separate from replace_objs because we don't want to replace dir windows with full ones and they share typepath var/obj/structure/window/replace_window @@ -38,15 +45,33 @@ * Arguments * * affected_turf - Turf to transform. */ -/datum/dimension_theme/proc/apply_theme(turf/affected_turf) +/datum/dimension_theme/proc/apply_theme(turf/affected_turf, skip_sound = FALSE) if (!replace_turf(affected_turf)) return - playsound(affected_turf, sound, 100, TRUE) + if (!skip_sound) + playsound(affected_turf, sound, 100, TRUE) for (var/obj/object in affected_turf) replace_object(object) + if (length(random_spawns) && prob(random_spawn_chance) && !affected_turf.is_blocked_turf(exclude_mobs = TRUE)) + var/random_spawn_picked = pick(random_spawns) + new random_spawn_picked(affected_turf) if (material) apply_materials(affected_turf) +/** + * Applies the transformation to a list of turfs, ensuring a sound is only played every few turfs to reduce noice spam + * + * Arguments + * * list/turf/all_turfs - List of turfs to transform. + */ +/datum/dimension_theme/proc/apply_theme_to_list_of_turfs(list/turf/all_turfs) + var/every_nth_turf = 0 + for (var/turf/turf as anything in all_turfs) + if(can_convert(turf)) + apply_theme(turf, skip_sound = (every_nth_turf % 7 != 0)) + every_nth_turf++ + CHECK_TICK + /** * Returns true if you actually can transform the provided turf. * @@ -75,6 +100,8 @@ * * affected_turf - Turf to transform. */ /datum/dimension_theme/proc/replace_turf(turf/affected_turf) + PROTECTED_PROC(TRUE) + if (isfloorturf(affected_turf)) if (isindestructiblefloor(affected_turf)) return FALSE @@ -96,6 +123,8 @@ * * affected_floor - Floor turf to transform. */ /datum/dimension_theme/proc/transform_floor(turf/open/floor/affected_floor) + PROTECTED_PROC(TRUE) + if (replace_floors.len == 0) return FALSE affected_floor.replace_floor(pick_weight(replace_floors), flags = CHANGETURF_INHERIT_AIR) @@ -108,6 +137,8 @@ * * object - Object to replace. */ /datum/dimension_theme/proc/replace_object(obj/object) + PROTECTED_PROC(TRUE) + if (istype(object, /obj/structure/window)) transform_window(object) return @@ -128,10 +159,11 @@ * * object - Object to transform. */ /datum/dimension_theme/proc/get_replacement_object_typepath(obj/object) + PROTECTED_PROC(TRUE) + for (var/type in replace_objs) if (istype(object, type)) return pick_weight(replace_objs[type]) - return /** * Replaces a window with a different window and recolours it. @@ -141,6 +173,8 @@ * * object - Object to transform. */ /datum/dimension_theme/proc/transform_window(obj/structure/window/window) + PROTECTED_PROC(TRUE) + if (!window.fulltile) return if (!replace_window) @@ -166,10 +200,10 @@ * * object - Object to transform. */ /datum/dimension_theme/proc/permit_replace_material(obj/object) - for (var/type in PERMITTED_MATERIAL_REPLACE_TYPES) - if (istype(object, type)) - return TRUE - return FALSE + PROTECTED_PROC(TRUE) + + return is_type_in_list(object, PERMITTED_MATERIAL_REPLACE_TYPES) + /** * Applies a new custom material to the contents of a provided turf. @@ -178,6 +212,8 @@ * * affected_turf - Turf to transform. */ /datum/dimension_theme/proc/apply_materials(turf/affected_turf) + PROTECTED_PROC(TRUE) + var/list/custom_materials = list(GET_MATERIAL_REF(material) = SHEET_MATERIAL_AMOUNT) if (istype(affected_turf, /turf/open/floor/material) || istype(affected_turf, /turf/closed/wall/material)) @@ -193,79 +229,110 @@ ///////////////////// /datum/dimension_theme/gold + name = "Gold" icon = 'icons/obj/stack_objects.dmi' icon_state = "sheet-gold_2" material = /datum/material/gold /datum/dimension_theme/plasma + name = "Plasma" icon = 'icons/obj/clothing/masks.dmi' icon_state = "gas_alt" material = /datum/material/plasma /datum/dimension_theme/clown + name = "Clown" icon = 'icons/obj/clothing/masks.dmi' icon_state = "clown" material = /datum/material/bananium sound = 'sound/items/bikehorn.ogg' /datum/dimension_theme/radioactive + name = "Radioactive" icon = 'icons/obj/ore.dmi' icon_state = "Uranium ore" material = /datum/material/uranium sound = 'sound/items/welder.ogg' /datum/dimension_theme/meat + name = "Meat" icon = 'icons/obj/food/meat.dmi' icon_state = "meat" material = /datum/material/meat sound = 'sound/items/eatfood.ogg' /datum/dimension_theme/pizza + name = "Pizza" icon = 'icons/obj/food/pizza.dmi' icon_state = "pizzamargherita" material = /datum/material/pizza sound = 'sound/items/eatfood.ogg' /datum/dimension_theme/natural + name = "Natural" icon = 'icons/obj/service/hydroponics/harvest.dmi' icon_state = "map_flower" window_colour = "#00f7ff" replace_floors = list(/turf/open/floor/grass = 1) replace_walls = /turf/closed/wall/mineral/wood/nonmetal - replace_objs = list(\ - /obj/structure/chair = list(/obj/structure/chair/wood = 3, /obj/structure/chair/wood/wings = 1), \ - /obj/machinery/door/airlock = list(/obj/machinery/door/airlock/wood = 1, /obj/machinery/door/airlock/wood/glass = 1), \ - /obj/structure/table = list(/obj/structure/table/wood = 5, /obj/structure/table/wood/fancy = 1),) + replace_objs = list( + /obj/structure/chair = list(/obj/structure/chair/wood = 3, /obj/structure/chair/wood/wings = 1), + /obj/machinery/door/airlock = list(/obj/machinery/door/airlock/wood = 1, /obj/machinery/door/airlock/wood/glass = 1), + /obj/structure/table = list(/obj/structure/table/wood = 5, /obj/structure/table/wood/fancy = 1), + ) /datum/dimension_theme/bamboo + name = "Bamboo" icon = 'icons/obj/service/hydroponics/harvest.dmi' icon_state = "bamboo" replace_floors = list(/turf/open/floor/bamboo = 1) replace_walls = /turf/closed/wall/mineral/bamboo replace_window = /obj/structure/window/paperframe - replace_objs = list(\ - /obj/structure/chair = list(/obj/structure/chair/stool/bamboo = 1), \ - /obj/machinery/door/airlock = list(/obj/machinery/door/airlock/wood = 1, /obj/machinery/door/airlock/wood/glass = 1), \ - /obj/structure/table = list(/obj/structure/table/wood = 1),) + replace_objs = list( + /obj/structure/chair = list(/obj/structure/chair/stool/bamboo = 1), + /obj/machinery/door/airlock = list(/obj/machinery/door/airlock/wood = 1, /obj/machinery/door/airlock/wood/glass = 1), + /obj/structure/table = list(/obj/structure/table/wood = 1), + ) /datum/dimension_theme/icebox - icon = 'icons/obj/clothing/shoes.dmi' - icon_state = "iceboots" + name = "Winter" + icon = 'icons/obj/clothing/head/costume.dmi' + icon_state = "snowman_h" window_colour = "#00f7ff" material = /datum/material/snow replace_floors = list(/turf/open/floor/fake_snow = 10, /turf/open/floor/fakeice/slippery = 1) replace_walls = /turf/closed/wall/mineral/snow + random_spawns = list( + /obj/structure/flora/grass/both/style_random, + /obj/structure/flora/grass/brown/style_random, + /obj/structure/flora/grass/green/style_random, + ) + random_spawn_chance = 8 + +/datum/dimension_theme/icebox/winter_cabin + name = "Winter Cabin" + icon = 'icons/obj/clothing/shoes.dmi' + icon_state = "iceboots" + replace_walls = /turf/closed/wall/mineral/wood + replace_objs = list( + /obj/structure/chair = list(/obj/structure/chair/wood = 1), + /obj/machinery/door/airlock = list(/obj/machinery/door/airlock/wood = 1), + /obj/structure/table = list(/obj/structure/table/wood = 1), + ) /datum/dimension_theme/lavaland + name = "Lavaland" icon = 'icons/obj/stack_objects.dmi' icon_state = "goliath_hide" window_colour = "#860000" replace_floors = list(/turf/open/floor/fakebasalt = 5, /turf/open/floor/fakepit = 1) replace_walls = /turf/closed/wall/mineral/cult - replace_objs = list(\ - /obj/machinery/door/airlock = list(/obj/machinery/door/airlock/external/glass/ruin = 1)) + replace_objs = list(/obj/machinery/door/airlock = list(/obj/machinery/door/airlock/external/glass/ruin = 1)) + random_spawns = list(/mob/living/basic/mining/goldgrub) + random_spawn_chance = 1 /datum/dimension_theme/space + name = "Space" icon = 'icons/effects/effects.dmi' icon_state = "blessed" window_colour = "#000000" @@ -275,6 +342,7 @@ replace_objs = list(/obj/machinery/door/airlock = list(/obj/machinery/door/airlock/external/glass/ruin = 1)) /datum/dimension_theme/glass + name = "Glass" icon = 'icons/obj/debris.dmi' icon_state = "small" material = /datum/material/glass @@ -282,6 +350,7 @@ sound = SFX_SHATTER /datum/dimension_theme/fancy + name = "Fancy" icon = 'icons/obj/clothing/head/costume.dmi' icon_state = "fancycrown" replace_walls = /turf/closed/wall/mineral/wood/nonmetal @@ -301,15 +370,18 @@ /turf/open/floor/carpet/royalblue,) /datum/dimension_theme/fancy/New() + . = ..() replace_floors = list(pick(FANCY_CARPETS) = 1) - replace_objs = list(\ - /obj/structure/chair = list(/obj/structure/chair/comfy = 1), \ - /obj/machinery/door/airlock = list(/obj/machinery/door/airlock/wood = 1, /obj/machinery/door/airlock/wood/glass = 1), \ - /obj/structure/table/wood = list(pick(subtypesof(/obj/structure/table/wood/fancy)) = 1),) + replace_objs = list( + /obj/structure/chair = list(/obj/structure/chair/comfy = 1), + /obj/machinery/door/airlock = list(/obj/machinery/door/airlock/wood = 1, /obj/machinery/door/airlock/wood/glass = 1), + /obj/structure/table/wood = list(pick(subtypesof(/obj/structure/table/wood/fancy)) = 1), + ) #undef FANCY_CARPETS /datum/dimension_theme/disco + name = "Disco" icon = 'icons/obj/lighting.dmi' icon_state = "lbulb" material = /datum/material/glass @@ -322,3 +394,40 @@ var/turf/open/floor/light/disco_floor = affected_floor disco_floor.currentcolor = pick(disco_floor.coloredlights) disco_floor.update_appearance() + +/datum/dimension_theme/jungle + name = "Jungle" + icon = 'icons/obj/tiles.dmi' + icon_state = "tile_grass" + sound = SFX_CRUNCHY_BUSH_WHACK + replace_floors = list(/turf/open/floor/grass = 1) + replace_walls = /turf/closed/wall/mineral/wood + replace_objs = list( + /obj/structure/chair = list(/obj/structure/chair/wood = 1), + /obj/machinery/door/airlock = list(/obj/machinery/door/airlock/wood = 1), + /obj/structure/table = list(/obj/structure/table/wood = 1), + ) + random_spawns = list( + /mob/living/carbon/human/species/monkey, + /obj/structure/flora/bush/ferny/style_random, + /obj/structure/flora/bush/grassy/style_random, + /obj/structure/flora/bush/leavy/style_random, + /obj/structure/flora/tree/palm/style_random, + /obj/structure/flora/bush/sparsegrass/style_random, + /obj/structure/flora/bush/sunny/style_random, + ) + random_spawn_chance = 20 + +/datum/dimension_theme/ayylmao + name = "Alien" + icon = 'icons/obj/antags/abductor.dmi' + icon_state = "sheet-abductor" + material = /datum/material/alloy/alien + replace_walls = /turf/closed/wall/mineral/abductor + replace_floors = list(/turf/open/floor/mineral/abductor = 1) + replace_objs = list( + /obj/structure/chair = list(/obj/structure/chair/greyscale = 9, /obj/structure/bed/abductor = 1), + /obj/machinery/door/airlock = list(/obj/machinery/door/airlock/material = 1, /obj/machinery/door/airlock/material/glass = 2), + /obj/structure/table = list(/obj/structure/table/greyscale = 9, /obj/structure/table/abductor = 1), + /obj/structure/toilet = list(/obj/structure/toilet/greyscale = 1), + ) diff --git a/code/modules/antagonists/wizard/grand_ritual/finales/midas.dm b/code/modules/antagonists/wizard/grand_ritual/finales/midas.dm index b2e3329261f..98eb56fadac 100644 --- a/code/modules/antagonists/wizard/grand_ritual/finales/midas.dm +++ b/code/modules/antagonists/wizard/grand_ritual/finales/midas.dm @@ -39,8 +39,4 @@ addtimer(CALLBACK(src, PROC_REF(transform_area), turfs_to_transform["[iterator]"]), (5 SECONDS) * iterator) /datum/grand_finale/midas/proc/transform_area(list/turfs) - for (var/turf/transform_turf as anything in turfs) - if (!chosen_theme.can_convert(transform_turf)) - continue - chosen_theme.apply_theme(transform_turf) - CHECK_TICK + chosen_theme.apply_theme_to_list_of_turfs(turfs) diff --git a/code/modules/antagonists/wizard/grand_ritual/grand_side_effect.dm b/code/modules/antagonists/wizard/grand_ritual/grand_side_effect.dm index 950390a7227..54e8d0fed5c 100644 --- a/code/modules/antagonists/wizard/grand_ritual/grand_side_effect.dm +++ b/code/modules/antagonists/wizard/grand_ritual/grand_side_effect.dm @@ -74,8 +74,7 @@ addtimer(CALLBACK(src, PROC_REF(staggered_transform), theme, range_turfs), (0.5 SECONDS) * iterator) /datum/grand_side_effect/transmogrify_area/proc/staggered_transform(datum/dimension_theme/theme, list/transform_turfs) - for (var/turf/target_turf as anything in transform_turfs) - theme.apply_theme(target_turf) + theme.apply_theme_to_list_of_turfs(transform_turfs) /// Minimum number of anomalies to create #define MIN_ANOMALIES_CREATED 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 f726fcb9819..6be52bf1c85 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -238,7 +238,6 @@ var/use_time = 0 /// If we are being used var/active = FALSE - var/list/affected_targets = list() var/activation_sound = 'sound/effects/break_stone.ogg' COOLDOWN_DECLARE(cooldown_timer) @@ -320,14 +319,28 @@ possible_methods = list(ACTIVATE_MOB_BUMP, ACTIVATE_SPEECH) activation_sound = 'sound/items/bikehorn.ogg' use_time = 3 SECONDS + /// List of REFs to mobs that have been turned into a clown + var/list/clowned_mob_refs = list() /obj/machinery/anomalous_crystal/honk/ActivationReaction(mob/user) - if(..() && ishuman(user) && !(user in affected_targets) && (user in viewers(src))) - var/mob/living/carbon/human/new_clown = user - for(var/obj/item/to_strip in new_clown) - new_clown.dropItemToGround(to_strip) - new_clown.dress_up_as_job(SSjob.GetJobType(/datum/job/clown)) - affected_targets.Add(new_clown) + . = ..() + if(!.) + return FALSE + + if(!ishuman(user)) + return FALSE + if(!(user in viewers(src))) + return FALSE + var/clown_ref = REF(user) + if(clown_ref in clowned_mob_refs) + return FALSE + + var/mob/living/carbon/human/new_clown = user + for(var/obj/item/to_strip in new_clown.get_equipped_items()) + new_clown.dropItemToGround(to_strip) + new_clown.dress_up_as_job(SSjob.GetJobType(/datum/job/clown)) + clowned_mob_refs += clown_ref + return TRUE /// Transforms the area to look like a new one /obj/machinery/anomalous_crystal/theme_warp @@ -335,130 +348,32 @@ activation_method = ACTIVATE_TOUCH cooldown_add = 20 SECONDS use_time = 5 SECONDS - var/datum/crystal_warp_theme/terrain_theme + /// Theme which we turn areas into on activation + var/datum/dimension_theme/terrain_theme + /// List of all areas we've affected + var/list/converted_areas = list() /obj/machinery/anomalous_crystal/theme_warp/Initialize(mapload) . = ..() - var/terrain_type = pick(subtypesof(/datum/crystal_warp_theme)) + var/terrain_type = pick(subtypesof(/datum/dimension_theme)) terrain_theme = new terrain_type() - observer_desc = "This crystal changes the area around it to match the theme of \"[terrain_theme]\"." + observer_desc = "This crystal changes the area around it to match the theme of \"[terrain_theme.name]\"." /obj/machinery/anomalous_crystal/theme_warp/ActivationReaction(mob/user, method) . = ..() if (!.) return FALSE var/area/current_area = get_area(src) - if (current_area in affected_targets) + if (current_area in converted_areas) return FALSE - if (terrain_theme.transform_area(current_area)) - affected_targets += current_area + terrain_theme.apply_theme_to_list_of_turfs(current_area.get_contained_turfs()) + converted_areas += current_area return TRUE -/// Transforms an area's turfs and objects into a different theme -/datum/crystal_warp_theme - /// Friendly name of theme - var/name = "" - /// Typepath of floor to replace open turfs with - var/floor - /// Typepath of wall to replace closed turfs with - var/wall - /// Typepath of object to replace chairs with - var/chair - /// Typepath of object to replace tables with - var/table - /// Typepath of things to potentially spawn on transformed open turfs - var/list/flora_and_fauna = list() - /// Chance per turf to create the things in the list above - var/flora_and_fauna_chance = 8 - -/// Change appropriate objects in provided area to those matching our theme, and spawn some plants or animals -/datum/crystal_warp_theme/proc/transform_area(area/target_area) - if (target_area.outdoors) - return FALSE - for(var/atom/thing in target_area) - if(isturf(thing)) - replace_turf(thing) - continue - if(chair && istype(thing, /obj/structure/chair)) - replace_object(thing, chair) - continue - if(table && istype(thing, /obj/structure/table)) - replace_object(thing, table) - continue - return TRUE - -/// Replaces a turf with a different themed turf -/datum/crystal_warp_theme/proc/replace_turf(turf/target_turf) - if(isindestructiblefloor(target_turf) || isindestructiblewall(target_turf) || isopenspaceturf(target_turf)) - return - - if(wall && iswallturf(target_turf)) - target_turf.ChangeTurf(wall) - return - - if(!isopenturf(target_turf)) - return - - if(length(flora_and_fauna) && !target_turf.is_blocked_turf(exclude_mobs = TRUE) && prob(flora_and_fauna_chance)) - var/atom/new_flora_and_fauna = pick(flora_and_fauna) - new new_flora_and_fauna(target_turf) - - if(floor) - var/turf/open/open_turf = target_turf - open_turf.replace_floor(floor, flags = CHANGETURF_IGNORE_AIR) - -/// Replaces an object with a different themed object -/datum/crystal_warp_theme/proc/replace_object(atom/original, new_type) - var/atom/new_thing = new new_type(original.loc) - new_thing.setDir(original.dir) - qdel(original) - -// Depressurizes the place... and free cult metal, I guess. -/datum/crystal_warp_theme/lavaland - name = "lavaland" - floor = /turf/open/floor/fakebasalt - wall = /turf/closed/wall/mineral/cult - flora_and_fauna = list(/mob/living/basic/mining/goldgrub) - flora_and_fauna_chance = 1 - -// Snow terrain is slow to move in and cold! Get the assistants to shovel your driveway. -/datum/crystal_warp_theme/winter - name = "winter" - floor = /turf/open/misc/snow/actually_safe - wall = /turf/closed/wall/mineral/wood - chair = /obj/structure/chair/wood - table = /obj/structure/table/glass - flora_and_fauna = list( - /obj/structure/flora/grass/both/style_random, - /obj/structure/flora/grass/brown/style_random, - /obj/structure/flora/grass/green/style_random, - ) - -// Beneficial due to actually having breathable air. Plus, monkeys and bows and arrows. -/datum/crystal_warp_theme/jungle - name = "jungle" - floor = /turf/open/floor/grass - wall = /turf/closed/wall/mineral/wood - chair = /obj/structure/chair/wood - table = /obj/structure/table/wood - flora_and_fauna = list( - /mob/living/carbon/human/species/monkey, - /obj/structure/flora/bush/ferny/style_random, - /obj/structure/flora/bush/grassy/style_random, - /obj/structure/flora/bush/leavy/style_random, - /obj/structure/flora/tree/palm/style_random, - /obj/structure/flora/bush/sparsegrass/style_random, - /obj/structure/flora/bush/sunny/style_random, - ) - flora_and_fauna_chance = 20 - -// Beneficial, turns stuff into alien alloy which is useful to cargo and research. Also repairs atmos. -/datum/crystal_warp_theme/ayylmao - name = "ayy lmao" - floor = /turf/open/floor/mineral/abductor - wall = /turf/closed/wall/mineral/abductor - chair = /obj/structure/bed/abductor //ayys apparently don't have chairs. An entire species of people who only recline. - table = /obj/structure/table/abductor +/obj/machinery/anomalous_crystal/theme_warp/Destroy() + QDEL_NULL(terrain_theme) + converted_areas.Cut() + return ..() /obj/machinery/anomalous_crystal/emitter //Generates a projectile when interacted with observer_desc = "This crystal generates a projectile when activated."