Files
Bubberstation/code/modules/assembly/timer.dm
SkyratBot c4afb8a473 [MIRROR] Fixes an exploit with stacking igniters. Refactors some assembly flag oddities. Limits assembly holders at 12 assemblies. [MDB IGNORE] (#17689)
* Fixes an exploit with stacking igniters. Refactors some assembly flag oddities. Limits assembly holders at 12 assemblies.  (#71264)

## About The Pull Request

Soft revert of #71224 , Fixes #71222

Fixes an exploit involving attachment of multiple igniters to one
assembly.
- Multiple igniters or condensers can no longer be attached to the same
assembly holder
- Assembly holders have a limit of 12 assemblies maximum
- I'm not sure if this is too low or limited, I picked it arbitrarily.
Please inform me if it could be upped a smidge.
- This lag exploit was born because of limitless assembly holders, which
is a little silly even with the exploit aside. All that uncapped holders
can bring are exploits or bugs, which I feel confident limited can
prevent. What use is there even for having so many?
- Cleans up / refactors some aspects of assemblies and assembly holders.
- Assemblies had a weird wire type flag that was only ever used by
signallers, but also used wrong by signallers. I did some scanning of
the code and realized that ... a lot of this was just straight up
unused, and not even assigned anywhere.
- Now, there is a flag assembly flag var, which everything is read off
of. Tested it and still seemed to all work fine.

## Why It's Good For The Game

Lag exploits are bad.

## Changelog

🆑 Melbert
fix: Fixed an exploit involving igniters attached to themselves.
Assembly holders are now limited to 12 assemblies maximum, and you
cannot attach multiple igniters to the same assembly.
refactor: Refactored some assembly jank, namely in how they pulse and
are pulsed.
/🆑

* Fixes an exploit with stacking igniters. Refactors some assembly flag oddities. Limits assembly holders at 12 assemblies.

Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
2022-11-24 14:34:57 -05:00

127 lines
3.5 KiB
Plaintext

/obj/item/assembly/timer
name = "timer"
desc = "Used to time things. Works well with contraptions which has to count down. Tick tock."
icon_state = "timer"
custom_materials = list(/datum/material/iron=500, /datum/material/glass=50)
attachable = TRUE
drop_sound = 'sound/items/handling/component_drop.ogg'
pickup_sound = 'sound/items/handling/component_pickup.ogg'
var/timing = FALSE
var/time = 10
var/saved_time = 10
var/loop = FALSE
var/hearing_range = 3
/obj/item/assembly/timer/suicide_act(mob/living/user)
user.visible_message(span_suicide("[user] looks at the timer and decides [user.p_their()] fate! It looks like [user.p_theyre()] going to commit suicide!"))
activate()//doesnt rely on timer_end to prevent weird metas where one person can control the timer and therefore someone's life. (maybe that should be how it works...)
addtimer(CALLBACK(src, PROC_REF(manual_suicide), user), time SECONDS)//kill yourself once the time runs out
return MANUAL_SUICIDE
/obj/item/assembly/timer/proc/manual_suicide(mob/living/user)
user.visible_message(span_suicide("[user]'s time is up!"))
user.adjustOxyLoss(200)
user.death(FALSE)
/obj/item/assembly/timer/Initialize(mapload)
. = ..()
START_PROCESSING(SSobj, src)
/obj/item/assembly/timer/Destroy()
STOP_PROCESSING(SSobj, src)
. = ..()
/obj/item/assembly/timer/examine(mob/user)
. = ..()
. += span_notice("The timer is [timing ? "counting down from [time]":"set for [time] seconds"].")
/obj/item/assembly/timer/activate()
if(!..())
return FALSE//Cooldown check
timing = !timing
update_appearance()
return TRUE
/obj/item/assembly/timer/toggle_secure()
secured = !secured
if(secured)
START_PROCESSING(SSobj, src)
else
timing = FALSE
STOP_PROCESSING(SSobj, src)
update_appearance()
return secured
/obj/item/assembly/timer/proc/timer_end()
if(secured && next_activate <= world.time)
pulse()
audible_message(span_infoplain("[icon2html(src, hearers(src))] *beep* *beep* *beep*"), null, hearing_range)
for(var/mob/hearing_mob in get_hearers_in_view(hearing_range, src))
hearing_mob.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
if(loop)
timing = TRUE
update_appearance()
/obj/item/assembly/timer/process(delta_time)
if(!timing)
return
time -= delta_time
if(time <= 0)
timing = FALSE
timer_end()
time = saved_time
/obj/item/assembly/timer/update_appearance()
. = ..()
holder?.update_appearance()
/obj/item/assembly/timer/update_overlays()
. = ..()
attached_overlays = list()
if(timing)
. += "timer_timing"
attached_overlays += "timer_timing"
/obj/item/assembly/timer/ui_status(mob/user)
if(is_secured(user))
return ..()
return UI_CLOSE
/obj/item/assembly/timer/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Timer", name)
ui.open()
/obj/item/assembly/timer/ui_data(mob/user)
var/list/data = list()
data["seconds"] = round(time % 60)
data["minutes"] = round((time - data["seconds"]) / 60)
data["timing"] = timing
data["loop"] = loop
return data
/obj/item/assembly/timer/ui_act(action, params)
. = ..()
if(.)
return
switch(action)
if("time")
timing = !timing
if(timing && istype(holder, /obj/item/transfer_valve))
log_bomber(usr, "activated a", src, "attachment on [holder]")
update_appearance()
. = TRUE
if("repeat")
loop = !loop
. = TRUE
if("input")
var/value = text2num(params["adjust"])
if(value)
value = round(time + value)
time = clamp(value, 1, 600)
saved_time = time
. = TRUE