[MIRROR] Tram malfunction adjustments (#28092)

* Tram malfunction adjustments (#83706)

## About The Pull Request

Adjusts tram malfunction and the tram malfunction event to be more
straightforward and similar to other telecoms machinery.

- Tram malfunction now requires engineering, borg, or AI to visit either
the tram or the tram controller in telecoms to press 'reset'
(previously: open the tram panel and find the appropriate tool to repair
it)
- Tram malfunction event only stops the tram once per event roll
- Adjust announcement to include message that engineers need to reset
the tram
- Removed loud priority_announce when the tram is fixed. Players know
the tram is fixed because they are using it again
- Tram doors no longer force crush during malfunction, since engineers
have no method to fix this
- EMP/communications blackout event will temporarily degrade crossing
signals, otherwise the tram continues to function normally
- Loss of telecoms power will degrade crossing signals, otherwise the
tram continues to function normally

Frequency of tram malfunction event is reduced to be in line with
communications blackout and grav gen blackout, and a maximum of 3
occurrences per round

Signal failure:
Previously: Signals fail until reset has physically been done on the
controller
New: Signal failure is moved to be part of the Communications Blackout
event, lasting the duration of EMP blast that hits telecoms

Communication loss:
Previously: For the duration of the Tram Malfunction event there is a 5%
chance the tram does a degraded stop, ending when the controller is
repaired or the timer ends
New: A guaranteed 1 degraded stop per event roll. To balance the
increase in occurrences it's been made easier to reset on the
controller. If the tram is not reset by the end of the timer, it is done
automatically

New telecoms room tram controller:

![dreamseeker_AGHpKvyunZ](https://github.com/tgstation/tgstation/assets/83487515/e8269607-11c9-407a-8f6e-d20f3f1b5f56)

## Why It's Good For The Game

Making the tram friendlier for engineering to pick up/understand, it
will function more predictably in the tram malfunction and
communications blackout event.

## Changelog

🆑 LT3
add: Telecoms now has a central tram controller
add: Tram controller is now included in communications blackout event
qol: Tram malfunction event only stops tram once, requiring engineering
to reset (no tools required)
qol: Tram malfunction event no longer sends a Central Command
announcement when fixed
del: Tram doors no longer force crush you during tram malfunction event
del: Silicons can no longer control the tram when communication is lost
/🆑

* Tram malfunction adjustments

---------

Co-authored-by: lessthanthree <83487515+lessthnthree@users.noreply.github.com>
This commit is contained in:
SkyratBot
2024-06-09 20:34:16 +05:30
committed by GitHub
co-authored by lessthanthree
parent bef7ec2b53
commit c607284ff4
9 changed files with 12342 additions and 12225 deletions
File diff suppressed because it is too large Load Diff
+39 -31
View File
@@ -2342,6 +2342,13 @@
/obj/structure/mirror/directional/west,
/turf/open/floor/iron/showroomfloor,
/area/station/commons/vacant_room)
"aiX" = (
/obj/machinery/door/poddoor/massdriver_trash{
id = "fortnitedoor"
},
/obj/structure/fans/tiny,
/turf/open/floor/plating,
/area/station/maintenance/disposal)
"ajc" = (
/obj/machinery/button/door/directional/west{
name = "Privacy Bolts";
@@ -6752,15 +6759,6 @@
/obj/machinery/photocopier,
/turf/open/floor/wood,
/area/station/service/lawoffice)
"bnY" = (
/obj/structure/table,
/obj/effect/turf_decal/trimline/yellow/filled/line{
dir = 8
},
/obj/item/radio/intercom/directional/west,
/obj/item/paper/fluff/jobs/engineering/frequencies,
/turf/open/floor/iron,
/area/station/tcommsat/computer)
"boc" = (
/obj/structure/cable,
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
@@ -26707,15 +26705,6 @@
/obj/item/flashlight,
/turf/open/floor/iron/dark,
/area/station/engineering/supermatter/room)
"iDB" = (
/obj/structure/table,
/obj/effect/turf_decal/trimline/yellow/filled/line{
dir = 9
},
/obj/item/folder/blue,
/obj/item/pen/blue,
/turf/open/floor/iron,
/area/station/tcommsat/computer)
"iDQ" = (
/obj/effect/turf_decal/tile/neutral/tram,
/obj/effect/turf_decal/stripes/white/line,
@@ -45873,6 +45862,10 @@
/obj/machinery/light/cold/directional/south,
/turf/open/floor/iron/freezer,
/area/station/security/prison)
"pmJ" = (
/obj/machinery/transport/tram_controller/tcomms,
/turf/open/floor/iron/dark/telecomms,
/area/station/tcommsat/server)
"pmM" = (
/obj/structure/closet/firecloset,
/obj/effect/turf_decal/tile/purple/fourcorners,
@@ -54275,6 +54268,16 @@
dir = 4
},
/area/station/service/theater)
"siB" = (
/obj/structure/table,
/obj/effect/turf_decal/trimline/yellow/filled/line{
dir = 9
},
/obj/item/folder/blue,
/obj/item/pen/blue,
/obj/item/paper/fluff/jobs/engineering/frequencies,
/turf/open/floor/iron,
/area/station/tcommsat/computer)
"siE" = (
/obj/machinery/disposal/bin,
/obj/effect/turf_decal/trimline/blue/filled/line{
@@ -63158,6 +63161,18 @@
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/turf/open/floor/iron,
/area/station/security/brig)
"vgo" = (
/obj/structure/table,
/obj/effect/turf_decal/trimline/yellow/filled/line{
dir = 8
},
/obj/item/radio/intercom/directional/west,
/obj/item/toy/plush/lizard_plushie/green{
name = "Runs-The-Rails";
desc = "An adorable, hard working lizard that runs in circles to keep the tram operating safely."
},
/turf/open/floor/iron,
/area/station/tcommsat/computer)
"vgD" = (
/obj/effect/turf_decal/stripes/corner{
dir = 8
@@ -66413,13 +66428,6 @@
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/catwalk_floor,
/area/station/hallway/primary/tram/right)
"woj" = (
/obj/machinery/door/poddoor/massdriver_trash{
id = "fortnitedoor"
},
/obj/structure/fans/tiny,
/turf/open/floor/plating,
/area/station/maintenance/disposal)
"woB" = (
/obj/structure/window/reinforced/spawner/directional/west,
/turf/open/floor/iron/white/smooth_corner{
@@ -97469,9 +97477,9 @@ abM
abM
abM
jIG
iDB
siB
mzV
bnY
vgo
lSp
wnq
dwR
@@ -98247,7 +98255,7 @@ dwR
ngp
dwR
dwR
cXL
ney
ney
sMr
sMr
@@ -98505,7 +98513,7 @@ gga
rBW
ffN
sMr
sMr
pmJ
drH
ney
tms
@@ -98761,7 +98769,7 @@ ocK
ngp
dwR
dwR
cXL
sMr
sMr
sMr
sMr
@@ -120302,7 +120310,7 @@ xSG
xSG
xSG
vle
woj
aiX
vle
aaa
aaa
-4
View File
@@ -170,10 +170,6 @@ PROCESSING_SUBSYSTEM_DEF(transport)
/datum/controller/subsystem/processing/transport/proc/pre_departure(datum/transport_controller/linear/tram/transport_controller, request_flags)
log_transport("Sub: [transport_controller.specific_transport_id] start pre-departure. Info: [SUB_TS_STATUS]")
// Tram Malfunction event
if(transport_controller.controller_status & COMM_ERROR)
request_flags |= BYPASS_SENSORS
// Lock the physical controls of the tram
transport_controller.set_status_code(PRE_DEPARTURE, TRUE)
transport_controller.set_status_code(CONTROLS_LOCKED, TRUE)
@@ -29,3 +29,7 @@
/datum/round_event/communications_blackout/start()
for(var/obj/machinery/telecomms/T in GLOB.telecomms_list)
T.emp_act(EMP_HEAVY)
for(var/datum/transport_controller/linear/tram/transport as anything in SStransport.transports_by_type[TRANSPORT_TYPE_TRAM])
if(!isnull(transport.home_controller))
var/obj/machinery/transport/tram_controller/tcomms/controller = transport.home_controller
controller.emp_act(EMP_HEAVY)
+4 -8
View File
@@ -4,11 +4,11 @@
/datum/round_event_control/tram_malfunction
name = "Tram Malfunction"
typepath = /datum/round_event/tram_malfunction
weight = 40
max_occurrences = 4
weight = 30
max_occurrences = 3
earliest_start = 15 MINUTES
category = EVENT_CATEGORY_ENGINEERING
description = "Tram crossing signals malfunction, tram collision damage is increased."
description = "Tram comes to an emergency stop, requiring engineering to reset."
min_wizard_trigger_potency = 0
max_wizard_trigger_potency = 3
@@ -34,9 +34,6 @@
/datum/round_event/tram_malfunction/setup()
end_when = rand(TRAM_MALFUNCTION_TIME_LOWER, TRAM_MALFUNCTION_TIME_UPPER)
/datum/round_event/tram_malfunction/announce()
priority_announce("Our automated control system has lost contact with the tram's onboard computer. Please take extra care while engineers diagnose and resolve the issue.", "[command_name()] Engineering Division")
/datum/round_event/tram_malfunction/start()
for(var/datum/transport_controller/linear/tram/malfunctioning_controller as anything in SStransport.transports_by_type[TRANSPORT_TYPE_TRAM])
if(malfunctioning_controller.specific_transport_id == specific_transport_id)
@@ -45,9 +42,8 @@
/datum/round_event/tram_malfunction/end()
for(var/datum/transport_controller/linear/tram/malfunctioning_controller as anything in SStransport.transports_by_type[TRANSPORT_TYPE_TRAM])
if(malfunctioning_controller.specific_transport_id == specific_transport_id && malfunctioning_controller.controller_status & COMM_ERROR)
if(malfunctioning_controller.specific_transport_id == specific_transport_id && malfunctioning_controller.malf_active)
malfunctioning_controller.end_malf_event()
priority_announce("The software on the tram has been reset, normal operations are now resuming. Sorry for any inconvienence this may have caused.", "[command_name()] Engineering Division")
return
#undef TRAM_MALFUNCTION_TIME_UPPER
+174 -80
View File
@@ -10,7 +10,10 @@
var/controller_active = FALSE
///whether all required parts of the tram are considered operational
var/controller_operational = TRUE
///the controller cabinet located on the tram
var/obj/machinery/transport/tram_controller/paired_cabinet
///the home controller located in telecoms
var/obj/machinery/transport/tram_controller/tcomms/home_controller
///if we're travelling, what direction are we going
var/travel_direction = NONE
///if we're travelling, how far do we have to go
@@ -50,16 +53,27 @@
///how many times we moved while costing less than 0.5 * SStransport.max_time milliseconds per movement
var/recovery_clear_count = 0
///if the tram's next stop will be the tram malfunction event sequence
var/malf_active = FALSE
///fluff information of the tram, such as ongoing kill count and age
var/datum/tram_mfg_info/tram_registration
///previous trams that have been destroyed
var/list/tram_history
/datum/tram_mfg_info
///serial number of this tram (what round ID it first appeared in)
var/serial_number
///is it the active tram for the map
var/active = TRUE
///date the tram was created
var/mfg_date
///what map the tram is used on
var/install_location
///lifetime distance the tram has travelled
var/distance_travelled = 0
///lifetime number of players hit by the tram
var/collisions = 0
/**
@@ -245,6 +259,9 @@
playsound(paired_cabinet, 'sound/machines/synth_yes.ogg', 40, vary = FALSE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE)
paired_cabinet.say("Controller reset.")
if(malf_active)
addtimer(CALLBACK(src, PROC_REF(announce_malf_event)), 1 SECONDS)
SEND_SIGNAL(src, COMSIG_TRAM_TRAVEL, idle_platform, destination_platform)
for(var/obj/structure/transport/linear/tram/transport_module as anything in transport_modules) //only thing everyone needs to know is the new location.
@@ -279,11 +296,7 @@
return PROCESS_KILL
if(!travel_remaining)
if(!controller_operational)
degraded_stop()
return PROCESS_KILL
if((controller_status & COMM_ERROR) && prob(5)) // malfunctioning tram has a small chance to e-stop
if(!controller_operational || malf_active)
degraded_stop()
else
normal_stop()
@@ -324,6 +337,9 @@
scheduled_move = world.time + speed_limiter
/**
* Tram stops normally, performs post-trip actions and updates the tram registration.
*/
/datum/transport_controller/linear/tram/proc/normal_stop()
cycle_doors(CYCLE_OPEN)
log_transport("TC: [specific_transport_id] trip completed. Info: nav_pos ([nav_beacon.x], [nav_beacon.y], [nav_beacon.z]) idle_pos ([destination_platform.x], [destination_platform.y], [destination_platform.z]).")
@@ -341,6 +357,9 @@
current_load = 0
speed_limiter = initial(speed_limiter)
/**
* Tram comes to an in-station degraded stop, throwing the players. Caused by power loss or tram malfunction event.
*/
/datum/transport_controller/linear/tram/proc/degraded_stop()
log_transport("TC: [specific_transport_id] trip completed with a degraded status. Info: [TC_TS_STATUS] nav_pos ([nav_beacon.x], [nav_beacon.y], [nav_beacon.z]) idle_pos ([destination_platform.x], [destination_platform.y], [destination_platform.z]).")
addtimer(CALLBACK(src, PROC_REF(unlock_controls)), 4 SECONDS)
@@ -350,6 +369,13 @@
paired_cabinet.say("Controller reset.")
log_transport("TC: [specific_transport_id] position data successfully reset. ")
speed_limiter = initial(speed_limiter)
if(malf_active)
set_status_code(SYSTEM_FAULT, TRUE)
addtimer(CALLBACK(src, PROC_REF(cycle_doors), CYCLE_OPEN), 2 SECONDS)
malf_active = FALSE
throw_chance = initial(throw_chance)
playsound(paired_cabinet, 'sound/machines/buzz-sigh.ogg', 60, vary = FALSE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE)
paired_cabinet.say("Controller error. Please contact your engineering department.")
idle_platform = destination_platform
tram_registration.distance_travelled += (travel_trip_length - travel_remaining)
travel_trip_length = 0
@@ -360,6 +386,9 @@
for(var/obj/structure/transport/linear/tram/module in transport_modules)
module.estop_throw(throw_direction)
/**
* Tram comes to an emergency stop without completing its trip. Caused by emergency stop button or some catastrophic tram failure.
*/
/datum/transport_controller/linear/tram/proc/halt_and_catch_fire()
if(controller_status & SYSTEM_FAULT)
if(!isnull(paired_cabinet))
@@ -382,6 +411,9 @@
current_speed = 0
current_load = 0
/**
* Performs a reset of the tram's position data by finding a predetermined reference landmark, then driving to it.
*/
/datum/transport_controller/linear/tram/proc/reset_position()
if(idle_platform)
if(get_turf(idle_platform) == get_turf(nav_beacon))
@@ -528,20 +560,36 @@
set_status_code(SYSTEM_FAULT, FALSE)
reset_position()
/datum/transport_controller/linear/tram/proc/set_home_controller(obj/machinery/transport/tram_controller/tcomms/tcomms_unit)
home_controller = tcomms_unit
RegisterSignal(tcomms_unit, COMSIG_MACHINERY_POWER_LOST, PROC_REF(home_power_lost))
RegisterSignal(tcomms_unit, COMSIG_MACHINERY_POWER_RESTORED, PROC_REF(home_power_restored))
RegisterSignal(tcomms_unit, COMSIG_QDELETING, PROC_REF(on_home_qdel))
log_transport("TC: [specific_transport_id] is now paired with home controller [tcomms_unit].")
if(controller_status & COMM_ERROR)
set_status_code(COMM_ERROR, FALSE)
/datum/transport_controller/linear/tram/proc/on_cabinet_qdel()
paired_cabinet = null
log_transport("TC: [specific_transport_id] received QDEL from controller cabinet.")
set_status_code(SYSTEM_FAULT, TRUE)
send_transport_active_signal()
/datum/transport_controller/linear/tram/proc/on_home_qdel()
home_controller = null
log_transport("TC: [specific_transport_id] received QDEL from controller cabinet.")
set_status_code(COMM_ERROR, TRUE)
/datum/transport_controller/linear/tram/proc/home_power_lost()
set_status_code(COMM_ERROR, TRUE)
/datum/transport_controller/linear/tram/proc/home_power_restored()
set_status_code(COMM_ERROR, FALSE)
/**
* Tram malfunction random event. Set comm error, increase tram lethality.
* Tram malfunction random event. Set comm error, requiring engineering or AI intervention.
*/
/datum/transport_controller/linear/tram/proc/start_malf_event()
set_status_code(COMM_ERROR, TRUE)
SEND_TRANSPORT_SIGNAL(COMSIG_COMMS_STATUS, src, FALSE)
paired_cabinet.generate_repair_signals()
collision_lethality *= 1.25
malf_active = TRUE
throw_chance *= 1.25
log_transport("TC: [specific_transport_id] starting Tram Malfunction event.")
@@ -552,15 +600,15 @@
* automagically reset it remotely.
*/
/datum/transport_controller/linear/tram/proc/end_malf_event()
if(!(controller_status & COMM_ERROR))
if(!(malf_active))
return
set_status_code(COMM_ERROR, FALSE)
paired_cabinet.clear_repair_signals()
collision_lethality = initial(collision_lethality)
malf_active = FALSE
throw_chance = initial(throw_chance)
SEND_TRANSPORT_SIGNAL(COMSIG_COMMS_STATUS, src, TRUE)
log_transport("TC: [specific_transport_id] ending Tram Malfunction event.")
/datum/transport_controller/linear/tram/proc/announce_malf_event()
priority_announce("Our automated control system has lost contact with the tram's onboard computer. Please stand by, engineering has been dispatched to the tram to perform a reset.", "[command_name()] Engineering Division")
/datum/transport_controller/linear/tram/proc/register_collision(points = 1)
tram_registration.collisions += points
SEND_TRANSPORT_SIGNAL(COMSIG_TRAM_COLLISION, SSpersistence.tram_hits_this_round)
@@ -689,11 +737,13 @@
name = "tram controller"
desc = "Makes the tram go, or something. Holds the tram's electronics, controls, and maintenance panel. A sticker above the card reader says 'Engineering access only.'"
icon = 'icons/obj/tram/tram_controllers.dmi'
icon_state = "controller-panel"
icon_state = "tram-controller"
base_icon_state = "tram"
anchored = TRUE
density = FALSE
armor_type = /datum/armor/transport_module
resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
interaction_flags_machine = parent_type::interaction_flags_machine | INTERACT_MACHINE_OFFLINE
max_integrity = 750
integrity_failure = 0.25
layer = SIGN_LAYER
@@ -701,6 +751,8 @@
idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.25
power_channel = AREA_USAGE_ENVIRON
var/datum/transport_controller/linear/tram/controller_datum
/// If this machine has a cover installed
var/has_cover = TRUE
/// If the cover is open
var/cover_open = FALSE
/// If the cover is locked
@@ -733,14 +785,13 @@
..()
/obj/machinery/transport/tram_controller/add_context(atom/source, list/context, obj/item/held_item, mob/user)
if(held_item?.tool_behaviour == TOOL_SCREWDRIVER)
if(held_item?.tool_behaviour == TOOL_SCREWDRIVER && has_cover)
context[SCREENTIP_CONTEXT_RMB] = panel_open ? "close panel" : "open panel"
if(!held_item)
if(!held_item && has_cover)
context[SCREENTIP_CONTEXT_LMB] = cover_open ? "access controls" : "open cabinet"
context[SCREENTIP_CONTEXT_RMB] = cover_open ? "close cabinet" : "toggle lock"
if(panel_open)
if(held_item?.tool_behaviour == TOOL_WRENCH)
context[SCREENTIP_CONTEXT_RMB] = "unscrew cabinet"
@@ -760,14 +811,15 @@
/obj/machinery/transport/tram_controller/examine(mob/user)
. = ..()
. += span_notice("The door appears to be [cover_locked ? "locked. Swipe an ID card to unlock" : "unlocked. Swipe an ID card to lock"].")
if(panel_open)
. += span_notice("It is secured to the tram wall with [EXAMINE_HINT("bolts.")]")
. += span_notice("The maintenance panel can be closed with a [EXAMINE_HINT("screwdriver.")]")
else
. += span_notice("The maintenance panel can be opened with a [EXAMINE_HINT("screwdriver.")]")
if(has_cover)
. += span_notice("The door appears to be [cover_locked ? "locked. Swipe an ID card to unlock" : "unlocked. Swipe an ID card to lock"].")
if(panel_open)
. += span_notice("It is secured to the tram wall with [EXAMINE_HINT("bolts.")]")
. += span_notice("The maintenance panel can be closed with a [EXAMINE_HINT("screwdriver.")]")
else
. += span_notice("The maintenance panel can be opened with a [EXAMINE_HINT("screwdriver.")]")
if(cover_open)
if(cover_open || !has_cover)
. += span_notice("The [EXAMINE_HINT("yellow reset button")] resets the tram controller if a problem occurs or needs to be restarted.")
. += span_notice("The [EXAMINE_HINT("red stop button")] immediately stops the tram, requiring a reset afterwards.")
. += span_notice("The cabinet can be closed with a [EXAMINE_HINT("Right-click.")]")
@@ -779,16 +831,17 @@
if(user.combat_mode || cover_open)
return ..()
var/obj/item/card/id/id_card = user.get_id_in_hand()
if(!isnull(id_card))
try_toggle_lock(user, id_card)
return
if(has_cover)
var/obj/item/card/id/id_card = user.get_id_in_hand()
if(!isnull(id_card))
try_toggle_lock(user, id_card)
return
return ..()
/obj/machinery/transport/tram_controller/attack_hand(mob/living/user, params)
. = ..()
if(cover_open)
if(cover_open || !has_cover)
return
if(cover_locked)
@@ -804,6 +857,8 @@
/obj/machinery/transport/tram_controller/attack_hand_secondary(mob/living/user, params)
. = ..()
if(!has_cover)
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
if(!cover_open)
var/obj/item/card/id/id_card = user.get_idcard(TRUE)
@@ -843,6 +898,9 @@
/obj/machinery/transport/tram_controller/wrench_act_secondary(mob/living/user, obj/item/tool)
. = ..()
if(!has_cover)
return
if(panel_open && cover_open)
balloon_alert(user, "unsecuring...")
tool.play_tool_sound(src)
@@ -878,53 +936,55 @@
/obj/machinery/transport/tram_controller/update_overlays()
. = ..()
if(!cover_open)
. += mutable_appearance(icon, "controller-closed")
if(cover_locked)
. += mutable_appearance(icon, "controller-locked")
if(has_cover)
if(!cover_open)
. += mutable_appearance(icon, "[base_icon_state]-closed")
if(cover_locked)
. += mutable_appearance(icon, "[base_icon_state]-locked")
else
var/mutable_appearance/controller_door = mutable_appearance(icon, "controller-open")
controller_door.pixel_w = -3
. += controller_door
else
var/mutable_appearance/controller_door = mutable_appearance(icon, "[base_icon_state]-open")
controller_door.pixel_w = -3
. += controller_door
if(machine_stat & NOPOWER)
. += mutable_appearance(icon, "estop")
. += emissive_appearance(icon, "estop", src, alpha = src.alpha)
. += mutable_appearance(icon, "[base_icon_state]-estop")
. += emissive_appearance(icon, "[base_icon_state]-estop", src, alpha = src.alpha)
return
. += mutable_appearance(icon, "power")
. += emissive_appearance(icon, "power", src, alpha = src.alpha)
. += mutable_appearance(icon, "[base_icon_state]-power")
. += emissive_appearance(icon, "[base_icon_state]-power", src, alpha = src.alpha)
if(!controller_datum)
. += mutable_appearance(icon, "fatal")
. += emissive_appearance(icon, "fatal", src, alpha = src.alpha)
. += mutable_appearance(icon, "[base_icon_state]-fatal")
. += emissive_appearance(icon, "[base_icon_state]-fatal", src, alpha = src.alpha)
return
if(controller_datum.controller_status & EMERGENCY_STOP)
. += mutable_appearance(icon, "estop")
. += emissive_appearance(icon, "estop", src, alpha = src.alpha)
. += mutable_appearance(icon, "[base_icon_state]-estop")
. += emissive_appearance(icon, "[base_icon_state]-estop", src, alpha = src.alpha)
return
if(controller_datum.controller_status & SYSTEM_FAULT || controller_datum.malf_active)
. += mutable_appearance(icon, "[base_icon_state]-fault")
. += emissive_appearance(icon, "[base_icon_state]-fault", src, alpha = src.alpha)
return
if(!(controller_datum.controller_status & DOORS_READY))
. += mutable_appearance(icon, "doors")
. += emissive_appearance(icon, "doors", src, alpha = src.alpha)
. += mutable_appearance(icon, "[base_icon_state]-doors")
. += emissive_appearance(icon, "[base_icon_state]-doors", src, alpha = src.alpha)
if(controller_datum.controller_active)
. += mutable_appearance(icon, "active")
. += emissive_appearance(icon, "active", src, alpha = src.alpha)
. += mutable_appearance(icon, "[base_icon_state]-active")
. += emissive_appearance(icon, "[base_icon_state]-active", src, alpha = src.alpha)
if(controller_datum.controller_status & SYSTEM_FAULT)
. += mutable_appearance(icon, "fault")
. += emissive_appearance(icon, "fault", src, alpha = src.alpha)
else if(controller_datum.controller_status & COMM_ERROR)
. += mutable_appearance(icon, "comms")
. += emissive_appearance(icon, "comms", src, alpha = src.alpha)
if(controller_datum.controller_status & COMM_ERROR)
. += mutable_appearance(icon, "[base_icon_state]-comms")
. += emissive_appearance(icon, "[base_icon_state]-comms", src, alpha = src.alpha)
else
. += mutable_appearance(icon, "normal")
. += emissive_appearance(icon, "normal", src, alpha = src.alpha)
. += mutable_appearance(icon, "[base_icon_state]-normal")
. += emissive_appearance(icon, "[base_icon_state]-normal", src, alpha = src.alpha)
/**
* Find the controller associated with the transport module the cabinet is sitting on.
@@ -972,24 +1032,12 @@
balloon_alert(user, "access controller shorted")
return TRUE
/**
* Check if the tram was malfunctioning due to the random event, and if so end the event on repair.
*/
/obj/machinery/transport/tram_controller/try_fix_machine(obj/machinery/transport/machine, mob/living/user, obj/item/tool)
. = ..()
/obj/machinery/transport/tram_controller/ui_status(mob/user, datum/ui_state/state)
if(HAS_SILICON_ACCESS(user) && (controller_datum.controller_status & SYSTEM_FAULT || controller_datum.controller_status & COMM_ERROR || !is_operational))
to_chat(user, span_warning("An error code flashes: Communications fault! The [src] is not responding to remote inputs!"))
return UI_CLOSE
if(. == FALSE)
return
if(!controller_datum)
return
var/datum/round_event/tram_malfunction/malfunction_event = locate(/datum/round_event/tram_malfunction) in SSevents.running
if(malfunction_event)
malfunction_event.end()
if(controller_datum.controller_status & COMM_ERROR)
controller_datum.set_status_code(COMM_ERROR, FALSE)
return ..()
/obj/machinery/transport/tram_controller/ui_interact(mob/user, datum/tgui/ui)
. = ..()
@@ -997,7 +1045,7 @@
if(!cover_open && !HAS_SILICON_ACCESS(user) && !isobserver(user))
return
if(!is_operational)
if(machine_stat & BROKEN)
return
ui = SStgui.try_update_ui(user, src, ui)
@@ -1043,6 +1091,10 @@
if(!COOLDOWN_FINISHED(src, manual_command_cooldown))
return
if(machine_stat & NOPOWER)
visible_message(span_warning("The button doesn't appear to do anything, the [src]'s power failure status is flashing!"), vision_distance = COMBAT_MESSAGE_RANGE)
return
switch(action)
if("dispatch")
@@ -1078,11 +1130,53 @@
COOLDOWN_START(src, manual_command_cooldown, 2 SECONDS)
/// Controller that sits in the telecoms room
/obj/machinery/transport/tram_controller/tcomms
name = "tram central controller"
desc = "This semi-conductor is half of the brains controlling the tram and its auxillary equipment."
icon_state = "home-controller"
base_icon_state = "home"
density = TRUE
layer = BELOW_OBJ_LAYER
power_channel = AREA_USAGE_EQUIP
cover_open = TRUE
has_cover = FALSE
/// Handles the machine being affected by an EMP, causing signal failure.
/obj/machinery/transport/tram_controller/tcomms/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
if(prob(100/severity) && !(machine_stat & EMPED))
set_machine_stat(machine_stat | EMPED)
controller_datum.set_status_code(COMM_ERROR, TRUE)
var/duration = (300 SECONDS)/severity
addtimer(CALLBACK(src, PROC_REF(de_emp)), rand(duration - 2 SECONDS, duration + 2 SECONDS))
/// Handles the machine stopping being affected by an EMP.
/obj/machinery/transport/tram_controller/tcomms/proc/de_emp()
set_machine_stat(machine_stat & ~EMPED)
controller_datum.set_status_code(COMM_ERROR, FALSE)
/obj/machinery/transport/tram_controller/tcomms/find_controller()
link_tram()
return
/obj/machinery/transport/tram_controller/tcomms/link_tram()
. = ..()
var/datum/transport_controller/linear/tram/tram = transport_ref?.resolve()
controller_datum = tram
if(!controller_datum)
return
controller_datum.set_home_controller(src)
RegisterSignal(SStransport, COMSIG_TRANSPORT_ACTIVE, PROC_REF(sync_controller))
/obj/item/wallframe/tram/controller
name = "tram controller cabinet"
desc = "A box that contains the equipment to control a tram. Just secure to the tram wall."
icon = 'icons/obj/tram/tram_controllers.dmi'
icon_state = "controller-panel"
icon_state = "tram-controller"
custom_materials = list(/datum/material/titanium = SHEET_MATERIAL_AMOUNT * 4, /datum/material/iron = SHEET_MATERIAL_AMOUNT * 2, /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2)
result_path = /obj/machinery/transport/tram_controller
pixel_shift = 32
@@ -91,6 +91,17 @@
/// The ID of the tram we're linked to
var/specific_transport_id = TRAMSTATION_LINE_1
/// We allow borgs to use the button locally, but not the AI remotely
/obj/machinery/button/transport/tram/attack_ai(mob/user)
if(isAI(user) || panel_open)
return
if(HAS_SILICON_ACCESS(user) && !issilicon(user)) //admins and remote controls can use it at a distance
return attack_hand(user)
if(in_range(user, src))
return attack_hand(user)
else
to_chat(user, span_warning("You are too far away to activate the button!"))
/obj/machinery/button/transport/tram/setup_device()
var/obj/item/assembly/control/transport/call_button/tram_device = device
tram_device.id = id
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB