mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-29 16:18:01 +01:00
Spraying items with lube can make them slip out of people's hands (#95224)
## About The Pull Request If you coat an item with lube, it becomes slippery. Not "clown pda" slippery but "harder to handle" slippery. Trying to pick up or use a slippery item has a chance of it falling out of your hands (Though there is another chance that you catch it, if you have an empty hand) "Use" includes arming grenades or firing guns. So if you try to arm a lubed grenade it might slip right to your feet! ## Why It's Good For The Game The clown can coat security's batons in lube. That's basically all I need to say ## Changelog 🆑 Melbert add: Spraying items with lube makes them slippery, causing them to fall out of people's hands who try to pick them up or use them. /🆑
This commit is contained in:
@@ -7,6 +7,9 @@
|
||||
/// From /datum/surgery_operation/failure(): (datum/surgery_operation/operation, atom/movable/operating_on, tool)
|
||||
#define COMSIG_ATOM_SURGERY_FAILED "atom_surgery_step_failed"
|
||||
|
||||
/// From /datum/surgery_operation/try_perform(), sent to the tool: (datum/surgery_operation/operation, atom/movable/operating_on, mob/living/surgeon)
|
||||
#define COMSIG_ITEM_USED_IN_SURGERY "item_used_in_surgery"
|
||||
|
||||
/// From /obj/item/shockpaddles/do_help, after the defib do_after is complete, but before any effects are applied: (mob/living/defibber, obj/item/shockpaddles/source)
|
||||
#define COMSIG_DEFIBRILLATOR_PRE_HELP_ZAP "carbon_being_defibbed"
|
||||
/// Return to stop default defib handling
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/// Item is slippery - picking it up or using it may cause it to immediately fall out of the user's hands
|
||||
/datum/component/slippery_item
|
||||
/// Chance the item will fall on pick up or use
|
||||
var/fall_chance = 50
|
||||
/// Chance the mob will catch the item if it falls (if they have an empty hand)
|
||||
var/fall_catch_chance = 0
|
||||
/// Message appended to examine when examining the item
|
||||
var/examine_msg
|
||||
/// Optional wash flags that removes the effect if washed
|
||||
var/wash_flags = NONE
|
||||
/// World.time of the last fall to avoid same tick falls
|
||||
VAR_PRIVATE/last_fall
|
||||
|
||||
/datum/component/slippery_item/Initialize(fall_chance = 50, fall_catch_chance = 0, examine_msg, duration = INFINITY, wash_flags = NONE)
|
||||
if(!isitem(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.fall_chance = fall_chance
|
||||
src.fall_catch_chance = fall_catch_chance
|
||||
src.examine_msg = examine_msg || "It looks very slippery, and may fall out of your hands when you try to use it."
|
||||
src.wash_flags = wash_flags
|
||||
if(duration != INFINITY)
|
||||
QDEL_IN(src, duration)
|
||||
|
||||
/datum/component/slippery_item/RegisterWithParent()
|
||||
RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
|
||||
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(on_cleaned))
|
||||
// bunch of generic "item used" triggers, feel free to expand
|
||||
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equip))
|
||||
RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK, PROC_REF(on_preattack))
|
||||
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, PROC_REF(on_afterattack))
|
||||
RegisterSignal(parent, COMSIG_GUN_TRY_FIRE, PROC_REF(on_tryfire))
|
||||
RegisterSignal(parent, COMSIG_GRENADE_ARMED, PROC_REF(on_grenade_arm))
|
||||
RegisterSignal(parent, COMSIG_ITEM_USED_IN_SURGERY, PROC_REF(on_surgery_started))
|
||||
|
||||
/datum/component/slippery_item/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(
|
||||
COMSIG_ATOM_EXAMINE,
|
||||
COMSIG_COMPONENT_CLEAN_ACT,
|
||||
COMSIG_ITEM_EQUIPPED,
|
||||
COMSIG_ITEM_PRE_ATTACK,
|
||||
COMSIG_ITEM_AFTERATTACK,
|
||||
COMSIG_GUN_TRY_FIRE,
|
||||
COMSIG_GRENADE_ARMED,
|
||||
COMSIG_ITEM_USED_IN_SURGERY,
|
||||
))
|
||||
|
||||
/datum/component/slippery_item/proc/on_examine(obj/item/source, mob/living/user, list/examine_list)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
examine_list += examine_msg
|
||||
|
||||
/datum/component/slippery_item/proc/on_cleaned(obj/item/source, clean_flags)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(wash_flags && (wash_flags & clean_flags))
|
||||
qdel(src)
|
||||
return COMPONENT_CLEANED
|
||||
|
||||
/datum/component/slippery_item/proc/on_equip(obj/item/source, mob/living/user, slot)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(slot & ITEM_SLOT_HANDS)
|
||||
try_fall(source, user)
|
||||
|
||||
/datum/component/slippery_item/proc/on_preattack(obj/item/source, atom/target, mob/living/user, ...)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(try_fall(source, user))
|
||||
return COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
|
||||
/datum/component/slippery_item/proc/on_afterattack(obj/item/source, atom/target, mob/living/user, ...)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
try_fall(source, user)
|
||||
|
||||
/datum/component/slippery_item/proc/on_tryfire(obj/item/source, mob/living/user, ...)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(try_fall(source, user))
|
||||
return COMPONENT_CANCEL_GUN_FIRE
|
||||
|
||||
/datum/component/slippery_item/proc/on_grenade_arm(obj/item/source, ...)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(isliving(source.loc))
|
||||
try_fall(source, source.loc)
|
||||
|
||||
/datum/component/slippery_item/proc/on_surgery_started(obj/item/source, datum/surgery_operation/surgery, atom/movable/operating_on, mob/living/surgeon)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(try_fall(source, surgeon))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
/// Check for falling and handle it if it happens.
|
||||
/// Returns TRUE if the item fell, FALSE otherwise
|
||||
/datum/component/slippery_item/proc/try_fall(obj/item/source, mob/living/user)
|
||||
set waitfor = FALSE
|
||||
// prevents fall -> catch -> fall -> catch. even though that'd be funny, you wouldn't even be able to see it happening.
|
||||
if(last_fall == world.time)
|
||||
return FALSE
|
||||
if(!prob(fall_chance))
|
||||
return FALSE
|
||||
if(source.loc != user || !user.dropItemToGround(source))
|
||||
return FALSE
|
||||
if(QDELETED(source))
|
||||
return FALSE // dropdel
|
||||
|
||||
playsound(source, 'sound/misc/slip.ogg', 20, TRUE, SILENCED_SOUND_EXTRARANGE)
|
||||
source.SpinAnimation(4, 1)
|
||||
|
||||
last_fall = world.time
|
||||
if(prob(fall_catch_chance) && !HAS_TRAIT(user, TRAIT_CLUMSY))
|
||||
for(var/empty_hand in user.get_empty_held_indexes())
|
||||
if(empty_hand == user.active_hand_index)
|
||||
continue
|
||||
if(user.putItemFromInventoryInHandIfPossible(source, empty_hand))
|
||||
to_chat(user, span_notice("[source] slips out of your hands - but you manage to catch it, just in time."))
|
||||
return TRUE
|
||||
|
||||
to_chat(user, span_warning("[source] slips out of your hands!"))
|
||||
return TRUE
|
||||
@@ -524,10 +524,20 @@
|
||||
|
||||
/datum/reagent/lube/expose_turf(turf/open/exposed_turf, reac_volume)
|
||||
. = ..()
|
||||
if(!istype(exposed_turf))
|
||||
return
|
||||
if(reac_volume >= 1)
|
||||
exposed_turf.MakeSlippery(lube_kind, 15 SECONDS, min(reac_volume * 2 SECONDS, 120))
|
||||
if(isopenturf(exposed_turf) && reac_volume >= 1)
|
||||
exposed_turf.MakeSlippery(lube_kind, 15 SECONDS, min(reac_volume * 2 SECONDS, 12 SECONDS))
|
||||
|
||||
/datum/reagent/lube/expose_obj(obj/exposed_obj, reac_volume, methods, show_message)
|
||||
. = ..()
|
||||
if(isitem(exposed_obj) && reac_volume >= 1)
|
||||
exposed_obj.AddComponent( \
|
||||
/datum/component/slippery_item, \
|
||||
fall_chance = (lube_kind == TURF_WET_SUPERLUBE ? 80 : 50), \
|
||||
fall_catch_chance = (lube_kind == TURF_WET_SUPERLUBE ? 10 : 30), \
|
||||
examine_msg = span_info("It's coated in a slippery substance!"), \
|
||||
wash_flags = CLEAN_TYPE_HARD_DECAL, \
|
||||
duration = min(reac_volume * 3 SECONDS, 30 SECONDS), \
|
||||
)
|
||||
|
||||
/datum/reagent/lube/used_on_fish(obj/item/fish/fish)
|
||||
ADD_TRAIT(fish, TRAIT_FISH_FED_LUBE, type) //required for the lubefish mutation
|
||||
|
||||
@@ -837,6 +837,12 @@ GLOBAL_DATUM_INIT(operations, /datum/operation_holder, new)
|
||||
if(!check_availability(patient, operating_on, surgeon, tool, operation_args[OPERATION_TARGET_ZONE]))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
if(isitem(tool))
|
||||
var/obj/item/realtool = tool
|
||||
var/tool_return = SEND_SIGNAL(realtool, COMSIG_ITEM_USED_IN_SURGERY, src, operating_on, surgeon)
|
||||
if(tool_return & ITEM_INTERACT_ANY_BLOCKER)
|
||||
return tool_return
|
||||
|
||||
if(!start_operation(operating_on, surgeon, tool, operation_args))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
|
||||
@@ -1308,6 +1308,7 @@
|
||||
#include "code\datums\components\slide_under_doors.dm"
|
||||
#include "code\datums\components\slime_friends.dm"
|
||||
#include "code\datums\components\slippery.dm"
|
||||
#include "code\datums\components\slippery_item.dm"
|
||||
#include "code\datums\components\smooth_tunes.dm"
|
||||
#include "code\datums\components\soapbox.dm"
|
||||
#include "code\datums\components\soul_stealer.dm"
|
||||
|
||||
Reference in New Issue
Block a user