Files
Alexis 21b4095dfd [MDB IGNORE] [IDB IGNORE] Upstream Sync - 04/17/2026 (#5453)
Upstream 04/17/2026

fixes https://github.com/Bubberstation/Bubberstation/issues/5549

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: tgstation-ci[bot] <179393467+tgstation-ci[bot]@users.noreply.github.com>
Co-authored-by: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com>
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: Rhials <28870487+Rhials@users.noreply.github.com>
Co-authored-by: rageguy505 <54517726+rageguy505@users.noreply.github.com>
Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com>
Co-authored-by: Aliceee2ch <160794176+Aliceee2ch@users.noreply.github.com>
Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com>
Co-authored-by: Tsar-Salat <62388554+Tsar-Salat@users.noreply.github.com>
Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com>
Co-authored-by: Maxipat <108554989+Maxipat112@users.noreply.github.com>
Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com>
Co-authored-by: SimplyLogan <47579821+loganuk@users.noreply.github.com>
Co-authored-by: loganuk <fakeemail123@aol.com>
Co-authored-by: Leland Kemble <70413276+lelandkemble@users.noreply.github.com>
Co-authored-by: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com>
Co-authored-by: Roxy <75404941+TealSeer@users.noreply.github.com>
Co-authored-by: Lucy <lucy@absolucy.moe>
Co-authored-by: siliconOpossum <138069572+siliconOpossum@users.noreply.github.com>
Co-authored-by: Isratosh <Isratosh@hotmail.com>
Co-authored-by: TheRyeGuyWhoWillNowDie <70169560+TheRyeGuyWhoWillNowDie@users.noreply.github.com>
Co-authored-by: Neocloudy <88008002+Neocloudy@users.noreply.github.com>
Co-authored-by: Alexander V. <volas@ya.ru>
Co-authored-by: ElGitificador <168473461+ElGitificador@users.noreply.github.com>
Co-authored-by: Twaticus <46540570+Twaticus@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com>
Co-authored-by: Cameron Lennox <killer65311@gmail.com>
Co-authored-by: Tim <timothymtorres@gmail.com>
Co-authored-by: Iamgoofball <iamgoofball@gmail.com>
Co-authored-by: Layzu666 <121319428+Layzu666@users.noreply.github.com>
Co-authored-by: Arturlang <24881678+Arturlang@users.noreply.github.com>
Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com>
Co-authored-by: mrmanlikesbt <99309552+mrmanlikesbt@users.noreply.github.com>
Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com>
Co-authored-by: John F. Kennedy <54908920+MacaroniCritter@users.noreply.github.com>
Co-authored-by: Cursor <102828457+theselfish@users.noreply.github.com>
Co-authored-by: Josh <josh.adam.powell@gmail.com>
Co-authored-by: Josh Powell <josh.powell@softwire.com>
Co-authored-by: Yobrocharlie <Charliemiller5617@gmail.com>
Co-authored-by: Hardly3D <66234359+Hardly3D@users.noreply.github.com>
Co-authored-by: shayoki <96078776+shayoki@users.noreply.github.com>
Co-authored-by: LT3 <83487515+lessthnthree@users.noreply.github.com>
2026-05-16 00:56:00 +02:00

199 lines
8.2 KiB
Plaintext

/// number of emagged meteor shields to get the first warning, a simple say message
#define EMAGGED_METEOR_SHIELD_THRESHOLD_ONE 3
/// number of emagged meteor shields to get the second warning, telling the user an announcement is coming
#define EMAGGED_METEOR_SHIELD_THRESHOLD_TWO 6
/// number of emagged meteor shields to get the third warning + an announcement to the crew
#define EMAGGED_METEOR_SHIELD_THRESHOLD_THREE 7
/// number of emagged meteor shields to get the fourth... ah shit the dark matt-eor is coming.
#define EMAGGED_METEOR_SHIELD_THRESHOLD_FOUR 10
/// how long between emagging meteor shields you have to wait
#define METEOR_SHIELD_EMAG_COOLDOWN 1 MINUTES
//Station Shield
// A chain of satellites encircles the station
// Satellites be actived to generate a shield that will block unorganic matter from passing it.
/datum/station_goal/station_shield
name = "Station Shield"
requires_space = TRUE
var/coverage_goal = 500
VAR_PRIVATE/cached_coverage_length
/datum/station_goal/station_shield/get_report()
return list(
"The station is located in a zone full of space debris.",
"We have a prototype shielding system you must deploy to reduce collision-related accidents.",
"",
"You can order the satellites and control systems at cargo.",
).Join("\n")
/datum/station_goal/station_shield/on_report()
//Unlock
var/datum/supply_pack/P = SSshuttle.supply_packs[/datum/supply_pack/engineering/shield_sat]
P.order_flags |= ORDER_SPECIAL_ENABLED
P = SSshuttle.supply_packs[/datum/supply_pack/engineering/shield_sat_control]
P.order_flags |= ORDER_SPECIAL_ENABLED
/datum/station_goal/station_shield/check_completion()
if(..())
return TRUE
update_coverage()
if(cached_coverage_length >= coverage_goal)
return TRUE
return FALSE
/datum/station_goal/station_shield/proc/get_coverage()
return cached_coverage_length
/// Gets the coverage of all active meteor shield satellites
/// Can be expensive, ensure you need this before calling it
/datum/station_goal/station_shield/proc/update_coverage()
var/list/coverage = list()
for(var/obj/machinery/satellite/meteor_shield/shield_satt as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/satellite/meteor_shield))
if(!shield_satt.active || !is_station_level(shield_satt.z))
continue
for(var/turf/covered in view(shield_satt.kill_range, shield_satt))
coverage |= covered
cached_coverage_length = length(coverage)
/obj/machinery/satellite/meteor_shield
name = "\improper Meteor Shield Satellite"
desc = "A meteor point-defense satellite."
mode = "M-SHIELD"
/// the range a meteor shield sat can destroy meteors
var/kill_range = 14
//emag behavior dark matt-eor stuff
/// Proximity monitor associated with this atom, needed for it to work.
var/datum/proximity_monitor/proximity_monitor
/// amount of emagged active meteor shields
var/static/emagged_active_meteor_shields = 0
/// the highest amount of shields you've ever emagged
var/static/highest_emagged_threshold_reached = 0
/// cooldown on emagging meteor shields because instantly summoning a dark matt-eor is very unfun
STATIC_COOLDOWN_DECLARE(shared_emag_cooldown)
/obj/machinery/satellite/meteor_shield/examine(mob/user)
. = ..()
if(active)
. += span_notice("It is currently active. You can interact with it to shut it down.")
if(obj_flags & EMAGGED)
. += span_warning("Rather than the usual sounds of beeps and pings, it produces a weird and constant hiss of white noise…")
else
. += span_notice("It emits periodic beeps and pings as it communicates with the satellite network.")
else
. += span_notice("It is currently disabled. You can interact with it to set it up.")
if(obj_flags & EMAGGED)
. += span_warning("But something seems off about it...?")
/obj/machinery/satellite/meteor_shield/proc/space_los(meteor)
for(var/turf/T in get_line(src,meteor))
if(!isspaceturf(T))
return FALSE
return TRUE
/obj/machinery/satellite/meteor_shield/Initialize(mapload)
. = ..()
proximity_monitor = new(src, /* range = */ 0)
/obj/machinery/satellite/meteor_shield/HasProximity(atom/movable/proximity_check_mob)
. = ..()
if(!istype(proximity_check_mob, /obj/effect/meteor))
return
var/obj/effect/meteor/meteor_to_destroy = proximity_check_mob
if(space_los(meteor_to_destroy))
var/turf/beam_from = get_turf(src)
beam_from.Beam(get_turf(meteor_to_destroy), icon_state="sat_beam", time = 5)
if(meteor_to_destroy.shield_defense(src))
qdel(meteor_to_destroy)
/obj/machinery/satellite/meteor_shield/toggle(user)
if(user)
balloon_alert(user, "looking for [active ? "off" : "on"] button")
if(user && !do_after(user, 2 SECONDS, src, IGNORE_HELD_ITEM))
return FALSE
if(!..(user))
return FALSE
if(obj_flags & EMAGGED)
update_emagged_meteor_sat(user)
if(active)
proximity_monitor.set_range(kill_range)
else
proximity_monitor.set_range(0)
var/datum/station_goal/station_shield/goal = SSstation.get_station_goal(/datum/station_goal/station_shield)
goal?.update_coverage()
/obj/machinery/satellite/meteor_shield/Destroy()
. = ..()
QDEL_NULL(proximity_monitor)
if(obj_flags & EMAGGED)
//satellites that are destroying are not active, this will count down the number of emagged sats
update_emagged_meteor_sat()
/obj/machinery/satellite/meteor_shield/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
balloon_alert(user, "already emagged!")
return FALSE
if(!COOLDOWN_FINISHED(src, shared_emag_cooldown))
balloon_alert(user, "on cooldown!")
to_chat(user, span_warning("The last satellite emagged needs [DisplayTimeText(COOLDOWN_TIMELEFT(src, shared_emag_cooldown))] to recalibrate first. Emagging another so soon could damage the satellite network."))
return FALSE
var/cooldown_applied = METEOR_SHIELD_EMAG_COOLDOWN
COOLDOWN_START(src, shared_emag_cooldown, cooldown_applied)
obj_flags |= EMAGGED
to_chat(user, span_notice("You access the satellite's debug mode and it begins emitting a strange signal, increasing the chance of meteor strikes."))
AddComponent(/datum/component/gps, "Corrupted Meteor Shield Attraction Signal")
say("Recalibrating... ETA:[DisplayTimeText(cooldown_applied)].")
if(active) //if we allowed inactive updates a sat could be worth -1 active meteor shields on first emag
update_emagged_meteor_sat(user)
return TRUE
/obj/machinery/satellite/meteor_shield/proc/update_emagged_meteor_sat(mob/user)
if(!active)
change_meteor_chance(0.5)
emagged_active_meteor_shields--
if(user)
balloon_alert(user, "meteor probability halved")
return
change_meteor_chance(2)
emagged_active_meteor_shields++
if(user)
balloon_alert(user, "meteor probability doubled")
if(emagged_active_meteor_shields > highest_emagged_threshold_reached)
highest_emagged_threshold_reached = emagged_active_meteor_shields
handle_new_emagged_shield_threshold()
/obj/machinery/satellite/meteor_shield/proc/handle_new_emagged_shield_threshold()
switch(highest_emagged_threshold_reached)
if(EMAGGED_METEOR_SHIELD_THRESHOLD_ONE)
say("Warning. Meteor strike probability entering dangerous ranges for more exotic meteors.")
if(EMAGGED_METEOR_SHIELD_THRESHOLD_TWO)
say("Warning. Risk of dark matter congealment entering existent ranges. Further tampering will be reported.")
if(EMAGGED_METEOR_SHIELD_THRESHOLD_THREE)
say("Warning. Further tampering has been reported.")
priority_announce("Warning. Tampering of meteor satellites puts the station at risk of exotic, deadly meteor collisions. Please intervene by checking your GPS devices for strange signals, and dismantling the tampered meteor shields.", "Strange Meteor Signal Warning")
if(EMAGGED_METEOR_SHIELD_THRESHOLD_FOUR)
say("Warning. Warning. Dark Matt-eor on course for station.")
force_event_async(/datum/round_event_control/dark_matteor, "an array of tampered meteor satellites")
/obj/machinery/satellite/meteor_shield/proc/change_meteor_chance(mod)
// Update the weight of all meteor events
for(var/datum/round_event_control/meteor_wave/meteors in SSevents.control)
meteors.weight *= mod
for(var/datum/round_event_control/stray_meteor/stray_meteor in SSevents.control)
stray_meteor.weight *= mod
#undef EMAGGED_METEOR_SHIELD_THRESHOLD_ONE
#undef EMAGGED_METEOR_SHIELD_THRESHOLD_TWO
#undef EMAGGED_METEOR_SHIELD_THRESHOLD_THREE
#undef EMAGGED_METEOR_SHIELD_THRESHOLD_FOUR
#undef METEOR_SHIELD_EMAG_COOLDOWN