Files
Aurora.3/code/modules/effects/map_effects/randomized_destruction.dm
Kano 22e1d93b39 Adds a new Odyssey map: Decrepit Shipyard (#21500)
## About PR

Adds an industrial themed away site for Odyssey scenarios. The map
starts with a shuttle, broken by a randomized destruction feature.
Actors or the crew may choose to repair it to make it fly once more

### Detailed Changelog
<details><summary>Details</summary>
<p>

- Added a new map_effect, randomized destruction. It comes with two
varieties and different impact ranges. The way it work is the effect
chooses a random amount of turfs in the area it's placed on, and calls
`ex_act` on applicable contents in the turf.
- Added unused sprites for low railing and documented relevant functions
in the existing code.
- Made it so when a railing has an open end that doesn't connect to
anywhere, it'll apply an end cap, making it look more smooth.
- Added ceiling lattices.
- Adjusted unit tests to avoid conflicts that may occur with ceiling
lattices.
- Fixed a bug where the Odyssey subsystem repeatedly added lastly loaded
z-level to the scenario z-levels, instead of all relevant levels to the
site. This was causing issues in Odyssey maps with shuttles.
- Fixed hydrogen tank not using its sprite. Also recoloured the tank to
match modern hydrogen canister colour.
- Fixed `/obj/machinery/door/airlock/maintenance` not using its intended
appearance.

</p>
</details> 

## Images

<img width="4128" height="2528" alt="StrongDMM-2025-11-10 21 33 47"
src="https://github.com/user-attachments/assets/09d8b671-457c-4ec5-88ac-e503641a0531"
/>
<img width="3424" height="2016" alt="StrongDMM-2025-11-10 21 34 27"
src="https://github.com/user-attachments/assets/943b8529-7f2a-41db-a7be-e57d5d30ead7"
/>
<img width="1312" height="800" alt="StrongDMM-2025-11-10 21 34 52"
src="https://github.com/user-attachments/assets/f665800a-367b-466e-a16e-a6f0b122e3bd"
/>
<img width="997" height="999" alt="Screenshot_54"
src="https://github.com/user-attachments/assets/c06667c6-0dfc-4dc4-af67-821f36ad2933"
/>
<img width="997" height="1001" alt="Screenshot_55"
src="https://github.com/user-attachments/assets/848a2847-9eb0-450a-87e9-08c371aaf78a"
/>
<img width="998" height="992" alt="Screenshot_61"
src="https://github.com/user-attachments/assets/e6174cb5-d4d6-4afc-82ab-bbf412eda607"
/>
<img width="998" height="990" alt="Screenshot_63"
src="https://github.com/user-attachments/assets/cc838bdc-9e22-4aed-ad16-0f8722442b8a"
/>
2025-12-24 13:17:24 +00:00

94 lines
3.2 KiB
Plaintext

/// An effect that chooses random turfs in an area, then calls `ex_act` on them. Useful for mapping randomized destruction!
ABSTRACT_TYPE(/obj/effect/map_effect/randomized_destruction)
name = "randomized destruction"
/// Amount of turfs that will be selected for destruction, randomized between its halved value (rand(max_turf_amount / 2, max_turf_amount))
var/max_turf_amount
/// Weighted assoc list that determines the destruction severity per picked turf, candidate is picked by `pick_weight()`
// we can't use integer numbers as a key, because Byond will flatten them and make this a regular list instead of assoc list
// we can't use defines like "[SEVERE_DESTRUCTION]" = 1 either without handling this in a proc, because non-constant. This shit is so ass
var/list/possible_severities = list(
"1" = 1, // Severe destruction
"2" = 1, // Moderate
"3" = 1, // Mild
)
var/static/list/ignored_atoms = typecacheof(list(
/obj/effect,
/obj/machinery/computer,
/obj/machinery/hologram,
/obj/machinery/atmospherics/pipe/tank,
/obj/machinery/atmospherics/unary,
/obj/machinery/embedded_controller,
/obj/machinery/airlock_sensor,
/obj/machinery/access_button,
/obj/machinery/shipsensors,
/obj/machinery/iff_beacon,
/obj/structure/fuel_port,
))
/obj/effect/map_effect/randomized_destruction/Initialize(mapload)
. = ..()
if(mapload)
addtimer(CALLBACK(src, PROC_REF(start_destruction)), 90 SECONDS)
return
start_destruction()
/obj/effect/map_effect/randomized_destruction/proc/start_destruction()
var/list/turf_pool = get_area_turfs(get_area(src))
var/list/picked_turfs = list()
for(var/i in 0 to round(rand(max_turf_amount / 2, max_turf_amount)))
picked_turfs += pick_n_take(turf_pool)
var/chosen_severity
for(var/turf/T in picked_turfs)
chosen_severity = text2num(pick_weight(possible_severities)) // severity value that'll also affect every applicaple atom in turfs content
for(var/atom/thing in T.contents)
if(!thing.simulated || is_type_in_typecache(thing, ignored_atoms))
continue
thing.ex_act(chosen_severity)
T.ex_act(chosen_severity)
qdel(src) // I did my part, goodbye world
// ---- Subtypes
// Mild impact
ABSTRACT_TYPE(/obj/effect/map_effect/randomized_destruction/mild)
possible_severities = list(
"1" = 0, // Severe 0%
"2" = 1, // Moderate 25%
"3" = 3, // Mild 75%
)
/obj/effect/map_effect/randomized_destruction/mild/low_range
name = "randomized destruction, mild impact low range"
icon_state = "rand_dest_mild_low"
max_turf_amount = 20
/obj/effect/map_effect/randomized_destruction/mild/high_range
name = "randomized destruction, mild impact high range"
icon_state = "rand_dest_mild_high"
max_turf_amount = 60
// Severe impact
ABSTRACT_TYPE(/obj/effect/map_effect/randomized_destruction/severe)
possible_severities = list(
"1" = 2, // Severe 10%
"2" = 9, // Moderate 45%
"3" = 9, // Mild 45%
)
/obj/effect/map_effect/randomized_destruction/severe/low_range
name = "randomized destruction, severe impact low range"
icon_state = "rand_dest_severe_low"
max_turf_amount = 20
/obj/effect/map_effect/randomized_destruction/severe/high_range
name = "randomized destruction, severe impact high range"
icon_state = "rand_dest_severe_high"
max_turf_amount = 60