From 34f67a1e57dd31b895cfba4bcc0ec4dcab0b5d88 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Tue, 27 Feb 2024 05:15:58 +0100 Subject: [PATCH] [MIRROR] Adds a multi-dimensional bomb payload to the black market. (#26663) * Adds a multi-dimensional bomb payload to the black market. (#81562) ## About The Pull Request This PR adds a !!!FUN!!! bomb payload to the blackmarket, which, upon detonation, transmutates all terrain in a range like the dimensional anomaly would. You can also select the dimensional theme to use by using it in your hand. I believe however, this thing should cost a fuckton to get and only show up occasionally. 8k to 10k was my original idea, but I think that's perhaps not high enough given its flagrant potential. Perhaps I should also make it so the more dangerous themes yield a shorter range than others. Suggestions are welcome. Screenshot of what happens when you don't set the theme: ![chaotic_mess](https://github.com/tgstation/tgstation/assets/42542238/e4c3264d-17e0-45b6-90c2-3c30a592ae2d) This PR also turns dimension themes into singletons so we access them more easily. Nothing to write home about. ## Why It's Good For The Game The black market could always use some extra thingy or two anyway, and this thing could either be a source of emergent gameplay, or a recipe for a disaster. Perhaps second to the Big Slappy for how funny it could be. ## Changelog :cl: add: Added a multi-dimensional bomb payload to the black market. It's very expensive. /:cl: * Adds a multi-dimensional bomb payload to the black market. --------- Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com> --- code/controllers/subsystem/materials.dm | 5 ++ code/game/machinery/syndicatebomb.dm | 62 +++++++++++++++++++ .../anomalies/anomalies_dimensional.dm | 10 ++- .../anomalies/anomalies_dimensional_themes.dm | 30 +++++---- .../cargo/markets/market_items/weapons.dm | 9 +++ .../hostile/megafauna/colossus.dm | 5 +- 6 files changed, 104 insertions(+), 17 deletions(-) diff --git a/code/controllers/subsystem/materials.dm b/code/controllers/subsystem/materials.dm index 4ae9272e970..25efd8695dc 100644 --- a/code/controllers/subsystem/materials.dm +++ b/code/controllers/subsystem/materials.dm @@ -33,6 +33,9 @@ SUBSYSTEM_DEF(materials) new /datum/stack_recipe("Carving block", /obj/structure/carving_block, 5, time = 3 SECONDS, one_per_turf = TRUE, on_solid_ground = TRUE, applies_mats = TRUE, category = CAT_STRUCTURE), ) + ///A list of dimensional themes used by the dimensional anomaly and other things, most of which require materials to function. + var/list/datum/dimension_theme/dimensional_themes + ///Ran on initialize, populated the materials and materials_by_category dictionaries with their appropiate vars (See these variables for more info) /datum/controller/subsystem/materials/proc/InitializeMaterials() materials = list() @@ -47,6 +50,8 @@ SUBSYSTEM_DEF(materials) continue // Do not initialize at mapload InitializeMaterial(list(mat_type)) + dimensional_themes = init_subtypes_w_path_keys(/datum/dimension_theme) + /** Creates and caches a material datum. * * Arugments: diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm index bc1523bde0e..ab381b14fad 100644 --- a/code/game/machinery/syndicatebomb.dm +++ b/code/game/machinery/syndicatebomb.dm @@ -584,6 +584,68 @@ qdel(src) +#define DIMENSION_CHOICE_RANDOM "None/Randomized" + +/obj/item/bombcore/dimensional + name = "multi-dimensional payload" + desc = "A wicked payload meant to wildly transmutate terrain over a wide area, a power no mere human should wield." + range_heavy = 17 + var/datum/dimension_theme/chosen_theme + +/obj/item/bombcore/dimensional/Destroy() + chosen_theme = null + return ..() + +/obj/item/bombcore/dimensional/examine(mob/user) + . = ..() + . += span_notice("Use in hand to change the linked dimension. Current dimension: [chosen_theme?.name || "None, output will be random"].") + +/obj/item/bombcore/dimensional/attack_self(mob/user) + . = ..() + var/list/choosable_dimensions = list() + var/datum/radial_menu_choice/null_choice = new + null_choice.name = DIMENSION_CHOICE_RANDOM + choosable_dimensions += null_choice + for(var/datum/dimension_theme/theme as anything in SSmaterials.dimensional_themes) + var/datum/radial_menu_choice/theme_choice = new + theme_choice.image = image(initial(theme.icon), initial(theme.icon_state)) + theme_choice.name = initial(theme.name) + choosable_dimensions[theme] = theme_choice + + var/datum/dimension_theme/picked = show_radial_menu(user, src, choosable_dimensions, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 38, require_near = TRUE) + if(isnull(picked)) + return + if(picked == DIMENSION_CHOICE_RANDOM) + chosen_theme = null + else + chosen_theme = picked + balloon_alert(user, "set to [chosen_theme?.name || DIMENSION_CHOICE_RANDOM]") + +/obj/item/bombcore/dimensional/proc/check_menu(mob/user) + if(!user.is_holding(src) || user.incapacitated()) + return FALSE + return TRUE + +/obj/item/bombcore/dimensional/detonate() + var/list/affected_turfs = circle_range_turfs(src, range_heavy) + var/theme_count = length(SSmaterials.dimensional_themes) + var/num_affected = 0 + for(var/turf/affected as anything in affected_turfs) + var/datum/dimension_theme/theme_to_use = chosen_theme + if(isnull(chosen_theme)) + theme_to_use = SSmaterials.dimensional_themes[SSmaterials.dimensional_themes[rand(1, theme_count)]] + if(!theme_to_use.can_convert(affected)) + continue + num_affected++ + var/skip_sound = TRUE + if(num_affected % 5) //makes it play the sound more sparingly + skip_sound = FALSE + var/time_mult = round(get_dist_euclidian(get_turf(src), affected)) + 1 + addtimer(CALLBACK(theme_to_use, TYPE_PROC_REF(/datum/dimension_theme, apply_theme), affected, skip_sound, TRUE), 0.1 SECONDS * time_mult) + qdel(src) + +#undef DIMENSION_CHOICE_RANDOM + ///Syndicate Detonator (aka the big red button)/// /obj/item/syndicatedetonator diff --git a/code/game/objects/effects/anomalies/anomalies_dimensional.dm b/code/game/objects/effects/anomalies/anomalies_dimensional.dm index 9aea9dfea6a..16dd5bafcfa 100644 --- a/code/game/objects/effects/anomalies/anomalies_dimensional.dm +++ b/code/game/objects/effects/anomalies/anomalies_dimensional.dm @@ -21,6 +21,11 @@ animate(src, transform = matrix()*0.85, time = 3, loop = -1) animate(transform = matrix(), time = 3, loop = -1) +/obj/effect/anomaly/dimensional/Destroy() + theme = null + target_turfs = null + return ..() + /obj/effect/anomaly/dimensional/anomalyEffect(seconds_per_tick) . = ..() transmute_area() @@ -36,8 +41,7 @@ return var/turf/affected_turf = target_turfs[1] - new /obj/effect/temp_visual/transmute_tile_flash(affected_turf) - theme.apply_theme(affected_turf) + theme.apply_theme(affected_turf, show_effect = TRUE) target_turfs -= affected_turf /** @@ -47,7 +51,7 @@ /obj/effect/anomaly/dimensional/proc/prepare_area(new_theme_path) if (!new_theme_path) new_theme_path = pick(subtypesof(/datum/dimension_theme)) - theme = new new_theme_path() + theme = SSmaterials.dimensional_themes[new_theme_path] apply_theme_icon() target_turfs = list() diff --git a/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm b/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm index 16408ea9ce6..c6190a0d84a 100644 --- a/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm +++ b/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm @@ -1,4 +1,3 @@ - /** * Datum which describes a theme and replaces turfs and objects in specified locations to match that theme */ @@ -44,12 +43,16 @@ * * Arguments * * affected_turf - Turf to transform. + * * skip_sound - If the sound shouldn't be played. + * * show_effect - if the temp visual effect should be shown. */ -/datum/dimension_theme/proc/apply_theme(turf/affected_turf, skip_sound = FALSE) +/datum/dimension_theme/proc/apply_theme(turf/affected_turf, skip_sound = FALSE, show_effect = FALSE) if (!replace_turf(affected_turf)) return if (!skip_sound) playsound(affected_turf, sound, 100, TRUE) + if(show_effect) + new /obj/effect/temp_visual/transmute_tile_flash(affected_turf) 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)) @@ -250,7 +253,7 @@ /datum/dimension_theme/radioactive name = "Radioactive" icon = 'icons/obj/ore.dmi' - icon_state = "Uranium ore" + icon_state = "uranium" material = /datum/material/uranium sound = 'sound/items/welder.ogg' @@ -353,7 +356,14 @@ name = "Fancy" icon = 'icons/obj/clothing/head/costume.dmi' icon_state = "fancycrown" + replace_floors = null replace_walls = /turf/closed/wall/mineral/wood/nonmetal + 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), + ) + ///cooldown for changing carpets, It's kinda dull to always use the same one, but we also can't make it too random. + COOLDOWN_DECLARE(carpet_switch_cd) #define FANCY_CARPETS list(\ /turf/open/floor/eighties, \ @@ -369,14 +379,12 @@ /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), - ) +/datum/dimension_theme/fancy/apply_theme(turf/affected_turf, skip_sound = FALSE, show_effect = FALSE) + if(COOLDOWN_FINISHED(src, carpet_switch_cd)) + replace_floors = list(pick(FANCY_CARPETS) = 1) + replace_objs[/obj/structure/table/wood] = list(pick(subtypesof(/obj/structure/table/wood/fancy)) = 1) + COOLDOWN_START(src, carpet_switch_cd, 90 SECONDS) + return ..() #undef FANCY_CARPETS diff --git a/code/modules/cargo/markets/market_items/weapons.dm b/code/modules/cargo/markets/market_items/weapons.dm index ee16daae7d5..052074a30b3 100644 --- a/code/modules/cargo/markets/market_items/weapons.dm +++ b/code/modules/cargo/markets/market_items/weapons.dm @@ -73,3 +73,12 @@ price_max = CARGO_CRATE_VALUE * 4 stock_max = 1 availability_prob = 75 + +/datum/market_item/weapon/dimensional_bomb + name = "Multi-Dimensional Bomb Core" + desc = "A special bomb core, one of a kind, for all your 'terraforming gone wrong' purposes." + item = /obj/item/bombcore/dimensional + price_min = CARGO_CRATE_VALUE * 40 + price_max = CARGO_CRATE_VALUE * 50 + stock_max = 1 + availability_prob = 15 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 9253448563b..ac9031f59c3 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -356,8 +356,7 @@ /obj/machinery/anomalous_crystal/theme_warp/Initialize(mapload) . = ..() - var/terrain_type = pick(subtypesof(/datum/dimension_theme)) - terrain_theme = new terrain_type() + terrain_theme = SSmaterials.dimensional_themes[pick(subtypesof(/datum/dimension_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) @@ -372,7 +371,7 @@ return TRUE /obj/machinery/anomalous_crystal/theme_warp/Destroy() - QDEL_NULL(terrain_theme) + terrain_theme = null converted_areas.Cut() return ..()