mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-24 00:21:52 +00:00
## About The Pull Request Closes #87221 by changing overlay layers when a mob is buckled to the chair. ## Changelog 🆑 fix: Fixed electrified chair overlay layering /🆑
223 lines
9.8 KiB
Plaintext
223 lines
9.8 KiB
Plaintext
///divide the power in the cable net under parent by this to determine the shock damage
|
|
#define ELECTRIC_BUCKLE_SHOCK_STRENGTH_DIVISOR 5000
|
|
///it will not shock the mob buckled to parent if its required to use a cable to shock and the cable has less than this power availaible
|
|
#define ELECTRIC_BUCKLE_MINUMUM_POWERNET_STRENGTH 10
|
|
|
|
|
|
/**
|
|
* # electrified_buckle component:
|
|
* attach it to any atom/movable that can be buckled to in order to have it shock mobs buckled to it. by default it shocks mobs buckled to parent every shock_loop_time.
|
|
* the parent is supposed to define its behavior with arguments in AddComponent
|
|
*/
|
|
/datum/component/electrified_buckle
|
|
///if usage_flags has SHOCK_REQUIREMENT_ITEM, this is the item required to be inside parent in order for it to shock buckled mobs
|
|
var/obj/item/required_object
|
|
///this is casted to the overlay we put on parent_chair
|
|
var/list/requested_overlays
|
|
///it will only shock once every shock_loop_time
|
|
COOLDOWN_DECLARE(electric_buckle_cooldown)
|
|
///these flags tells this instance what is required in order to allow shocking
|
|
var/usage_flags
|
|
///if true, this will shock the buckled mob every shock_loop_time in process()
|
|
var/shock_on_loop = 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
|
|
|
|
/**
|
|
* Initialize args:
|
|
*
|
|
* * input_requirements - bitflag that defines how the component is supposed to act, see __DEFINES/electrified_buckle.dm for the options. sets usage_flags
|
|
* * input_item - if set to an item and input_requirements has SHOCK_REQUIREMENT_ITEM, moves that item inside parent and the component will delete itself if input_item no longer exists/moves out of parent. sets required_object
|
|
* * 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
|
|
* * 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
|
|
*/
|
|
/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)
|
|
var/atom/movable/parent_as_movable = parent
|
|
if(!istype(parent_as_movable))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
usage_flags = input_requirements
|
|
|
|
if(!parent_as_movable.can_buckle && !override_buckle)
|
|
return COMPONENT_INCOMPATIBLE
|
|
else if (override_buckle)
|
|
parent_as_movable.can_buckle = TRUE
|
|
|
|
if((usage_flags & SHOCK_REQUIREMENT_ITEM) && QDELETED(input_item))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
if(HAS_TRAIT(parent_as_movable, TRAIT_ELECTRIFIED_BUCKLE))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
if(usage_flags & SHOCK_REQUIREMENT_ITEM)
|
|
required_object = input_item
|
|
required_object.Move(parent_as_movable)
|
|
RegisterSignal(required_object, COMSIG_QDELETING, PROC_REF(delete_self))
|
|
RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_SCREWDRIVER), PROC_REF(move_required_object_from_contents))
|
|
|
|
if(usage_flags & SHOCK_REQUIREMENT_ON_SIGNAL_RECEIVED)
|
|
shock_on_loop = FALSE
|
|
RegisterSignal(required_object, COMSIG_ASSEMBLY_PULSED, PROC_REF(shock_on_demand))
|
|
else if(usage_flags & SHOCK_REQUIREMENT_SIGNAL_RECEIVED_TOGGLE)
|
|
RegisterSignal(required_object, COMSIG_ASSEMBLY_PULSED, PROC_REF(toggle_shock_loop))
|
|
|
|
if((usage_flags & SHOCK_REQUIREMENT_PARENT_MOB_ISALIVE) && ismob(parent))
|
|
RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(delete_self))
|
|
|
|
RegisterSignal(parent, COMSIG_MOVABLE_BUCKLE, PROC_REF(on_buckle))
|
|
RegisterSignal(parent, COMSIG_MOVABLE_UNBUCKLE, PROC_REF(on_unbuckle))
|
|
RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays))
|
|
|
|
ADD_TRAIT(parent_as_movable, TRAIT_ELECTRIFIED_BUCKLE, INNATE_TRAIT)
|
|
|
|
//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))
|
|
requested_signal_parent_emits = signal_to_register_from_parent
|
|
|
|
if(overlays_to_add)
|
|
requested_overlays = overlays_to_add
|
|
parent_as_movable.add_overlay(requested_overlays)
|
|
|
|
parent_as_movable.name = "electrified [initial(parent_as_movable.name)]"
|
|
|
|
shock_damage = damage_on_shock
|
|
|
|
if(loop_length)
|
|
shock_loop_time = loop_length
|
|
|
|
if(parent_as_movable.has_buckled_mobs())
|
|
for(var/mob/living/possible_guinea_pig as anything in parent_as_movable.buckled_mobs)
|
|
if(on_buckle(src, possible_guinea_pig))
|
|
break
|
|
|
|
/datum/component/electrified_buckle/UnregisterFromParent()
|
|
var/atom/movable/parent_as_movable = parent
|
|
|
|
parent_as_movable.cut_overlay(requested_overlays)
|
|
parent_as_movable.name = initial(parent_as_movable.name)
|
|
parent_as_movable.can_buckle = initial(parent_as_movable.can_buckle)
|
|
|
|
if(parent)
|
|
REMOVE_TRAIT(parent_as_movable, TRAIT_ELECTRIFIED_BUCKLE, INNATE_TRAIT)
|
|
UnregisterSignal(parent, list(COMSIG_MOVABLE_BUCKLE, COMSIG_MOVABLE_UNBUCKLE, COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_ATOM_TOOL_ACT(TOOL_SCREWDRIVER)))
|
|
if(requested_signal_parent_emits)
|
|
UnregisterSignal(parent, requested_signal_parent_emits)
|
|
|
|
if(required_object)
|
|
UnregisterSignal(required_object, list(COMSIG_QDELETING, COMSIG_ASSEMBLY_PULSED))
|
|
if(parent_as_movable && (required_object in parent_as_movable.contents))
|
|
required_object.Move(parent_as_movable.loc)
|
|
|
|
required_object = null
|
|
STOP_PROCESSING(SSprocessing, src)
|
|
|
|
/datum/component/electrified_buckle/proc/delete_self()
|
|
SIGNAL_HANDLER
|
|
qdel(src)
|
|
|
|
/datum/component/electrified_buckle/proc/move_required_object_from_contents(datum/source, mob/living/user, obj/item/tool, tool_type)
|
|
SIGNAL_HANDLER
|
|
var/atom/movable/parent_as_movable = parent
|
|
if(!QDELETED(parent_as_movable))
|
|
tool.play_tool_sound(parent_as_movable)
|
|
required_object.Move(parent_as_movable.loc)
|
|
qdel(src)
|
|
|
|
/datum/component/electrified_buckle/proc/on_buckle(atom/source, mob/living/mob_to_buckle, _force)
|
|
SIGNAL_HANDLER
|
|
if(!istype(mob_to_buckle))
|
|
return FALSE
|
|
|
|
if (requested_overlays)
|
|
source.update_appearance()
|
|
COOLDOWN_START(src, electric_buckle_cooldown, shock_loop_time)
|
|
if(!(usage_flags & SHOCK_REQUIREMENT_ON_SIGNAL_RECEIVED) && shock_on_loop)
|
|
START_PROCESSING(SSprocessing, src)
|
|
return TRUE
|
|
|
|
/datum/component/electrified_buckle/proc/on_unbuckle(atom/source, mob/living/unbuckled_mob, _force)
|
|
SIGNAL_HANDLER
|
|
if(!istype(unbuckled_mob))
|
|
return FALSE
|
|
|
|
if (requested_overlays)
|
|
source.update_appearance()
|
|
|
|
/datum/component/electrified_buckle/proc/on_update_overlays(atom/movable/source, list/overlays)
|
|
SIGNAL_HANDLER
|
|
var/overlay_layer = length(source.buckled_mobs) ? ABOVE_MOB_LAYER : OBJ_LAYER
|
|
for (var/image/overlay_image in requested_overlays)
|
|
overlay_image.layer = overlay_layer
|
|
overlays += overlay_image
|
|
|
|
///where the guinea pig is actually shocked if possible
|
|
/datum/component/electrified_buckle/process(seconds_per_tick)
|
|
var/atom/movable/parent_as_movable = parent
|
|
if(QDELETED(parent_as_movable) || !parent_as_movable.has_buckled_mobs())
|
|
return PROCESS_KILL
|
|
|
|
if(!shock_on_loop)
|
|
return PROCESS_KILL
|
|
|
|
if(!COOLDOWN_FINISHED(src, electric_buckle_cooldown))
|
|
return
|
|
|
|
COOLDOWN_START(src, electric_buckle_cooldown, shock_loop_time)
|
|
|
|
var/turf/our_turf = get_turf(parent_as_movable)
|
|
var/obj/structure/cable/live_cable = our_turf.get_cable_node()
|
|
|
|
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()
|
|
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()
|
|
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)
|
|
var/shock_damage = round(live_cable.powernet.avail / ELECTRIC_BUCKLE_SHOCK_STRENGTH_DIVISOR)
|
|
guinea_pig.electrocute_act(shock_damage, parent_as_movable)
|
|
break
|
|
|
|
/datum/component/electrified_buckle/proc/toggle_shock_loop()
|
|
SIGNAL_HANDLER
|
|
var/atom/movable/parent_as_movable = parent
|
|
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."))
|
|
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!"))
|
|
|
|
#undef ELECTRIC_BUCKLE_SHOCK_STRENGTH_DIVISOR
|
|
#undef ELECTRIC_BUCKLE_MINUMUM_POWERNET_STRENGTH
|