mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-15 20:22:07 +00:00
* Micro-optimize qdel by only permitting one parameter (#80628) Productionizes #80615. The core optimization is this: ```patch - var/hint = to_delete.Destroy(arglist(args.Copy(2))) // Let our friend know they're about to get fucked up. + var/hint = to_delete.Destroy(force) // Let our friend know they're about to get fucked up. ``` We avoid a heap allocation in the form of copying the args over to a new list. A/B testing shows this results in 33% better overtime, and in a real round shaving off a full second of self time and 0.4 seconds of overtime--both of these would be doubled in the event this is merged as the new proc was only being run 50% of the time. * Micro-optimize qdel by only permitting one parameter --------- Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
144 lines
5.6 KiB
Plaintext
144 lines
5.6 KiB
Plaintext
/**
|
|
* # Nuclear Bomb Operator
|
|
*
|
|
* Component applied to handless non-carbon mobs to allow them to perform the function of a nuclear operative.
|
|
* Effectively this means they need to be able to:
|
|
* * Strip people
|
|
* * Pick up the nuke disc, without having hands
|
|
* * Place the nuke disc into the nuke
|
|
* * Activate the nuke
|
|
*
|
|
* Human mobs do not need this component because they can already do all of those things.
|
|
*/
|
|
/datum/component/nuclear_bomb_operator
|
|
/// A weak reference to a held nuclear disk, in place of holding it in our inventory, because we don't have one
|
|
var/datum/weakref/disky
|
|
/// Something to call when we collect the disk
|
|
var/datum/callback/on_disk_collected
|
|
/// Should return some overlays to display on the mob to show they're carrying a disk
|
|
var/datum/callback/add_disk_overlays
|
|
|
|
/datum/component/nuclear_bomb_operator/Initialize(datum/callback/on_disk_collected, datum/callback/add_disk_overlays)
|
|
if (!ismob(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
if (iscarbon(parent)) // Redundant
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
src.on_disk_collected = on_disk_collected
|
|
src.add_disk_overlays = add_disk_overlays
|
|
|
|
/datum/component/nuclear_bomb_operator/RegisterWithParent()
|
|
. = ..()
|
|
RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
|
|
RegisterSignals(parent, list(COMSIG_LIVING_DEATH, COMSIG_QDELETING), PROC_REF(on_death))
|
|
RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(owner_attacked_atom)) // This only works for players, but I am not sure this should have AI anyway
|
|
RegisterSignal(parent, COMSIG_ATOM_EXITED, PROC_REF(atom_exited_owner))
|
|
RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_update_overlays))
|
|
parent.add_traits(list(TRAIT_DISK_VERIFIER, TRAIT_CAN_STRIP, TRAIT_CAN_USE_NUKE), NUKE_OP_MINION_TRAIT)
|
|
|
|
/datum/component/nuclear_bomb_operator/UnregisterFromParent()
|
|
. = ..()
|
|
UnregisterSignal(parent, list(
|
|
COMSIG_ATOM_EXAMINE,
|
|
COMSIG_LIVING_DEATH,
|
|
COMSIG_QDELETING,
|
|
COMSIG_ATOM_ATTACK_HAND,
|
|
COMSIG_ATOM_EXITED,
|
|
COMSIG_ATOM_UPDATE_OVERLAYS,
|
|
))
|
|
parent.remove_traits(list(TRAIT_DISK_VERIFIER, TRAIT_CAN_STRIP, TRAIT_CAN_USE_NUKE), NUKE_OP_MINION_TRAIT)
|
|
|
|
/datum/component/nuclear_bomb_operator/Destroy(force)
|
|
QDEL_NULL(disky)
|
|
on_disk_collected = null
|
|
add_disk_overlays = null
|
|
return ..()
|
|
|
|
/// Drop the disk on the floor, if we have it
|
|
/datum/component/nuclear_bomb_operator/proc/drop_disky()
|
|
var/obj/item/disk/nuclear/held_disk = disky?.resolve()
|
|
if (!held_disk)
|
|
return
|
|
var/mob/mob_parent = parent
|
|
held_disk.forceMove(mob_parent.drop_location())
|
|
mob_parent.visible_message(span_danger("[mob_parent] drops [held_disk] onto the ground!"))
|
|
disky = null
|
|
mob_parent.update_appearance(updates = UPDATE_ICON)
|
|
|
|
/// Add details about carrying the nuke disc to examination.
|
|
/datum/component/nuclear_bomb_operator/proc/on_examine(atom/parent_atom, mob/examiner, list/examine_list)
|
|
SIGNAL_HANDLER
|
|
var/obj/item/disk/nuclear/held_disk = disky?.resolve()
|
|
if (!held_disk)
|
|
return
|
|
var/mob/mob_parent = parent
|
|
examine_list += span_notice("Wait... [mob_parent.p_are()] [mob_parent.p_they()] holding [held_disk]?")
|
|
|
|
/// Drop the disk when we are killed
|
|
/datum/component/nuclear_bomb_operator/proc/on_death(atom/parent_atom)
|
|
SIGNAL_HANDLER
|
|
drop_disky()
|
|
|
|
/// Try to pick up the disk, put it down, or open the nuke panel
|
|
/datum/component/nuclear_bomb_operator/proc/owner_attacked_atom(atom/parent_atom, atom/attacked_target, proximity, modifiers)
|
|
SIGNAL_HANDLER
|
|
if (!proximity)
|
|
return
|
|
if (!LAZYACCESS(modifiers, LEFT_CLICK))
|
|
return
|
|
var/obj/item/disk/nuclear/held_disk = disky?.resolve()
|
|
if (held_disk)
|
|
return try_put_down_disk(held_disk, attacked_target)
|
|
|
|
if (istype(attacked_target, /obj/item/disk/nuclear))
|
|
return try_pick_up_disk(attacked_target)
|
|
|
|
if (istype(attacked_target, /obj/machinery/nuclearbomb))
|
|
attacked_target.ui_interact(parent)
|
|
return COMPONENT_CANCEL_ATTACK_CHAIN
|
|
|
|
/// Picks up the nuke disk, if it can be picked up
|
|
/datum/component/nuclear_bomb_operator/proc/try_pick_up_disk(obj/item/disk/nuclear/potential_disky)
|
|
if(potential_disky.anchored)
|
|
return
|
|
var/mob/mob_parent = parent
|
|
potential_disky.forceMove(mob_parent)
|
|
disky = WEAKREF(potential_disky)
|
|
mob_parent.update_appearance(updates = UPDATE_ICON)
|
|
mob_parent.balloon_alert(mob_parent, "disk secured!")
|
|
on_disk_collected?.InvokeAsync(potential_disky)
|
|
|
|
/// Uses the disk on clicked atom, or places it on the ground
|
|
/datum/component/nuclear_bomb_operator/proc/try_put_down_disk(obj/item/disk/nuclear/held_disk, atom/attacked_target)
|
|
var/mob/mob_parent = parent
|
|
if(!isopenturf(attacked_target))
|
|
INVOKE_ASYNC(held_disk, TYPE_PROC_REF(/obj/item, melee_attack_chain), mob_parent, attacked_target)
|
|
mob_parent.do_item_attack_animation(attacked_target, used_item = held_disk)
|
|
return COMPONENT_CANCEL_ATTACK_CHAIN
|
|
|
|
held_disk.forceMove(attacked_target)
|
|
disky = null
|
|
mob_parent.balloon_alert(mob_parent, "disk dropped!")
|
|
mob_parent.update_appearance(updates = UPDATE_ICON)
|
|
return COMPONENT_CANCEL_ATTACK_CHAIN
|
|
|
|
/// Don't hold onto the reference if we lose the disk somehow
|
|
/datum/component/nuclear_bomb_operator/proc/atom_exited_owner(atom/parent_atom, atom/movable/gone)
|
|
SIGNAL_HANDLER
|
|
var/obj/item/disk/nuclear/held_disk = disky?.resolve()
|
|
if (held_disk != gone)
|
|
return
|
|
disky = null
|
|
var/mob/mob_parent = parent
|
|
mob_parent.update_appearance(updates = UPDATE_ICON)
|
|
|
|
/// Display any disk-related overlays which need displaying
|
|
/datum/component/nuclear_bomb_operator/proc/on_update_overlays(atom/parent_atom, list/overlays)
|
|
SIGNAL_HANDLER
|
|
if (!disky?.resolve())
|
|
return
|
|
var/mob/mob_parent = parent
|
|
if (!istype(mob_parent) || mob_parent.stat == DEAD)
|
|
return
|
|
add_disk_overlays?.InvokeAsync(overlays)
|