Files
Bubberstation/code/game/objects/effects/anomaly_dimensional_themes.dm
T
a4bfe65cb1 [MIRROR] Dimensional Anomaly [MDB IGNORE] (#15974)
* Dimensional Anomaly (#69512)

About The Pull Request

Everyone has been asking: "When will there be an anomaly like the bioscrambler, but for the space station? Please, we need more things which replace objects with different objects from the same typepath."
Well I made it and it looked like ass because non-tiling floor and walls look terrible, so then I made this instead.
Dimensional.mp4

The "dimensional anomaly" shifts matter into a parallel dimension where objects are made out of something else.
Like the Bioscrambler anomaly, it does not expire on its own and only leaves when someone signals it or uses an anomaly remover.
When it spawns it picks a "theme" and converts terrain around it until it covers a 7x7 square, then it teleports somewhere else and picks a new theme.

A lot of these themes are relatively benign like "meat", "fancy carpet", or "gold". Some of them are kind of annoying like "icebox" because it creates floor which slows you down, or "clown" because bananium is intentionally annoying. Some of them are actively dangerous, mostly "uranium" and "plasma".
The main problem this will usually cause for crewmembers is decreasing area security. When it replaces doors it replaces them with ones which don't have any access control, and it will also replace RWalls with normal and much more vulnerable walls which will make breaking and entering significantly easier until someone has taken the time to fix the damage. But also sometimes it will irradiate them, you never know.

The fact that sometimes the changes are benign (or provide uncommon materials) and might be happening in places you don't care about access to might encourage people to push their luck and leave it alone until it starts turning the captain's office into a bamboo room or repainting medbay a fetching shade of flammable purple, which I would consider a success.
Armour.mp4

If you successfully harvest the anomaly core you can place it into the reactive armour to get Reactive Barricade Armour, which shifts your dimension when you take damage and attempts to place some randomised (not terribly durable) objects between you and hopefully your attacker (it really just picks up to four random unoccupied tiles next to you). If you're EMPed then the changes it make to the environment will often be as unpleasant for you as they are for a pursuer, and significantly more likely to harm both of you rather than just provide obstacles.

Other changes:
I split anomalies out into their own dmi file, seems to be all the rage lately.
I moved the anomaly placing code into a datum instead of the event because I wanted to reuse it but if you have a better idea about where I could have put it let me know.
This also fixes a bug where the material spreader component wasn't working when I applied plasma materials to something, the extra whitespace was parsing as another argument for some reason and meant it would runtime.
Supermatter delamination was still pointing to Delimber anomalies instead of Bioscrambler.

* Dimensional Anomaly

* Fixes the upstream merge skew

Co-authored-by: Jacquerel <hnevard@gmail.com>
Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com>
Co-authored-by: GoldenAlpharex <jerego1234@hotmail.com>
2022-09-05 17:59:34 -04:00

329 lines
10 KiB
Plaintext

/**
* Datum which describes a theme and replaces turfs and objects in specified locations to match that theme
*/
/datum/dimension_theme
/// An icon to display to represent the theme
var/icon/icon
/// Icon state to use to represent the theme
var/icon_state
/// Typepath of custom material to use for objects.
var/datum/material/material
/// Sound to play when transforming a tile
var/sound = 'sound/magic/blind.ogg'
/// Weighted list of turfs to replace the floor with.
var/list/replace_floors = list(/turf/open/floor/material = 1)
/// 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),)
/// 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
/// Colour to recolour windows with, replaced by material colour if material was specified.
var/window_colour = "#ffffff"
/datum/dimension_theme/New()
if (material)
var/datum/material/using_mat = GET_MATERIAL_REF(material)
window_colour = using_mat.greyscale_colors
/**
* Returns a subtype of dimensional theme.
*/
/datum/dimension_theme/proc/get_random_theme()
var/subtype = pick(subtypesof(/datum/dimension_theme))
return new subtype()
/**
* Applies themed transformation to the provided turf.
*
* Arguments
* * affected_turf - Turf to transform.
*/
/datum/dimension_theme/proc/apply_theme(turf/affected_turf)
if (!replace_turf(affected_turf))
return
playsound(affected_turf, sound, 100, TRUE)
for (var/obj/object in affected_turf)
replace_object(object)
if (material)
apply_materials(affected_turf)
/**
* Returns true if you actually can transform the provided turf.
*
* Arguments
* * affected_turf - Turf to transform.
*/
/datum/dimension_theme/proc/can_convert(turf/affected_turf)
if (isspaceturf(affected_turf))
return FALSE
if (isfloorturf(affected_turf))
if (isindestructiblefloor(affected_turf))
return FALSE
if (affected_turf.holodeck_compatible)
return FALSE
return replace_floors.len > 0
if (iswallturf(affected_turf))
if (isindestructiblewall(affected_turf))
return FALSE
return TRUE
return FALSE
/**
* Replaces the provided turf with a different one.
*
* Arguments
* * affected_turf - Turf to transform.
*/
/datum/dimension_theme/proc/replace_turf(turf/affected_turf)
if (isfloorturf(affected_turf))
if (isindestructiblefloor(affected_turf))
return FALSE
if (affected_turf.holodeck_compatible)
return FALSE
return transform_floor(affected_turf)
if (!iswallturf(affected_turf))
return FALSE
if (isindestructiblewall(affected_turf))
return FALSE
affected_turf.ChangeTurf(replace_walls)
return TRUE
/**
* Replaces the provided floor turf with a different one.
*
* Arguments
* * affected_floor - Floor turf to transform.
*/
/datum/dimension_theme/proc/transform_floor(turf/open/floor/affected_floor)
if (replace_floors.len == 0)
return FALSE
affected_floor.ChangeTurf(pick_weight(replace_floors), flags = CHANGETURF_INHERIT_AIR)
return TRUE
/**
* Replaces the provided object with a different one.
*
* Arguments
* * object - Object to replace.
*/
/datum/dimension_theme/proc/replace_object(obj/object)
if (istype(object, /obj/structure/window))
transform_window(object)
return
var/replace_path = get_replacement_object_typepath(object)
if (!replace_path)
return
var/obj/new_object = new replace_path(object.loc)
new_object.setDir(object.dir)
qdel(object)
/**
* Returns the typepath of an object to replace the provided object.
*
* Arguments
* * object - Object to transform.
*/
/datum/dimension_theme/proc/get_replacement_object_typepath(obj/object)
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.
* This needs its own function because we only want to replace full tile windows.
*
* Arguments
* * object - Object to transform.
*/
/datum/dimension_theme/proc/transform_window(obj/structure/window/window)
if (!window.fulltile)
return
if (!replace_window)
window.add_atom_colour(window_colour, FIXED_COLOUR_PRIORITY)
return
var/obj/structure/window/new_window = new replace_window(window.loc)
new_window.add_atom_colour(window_colour, FIXED_COLOUR_PRIORITY)
qdel(window)
#define PERMITTED_MATERIAL_REPLACE_TYPES list(\
/obj/structure/chair, \
/obj/machinery/door/airlock, \
/obj/structure/table, \
/obj/structure/toilet, \
/obj/structure/window, \
/obj/structure/sink,)
/**
* Returns true if the provided object can have its material modified.
*
* Arguments
* * 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
/**
* Applies a new custom material to the contents of a provided turf.
*
* Arguments
* * affected_turf - Turf to transform.
*/
/datum/dimension_theme/proc/apply_materials(turf/affected_turf)
var/list/custom_materials = list(GET_MATERIAL_REF(material) = MINERAL_MATERIAL_AMOUNT)
if (istype(affected_turf, /turf/open/floor/material) || istype(affected_turf, /turf/closed/wall/material))
affected_turf.set_custom_materials(custom_materials)
for (var/obj/thing in affected_turf)
if (!permit_replace_material(thing))
continue
thing.set_custom_materials(custom_materials)
#undef PERMITTED_MATERIAL_REPLACE_TYPES
/////////////////////
/datum/dimension_theme/gold
icon = 'icons/obj/stack_objects.dmi'
icon_state = "sheet-gold_2"
material = /datum/material/gold
/datum/dimension_theme/plasma
icon = 'icons/obj/clothing/masks.dmi'
icon_state = "gas_alt"
material = /datum/material/plasma
/datum/dimension_theme/clown
icon = 'icons/obj/clothing/masks.dmi'
icon_state = "clown"
material = /datum/material/bananium
sound = 'sound/items/bikehorn.ogg'
/datum/dimension_theme/radioactive
icon = 'icons/obj/ore.dmi'
icon_state = "Uranium ore"
material = /datum/material/uranium
sound = 'sound/items/welder.ogg'
/datum/dimension_theme/meat
icon = 'icons/obj/food/meat.dmi'
icon_state = "meat"
material = /datum/material/meat
sound = 'sound/items/eatfood.ogg'
/datum/dimension_theme/pizza
icon = 'icons/obj/food/pizza.dmi'
icon_state = "pizzamargherita"
material = /datum/material/pizza
sound = 'sound/items/eatfood.ogg'
/datum/dimension_theme/natural
icon = 'icons/obj/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),)
/datum/dimension_theme/bamboo
icon = 'icons/obj/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),)
/datum/dimension_theme/icebox
icon = 'icons/obj/clothing/shoes.dmi'
icon_state = "iceboots"
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
/datum/dimension_theme/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))
/datum/dimension_theme/space
icon = 'icons/effects/effects.dmi'
icon_state = "blessed"
window_colour = "#000000"
material = /datum/material/glass
replace_floors = list(/turf/open/floor/fakespace = 1)
replace_walls = /turf/closed/wall/rock/porous
replace_objs = list(/obj/machinery/door/airlock = list(/obj/machinery/door/airlock/external/glass/ruin = 1))
/datum/dimension_theme/glass
icon = 'icons/obj/shards.dmi'
icon_state = "small"
material = /datum/material/glass
replace_floors = list(/turf/open/floor/glass = 1)
sound = SFX_SHATTER
/datum/dimension_theme/fancy
icon = 'icons/obj/clothing/hats.dmi'
icon_state = "fancycrown"
replace_walls = /turf/closed/wall/mineral/wood/nonmetal
#define FANCY_CARPETS list(\
/turf/open/floor/eighties, \
/turf/open/floor/eighties/red, \
/turf/open/floor/carpet/lone/star, \
/turf/open/floor/carpet/black, \
/turf/open/floor/carpet/blue, \
/turf/open/floor/carpet/cyan, \
/turf/open/floor/carpet/green, \
/turf/open/floor/carpet/orange, \
/turf/open/floor/carpet/purple, \
/turf/open/floor/carpet/red, \
/turf/open/floor/carpet/royalblack, \
/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),)
#undef FANCY_CARPETS
/datum/dimension_theme/disco
icon = 'icons/obj/lighting.dmi'
icon_state = "lbulb"
material = /datum/material/glass
replace_floors = list(/turf/open/floor/light = 1)
/datum/dimension_theme/disco/transform_floor(turf/open/floor/affected_floor)
. = ..()
if (!.)
return
var/turf/open/floor/light/disco_floor = affected_floor
disco_floor.currentcolor = pick(disco_floor.coloredlights)
disco_floor.update_appearance()