mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-14 11:42:27 +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>
128 lines
4.4 KiB
Plaintext
128 lines
4.4 KiB
Plaintext
/**
|
|
* ### Spin 2 Win component!
|
|
*
|
|
* Component that attaches to items, making their attack_self begin a spin 2 win
|
|
*/
|
|
/datum/component/spin2win
|
|
/// How long you spin for
|
|
var/spin_duration = 5 SECONDS
|
|
///the cooldown for spinning to winning
|
|
COOLDOWN_DECLARE(spin_cooldown)
|
|
///how long a spin2win takes to recharge.
|
|
var/spin_cooldown_time
|
|
///whether we are currently spin2winning or not.
|
|
var/spinning = FALSE
|
|
///Timer id for when we should stop spinning.
|
|
var/stop_spinning_timer_id
|
|
|
|
var/datum/callback/on_spin_callback
|
|
var/datum/callback/on_unspin_callback
|
|
|
|
var/start_spin_message
|
|
var/end_spin_message
|
|
|
|
/datum/component/spin2win/Initialize(
|
|
spin_cooldown_time = 10 SECONDS,
|
|
on_spin_callback = null,
|
|
on_unspin_callback = null,
|
|
start_spin_message = "",
|
|
end_spin_message = ""
|
|
)
|
|
|
|
if(!isitem(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
src.spin_cooldown_time = spin_cooldown_time
|
|
src.on_spin_callback = on_spin_callback
|
|
src.on_unspin_callback = on_unspin_callback
|
|
src.start_spin_message = start_spin_message
|
|
src.end_spin_message = end_spin_message
|
|
|
|
/datum/component/spin2win/Destroy(force)
|
|
on_spin_callback = null
|
|
on_unspin_callback = null
|
|
return ..()
|
|
|
|
/datum/component/spin2win/RegisterWithParent()
|
|
RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
|
|
RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, PROC_REF(on_attack_self))
|
|
|
|
/datum/component/spin2win/UnregisterFromParent()
|
|
UnregisterSignal(parent, list(COMSIG_ATOM_EXAMINE, COMSIG_ITEM_ATTACK_SECONDARY))
|
|
|
|
///signal called on parent being examined
|
|
/datum/component/spin2win/proc/on_examine(datum/source, mob/user, list/examine_list)
|
|
SIGNAL_HANDLER
|
|
|
|
examine_list += span_notice("Using [parent] in your hands will make you spin your weapon around for a few moments, attacking everyone near you repeatedly!")
|
|
if(spinning)
|
|
examine_list += span_warning("...Of which you are currently doing right now!")
|
|
return
|
|
if(COOLDOWN_FINISHED(src, spin_cooldown))
|
|
examine_list += span_notice("It has a cooldown of [DisplayTimeText(spin_cooldown_time)].")
|
|
else
|
|
examine_list += span_notice("It will be ready to spin again in [DisplayTimeText(COOLDOWN_TIMELEFT(src, spin_cooldown))].")
|
|
|
|
/datum/component/spin2win/proc/on_attack_self(datum/source, mob/user, location, direction)
|
|
SIGNAL_HANDLER
|
|
|
|
if(spinning)
|
|
user.balloon_alert(user, "already active!")
|
|
return
|
|
if(!COOLDOWN_FINISHED(src, spin_cooldown))
|
|
user.balloon_alert(user, "on cooldown!")
|
|
return
|
|
|
|
start_spinning(user)
|
|
|
|
/datum/component/spin2win/proc/start_spinning(mob/living/spinning_user)
|
|
//user will always exist for the start
|
|
spinning = TRUE
|
|
spinning_user.changeNext_move(spin_duration)
|
|
if(on_spin_callback)
|
|
on_spin_callback.Invoke(spinning_user, spin_duration)
|
|
if(start_spin_message)
|
|
var/message = replacetext(start_spin_message, "%USER", spinning_user)
|
|
spinning_user.visible_message(message)
|
|
playsound(spinning_user, 'sound/weapons/fwoosh.ogg', 75, FALSE)
|
|
stop_spinning_timer_id = addtimer(CALLBACK(src, PROC_REF(stop_spinning), spinning_user), spin_duration, TIMER_STOPPABLE|TIMER_DELETE_ME)
|
|
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_spin_equipped))
|
|
RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_spin_dropped))
|
|
START_PROCESSING(SSprocessing, src)
|
|
|
|
/datum/component/spin2win/proc/stop_spinning(mob/living/user)
|
|
//user might not exist for the end
|
|
STOP_PROCESSING(SSprocessing, src)
|
|
UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED))
|
|
deltimer(stop_spinning_timer_id)
|
|
playsound(user, 'sound/weapons/fwoosh.ogg', 75, FALSE)
|
|
if(user && end_spin_message)
|
|
var/message = replacetext(end_spin_message, "%USER", user)
|
|
user.visible_message(message)
|
|
if(on_unspin_callback)
|
|
on_unspin_callback.Invoke(user, spin_duration)
|
|
COOLDOWN_START(src, spin_cooldown, spin_cooldown_time)
|
|
spinning = FALSE
|
|
|
|
/datum/component/spin2win/process(seconds_per_tick)
|
|
var/obj/item/spinning_item = parent
|
|
if(!isliving(spinning_item.loc))
|
|
stop_spinning()
|
|
return PROCESS_KILL
|
|
var/mob/living/item_owner = spinning_item.loc
|
|
item_owner.emote("spin")
|
|
playsound(item_owner, 'sound/weapons/fwoosh.ogg', 75, FALSE)
|
|
for(var/mob/living/victim in orange(1, item_owner))
|
|
spinning_item.attack(victim, item_owner)
|
|
|
|
/datum/component/spin2win/proc/on_spin_dropped(datum/source, mob/user)
|
|
SIGNAL_HANDLER
|
|
|
|
stop_spinning(user)
|
|
|
|
/datum/component/spin2win/proc/on_spin_equipped(datum/source, mob/equipper, slot)
|
|
SIGNAL_HANDLER
|
|
|
|
if(slot != ITEM_SLOT_HANDS)
|
|
stop_spinning(equipper)
|