Skip to content

Commit

Permalink
Weather Radio Port (#2517)
Browse files Browse the repository at this point in the history
<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may
not be viewable. -->
<!-- You can view Contributing.MD for a detailed description of the pull
request process. -->

## About The Pull Request
Port of tgstation/tgstation#76961, which is
itself a port of lizardqueenlexi/orbstation#630.
This PR will add one new object, the portable weather radio.

![theradio](https://github.com/shiptest-ss13/Shiptest/assets/34109002/2d9acb59-30fa-4354-944d-f5bcc3b88666)

![image](https://github.com/shiptest-ss13/Shiptest/assets/34109002/76bad17f-b15e-4c50-99de-5cb860b19a89)

![image](https://github.com/shiptest-ss13/Shiptest/assets/34109002/ca0db81b-d8dc-43d9-9e8c-8a85b083d7cb)
Wallmount shown in these has been axed.

### Todo

- [x] Fix the existing code to work for our cases.
- [x] Fix runtime errors.
- [x] Stay hydrated.

<!-- Describe The Pull Request. Please be sure every change is
documented or this can delay review and even discourage maintainers from
merging your PR! -->

## Why It's Good For The Game
They look neat, they add flavor, and the barometer function on analyzers
is used maybe once every 50 rounds.
<!-- Please add a short description of why you think these changes would
benefit the game. If you can't justify it in words, it might not be
worth adding. -->

## Changelog

🆑 CoiledLamb, Jacquerel, GenericDM
add: Adds Weather Radios!
/🆑

<!-- Both 🆑's are required for the changelog to work! You can put
your name to the right of the first 🆑 if you want to overwrite your
GitHub username as author ingame. -->
<!-- You can use multiple of the same prefix (they're only used for the
icon ingame) and delete the unneeded ones. Despite some of the tags,
changelogs should generally represent how a player might be affected by
the changes rather than a summary of the PR's contents. -->
  • Loading branch information
GenericDM authored Dec 6, 2023
1 parent 563a7d4 commit ec0c636
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 2 deletions.
2 changes: 2 additions & 0 deletions code/__DEFINES/colors.dm
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@
#define LIGHT_COLOR_LAVA "#C48A18"
/// Bright, non-saturated red. Leaning slightly towards pink for visibility. rgb(250, 100, 75)
#define LIGHT_COLOR_FLARE "#FA644B"
/// Vivid red. Leans a bit darker to accentuate red colors and leave other channels a bit dry. rgb(200, 25, 25)
#define LIGHT_COLOR_INTENSE_RED "#C81919"
/// Weird color, between yellow and green, very slimy. rgb(175, 200, 75)
#define LIGHT_COLOR_SLIME_LAMP "#AFC84B"
/// Extremely diluted yellow, close to skin color (for some reason). rgb(250, 225, 175)
Expand Down
170 changes: 170 additions & 0 deletions code/datums/components/weatherannouncer.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#define WEATHER_ALERT_CLEAR 0
#define WEATHER_ALERT_INCOMING 1
#define WEATHER_ALERT_IMMINENT_OR_ACTIVE 2

/// Component which makes you yell about what the weather is
/datum/component/weather_announcer
/// Currently displayed warning level
var/warning_level = WEATHER_ALERT_CLEAR
/// Whether the incoming weather is actually going to harm you
var/is_weather_dangerous = TRUE
/// Are we actually turned on right now?
var/enabled = TRUE
/// Overlay added when things are alright
var/state_normal
/// Overlay added when you should start looking for shelter
var/state_warning
/// Overlay added when you are in danger
var/state_danger

/datum/component/weather_announcer/Initialize(
state_normal,
state_warning,
state_danger,
)
. = ..()
if (!ismovable(parent))
return COMPONENT_INCOMPATIBLE

START_PROCESSING(SSprocessing, src)
RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays))
RegisterSignal(parent, COMSIG_MACHINERY_POWER_RESTORED, PROC_REF(on_powered))
RegisterSignal(parent, COMSIG_MACHINERY_POWER_LOST, PROC_REF(on_power_lost))

src.state_normal = state_normal
src.state_warning = state_warning
src.state_danger = state_danger
var/atom/speaker = parent
speaker.update_appearance(UPDATE_ICON)
update_light_color()

/datum/component/weather_announcer/Destroy(force, silent)
STOP_PROCESSING(SSprocessing, src)
return ..()

/// Add appropriate overlays
/datum/component/weather_announcer/proc/on_update_overlays(atom/parent_atom, list/overlays)
SIGNAL_HANDLER
if (!enabled || !state_normal || !state_warning || !state_danger)
return

switch (warning_level)
if(WEATHER_ALERT_CLEAR)
overlays += state_normal
if(WEATHER_ALERT_INCOMING)
overlays += state_warning
if(WEATHER_ALERT_IMMINENT_OR_ACTIVE)
overlays += (is_weather_dangerous) ? state_danger : state_warning

/// If powered, receive updates
/datum/component/weather_announcer/proc/on_powered()
SIGNAL_HANDLER
enabled = TRUE
var/atom/speaker = parent
speaker.update_appearance(UPDATE_ICON)

/// If no power, don't receive updates
/datum/component/weather_announcer/proc/on_power_lost()
SIGNAL_HANDLER
enabled = FALSE
var/atom/speaker = parent
speaker.update_appearance(UPDATE_ICON)

/datum/component/weather_announcer/process(seconds_per_tick)
if (!enabled)
return

var/previous_level = warning_level
var/previous_danger = is_weather_dangerous
set_current_alert_level()
if(previous_level == warning_level && previous_danger == is_weather_dangerous)
return // No change
var/atom/movable/speaker = parent
speaker.say(get_warning_message())
speaker.update_appearance(UPDATE_ICON)
update_light_color()

/datum/component/weather_announcer/proc/update_light_color()
var/atom/movable/light = parent
switch(warning_level)
if(WEATHER_ALERT_CLEAR)
light.set_light_color(LIGHT_COLOR_GREEN)
if(WEATHER_ALERT_INCOMING)
light.set_light_color(LIGHT_COLOR_YELLOW)
if(WEATHER_ALERT_IMMINENT_OR_ACTIVE)
light.set_light_color(LIGHT_COLOR_INTENSE_RED)
light.update_light()

/// Returns a string we should display to communicate what you should be doing
/datum/component/weather_announcer/proc/get_warning_message()
if (!is_weather_dangerous)
return "No risk expected from incoming weather front."
switch(warning_level)
if(WEATHER_ALERT_CLEAR)
return "All clear, no weather alerts to report."
if(WEATHER_ALERT_INCOMING)
return "Weather front incoming, begin to seek shelter."
if(WEATHER_ALERT_IMMINENT_OR_ACTIVE)
return "Weather front imminent, find shelter immediately."
return "Error in meteorological calculation. Please report this deviation to a trained programmer."

/datum/component/weather_announcer/proc/time_till_storm()
var/datum/weather_controller/local_weather_controller = SSmapping.get_map_zone_weather_controller(parent)
if(!local_weather_controller.next_weather)
return null
for(var/type_index in local_weather_controller.current_weathers)
var/datum/weather/check_weather = local_weather_controller.current_weathers[type_index]
if(!check_weather.barometer_predictable || check_weather.stage == WIND_DOWN_STAGE || check_weather.stage == END_STAGE)
continue
warning_level = WEATHER_ALERT_IMMINENT_OR_ACTIVE
return 0

var/time_until_next = INFINITY
var/next_time = local_weather_controller.next_weather - world.time || INFINITY
if (next_time && next_time < time_until_next)
time_until_next = next_time
return time_until_next

/// Polls existing weather for what kind of warnings we should be displaying.
/datum/component/weather_announcer/proc/set_current_alert_level()
var/time_until_next = time_till_storm()
if(isnull(time_until_next))
return // No problems if there are no mining z levels
if(time_until_next >= 2 MINUTES)
warning_level = WEATHER_ALERT_CLEAR
return

if(time_until_next >= 30 SECONDS)
warning_level = WEATHER_ALERT_INCOMING
return

// Weather is here, now we need to figure out if it is dangerous
warning_level = WEATHER_ALERT_IMMINENT_OR_ACTIVE

var/datum/weather_controller/local_weather_controller = SSmapping.get_map_zone_weather_controller(parent)
for(var/type_index in local_weather_controller.current_weathers)
var/datum/weather/check_weather = local_weather_controller.current_weathers[type_index]
if(!check_weather.barometer_predictable || check_weather.stage == WIND_DOWN_STAGE || check_weather.stage == END_STAGE)
continue
is_weather_dangerous = !check_weather.aesthetic
return

/datum/component/weather_announcer/proc/on_examine(atom/radio, mob/examiner, list/examine_texts)
var/time_until_next = time_till_storm()
if(isnull(time_until_next))
return
if (time_until_next == 0)
examine_texts += span_warning ("A storm is currently active, please seek shelter.")
else
examine_texts += span_notice("The next storm is inbound in [DisplayTimeText(time_until_next)].")

/datum/component/weather_announcer/RegisterWithParent()
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine))

/datum/component/weather_announcer/UnregisterFromParent()
.=..()
UnregisterSignal(parent, COMSIG_PARENT_EXAMINE)

#undef WEATHER_ALERT_CLEAR
#undef WEATHER_ALERT_INCOMING
#undef WEATHER_ALERT_IMMINENT_OR_ACTIVE
3 changes: 2 additions & 1 deletion code/modules/jobs/job_types/shaft_miner.dm
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
backpack_contents = list(
/obj/item/flashlight/seclite=1,\
/obj/item/kitchen/knife/combat/survival=1,\
/obj/item/stack/marker_beacon/ten=1)
/obj/item/stack/marker_beacon/ten=1,\
/obj/item/radio/weather_monitor=1)

backpack = /obj/item/storage/backpack/explorer
satchel = /obj/item/storage/backpack/satchel/explorer
Expand Down
23 changes: 23 additions & 0 deletions code/modules/mining/equipment/miningradio.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/// Portable mining radio purchasable by miners
/obj/item/radio/weather_monitor
icon = 'icons/obj/miningradio.dmi'
name = "mining weather radio"
icon_state = "miningradio"
desc = "A weather radio designed for use in inhospitable environments. Gives audible warnings when storms approach."
luminosity = 1
light_power = 1
light_range = 1.6

/obj/item/radio/weather_monitor/update_overlays()
. = ..()
. += emissive_appearance(icon, "small_emissive", src, alpha = src.alpha)

/obj/item/radio/weather_monitor/Initialize(mapload)
. = ..()
AddComponent( \
/datum/component/weather_announcer, \
state_normal = "weatherwarning", \
state_warning = "urgentwarning", \
state_danger = "direwarning", \
)
set_frequency(FREQ_COMMON)
10 changes: 10 additions & 0 deletions code/modules/research/designs/mining_designs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,13 @@
build_path = /obj/item/borg/upgrade/modkit/aoe/turfs
category = list("Mining Designs", "Cyborg Upgrade Modules")
departmental_flags = DEPARTMENTAL_FLAG_CARGO

/datum/design/weather_monitor
name = "Weather Radio"
desc = "A weather radio designed for use in inhospitable environments. Gives audible warnings when storms approach."
id = "weatherradio"
build_type = PROTOLATHE
materials = list(/datum/material/iron=75, /datum/material/glass=25)
build_path = /obj/item/radio/weather_monitor
category = list("Mining Designs")
departmental_flags = DEPARTMENTAL_FLAG_CARGO
2 changes: 1 addition & 1 deletion code/modules/research/techweb/all_nodes.dm
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@
display_name = "Mining Technology"
description = "Better than Efficiency V."
prereq_ids = list("engineering", "basic_plasma")
design_ids = list("drill", "superresonator", "triggermod", "damagemod", "cooldownmod", "rangemod", "ore_redemption", "mining_equipment_vendor", "cargoexpress", "plasmacutter", "mecha_kineticgun")//e a r l y g a m e)
design_ids = list("drill", "superresonator", "triggermod", "damagemod", "cooldownmod", "rangemod", "ore_redemption", "mining_equipment_vendor", "cargoexpress", "plasmacutter", "mecha_kineticgun", "weatherradio")//e a r l y g a m e)
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000

Expand Down
Binary file added icons/obj/miningradio.dmi
Binary file not shown.
2 changes: 2 additions & 0 deletions shiptest.dme
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,7 @@
#include "code\datums\components\udder.dm"
#include "code\datums\components\uplink.dm"
#include "code\datums\components\wearertargeting.dm"
#include "code\datums\components\weatherannouncer.dm"
#include "code\datums\components\wet_floor.dm"
#include "code\datums\components\crafting\crafting.dm"
#include "code\datums\components\crafting\guncrafting.dm"
Expand Down Expand Up @@ -2365,6 +2366,7 @@
#include "code\modules\mining\equipment\marker_beacons.dm"
#include "code\modules\mining\equipment\mineral_scanner.dm"
#include "code\modules\mining\equipment\mining_tools.dm"
#include "code\modules\mining\equipment\miningradio.dm"
#include "code\modules\mining\equipment\regenerative_core.dm"
#include "code\modules\mining\equipment\resonator.dm"
#include "code\modules\mining\equipment\survival_pod.dm"
Expand Down

0 comments on commit ec0c636

Please sign in to comment.