Files
Bubberstation/code/datums/components/nuclear_bomb_operator.dm
SkyratBot 067188d366 [MIRROR] Micro-optimize qdel by only permitting one parameter [MDB IGNORE] (#25889)
* 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>
2023-12-29 14:41:12 +00:00

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)