You can cuff people to the tram rails #90293 (#3445)

## About The Pull Request

https://github.com/tgstation/tgstation/pull/90293


![image](https://private-user-images.githubusercontent.com/7483112/427767772-688e23ff-93df-4f51-990c-4bc475d344fb.gif?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDM4MjY2MzAsIm5iZiI6MTc0MzgyNjMzMCwicGF0aCI6Ii83NDgzMTEyLzQyNzc2Nzc3Mi02ODhlMjNmZi05M2RmLTRmNTEtOTkwYy00YmM0NzVkMzQ0ZmIuZ2lmP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDQwNSUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTA0MDVUMDQxMjEwWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MDBiNTNhZGRjYjY5YWRmMjQyZTM4YjY3MGM3MGMyZTIzM2I4MDkwMGYwNTEwODc2YmE0YWE1ZGFiMDJjZWI1MyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.6w2hr_2ruJTsAcXoAlcbsZe5bM3ii83iBQk7aDQhvMs)

Handcuffed people can be buckled to the tram rails.
If the tram hits them then they will die badly.
If they're not shockproof and are buckled to a powered rail, it will zap
them repeatedly for a little bit of damage (but not a lot because you
probably want them to die from something else).
Unbuckling someone from a powered rail is also pretty dangerous.

While doing this I fucked around a bit with how the "is the tram deadly"
calculation worked because I didn't like how a deadly tram cuts your
head off but does literally no other damage. Now it pulverises and
beheads you.

## Why It's Good For The Game


![image](https://github.com/user-attachments/assets/dd851dda-56b0-41c9-b6aa-26c9db0b9a28)

---------

Co-authored-by: tgstation-ci[bot] <179393467+tgstation-ci[bot]@users.noreply.github.com>
This commit is contained in:
LT3
2025-04-04 23:16:53 -07:00
committed by GitHub
co-authored by tgstation-ci[bot] <179393467+tgstation-ci[bot]@users.noreply.github.com>
parent 3c1c05052f
commit c3fe3d31ba
13 changed files with 217 additions and 140 deletions
+6 -3
View File
@@ -71459,9 +71459,12 @@
/turf/closed/wall/r_wall/rust,
/area/moonstation/underground)
"tFI" = (
/obj/structure/tram,
/obj/structure/fluff/tram_rail/electric{
dir = 1
},
/obj/structure/transport/linear/tram,
/obj/structure/plaque/static_plaque/tram{
/obj/structure/thermoplastic,
/obj/structure/sign/tram_plate/directional/south{
specific_transport_id = "moon_1"
},
/turf/open/floor/plating,
@@ -222519,8 +222522,8 @@ iiB
sqG
iWG
eNL
iMX
tFI
sDL
tHD
asy
wpy
+2 -7
View File
@@ -37296,6 +37296,7 @@
},
/obj/structure/transport/linear/tram,
/obj/structure/thermoplastic,
/obj/structure/sign/tram_plate/directional/south,
/turf/open/openspace,
/area/station/hallway/primary/tram/center)
"may" = (
@@ -39729,12 +39730,6 @@
/obj/effect/turf_decal/trimline/blue/filled/line,
/turf/open/floor/iron/white,
/area/station/medical/surgery/fore)
"mXi" = (
/obj/structure/transport/linear/tram,
/obj/structure/tram,
/obj/structure/plaque/static_plaque/tram,
/turf/open/openspace,
/area/station/hallway/primary/tram/center)
"mXo" = (
/obj/structure/kitchenspike,
/obj/effect/turf_decal/weather/snow,
@@ -170305,7 +170300,7 @@ oKm
uzl
xBS
mar
mXi
oKm
dhI
lej
fxs
@@ -4,6 +4,9 @@
/// Sent from /obj/structure/transport/linear/tram when it hits someone: ()
#define COMSIG_TRAM_COLLISION "tram_collided"
/// Sent from a mob that just got hit by the tram
#define COMSIG_LIVING_HIT_BY_TRAM "tram_hit_me"
// Sent to and from SStransport for control between various components
/// Requesting transport move to a destination
#define COMSIG_TRANSPORT_REQUEST "!REQ"
+2
View File
@@ -8,6 +8,8 @@
#define SHOCK_REQUIREMENT_PARENT_MOB_ISALIVE (1<<3)
///a signal can toggle the ability to shock on a timer
#define SHOCK_REQUIREMENT_SIGNAL_RECEIVED_TOGGLE (1<<4)
///electrified buckle requires the area to be powered but not necessarily connected by cable
#define SHOCK_REQUIREMENT_AREA_POWER (1<<5)
///This trait signifies that the object can be used to electrify things buckled to it
+47 -25
View File
@@ -20,12 +20,20 @@
var/usage_flags
///if true, this will shock the buckled mob every shock_loop_time in process()
var/shock_on_loop = TRUE
///if true we zap the buckled mob as soon as it becomes buckled
var/shock_immediately = FALSE
///do we output a message every time someone gets shocked?
var/print_message = TRUE
///how long the component waits before shocking the mob buckled to parent again
var/shock_loop_time = 5 SECONDS
///how much damage is done per shock iff usage_flags doesnt have SHOCK_REQUIREMENT_LIVE_CABLE
var/shock_damage = 50
///this signal was given as an argument to register for parent to emit, if its emitted to parent then shock_on_demand is called. var is so it can be unregistered
var/requested_signal_parent_emits = null
///what area power channel do we check if area power is required?
var/area_power_channel = AREA_USAGE_EQUIP
///details of how we electrocute people
var/shock_flags
/**
* Initialize args:
@@ -35,14 +43,22 @@
* * overlays_to_add - pass in a list of images and the component will add them to parent as well as remove them in UnregisterFromParent(). sets requested_overlays
* * override_buckle - if TRUE, sets parent.can_buckle = TRUE and resets it on UnregisterFromParent(), usually objects that have need to be overridden will look janky on buckle
* * damage_on_shock - if SHOCK_REQUIREMENT_LIVE_CABLE is not set in input_requirements, then this is how much damage each shock does. sets shock_damage
* * shock_immediately - if TRUE we will shock the buckled mob the first time we process after buckling, otherwise we wait until the cooldown has passed
* * print_message - if TRUE we will show a message every time we electrocute someone during the shock loop
* * signal_to_register_from_parent - if set, the component registers to listen for this signal targeting parent to manually shock. sets requested_signal_parent_emits
* * area_power_channel - if SHOCK_REQUIREMENT_AREA_POWER is set in input_requirements, it will check this power channel in the area
* * shock_flags - flags passed into electrocute_act when we zap someone
*/
/datum/component/electrified_buckle/Initialize(input_requirements, obj/item/input_item, list/overlays_to_add, override_buckle, damage_on_shock = 50, signal_to_register_from_parent, loop_length)
/datum/component/electrified_buckle/Initialize(input_requirements, obj/item/input_item, list/overlays_to_add, override_buckle = FALSE, damage_on_shock = 50, shock_immediately = FALSE, print_message = TRUE, signal_to_register_from_parent, loop_length, area_power_channel, shock_flags = NONE)
var/atom/movable/parent_as_movable = parent
if(!istype(parent_as_movable))
return COMPONENT_INCOMPATIBLE
usage_flags = input_requirements
src.shock_immediately = shock_immediately
src.print_message = print_message
src.area_power_channel = area_power_channel
src.shock_flags = shock_flags
if(!parent_as_movable.can_buckle && !override_buckle)
return COMPONENT_INCOMPATIBLE
@@ -63,7 +79,7 @@
if(usage_flags & SHOCK_REQUIREMENT_ON_SIGNAL_RECEIVED)
shock_on_loop = FALSE
RegisterSignal(required_object, COMSIG_ASSEMBLY_PULSED, PROC_REF(shock_on_demand))
RegisterSignal(required_object, COMSIG_ASSEMBLY_PULSED, PROC_REF(do_electrocution))
else if(usage_flags & SHOCK_REQUIREMENT_SIGNAL_RECEIVED_TOGGLE)
RegisterSignal(required_object, COMSIG_ASSEMBLY_PULSED, PROC_REF(toggle_shock_loop))
@@ -78,7 +94,7 @@
//if parent wants us to manually shock on some specified action
if(signal_to_register_from_parent)
RegisterSignal(parent, signal_to_register_from_parent, PROC_REF(shock_on_demand))
RegisterSignal(parent, signal_to_register_from_parent, PROC_REF(do_electrocution))
requested_signal_parent_emits = signal_to_register_from_parent
if(overlays_to_add)
@@ -137,6 +153,9 @@
if (requested_overlays)
source.update_appearance()
if (shock_immediately)
do_electrocution()
COOLDOWN_START(src, electric_buckle_cooldown, shock_loop_time)
if(!(usage_flags & SHOCK_REQUIREMENT_ON_SIGNAL_RECEIVED) && shock_on_loop)
START_PROCESSING(SSprocessing, src)
@@ -171,31 +190,20 @@
return
COOLDOWN_START(src, electric_buckle_cooldown, shock_loop_time)
do_electrocution()
var/turf/our_turf = get_turf(parent_as_movable)
var/obj/structure/cable/live_cable = our_turf.get_cable_node()
if (print_message)
parent_as_movable.visible_message(span_danger("[parent_as_movable] delivers a powerful shock!"), span_hear("You hear a deep sharp shock!"))
if(usage_flags & SHOCK_REQUIREMENT_LIVE_CABLE)
if((!live_cable || !live_cable.powernet || live_cable.powernet.avail < ELECTRIC_BUCKLE_MINUMUM_POWERNET_STRENGTH))
return
for(var/mob/living/guinea_pig as anything in parent_as_movable.buckled_mobs)
guinea_pig.electrocute_act(round(live_cable.powernet.avail / ELECTRIC_BUCKLE_SHOCK_STRENGTH_DIVISOR), parent_as_movable)
break
else
for(var/mob/living/guinea_pig as anything in parent_as_movable.buckled_mobs)
guinea_pig.electrocute_act(shock_damage, parent_as_movable)
break
parent_as_movable.visible_message(span_danger("The electric chair went off!"), span_hear("You hear a deep sharp shock!"))
///a shock that is toggled manually
/datum/component/electrified_buckle/proc/shock_on_demand()
/// Zap whoever is buckled to us
/datum/component/electrified_buckle/proc/do_electrocution()
SIGNAL_HANDLER
if((usage_flags & SHOCK_REQUIREMENT_ITEM) && QDELETED(required_object))
return
var/atom/movable/parent_as_movable = parent
if(usage_flags & SHOCK_REQUIREMENT_LIVE_CABLE)
var/turf/our_turf = get_turf(parent_as_movable)
var/obj/structure/cable/live_cable = our_turf.get_cable_node()
@@ -204,8 +212,22 @@
for(var/mob/living/guinea_pig as anything in parent_as_movable.buckled_mobs)
var/shock_damage = round(live_cable.powernet.avail / ELECTRIC_BUCKLE_SHOCK_STRENGTH_DIVISOR)
guinea_pig.electrocute_act(shock_damage, parent_as_movable)
break
guinea_pig.electrocute_act(shock_damage, parent_as_movable, flags = shock_flags)
return
if(usage_flags & SHOCK_REQUIREMENT_AREA_POWER)
var/area/our_area = get_area(parent)
if (!our_area.powered(area_power_channel))
return
for(var/mob/living/guinea_pig as anything in parent_as_movable.buckled_mobs)
guinea_pig.electrocute_act(shock_damage, parent_as_movable, flags = shock_flags)
return
for(var/mob/living/guinea_pig as anything in parent_as_movable.buckled_mobs)
guinea_pig.electrocute_act(shock_damage, parent_as_movable, flags = shock_flags)
/datum/component/electrified_buckle/proc/toggle_shock_loop()
SIGNAL_HANDLER
@@ -213,11 +235,11 @@
if(shock_on_loop)
shock_on_loop = FALSE
STOP_PROCESSING(SSprocessing, src)
parent_as_movable.visible_message(span_notice("The electric chair emits a snap as its circuit opens, making it safe for now."))
parent_as_movable.visible_message(span_notice("\The [parent_as_movable] emits a snap as its circuit opens, making it safe for now."))
else
shock_on_loop = TRUE
START_PROCESSING(SSprocessing, src)
parent_as_movable.visible_message(span_notice("You hear the sound of an electric circuit closing coming from the electric chair!"))
parent_as_movable.visible_message(span_notice("You hear the sound of an electric circuit closing coming from \the [parent_as_movable]!"))
#undef ELECTRIC_BUCKLE_SHOCK_STRENGTH_DIVISOR
#undef ELECTRIC_BUCKLE_MINUMUM_POWERNET_STRENGTH
+40 -4
View File
@@ -289,6 +289,25 @@
plane = FLOOR_PLANE
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
deconstructible = FALSE
can_buckle = TRUE
buckle_requires_restraints = TRUE
buckle_lying = 90
/obj/structure/fluff/tram_rail/post_buckle_mob(mob/living/target)
. = ..()
target.pixel_y += dir == SOUTH ? -3 : 14
RegisterSignal(target, COMSIG_LIVING_HIT_BY_TRAM, PROC_REF(on_buckled_tram_smashed))
/obj/structure/fluff/tram_rail/post_unbuckle_mob(mob/living/target)
. = ..()
target.pixel_y -= dir == SOUTH ? -3 : 14
UnregisterSignal(target, COMSIG_LIVING_HIT_BY_TRAM)
/// If someone gets hit by the tram while buckled to us (mission accomplished) unbuckle them so that they can fly away
/// Also we rip one of their arms off to "uncuff" them
/obj/structure/fluff/tram_rail/proc/on_buckled_tram_smashed(mob/living/smashed)
SIGNAL_HANDLER
unbuckle_mob(smashed, force = TRUE, can_fall = FALSE) // Make sure they don't fall down a z-level until they've been thrown
/obj/structure/fluff/tram_rail/floor
name = "tram rail protective cover"
@@ -297,19 +316,36 @@
/obj/structure/fluff/tram_rail/end
icon_state = "railend"
/obj/structure/fluff/tram_rail/electric
desc = "Great for trams, not so great for skating. This one is a power rail."
/obj/structure/fluff/tram_rail/anchor
name = "tram rail anchor"
icon_state = "anchor"
/obj/structure/fluff/tram_rail/electric
desc = "Great for trams, not so great for skating. This one is a power rail."
/// What power channel from the APC do we check for power?
var/power_channel = AREA_USAGE_ENVIRON
/obj/structure/fluff/tram_rail/electric/anchor
name = "tram rail anchor"
icon_state = "anchor"
/obj/structure/fluff/tram_rail/electric/Initialize(mapload)
. = ..()
AddComponent(\
/datum/component/electrified_buckle,\
input_requirements = SHOCK_REQUIREMENT_AREA_POWER,\
shock_immediately = TRUE,\
print_message = FALSE,\
damage_on_shock = 5,\
loop_length = 8 SECONDS,\
area_power_channel = power_channel,\
shock_flags = SHOCK_NOSTUN\
)
/obj/structure/fluff/tram_rail/electric/attack_hand(mob/living/user, list/modifiers)
if(user.electrocute_act(75, src))
. = ..()
var/area/our_area = get_area(src)
if(our_area?.powered(power_channel) && user.electrocute_act(75, src))
do_sparks(5, TRUE, src)
/obj/structure/fluff/broken_canister_frame
@@ -25,83 +25,6 @@
/obj/structure/plaque/static_plaque/golden/captain
name = "The Most Robust Captain Award for Robustness"
/obj/structure/plaque/static_plaque/tram
/// The tram we have info about
var/specific_transport_id = TRAMSTATION_LINE_1
/// Weakref to the tram we have info about
var/datum/weakref/transport_ref
/// Serial number of the tram
var/tram_serial
name = "\improper tram information plate"
icon_state = "commission_tram"
custom_materials = list(/datum/material/titanium = SHEET_MATERIAL_AMOUNT)
layer = SIGN_LAYER
/obj/structure/plaque/static_plaque/tram/Initialize(mapload)
. = ..()
return INITIALIZE_HINT_LATELOAD
/obj/structure/plaque/static_plaque/tram/LateInitialize()
link_tram()
set_tram_serial()
/obj/structure/plaque/static_plaque/tram/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = ..()
if(isnull(held_item))
context[SCREENTIP_CONTEXT_LMB] = "View details"
return CONTEXTUAL_SCREENTIP_SET
/obj/structure/plaque/static_plaque/tram/proc/link_tram()
for(var/datum/transport_controller/linear/tram/tram as anything in SStransport.transports_by_type[TRANSPORT_TYPE_TRAM])
if(tram.specific_transport_id == specific_transport_id)
transport_ref = WEAKREF(tram)
break
/obj/structure/plaque/static_plaque/tram/proc/set_tram_serial()
var/datum/transport_controller/linear/tram/tram = transport_ref?.resolve()
if(isnull(tram) || isnull(tram.tram_registration))
return
tram_serial = tram.tram_registration.serial_number
desc = "A plate showing details from the manufacturer about this Nakamura Engineering SkyyTram Mk VI, serial number [tram_serial].<br><br>We are not responsible for any injuries or fatalities caused by usage of the tram. \
Using the tram carries inherent risks, and we cannot guarantee the safety of all passengers. By using the tram, you assume, acknowledge, and accept all the risks and responsibilities. <br><br>\
Please be aware that riding the tram can cause a variety of injuries, including but not limited to: slips, trips, and falls; collisions with other passengers or objects; strains, sprains, and other musculoskeletal injuries; \
cuts, bruises, and lacerations; and more severe injuries such as head trauma, spinal cord injuries, and even death. These injuries can be caused by a variety of factors, including the movements of the tram, the behaviour \
of other passengers, and unforeseen circumstances such as foul play or mechanical issues.<br><br>\
By entering the tram, guideway, or crossings you agree Nanotrasen is not liable for any injuries, damages, or losses that may occur. If you do not agree to these terms, please do not use the tram.<br>"
/obj/structure/plaque/static_plaque/tram/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "TramPlaque")
ui.autoupdate = FALSE
ui.open()
/obj/structure/plaque/static_plaque/tram/ui_static_data(mob/user)
var/datum/transport_controller/linear/tram/tram = transport_ref?.resolve()
var/list/data = list()
var/list/current_tram = list()
var/list/previous_trams = list()
current_tram += list(list(
"serialNumber" = tram.tram_registration.serial_number,
"mfgDate" = tram.tram_registration.mfg_date,
"distanceTravelled" = tram.tram_registration.distance_travelled,
"tramCollisions" = tram.tram_registration.collisions,
))
for(var/datum/tram_mfg_info/previous_tram as anything in tram.tram_history)
previous_trams += list(list(
"serialNumber" = previous_tram.serial_number,
"mfgDate" = previous_tram.mfg_date,
"distanceTravelled" = previous_tram.distance_travelled,
"tramCollisions" = previous_tram.collisions,
))
data["currentTram"] = current_tram
data["previousTrams"] = previous_trams
return data
// Commission plaques, to give a little backstory to the stations. Commission dates are date of merge (or best approximation, in the case of Meta) + 540 years to convert to SS13 dates.
// Where PRs are available, I've linked them. Where they are unavailable, a git hash is provided instead for the direct commit that added/removed the map.
// Please enjoy this trip through SS13's history.
+1 -1
View File
@@ -210,7 +210,7 @@
return ..()
/obj/item/sign/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
if(!iswallturf(interacting_with))
if(!iswallturf(interacting_with) && !istype(interacting_with, /obj/structure/tram))
return NONE
var/turf/target_turf = interacting_with
var/turf/user_turf = get_turf(user)
@@ -27,3 +27,85 @@
desc = "85cr for a iced lactose-free caramel frappe?! Who buys that?!"
MAPPING_DIRECTIONAL_HELPERS(/obj/structure/sign/xenobio_guide, 32)
// Tram-mounted statistics plate
/obj/structure/sign/tram_plate
/// The tram we have info about
var/specific_transport_id = TRAMSTATION_LINE_1
/// Weakref to the tram we have info about
var/datum/weakref/transport_ref
/// Serial number of the tram
var/tram_serial
name = "tram information plate"
sign_change_name = "Information - Tram Statistics"
icon_state = "commission_tram"
max_integrity = 150
armor_type = /datum/armor/tram_structure
is_editable = FALSE
/obj/structure/sign/tram_plate/Initialize(mapload)
. = ..()
return INITIALIZE_HINT_LATELOAD
/obj/structure/sign/tram_plate/LateInitialize()
link_tram()
set_tram_serial()
/obj/structure/sign/tram_plate/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = ..()
if(isnull(held_item))
context[SCREENTIP_CONTEXT_LMB] = "View details"
return CONTEXTUAL_SCREENTIP_SET
/obj/structure/sign/tram_plate/proc/link_tram()
for(var/datum/transport_controller/linear/tram/tram as anything in SStransport.transports_by_type[TRANSPORT_TYPE_TRAM])
if(tram.specific_transport_id == specific_transport_id)
transport_ref = WEAKREF(tram)
break
/obj/structure/sign/tram_plate/proc/set_tram_serial()
var/datum/transport_controller/linear/tram/tram = transport_ref?.resolve()
if(isnull(tram) || isnull(tram.tram_registration))
return
tram_serial = tram.tram_registration.serial_number
desc = "A plate showing details from the manufacturer about this Nakamura Engineering SkyyTram Mk VI, serial number [tram_serial].<br><br>We are not responsible for any injuries or fatalities caused by usage of the tram. \
Using the tram carries inherent risks, and we cannot guarantee the safety of all passengers. By using the tram, you assume, acknowledge, and accept all the risks and responsibilities. <br><br>\
Please be aware that riding the tram can cause a variety of injuries, including but not limited to: slips, trips, and falls; collisions with other passengers or objects; strains, sprains, and other musculoskeletal injuries; \
cuts, bruises, and lacerations; and more severe injuries such as head trauma, spinal cord injuries, and even death. These injuries can be caused by a variety of factors, including the movements of the tram, the behaviour \
of other passengers, and unforeseen circumstances such as foul play or mechanical issues.<br><br>\
By entering the tram, guideway, or crossings you agree Nanotrasen is not liable for any injuries, damages, or losses that may occur. If you do not agree to these terms, please do not use the tram.<br>"
/obj/structure/sign/tram_plate/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "TramPlaque")
ui.autoupdate = FALSE
ui.open()
/obj/structure/sign/tram_plate/ui_static_data(mob/user)
var/datum/transport_controller/linear/tram/tram = transport_ref?.resolve()
var/list/data = list()
var/list/current_tram = list()
var/list/previous_trams = list()
current_tram += list(list(
"serialNumber" = tram.tram_registration.serial_number,
"mfgDate" = tram.tram_registration.mfg_date,
"distanceTravelled" = tram.tram_registration.distance_travelled,
"tramCollisions" = tram.tram_registration.collisions,
))
for(var/datum/tram_mfg_info/previous_tram as anything in tram.tram_history)
previous_trams += list(list(
"serialNumber" = previous_tram.serial_number,
"mfgDate" = previous_tram.mfg_date,
"distanceTravelled" = previous_tram.distance_travelled,
"tramCollisions" = previous_tram.collisions,
))
data["currentTram"] = current_tram
data["previousTrams"] = previous_trams
return data
MAPPING_DIRECTIONAL_HELPERS(/obj/structure/sign/tram_plate, 32)
+25 -23
View File
@@ -417,9 +417,11 @@
var/extra_ouch = FALSE // if emagged you're gonna have a really bad time
if(speed_limiter == 0.5) // slow trams don't cause extra damage
for(var/obj/structure/tram/spoiler/my_spoiler in transport_contents)
if(istype(victim_living.buckled, /obj/structure/fluff/tram_rail))
extra_ouch = TRUE
break
if(get_dist(my_spoiler, victim_living) != 1)
continue
if(my_spoiler.deployed)
extra_ouch = TRUE
break
@@ -427,31 +429,31 @@
if(transport_controller_datum.ignored_smashthroughs[victim_living.type])
continue
to_chat(victim_living, span_userdanger("[src] collides into you!"))
SEND_SIGNAL(victim_living, COMSIG_LIVING_HIT_BY_TRAM, src)
playsound(src, 'sound/effects/splat.ogg', 50, TRUE)
var/damage = 0
switch(extra_ouch)
if(TRUE)
playsound(src, 'sound/effects/grillehit.ogg', 50, TRUE)
var/obj/item/bodypart/head/head = victim_living.get_bodypart("head")
if(head)
log_combat(src, victim_living, "beheaded")
head.dismember()
victim_living.regenerate_icons()
add_overlay(mutable_appearance(icon, "blood_overlay"))
register_collision(points = 3)
if(FALSE)
log_combat(src, victim_living, "collided with")
if(prob(15)) //sorry buddy, luck wasn't on your side
damage = 29 * collision_lethality * damage_multiplier
else
damage = rand(7, 21) * collision_lethality * damage_multiplier
victim_living.apply_damage(2 * damage, BRUTE, BODY_ZONE_HEAD, wound_bonus = 7)
victim_living.apply_damage(3 * damage, BRUTE, BODY_ZONE_CHEST, wound_bonus = 21)
victim_living.apply_damage(0.5 * damage, BRUTE, BODY_ZONE_L_LEG, wound_bonus = 14)
victim_living.apply_damage(0.5 * damage, BRUTE, BODY_ZONE_R_LEG, wound_bonus = 14)
victim_living.apply_damage(0.5 * damage, BRUTE, BODY_ZONE_L_ARM, wound_bonus = 14)
victim_living.apply_damage(0.5 * damage, BRUTE, BODY_ZONE_R_ARM, wound_bonus = 14)
log_combat(src, victim_living, "collided with")
if(prob(15)) //sorry buddy, luck wasn't on your side
damage = 29 * collision_lethality * damage_multiplier
else
damage = rand(7, 21) * collision_lethality * damage_multiplier
victim_living.apply_damage(2 * damage, BRUTE, BODY_ZONE_HEAD, wound_bonus = 7)
victim_living.apply_damage(3 * damage, BRUTE, BODY_ZONE_CHEST, wound_bonus = 21)
victim_living.apply_damage(0.5 * damage, BRUTE, BODY_ZONE_L_LEG, wound_bonus = 14)
victim_living.apply_damage(0.5 * damage, BRUTE, BODY_ZONE_R_LEG, wound_bonus = 14)
victim_living.apply_damage(0.5 * damage, BRUTE, BODY_ZONE_L_ARM, wound_bonus = 14)
victim_living.apply_damage(0.5 * damage, BRUTE, BODY_ZONE_R_ARM, wound_bonus = 14)
if (extra_ouch)
playsound(src, 'sound/effects/grillehit.ogg', 50, TRUE)
var/obj/item/bodypart/head/head = victim_living.get_bodypart("head")
if(head)
log_combat(src, victim_living, "beheaded")
head.dismember()
victim_living.regenerate_icons()
add_overlay(mutable_appearance(icon, "blood_overlay"))
register_collision(points = 3)
if(QDELETED(victim_living)) //in case it was a mob that dels on death
continue
@@ -0,0 +1,5 @@
author: "Jacquerel"
delete-after: True
changes:
- rscadd: "Handcuffed people can now be tied to the tram rails"
- balance: "tram rails will no longer electrocute you if they're not powered"
@@ -0,0 +1,4 @@
author: "LT3"
delete-after: True
changes:
- bugfix: "Tram information plate and other signs mount correctly on tram walls"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 170 KiB