Skip to content

Commit

Permalink
Strangles some severe BSRPED grief exploits in the crib (#10239)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tsar-Salat authored Nov 29, 2023
1 parent 8f5f0ff commit 6bcad70
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 9 deletions.
5 changes: 5 additions & 0 deletions code/__DEFINES/dcs/signals/signals_datum/signals_datum.dm
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
/// Sent when the amount of materials in material_container changes
#define COMSIG_MATERIAL_CONTAINER_CHANGED "material_container_changed"

///from base of [/datum/reagents/proc/add_reagent] - Sent before the reagent is added: (reagenttype, amount, reagtemp, data, no_react)
#define COMSIG_REAGENTS_PRE_ADD_REAGENT "reagents_pre_add_reagent"
/// Prevents the reagent from being added.
#define COMPONENT_CANCEL_REAGENT_ADD (1<<0)

// /datum/species signals
#define COMSIG_SPECIES_GAIN "species_gain" //! from datum/species/on_species_gain(): (datum/species/new_species, datum/species/old_species)
#define COMSIG_SPECIES_LOSS "species_loss" //! from datum/species/on_species_loss(): (datum/species/lost_species)
Expand Down
7 changes: 7 additions & 0 deletions code/game/machinery/_machinery.dm
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,13 @@ Class Procs:
break
for(var/obj/item/B in W.contents)
if(istype(B, P) && istype(A, P))
// If it's a corrupt or rigged cell, attempting to send it through Bluespace could have unforeseen consequences.
if(istype(B, /obj/item/stock_parts/cell) && W.works_from_distance)
var/obj/item/stock_parts/cell/checked_cell = B
// If it's rigged or corrupted, max the charge. Then explode it.
if(checked_cell.rigged || checked_cell.corrupted)
checked_cell.charge = checked_cell.maxcharge
checked_cell.explode()
if(B.get_part_rating() > A.get_part_rating())
if(istype(B,/obj/item/stack)) //conveniently this will mean A is also a stack and I will kill the first person to prove me wrong
var/obj/item/stack/SA = A
Expand Down
13 changes: 10 additions & 3 deletions code/modules/power/cell.dm
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
var/maxcharge = 1000
materials = list(/datum/material/iron=700, /datum/material/glass=50)
grind_results = list(/datum/reagent/lithium = 15, /datum/reagent/iron = 5, /datum/reagent/silicon = 5)
/// true if rigged to explode
/// If the cell has been booby-trapped by injecting it with plasma. Chance on use() to explode.
var/rigged = FALSE
/// If the power cell was damaged by an explosion, chance for it to become corrupted and function the same as rigged.
var/corrupted = FALSE
///how much power is given every tick in a recharger
var/chargerate = 100
///does it self recharge, over time, or not?
Expand Down Expand Up @@ -112,8 +114,8 @@
return FIRELOSS

/obj/item/stock_parts/cell/on_reagent_change(changetype)
rigged = !isnull(reagents.has_reagent(/datum/reagent/toxin/plasma, 5)) //has_reagent returns the reagent datum
..()
rigged = (corrupted || reagents.has_reagent(/datum/reagent/toxin/plasma, 5)) //has_reagent returns the reagent datum
return ..()


/obj/item/stock_parts/cell/proc/explode()
Expand All @@ -128,6 +130,10 @@
rigged = FALSE
corrupt()
return

message_admins("[ADMIN_LOOKUPFLW(usr)] has triggered a rigged/corrupted power cell explosion at [AREACOORD(T)].")
log_game("[key_name(usr)] has triggered a rigged/corrupted power cell explosion at [AREACOORD(T)].")

//explosion(T, 0, 1, 2, 2)
explosion(T, devastation_range, heavy_impact_range, light_impact_range, flash_range)
qdel(src)
Expand All @@ -137,6 +143,7 @@
maxcharge = max(maxcharge/2, chargerate)
if (prob(10))
rigged = TRUE //broken batterys are dangerous
corrupted = TRUE

/obj/item/stock_parts/cell/emp_act(severity)
. = ..()
Expand Down
9 changes: 7 additions & 2 deletions code/modules/reagents/chemistry/holder.dm
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@
var/transfer_amount = T.volume * part
if(preserve_data)
trans_data = copy_data(T)
R.add_reagent(T.type, transfer_amount * multiplier, trans_data, chem_temp, no_react = 1) //we only handle reaction after every reagent has been transfered.
if(!R.add_reagent(T.type, transfer_amount * multiplier, trans_data, chem_temp, no_react = TRUE)) //we only handle reaction after every reagent has been transfered.
continue
if(method)
R.react_single(T, target_atom, method, part, show_message)
T.on_transfer(target_atom, method, transfer_amount * multiplier)
Expand All @@ -218,7 +219,8 @@
var/transfer_amount = amount
if(amount > T.volume)
transfer_amount = T.volume
R.add_reagent(T.type, transfer_amount * multiplier, trans_data, chem_temp, no_react = 1)
if(!R.add_reagent(T.type, transfer_amount * multiplier, trans_data, chem_temp, no_react = TRUE)) //we only handle reaction after every reagent has been transfered.
continue
to_transfer = max(to_transfer - transfer_amount , 0)
if(method)
R.react_single(T, target_atom, method, transfer_amount, show_message)
Expand Down Expand Up @@ -640,6 +642,9 @@
if(amount <= 0)
return FALSE

if(SEND_SIGNAL(src, COMSIG_REAGENTS_PRE_ADD_REAGENT, reagent, amount, reagtemp, data, no_react) & COMPONENT_CANCEL_REAGENT_ADD)
return FALSE

var/datum/reagent/D = GLOB.chemical_reagents_list[reagent]
if(!D)
WARNING("[my_atom] attempted to add a reagent called '[reagent]' which doesn't exist. ([usr])")
Expand Down
67 changes: 63 additions & 4 deletions code/modules/research/stock_parts.dm
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
if(!user.Adjacent(attacked_object)) // no TK upgrading.
return ..()

if(istype(attacked_object, /obj/machinery))
if(ismachinery(attacked_object))
var/obj/machinery/attacked_machinery = attacked_object

if(!attacked_machinery.component_parts)
Expand All @@ -36,13 +36,14 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi

if(!attacked_frame.components)
return ..()
attacked_frame.attackby(src, user)

if(works_from_distance)
user.Beam(attacked_frame, icon_state = "rped_upgrade", time = 5)
attacked_frame.attackby(src, user)
return TRUE

/obj/item/storage/part_replacer/afterattack(obj/attacked_object, mob/living/user, adjacent, params)
if(!istype(attacked_object, /obj/machinery) && !istype(attacked_object, /obj/structure/frame/machine))
if(!ismachinery(attacked_object) && !istype(attacked_object, /obj/structure/frame/machine))
return ..()

if(adjacent)
Expand All @@ -60,14 +61,15 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
return

var/obj/structure/frame/machine/attacked_frame = attacked_object

if(!adjacent && !works_from_distance)
return
if(!attacked_frame.components)
return ..()

attacked_frame.attackby(src, user)
if(works_from_distance)
user.Beam(attacked_frame, icon_state = "rped_upgrade", time = 5)
attacked_frame.attackby(src, user)

/obj/item/storage/part_replacer/proc/play_rped_sound()
//Plays the sound for RPED exhanging or installing parts.
Expand All @@ -87,6 +89,63 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
alt_sound = 'sound/items/pshoom_2.ogg'
component_type = /datum/component/storage/concrete/bluespace/rped

/obj/item/storage/part_replacer/bluespace/Initialize(mapload)
. = ..()

RegisterSignal(src, COMSIG_ATOM_ENTERED, PROC_REF(on_part_entered))
RegisterSignal(src, COMSIG_ATOM_EXITED,PROC_REF(on_part_exited))

/**
* Signal handler for when a part has been inserted into the BRPED.
*
* If the inserted item is a rigged or corrupted cell, does some logging.
*
* If it has a reagent holder, clears the reagents and registers signals to prevent new
* reagents being added and registers clean up signals on inserted item's removal from
* the BRPED.
*/
/obj/item/storage/part_replacer/bluespace/proc/on_part_entered(datum/source, obj/item/inserted_component)
SIGNAL_HANDLER

if(istype(inserted_component, /obj/item/stock_parts/cell))
var/obj/item/stock_parts/cell/inserted_cell = inserted_component
if(inserted_cell.rigged || inserted_cell.corrupted)
message_admins("[ADMIN_LOOKUPFLW(usr)] has inserted rigged/corrupted [inserted_cell] into [src].")
usr.log_message("has inserted rigged/corrupted [inserted_cell] into [src].", LOG_GAME)
usr.log_message("inserted rigged/corrupted [inserted_cell] into [src]", LOG_ATTACK)
return

if(inserted_component.reagents)
if(length(inserted_component.reagents.reagent_list))
inserted_component.reagents.clear_reagents()
to_chat(usr, "<span class='warning'>[src] churns as [inserted_component] has its reagents emptied into bluespace.</span>")
RegisterSignal(inserted_component.reagents, COMSIG_REAGENTS_PRE_ADD_REAGENT, PROC_REF(on_insered_component_reagent_pre_add))

/**
* Signal handler for when the reagents datum of an inserted part has reagents added to it.
*
* Registers the PRE_ADD variant which allows the signal handler to stop reagents being
* added.
*
* Simply returns COMPONENT_CANCEL_REAGENT_ADD. We never want to allow people to add
* reagents to beakers in BRPEDs as they can then be used for spammable remote bombing.
*/
/obj/item/storage/part_replacer/bluespace/proc/on_insered_component_reagent_pre_add(datum/source, reagent, amount, reagtemp, data, no_react)
SIGNAL_HANDLER

return COMPONENT_CANCEL_REAGENT_ADD

/**
* Signal handler for a part is removed from the BRPED.
*
* Does signal registration cleanup on its reagents, if it has any.
*/
/obj/item/storage/part_replacer/bluespace/proc/on_part_exited(datum/source, obj/item/removed_component)
SIGNAL_HANDLER

if(removed_component.reagents)
UnregisterSignal(removed_component.reagents, COMSIG_REAGENTS_PRE_ADD_REAGENT)

/obj/item/storage/part_replacer/bluespace/tier1

/obj/item/storage/part_replacer/bluespace/tier1/PopulateContents()
Expand Down

0 comments on commit 6bcad70

Please sign in to comment.