mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-17 10:08:09 +01:00
## About The Pull Request changelog should say pretty much enough, dont want to double it here. ## Why It's Good For The Game as paramedic later into the game you'll prefer jaws of life over jaws of recovery because theyre both silent AND have no area restrictions, but heres the thing: you cant wear it in suit storage, nor it can act as bonesetter additionally (why would paramed need wirecutter?) this PR is aimed to combie both of those jaws into one modified, that would be useful for paramedic. also you really should be able to wear them in mod suit storage, trust me, it sucks to carry paramedic jacket/coat in inventory everytime and waste time on swapping ## Changelog 🆑 qol: Jaws of Recovery can be worn on medical MODSuit suit storage now. add: Added modified Jaws of Recovery and recipe for them. Made from regular Jaws of Life they act like one, without area restrictions and radio announcements. /🆑
406 lines
17 KiB
Plaintext
406 lines
17 KiB
Plaintext
/obj/item/crowbar
|
|
name = "pocket crowbar"
|
|
desc = "A small crowbar. This handy tool is useful for lots of things, such as prying floor tiles or opening unpowered doors."
|
|
icon = 'icons/obj/tools.dmi'
|
|
icon_state = "crowbar"
|
|
inhand_icon_state = "crowbar"
|
|
icon_angle = -45
|
|
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
|
usesound = 'sound/items/tools/crowbar.ogg'
|
|
operating_sound = 'sound/items/tools/crowbar_prying.ogg'
|
|
obj_flags = CONDUCTS_ELECTRICITY
|
|
slot_flags = ITEM_SLOT_BELT
|
|
force = 5
|
|
throwforce = 7
|
|
demolition_mod = 1.25
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT*0.5)
|
|
drop_sound = 'sound/items/handling/tools/crowbar_drop.ogg'
|
|
pickup_sound = 'sound/items/handling/tools/crowbar_pickup.ogg'
|
|
|
|
attack_verb_continuous = list("attacks", "bashes", "batters", "bludgeons", "whacks")
|
|
attack_verb_simple = list("attack", "bash", "batter", "bludgeon", "whack")
|
|
tool_behaviour = TOOL_CROWBAR
|
|
toolspeed = 1
|
|
armor_type = /datum/armor/item_crowbar
|
|
var/force_opens = FALSE
|
|
|
|
/datum/armor/item_crowbar
|
|
fire = 50
|
|
acid = 30
|
|
|
|
/obj/item/crowbar/Initialize(mapload)
|
|
. = ..()
|
|
AddElement(/datum/element/falling_hazard, damage = force, wound_bonus = wound_bonus, hardhat_safety = TRUE, crushes = FALSE, impact_sound = hitsound)
|
|
|
|
/obj/item/crowbar/suicide_act(mob/living/user)
|
|
user.visible_message(span_suicide("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
|
|
playsound(loc, 'sound/items/weapons/genhit.ogg', 50, TRUE, -1)
|
|
return BRUTELOSS
|
|
|
|
/obj/item/crowbar/red
|
|
icon_state = "crowbar_red"
|
|
inhand_icon_state = "crowbar_red"
|
|
force = 8
|
|
|
|
/obj/item/crowbar/abductor
|
|
name = "alien crowbar"
|
|
desc = "A hard-light crowbar. It appears to pry by itself, without any effort required."
|
|
icon = 'icons/obj/antags/abductor.dmi'
|
|
usesound = 'sound/items/weapons/sonic_jackhammer.ogg'
|
|
custom_materials = list(/datum/material/iron =SHEET_MATERIAL_AMOUNT * 2.5, /datum/material/silver = SHEET_MATERIAL_AMOUNT*1.25, /datum/material/plasma =HALF_SHEET_MATERIAL_AMOUNT, /datum/material/titanium =SHEET_MATERIAL_AMOUNT, /datum/material/diamond =SHEET_MATERIAL_AMOUNT)
|
|
icon_state = "crowbar"
|
|
inside_belt_icon_state = "crowbar_alien"
|
|
toolspeed = 0.1
|
|
|
|
/obj/item/crowbar/large
|
|
name = "large crowbar"
|
|
desc = "It's a big crowbar. It doesn't fit in your pockets, because it's big."
|
|
force = 12
|
|
w_class = WEIGHT_CLASS_NORMAL
|
|
throw_speed = 3
|
|
throw_range = 3
|
|
custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT*0.7)
|
|
icon_state = "crowbar_large"
|
|
worn_icon_state = "crowbar"
|
|
toolspeed = 0.7
|
|
|
|
/obj/item/crowbar/large/emergency
|
|
name = "emergency crowbar"
|
|
desc = "It's a bulky crowbar. It almost seems deliberately designed to not be able to fit inside of a backpack."
|
|
w_class = WEIGHT_CLASS_BULKY
|
|
|
|
/obj/item/crowbar/hammer
|
|
name = "claw hammer"
|
|
desc = "It's a heavy hammer with a pry bar on the back of its head. Nails aren't common in space, but this tool can still be used as a weapon or a crowbar."
|
|
force = 11
|
|
w_class = WEIGHT_CLASS_NORMAL
|
|
icon = 'icons/obj/weapons/hammer.dmi'
|
|
icon_state = "clawhammer"
|
|
icon_angle = -45
|
|
lefthand_file = 'icons/mob/inhands/weapons/hammers_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/weapons/hammers_righthand.dmi'
|
|
inhand_icon_state = "clawhammer"
|
|
inside_belt_icon_state = "clawhammer"
|
|
throwforce = 10
|
|
throw_range = 5
|
|
throw_speed = 3
|
|
toolspeed = 2
|
|
custom_materials = list(/datum/material/wood=SMALL_MATERIAL_AMOUNT*0.5, /datum/material/iron=SMALL_MATERIAL_AMOUNT*0.7)
|
|
wound_bonus = 35
|
|
|
|
/obj/item/crowbar/hammer/Initialize(mapload)
|
|
. = ..()
|
|
AddElement(/datum/element/kneejerk)
|
|
|
|
/obj/item/crowbar/large/twenty_force //from space ruin
|
|
name = "heavy crowbar"
|
|
desc = "It's a big crowbar. It doesn't fit in your pockets, because it's big. It feels oddly heavy.."
|
|
force = 20
|
|
icon_state = "crowbar_powergame"
|
|
inhand_icon_state = "crowbar_red"
|
|
|
|
/obj/item/crowbar/large/old
|
|
name = "old crowbar"
|
|
desc = "It's an old crowbar. Much larger than the pocket sized ones, carrying a lot more heft. They don't make 'em like they used to."
|
|
throwforce = 10
|
|
throw_speed = 2
|
|
|
|
/obj/item/crowbar/large/old/Initialize(mapload)
|
|
. = ..()
|
|
if(prob(50))
|
|
icon_state = "crowbar_powergame"
|
|
|
|
/obj/item/crowbar/power
|
|
name = "jaws of life"
|
|
desc = "A set of jaws of life, compressed through the magic of science."
|
|
icon_state = "jaws"
|
|
inhand_icon_state = "jawsoflife"
|
|
worn_icon_state = "jawsoflife"
|
|
icon_angle = 180
|
|
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
|
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT*2.25, /datum/material/silver = SHEET_MATERIAL_AMOUNT*1.25, /datum/material/titanium = SHEET_MATERIAL_AMOUNT*1.75)
|
|
usesound = 'sound/items/tools/jaws_pry.ogg'
|
|
hitsound = SFX_SWING_HIT
|
|
force = 15
|
|
w_class = WEIGHT_CLASS_NORMAL
|
|
toolspeed = 0.7
|
|
force_opens = TRUE
|
|
/// Used on Initialize, how much time to cut cable restraints and zipties.
|
|
var/snap_time_weak_handcuffs = 0 SECONDS
|
|
/// Used on Initialize, how much time to cut real handcuffs. Null means it can't.
|
|
var/snap_time_strong_handcuffs = 0 SECONDS
|
|
/// The text used for our jaws tool description while active
|
|
var/active_text = "cutting"
|
|
/// The text used for our jaws tool description while inactive
|
|
var/inactive_text = "prying"
|
|
/// The default tool behavior. This should match tool_behavior
|
|
var/first_tool_behavior = TOOL_CROWBAR
|
|
/// The active tool behavior. This should not match tool_behavior on init.
|
|
var/second_tool_behavior = TOOL_WIRECUTTER
|
|
/// Determines if we want to limit our jaws of life from opening certain doors or not.
|
|
var/limit_jaws_access = FALSE
|
|
/// The access on doors that block our jaws of life from opening if limit_jaws_access is TRUE. Does nothing if FALSE.
|
|
var/list/blacklisted_access = list()
|
|
/// Whether or not our jaws throw out an alert when we pry open a door. Default alert sends out a message to security comms.
|
|
var/radio_alert = FALSE
|
|
/// If radio_alert is TRUE, access in this list that is found on our pried open door is ignored.
|
|
var/list/ignored_access = list(
|
|
ACCESS_MAINT_TUNNELS,
|
|
ACCESS_AUX_BASE,
|
|
ACCESS_EXTERNAL_AIRLOCKS,
|
|
)
|
|
COOLDOWN_DECLARE(alert_cooldown)
|
|
/// How long between announcements from our jaws of life. Keeps the jaws from getting too radio spammy.
|
|
var/alert_cooldown_time = 1 MINUTES
|
|
|
|
/obj/item/crowbar/power/get_all_tool_behaviours()
|
|
return list(first_tool_behavior, second_tool_behavior)
|
|
|
|
/obj/item/crowbar/power/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent( \
|
|
/datum/component/transforming, \
|
|
force_on = force, \
|
|
throwforce_on = throwforce, \
|
|
hitsound_on = hitsound, \
|
|
w_class_on = w_class, \
|
|
clumsy_check = FALSE, \
|
|
inhand_icon_change = FALSE, \
|
|
)
|
|
RegisterSignal(src, COMSIG_TRANSFORMING_ON_TRANSFORM, PROC_REF(on_transform))
|
|
RegisterSignal(src, COMSIG_TOOL_FORCE_OPEN_AIRLOCK, PROC_REF(on_force_open))
|
|
|
|
/obj/item/crowbar/power/examine()
|
|
. = ..()
|
|
. += " It's fitted with a [tool_behaviour == first_tool_behavior ? inactive_text : active_text] head."
|
|
|
|
/*
|
|
* Signal proc for [COMSIG_TRANSFORMING_ON_TRANSFORM].
|
|
*
|
|
* Toggles between crowbar and wirecutters and gives feedback to the user.
|
|
*/
|
|
/obj/item/crowbar/power/proc/on_transform(obj/item/source, mob/user, active)
|
|
SIGNAL_HANDLER
|
|
|
|
tool_behaviour = (active ? second_tool_behavior : first_tool_behavior)
|
|
if(user)
|
|
balloon_alert(user, "attached [tool_behaviour == first_tool_behavior ? inactive_text : active_text]")
|
|
playsound(src, 'sound/items/tools/change_jaws.ogg', 50, TRUE)
|
|
if(tool_behaviour != TOOL_WIRECUTTER)
|
|
RemoveElement(/datum/element/cuffsnapping, snap_time_weak_handcuffs, snap_time_strong_handcuffs)
|
|
else
|
|
AddElement(/datum/element/cuffsnapping, snap_time_weak_handcuffs, snap_time_strong_handcuffs)
|
|
return COMPONENT_NO_DEFAULT_MESSAGE
|
|
|
|
/*
|
|
* Signal proc for [COMSIG_TOOL_FORCE_OPEN_AIRLOCK].
|
|
*
|
|
* Determines if our jaws of life is restricted from opening some doors, and whether or not we need to alert over the radio whenever they are used to
|
|
* pry open a door. Useful if you want to restrict jaws of life in some fashion.
|
|
*/
|
|
|
|
/obj/item/crowbar/power/proc/on_force_open(obj/item/source, mob/user, obj/machinery/door/airlock/target)
|
|
SIGNAL_HANDLER
|
|
|
|
var/list/collective_access = list()
|
|
collective_access += target.req_access
|
|
collective_access += target.req_one_access
|
|
|
|
if(limit_jaws_access)
|
|
for(var/possible_blacklisted_access in collective_access)
|
|
if(possible_blacklisted_access in blacklisted_access)
|
|
playsound(src.loc, 'sound/machines/buzz/buzz-sigh.ogg', 50, FALSE)
|
|
user.balloon_alert(user, "cannot pry open!")
|
|
return COMPONENT_TOOL_DO_NOT_ALLOW_FORCE_OPEN
|
|
|
|
if(radio_alert && COOLDOWN_FINISHED(src, alert_cooldown))
|
|
|
|
if(!collective_access) //Return if the door has literally no access at all
|
|
return COMPONENT_TOOL_ALLOW_FORCE_OPEN
|
|
|
|
for(var/possible_public_access in collective_access) //Return if the door has otherwise unimportant access
|
|
if((possible_public_access in ignored_access))
|
|
return COMPONENT_TOOL_ALLOW_FORCE_OPEN
|
|
|
|
sound_the_alarms(user, target)
|
|
COOLDOWN_START(src, alert_cooldown, alert_cooldown_time)
|
|
return COMPONENT_TOOL_ALLOW_FORCE_OPEN
|
|
|
|
///Our alert for our jaws of life.
|
|
/obj/item/crowbar/power/proc/sound_the_alarms(mob/user, obj/machinery/door/airlock/target)
|
|
aas_config_announce(/datum/aas_config_entry/jaws_entry_alert, list(
|
|
"PERSON" = user.name,
|
|
"LOCATION" = get_area_name(target),
|
|
"TOOL" = name), src, list(RADIO_CHANNEL_SECURITY), RADIO_CHANNEL_SECURITY)
|
|
|
|
/datum/aas_config_entry/jaws_entry_alert
|
|
// This tool screams into the radio whenever the user successfully pries open an airlock.
|
|
name = "Door Forced Entry Alert"
|
|
announcement_lines_map = list(
|
|
RADIO_CHANNEL_SECURITY = "SECURITY ALERT: %PERSON has forced open a door at %LOCATION using %TOOL. Confirm that this was done during an emergency by authorized staff.",
|
|
)
|
|
vars_and_tooltips_map = list(
|
|
"PERSON" = "will be replaced with the name of the user",
|
|
"LOCATION" = "with the area of the door",
|
|
"TOOL" = "replaced with the tool used",
|
|
)
|
|
|
|
/obj/item/crowbar/power/suicide_act(mob/living/user)
|
|
if(tool_behaviour == TOOL_CROWBAR)
|
|
user.visible_message(span_suicide("[user] is putting [user.p_their()] head in [src], it looks like [user.p_theyre()] trying to commit suicide!"))
|
|
playsound(loc, 'sound/items/tools/jaws_pry.ogg', 50, TRUE, -1)
|
|
else
|
|
user.visible_message(span_suicide("[user] is wrapping \the [src] around [user.p_their()] neck. It looks like [user.p_theyre()] trying to rip [user.p_their()] head off!"))
|
|
playsound(loc, 'sound/items/tools/jaws_cut.ogg', 50, TRUE, -1)
|
|
if(iscarbon(user))
|
|
var/mob/living/carbon/suicide_victim = user
|
|
var/obj/item/bodypart/target_bodypart = suicide_victim.get_bodypart(BODY_ZONE_HEAD)
|
|
if(target_bodypart)
|
|
target_bodypart.drop_limb()
|
|
playsound(loc, SFX_DESECRATION, 50, TRUE, -1)
|
|
return BRUTELOSS
|
|
|
|
/obj/item/crowbar/power/syndicate
|
|
name = "jaws of death"
|
|
desc = "An improved, faster, and smaller copy of Nanotrasen's standard jaws of life. Can be used to force open airlocks in its crowbar configuration."
|
|
icon_state = "jaws_syndie"
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
toolspeed = 0.5
|
|
|
|
/obj/item/crowbar/power/paramedic
|
|
name = "jaws of recovery"
|
|
desc = "A specialized version of the jaws of life, primarily to be used by paramedics to recover the injured and the recently deceased. Rather than a cutting arm, this tool has a bonesetting apparatus. \
|
|
Cannot access certain high security areas due to safety concerns."
|
|
icon_state = "jaws_paramedic"
|
|
inhand_icon_state = "jawsparamedic"
|
|
worn_icon_state = "jawsparamedic"
|
|
w_class = WEIGHT_CLASS_BULKY
|
|
toolspeed = 1
|
|
slot_flags = null
|
|
active_text = "bonesetting"
|
|
second_tool_behavior = TOOL_BONESET
|
|
limit_jaws_access = TRUE
|
|
blacklisted_access = list(
|
|
ACCESS_COMMAND,
|
|
ACCESS_AI_UPLOAD,
|
|
ACCESS_CAPTAIN,
|
|
ACCESS_HOP,
|
|
ACCESS_SECURITY,
|
|
ACCESS_BRIG,
|
|
ACCESS_ARMORY,
|
|
ACCESS_HOS,
|
|
ACCESS_DETECTIVE,
|
|
ACCESS_CE,
|
|
ACCESS_CMO,
|
|
ACCESS_QM,
|
|
ACCESS_VAULT,
|
|
ACCESS_RD,
|
|
ACCESS_SYNDICATE,
|
|
)
|
|
radio_alert = TRUE
|
|
|
|
/obj/item/crowbar/power/paramedic/sound_the_alarms(mob/user, obj/machinery/door/airlock/target)
|
|
aas_config_announce(/datum/aas_config_entry/jaws_entry_alert_paramedic, list(
|
|
"PERSON" = user.name,
|
|
"LOCATION" = get_area_name(target),
|
|
"TOOL" = name), src, list(RADIO_CHANNEL_SECURITY), RADIO_CHANNEL_SECURITY)
|
|
|
|
aas_config_announce(/datum/aas_config_entry/jaws_entry_alert_paramedic, list(
|
|
"PERSON" = user.name,
|
|
"LOCATION" = get_area_name(target),
|
|
"TOOL" = name), src, list(RADIO_CHANNEL_MEDICAL), RADIO_CHANNEL_MEDICAL)
|
|
|
|
/datum/aas_config_entry/jaws_entry_alert_paramedic
|
|
// This tool screams into the radio whenever the user successfully pries open an airlock.
|
|
name = "Door Forced Entry Medical Alert"
|
|
announcement_lines_map = list(
|
|
RADIO_CHANNEL_SECURITY = "SECURITY ALERT: %PERSON has forced open a door at %LOCATION using %TOOL. Confirm that this was done during an emergency by authorized staff.",
|
|
RADIO_CHANNEL_MEDICAL = "MEDICAL ALERT: %PERSON has forced open a door at %LOCATION using %TOOL. Confirm that this was done during an emergency by authorized staff.",
|
|
)
|
|
vars_and_tooltips_map = list(
|
|
"PERSON" = "will be replaced with the name of the user",
|
|
"LOCATION" = "with the area of the door",
|
|
"TOOL" = "replaced with the tool used",
|
|
)
|
|
|
|
/obj/item/crowbar/power/paramedic/silent
|
|
name = "modified jaws of recovery"
|
|
desc = "Modified version for jaws of life, made to act like jaws of recovery. This one doesn't announce doors you're prying open and lets you pry any door, acting like regular jaws of life"
|
|
limit_jaws_access = FALSE
|
|
radio_alert = FALSE
|
|
|
|
/obj/item/crowbar/cyborg
|
|
name = "hydraulic crowbar"
|
|
desc = "A hydraulic prying tool, simple but powerful."
|
|
icon = 'icons/obj/items_cyborg.dmi'
|
|
icon_state = "toolkit_engiborg_crowbar"
|
|
worn_icon_state = "toolkit_engiborg_crowbar" //error sprite - this shouldn't have been dropped
|
|
icon_angle = 0
|
|
usesound = 'sound/items/tools/jaws_pry.ogg'
|
|
force = 10
|
|
toolspeed = 0.5
|
|
|
|
/obj/item/crowbar/mechremoval
|
|
name = "mech removal tool"
|
|
desc = "A... really big crowbar. You're pretty sure it could pry open a mech, but it seems unwieldy otherwise."
|
|
icon_state = "mechremoval0"
|
|
base_icon_state = "mechremoval"
|
|
inhand_icon_state = null
|
|
icon = 'icons/obj/mechremoval.dmi'
|
|
icon_angle = -65
|
|
w_class = WEIGHT_CLASS_HUGE
|
|
slot_flags = NONE
|
|
toolspeed = 1.25
|
|
armor_type = /datum/armor/crowbar_mechremoval
|
|
resistance_flags = FIRE_PROOF
|
|
exposed_wound_bonus = 15
|
|
wound_bonus = 10
|
|
|
|
/datum/armor/crowbar_mechremoval
|
|
bomb = 100
|
|
fire = 100
|
|
|
|
/obj/item/crowbar/mechremoval/Initialize(mapload)
|
|
. = ..()
|
|
transform = transform.Translate(0, -8)
|
|
AddComponent(/datum/component/two_handed, force_unwielded = 5, force_wielded = 19, icon_wielded = "[base_icon_state]1")
|
|
|
|
/obj/item/crowbar/mechremoval/update_icon_state()
|
|
icon_state = "[base_icon_state]0"
|
|
return ..()
|
|
|
|
/obj/item/crowbar/mechremoval/proc/empty_mech(obj/vehicle/sealed/mecha/mech, mob/user)
|
|
if(!HAS_TRAIT(src, TRAIT_WIELDED))
|
|
mech.balloon_alert(user, "not wielded!")
|
|
return
|
|
var/obj/item/mecha_parts/mecha_equipment/sleeper/mech_sleeper = locate() in mech
|
|
if((!LAZYLEN(mech.occupants) || (LAZYLEN(mech.occupants) == 1 && mech.mecha_flags & SILICON_PILOT)) && (!mech_sleeper || !mech_sleeper.patient)) //if no occupants, or only an ai
|
|
mech.balloon_alert(user, "it's empty!")
|
|
return
|
|
var/list/log_list_before = LAZYCOPY(mech.occupants)
|
|
if(mech_sleeper?.patient)
|
|
log_list_before += mech_sleeper.patient
|
|
user.log_message("tried to pry open [mech], located at [loc_name(mech)], which is occupied by [log_list_before.Join(", ")].", LOG_ATTACK)
|
|
var/mech_dir = mech.dir
|
|
mech.balloon_alert(user, "prying open...")
|
|
playsound(mech, 'sound/machines/airlock/airlock_alien_prying.ogg', 100, TRUE)
|
|
if(!use_tool(mech, user, (mech.mecha_flags & IS_ENCLOSED) ? 5 SECONDS : 3 SECONDS, volume = 0, extra_checks = CALLBACK(src, PROC_REF(extra_checks), mech, mech_dir, mech_sleeper)))
|
|
mech.balloon_alert(user, "interrupted!")
|
|
return
|
|
var/list/log_list_after = LAZYCOPY(mech.occupants)
|
|
if(mech_sleeper?.patient)
|
|
log_list_after += mech_sleeper.patient
|
|
mech_sleeper.go_out()
|
|
user.log_message("pried open [mech], located at [loc_name(mech)], which was occupied by [log_list_after.Join(", ")].", LOG_ATTACK)
|
|
for(var/mob/living/occupant as anything in SANITIZE_LIST(mech.occupants))
|
|
if(isAI(occupant) || isbrain(occupant))
|
|
continue
|
|
mech.mob_exit(occupant)
|
|
playsound(mech, 'sound/machines/airlock/airlockforced.ogg', 75, TRUE)
|
|
|
|
/obj/item/crowbar/mechremoval/proc/extra_checks(obj/vehicle/sealed/mecha/mech, mech_dir, obj/item/mecha_parts/mecha_equipment/sleeper/mech_sleeper)
|
|
return HAS_TRAIT(src, TRAIT_WIELDED) && (LAZYLEN(mech.occupants) || mech_sleeper?.patient) && (mech.dir == mech_dir)
|