mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-22 12:41:09 +01:00
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. /🆑
This commit is contained in:
@@ -1,9 +1,3 @@
|
||||
#define WIRE_RECEIVE (1<<0)
|
||||
#define WIRE_PULSE (1<<1)
|
||||
#define WIRE_PULSE_SPECIAL (1<<2)
|
||||
#define WIRE_RADIO_RECEIVE (1<<3)
|
||||
#define WIRE_RADIO_PULSE (1<<4)
|
||||
#define ASSEMBLY_BEEP_VOLUME 5
|
||||
|
||||
/obj/item/assembly
|
||||
name = "assembly"
|
||||
@@ -24,10 +18,11 @@
|
||||
* This will prevent things such as visible lasers from facing the incorrect direction when transformed by assembly_holder's update_appearance()
|
||||
*/
|
||||
var/is_position_sensitive = FALSE
|
||||
/// Flags related to this assembly. See [assemblies.dm]
|
||||
var/assembly_flags = NONE
|
||||
var/secured = TRUE
|
||||
var/list/attached_overlays = null
|
||||
var/obj/item/assembly_holder/holder = null
|
||||
var/wire_type = WIRE_RECEIVE | WIRE_PULSE
|
||||
var/attachable = FALSE // can this be attached to wires
|
||||
var/datum/wires/connected = null
|
||||
var/next_activate = 0 //When we're next allowed to activate - for spam control
|
||||
@@ -75,24 +70,26 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
///Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs
|
||||
/obj/item/assembly/proc/pulsed(radio = FALSE, mob/pulser)
|
||||
if(wire_type & WIRE_RECEIVE)
|
||||
INVOKE_ASYNC(src, PROC_REF(activate), pulser)
|
||||
if(radio && (wire_type & WIRE_RADIO_RECEIVE))
|
||||
INVOKE_ASYNC(src, PROC_REF(activate), pulser)
|
||||
/**
|
||||
* Pulsed: This device was pulsed by another device
|
||||
*
|
||||
* * pulser: Who triggered the pulse
|
||||
*/
|
||||
/obj/item/assembly/proc/pulsed(mob/pulser)
|
||||
INVOKE_ASYNC(src, PROC_REF(activate), pulser)
|
||||
SEND_SIGNAL(src, COMSIG_ASSEMBLY_PULSED)
|
||||
return TRUE
|
||||
|
||||
///Called when this device attempts to act on another device, var/radio determines if it was sent via radio or direct
|
||||
/obj/item/assembly/proc/pulse(radio = FALSE)
|
||||
if(connected && wire_type)
|
||||
/**
|
||||
* Pulse: This device is emitting a pulse to act on another device
|
||||
*/
|
||||
/obj/item/assembly/proc/pulse()
|
||||
// if we have connected wires and are a pulsing assembly, pulse it
|
||||
if(connected)
|
||||
connected.pulse_assembly(src)
|
||||
return TRUE
|
||||
if(holder && (wire_type & WIRE_PULSE))
|
||||
holder.process_activation(src, 1, 0)
|
||||
if(holder && (wire_type & WIRE_PULSE_SPECIAL))
|
||||
holder.process_activation(src, 0, 1)
|
||||
// otherwise if we're attached to a holder, process the activation of it with our flags
|
||||
else if(holder)
|
||||
holder.process_activation(src)
|
||||
return TRUE
|
||||
|
||||
/// What the device does when turned on
|
||||
@@ -116,21 +113,29 @@
|
||||
return
|
||||
. = ..()
|
||||
|
||||
/obj/item/assembly/attackby(obj/item/W, mob/user, params)
|
||||
if(isassembly(W))
|
||||
var/obj/item/assembly/A = W
|
||||
if((!A.secured) && (!secured))
|
||||
holder = new/obj/item/assembly_holder(get_turf(src))
|
||||
holder.assemble(src,A,user)
|
||||
to_chat(user, span_notice("You attach and secure \the [A] to \the [src]!"))
|
||||
else
|
||||
to_chat(user, span_warning("Both devices must be in attachable mode to be attached together."))
|
||||
/obj/item/assembly/attackby(obj/item/attacking_item, mob/user, params)
|
||||
if(isassembly(attacking_item))
|
||||
var/obj/item/assembly/new_assembly = attacking_item
|
||||
// Check both our's and their's assembly flags to see if either should not duplicate
|
||||
// If so, and we match types, don't create a holder - block it
|
||||
if(((new_assembly.assembly_flags|assembly_flags) & ASSEMBLY_NO_DUPLICATES) && istype(new_assembly, type))
|
||||
balloon_alert(user, "can't attach another of that!")
|
||||
return
|
||||
if(new_assembly.secured || secured)
|
||||
balloon_alert(user, "both devices not attachable!")
|
||||
return
|
||||
|
||||
holder = new /obj/item/assembly_holder(drop_location())
|
||||
holder.assemble(src, new_assembly, user)
|
||||
holder.balloon_alert(user, "parts combined")
|
||||
return
|
||||
if(istype(W, /obj/item/assembly_holder))
|
||||
if(!secured)
|
||||
var/obj/item/assembly_holder/added_to_holder = W
|
||||
added_to_holder.add_assembly(src, user)
|
||||
..()
|
||||
|
||||
if(istype(attacking_item, /obj/item/assembly_holder))
|
||||
var/obj/item/assembly_holder/added_to_holder = attacking_item
|
||||
added_to_holder.try_add_assembly(src, user)
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/screwdriver_act(mob/living/user, obj/item/I)
|
||||
if(..())
|
||||
|
||||
@@ -46,6 +46,24 @@
|
||||
for(var/obj/item/assembly/assembly in assemblies)
|
||||
assembly.on_attach()
|
||||
|
||||
/obj/item/assembly_holder/proc/try_add_assembly(obj/item/assembly/attached_assembly, mob/user)
|
||||
if(attached_assembly.secured)
|
||||
balloon_alert(attached_assembly, "not attachable!")
|
||||
return FALSE
|
||||
|
||||
if(LAZYLEN(assemblies) >= HOLDER_MAX_ASSEMBLIES)
|
||||
balloon_alert(user, "too many assemblies!")
|
||||
return FALSE
|
||||
|
||||
if(attached_assembly.assembly_flags & ASSEMBLY_NO_DUPLICATES)
|
||||
if(locate(attached_assembly.type) in assemblies)
|
||||
balloon_alert(user, "can't attach another of that!")
|
||||
return FALSE
|
||||
|
||||
add_assembly(attached_assembly, user)
|
||||
balloon_alert(user, "part attached")
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Adds an assembly to the assembly holder
|
||||
*
|
||||
@@ -118,12 +136,11 @@
|
||||
|
||||
/obj/item/assembly_holder/attackby(obj/item/weapon, mob/user, params)
|
||||
if(isassembly(weapon))
|
||||
var/obj/item/assembly/attached_assembly = weapon
|
||||
if(!attached_assembly.secured)
|
||||
add_assembly(attached_assembly, user)
|
||||
balloon_alert(user, "part added")
|
||||
try_add_assembly(weapon, user)
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly_holder/AltClick(mob/user)
|
||||
return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation
|
||||
|
||||
@@ -153,16 +170,14 @@
|
||||
* send a pulse to the assembly holder, which then calls this proc that actually activates the assemblies
|
||||
* Arguments:
|
||||
* * /obj/device - the device we sent the pulse from which called this proc
|
||||
* * normal - if this is a normal activation
|
||||
* * special - if this is a special activation
|
||||
*/
|
||||
/obj/item/assembly_holder/proc/process_activation(obj/device, normal = TRUE, special = TRUE)
|
||||
/obj/item/assembly_holder/proc/process_activation(obj/device)
|
||||
if(!device)
|
||||
return FALSE
|
||||
if(normal && LAZYLEN(assemblies) >= 2)
|
||||
if(LAZYLEN(assemblies) >= 2)
|
||||
for(var/obj/item/assembly/assembly as anything in assemblies)
|
||||
if(assembly != device)
|
||||
assembly.pulsed(FALSE)
|
||||
assembly.pulsed()
|
||||
if(master)
|
||||
master.receive_signal()
|
||||
return TRUE
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
heat = 1000
|
||||
drop_sound = 'sound/items/handling/component_drop.ogg'
|
||||
pickup_sound = 'sound/items/handling/component_pickup.ogg'
|
||||
assembly_flags = ASSEMBLY_NO_DUPLICATES
|
||||
|
||||
/obj/item/assembly/igniter/suicide_act(mob/living/carbon/user)
|
||||
user.visible_message(span_suicide("[user] is trying to ignite [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
|
||||
@@ -43,13 +44,6 @@
|
||||
sparks.start()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/igniter/attackby(obj/item/potential_igniter, mob/user, params)
|
||||
if(isigniter(potential_igniter))
|
||||
to_chat(user, "You briefly consider attaching [potential_igniter] to [src], and then conclude that's a very silly thing to do and move on.")
|
||||
return
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/assembly/igniter/attack_self(mob/user)
|
||||
activate()
|
||||
add_fingerprint(user)
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
switchListener(location)
|
||||
if(!secured || !on || next_activate > world.time)
|
||||
return FALSE
|
||||
pulse(FALSE)
|
||||
pulse()
|
||||
audible_message("<span class='infoplain'>[icon2html(src, hearers(src))] *beep* *beep* *beep*</span>", 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)
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
var/mob/living/carbon/human/user = usr
|
||||
if((HAS_TRAIT(user, TRAIT_DUMB) || HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50))
|
||||
to_chat(user, span_warning("Your hand slips, setting off the trigger!"))
|
||||
pulse(FALSE)
|
||||
pulse()
|
||||
update_appearance()
|
||||
playsound(src, 'sound/weapons/handcuffs.ogg', 30, TRUE, -3)
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
var/mob/living/carbon/human/victim = target
|
||||
if(HAS_TRAIT(victim, TRAIT_PIERCEIMMUNE))
|
||||
playsound(src, 'sound/effects/snap.ogg', 50, TRUE)
|
||||
pulse(FALSE)
|
||||
pulse()
|
||||
return FALSE
|
||||
switch(type)
|
||||
if("feet")
|
||||
@@ -148,7 +148,7 @@
|
||||
visible_message(span_boldannounce("Skreeeee!")) //He's simply too large to be affected by a tiny mouse trap.
|
||||
|
||||
playsound(src, 'sound/effects/snap.ogg', 50, TRUE)
|
||||
pulse(FALSE)
|
||||
pulse()
|
||||
|
||||
/**
|
||||
* clumsy_check: Sets off the mousetrap if handled by a clown (with some probability)
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
/obj/item/assembly/prox_sensor/proc/sense()
|
||||
if(!scanning || !secured || next_activate > world.time)
|
||||
return FALSE
|
||||
pulse(FALSE)
|
||||
pulse()
|
||||
audible_message("<span class='infoplain'>[icon2html(src, hearers(src))] *beep* *beep* *beep*</span>", 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)
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi'
|
||||
custom_materials = list(/datum/material/iron=400, /datum/material/glass=120)
|
||||
wires = WIRE_RECEIVE | WIRE_PULSE | WIRE_RADIO_PULSE | WIRE_RADIO_RECEIVE
|
||||
attachable = TRUE
|
||||
drop_sound = 'sound/items/handling/component_drop.ogg'
|
||||
pickup_sound = 'sound/items/handling/component_pickup.ogg'
|
||||
@@ -156,8 +155,6 @@
|
||||
return
|
||||
if(signal.data["code"] != code)
|
||||
return
|
||||
if(!(src.wires & WIRE_RADIO_RECEIVE))
|
||||
return
|
||||
if(suicider)
|
||||
manual_suicide(suicider)
|
||||
return
|
||||
@@ -165,7 +162,7 @@
|
||||
// If the holder is a TTV, we want to store the last received signal to incorporate it into TTV logging, else wipe it.
|
||||
last_receive_signal_log = istype(holder, /obj/item/transfer_valve) ? signal.logging_data : null
|
||||
|
||||
pulse(TRUE)
|
||||
pulse()
|
||||
audible_message("<span class='infoplain'>[icon2html(src, hearers(src))] *beep* *beep* *beep*</span>", 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)
|
||||
@@ -177,34 +174,6 @@
|
||||
radio_connection = SSradio.add_object(src, frequency, RADIO_SIGNALER)
|
||||
return
|
||||
|
||||
// Embedded signaller used in grenade construction.
|
||||
// It's necessary because the signaler doens't have an off state.
|
||||
// Generated during grenade construction. -Sayu
|
||||
/obj/item/assembly/signaler/receiver
|
||||
var/on = FALSE
|
||||
|
||||
/obj/item/assembly/signaler/receiver/proc/toggle_safety()
|
||||
on = !on
|
||||
|
||||
/obj/item/assembly/signaler/receiver/activate()
|
||||
toggle_safety()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/signaler/receiver/examine(mob/user)
|
||||
. = ..()
|
||||
. += span_notice("The radio receiver is [on?"on":"off"].")
|
||||
|
||||
/obj/item/assembly/signaler/receiver/receive_signal(datum/signal/signal)
|
||||
if(!on)
|
||||
return
|
||||
return ..(signal)
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/attack_self()
|
||||
return
|
||||
|
||||
/obj/item/assembly/signaler/crystal_anomaly/attack_self()
|
||||
return
|
||||
|
||||
/obj/item/assembly/signaler/cyborg
|
||||
|
||||
/obj/item/assembly/signaler/cyborg/attackby(obj/item/W, mob/user, params)
|
||||
@@ -228,4 +197,3 @@
|
||||
if(ispAI(user))
|
||||
return TRUE
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
/obj/item/assembly/timer/proc/timer_end()
|
||||
if(secured && next_activate <= world.time)
|
||||
pulse(FALSE)
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user