diff --git a/code/controllers/subsystem/sun.dm b/code/controllers/subsystem/sun.dm
index 3f8e15df05a..fc691c3a0c0 100644
--- a/code/controllers/subsystem/sun.dm
+++ b/code/controllers/subsystem/sun.dm
@@ -9,6 +9,7 @@ SUBSYSTEM_DEF(sun)
var/dy
var/rate
var/list/solars = list()
+ var/solar_gen_rate = 1500
/datum/controller/subsystem/sun/Initialize(start_timeofday)
// Lets work out an angle for the "sun" to rotate around the station
diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm
index 6d36b81f7b4..a4295f8aeba 100644
--- a/code/datums/weather/weather.dm
+++ b/code/datums/weather/weather.dm
@@ -45,10 +45,7 @@
..()
impacted_z_levels = z_levels
-/datum/weather/proc/telegraph()
- if(stage == STARTUP_STAGE)
- return
- stage = STARTUP_STAGE
+/datum/weather/proc/generate_area_list()
var/list/affectareas = list()
for(var/V in get_areas(area_type))
affectareas += V
@@ -58,6 +55,12 @@
var/area/A = V
if(A.z in impacted_z_levels)
impacted_areas |= A
+
+/datum/weather/proc/telegraph()
+ if(stage == STARTUP_STAGE)
+ return
+ stage = STARTUP_STAGE
+ generate_area_list()
weather_duration = rand(weather_duration_lower, weather_duration_upper)
START_PROCESSING(SSweather, src)
update_areas()
diff --git a/code/datums/weather/weather_types/solar_flare.dm b/code/datums/weather/weather_types/solar_flare.dm
new file mode 100644
index 00000000000..97e4d82596e
--- /dev/null
+++ b/code/datums/weather/weather_types/solar_flare.dm
@@ -0,0 +1,48 @@
+/datum/weather/solar_flare
+ name = "solar flare"
+ desc = "An intense blast of light and heat from the sun, affecting all space around the station."
+
+ telegraph_duration = 30 SECONDS
+ telegraph_message = null // handled via event announcement
+
+ weather_message = "A solar flare has arrived! Find shelter!"
+ weather_overlay = "light_ash"
+ weather_duration_lower = 5 MINUTES
+ weather_duration_upper = 10 MINUTES
+ weather_color = COLOR_YELLOW
+ weather_sound = 'sound/misc/bloblarm.ogg' // also used by radiation storm and SM
+
+ end_duration = 10 // wind_down() does not do anything for this event, so we just trigger end() semi-immediately
+ end_message = null
+ area_type = /area/space // read generate_area_list() as well below
+ protected_areas = list()
+ target_trait = STATION_LEVEL
+ immunity_type = "burn"
+
+/datum/weather/solar_flare/generate_area_list()
+ ..()
+ var/list/bonus_areas = get_areas(/area/solar)
+ // no, solars in space are NOT a subtype of /area/space.
+ // no, we don't want to re-path every reference to all the subtypes of /area/solar across every map file.
+ // no, we don't want to change /datum/weather/var/area_type into a list as that requires changing every item that touches weather
+ for(var/V in bonus_areas)
+ var/area/A = V
+ if(A.z in impacted_z_levels)
+ impacted_areas |= A
+
+/datum/weather/solar_flare/start()
+ ..()
+ // Solars produce 40x as much power. 240KW becomes 9.6MW. Enough to cause APCs to arc all over the station if >=2 solars are hotwired.
+ SSsun.solar_gen_rate = initial(SSsun.solar_gen_rate) * 40
+
+/datum/weather/solar_flare/weather_act(mob/living/L)
+ L.adjustFireLoss(1)
+ if(prob(10))
+ to_chat(L, "The solar flare burns you! Seek shelter!")
+
+/datum/weather/solar_flare/end()
+ if(..())
+ return
+ GLOB.event_announcement.Announce("The solar flare has passed.", "Solar Flare Advisory")
+ // Ends the temporary 40x increase that happened during the weather event
+ SSsun.solar_gen_rate = initial(SSsun.solar_gen_rate)
diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm
index 7b165f34213..65d64069cf2 100644
--- a/code/modules/events/event_container.dm
+++ b/code/modules/events/event_container.dm
@@ -151,6 +151,7 @@ GLOBAL_LIST_EMPTY(event_last_fired)
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Rogue Drones", /datum/event/rogue_drone, 0, list(ASSIGNMENT_SECURITY = 20)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space Vines", /datum/event/spacevine, 250, list(ASSIGNMENT_ENGINEER = 10)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meteor Shower", /datum/event/meteor_wave, 0, list(ASSIGNMENT_ENGINEER = 25)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Solar Flare", /datum/event/solar_flare, 0, list(ASSIGNMENT_ENGINEER = 25)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meaty Ores", /datum/event/dust/meaty, 0, list(ASSIGNMENT_ENGINEER = 20)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Communication Blackout", /datum/event/communications_blackout, 500, list(ASSIGNMENT_AI = 150, ASSIGNMENT_SECURITY = 120)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Prison Break", /datum/event/prison_break, 0, list(ASSIGNMENT_SECURITY = 100)),
diff --git a/code/modules/events/solarflare.dm b/code/modules/events/solarflare.dm
new file mode 100644
index 00000000000..edd1726cbb2
--- /dev/null
+++ b/code/modules/events/solarflare.dm
@@ -0,0 +1,10 @@
+/datum/event/solar_flare
+ startWhen = 2
+ endWhen = 3
+ announceWhen = 1
+
+/datum/event/solar_flare/announce()
+ GLOB.event_announcement.Announce("A solar flare has been detected on collision course with the station.", "Incoming Solar Flare", 'sound/AI/attention.ogg')
+
+/datum/event/solar_flare/start()
+ SSweather.run_weather(/datum/weather/solar_flare)
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index c4d3fb6cb91..df9abed6733 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -1195,8 +1195,13 @@
charging = 0
chargecount = 0
- if(excess >= 5000000 && !shock_proof) //If there's more than 5,000,000 watts in the grid, start arcing and shocking people.
- if(prob(5))
+ if(excess >= 2500000 && !shock_proof)
+ var/shock_chance = 5 // 5%
+ if(excess >= 7500000)
+ shock_chance = 15
+ else if(excess >= 5000000)
+ shock_chance = 10
+ if(prob(shock_chance))
var/list/shock_mobs = list()
for(var/C in view(get_turf(src), 5)) //We only want to shock a single random mob in range, not every one.
if(isliving(C))
diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm
index 7bb2f16b64a..e8295eedeb2 100644
--- a/code/modules/power/solar.dm
+++ b/code/modules/power/solar.dm
@@ -1,5 +1,4 @@
#define SOLAR_MAX_DIST 40
-#define SOLARGENRATE 1500
/obj/machinery/power/solar
name = "solar panel"
@@ -131,7 +130,7 @@
if(powernet == control.powernet)//check if the panel is still connected to the computer
if(obscured) //get no light from the sun, so don't generate power
return
- var/sgen = SOLARGENRATE * sunfrac
+ var/sgen = SSsun.solar_gen_rate * sunfrac
add_avail(sgen)
control.gen += sgen
else //if we're no longer on the same powernet, remove from control computer
@@ -379,7 +378,7 @@
/obj/machinery/power/solar_control/tgui_data(mob/user)
var/list/data = list()
data["generated"] = round(lastgen) //generated power by all connected panels
- data["generated_ratio"] = data["generated"] / round(max(connected_panels.len, 1) * SOLARGENRATE) //power generation ratio. Used for the power bar
+ data["generated_ratio"] = data["generated"] / round(max(connected_panels.len, 1) * SSsun.solar_gen_rate) //power generation ratio. Used for the power bar
data["direction"] = angle2text(cdir) //current orientation of the panels
data["cdir"] = cdir //current orientation of the of the panels in degrees
data["tracking_state"] = track //tracker status: TRACKER_OFF, TRACKER_TIMED, TRACKER_AUTO
diff --git a/paradise.dme b/paradise.dme
index 419b5332d6b..8d001f1e0ad 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -435,6 +435,7 @@
#include "code\datums\weather\weather_types\floor_is_lava.dm"
#include "code\datums\weather\weather_types\radiation_storm.dm"
#include "code\datums\weather\weather_types\snow_storm.dm"
+#include "code\datums\weather\weather_types\solar_flare.dm"
#include "code\datums\wires\airlock.dm"
#include "code\datums\wires\alarm.dm"
#include "code\datums\wires\apc.dm"
@@ -1473,6 +1474,7 @@
#include "code\modules\events\rogue_drones.dm"
#include "code\modules\events\sentience.dm"
#include "code\modules\events\slaughterevent.dm"
+#include "code\modules\events\solarflare.dm"
#include "code\modules\events\spacevine.dm"
#include "code\modules\events\spider_infestation.dm"
#include "code\modules\events\spider_terror.dm"