Bitrunning glitches take much longer to escape their simulation if there are remaining active bitrunners (#95934)

## About The Pull Request

For every living, connected bit avatar remaining in the simulation, the
`do_after()` for leaving the simulation as a bitrunning glitch ghost
role is multiplied by 5. The base timer remains at it was, two seconds.

Additionally, there is an exception in place for the "Island Brawl"
domain, which is the FFA with infinite respawns. It still multiplies by
5 for each active bitrunner, but that multiplier is reduced by 1 for
each death, so you likely only have to kill one wave of bitrunners for
normal escape time.

Additionally, because of necessity for the exception and also basic good
sense, bitrunning points are no longer component-based on specific turfs
in the domain, and are held in the server. It never should have been a
component, it had no reason to be one. This, as a consenquence, also
fixes that you could completely softlock any domain using points by
simply crowbarring the turf that the crate was yet to spawn on.

## Why It's Good For The Game

Yesterday, I saw one of the lamest things I've ever seen in the game. A
bitrunning glitch spawns in, walks literally right by two bitrunners as
they ask who he is, and leaves the simulation to go on a killing spree
unburdened. There was extenuating circumstances in that situation, but
it still was a miserable breakdown of what I think the intended gameplay
of a bitrunning glitch is, and shows how ridiculously easy it is to
simply not engage with the intended hurdle in your path. The
primary(and, really, only) job of a glitch is to kill bit avatars, and
this PR makes it significantly more difficult to just... walk by them to
go on your killing spree on station. Work, then play.

## Changelog
🆑

balance: For every living, connected bitrunner remaining in a domain,
bitrunning glitches will take five times longer to escape.
fix: You can no longer softlock any virtual domain that uses points by
crowbarring the reward turf before the crate spawns.

/🆑
This commit is contained in:
Leland Kemble
2026-05-29 13:35:45 -04:00
committed by GitHub
parent af6d8bc211
commit d49c825f8e
6 changed files with 39 additions and 46 deletions
@@ -1,36 +0,0 @@
/// Attaches to a turf so it spawns a crate when a certain amount of points are added to it.
/datum/component/bitrunning_points
/// The amount required to spawn a crate
var/points_goal = 10
/// A special condition limits this from spawning a crate
var/points_received = 0
/datum/component/bitrunning_points/Initialize(datum/lazy_template/virtual_domain/domain)
if(!isturf(parent))
return COMPONENT_INCOMPATIBLE
RegisterSignal(domain, COMSIG_BITRUNNER_GOAL_POINT, PROC_REF(on_add_points))
/// Listens for points to be added which will eventually spawn a crate.
/datum/component/bitrunning_points/proc/on_add_points(datum/source, points_to_add)
SIGNAL_HANDLER
points_received += points_to_add
if(points_received < points_goal)
return
reveal()
/// Spawns the crate with some effects
/datum/component/bitrunning_points/proc/reveal()
playsound(src, 'sound/effects/magic/blink.ogg', 50, TRUE)
var/turf/tile = parent
var/obj/structure/closet/crate/secure/bitrunning/encrypted/crate = new()
crate.forceMove(tile) // Triggers any on-move effects on that turf
do_sparks(5, FALSE, tile, spark_type = /datum/effect_system/basic/spark_spread/quantum)
qdel(src)
@@ -53,12 +53,12 @@
scrub_vdom()
is_ready = TRUE
return FALSE
//We will want to record how the domain was selected. Either entirely randomly, with the name redacted, or with full information.
//Without this, it is difficult to determine what domains are selected more often intentionallly, vs unintentionally.
var/selection_type
if(was_random_selection)
selection_type = "random selection"
else
@@ -168,8 +168,7 @@
continue
if(istype(thing, /obj/effect/landmark/bitrunning/loot_signal))
var/turf/signaler_turf = get_turf(thing)
signaler_turf.AddComponent(/datum/component/bitrunning_points, generated_domain)
generated_domain.main_crate_loc = thing.loc
qdel(thing)
continue
+16
View File
@@ -142,6 +142,22 @@
aas.broadcast("QUANTUM SERVER ALERT: Fabrication protocols have crashed unexpectedly. Please evacuate the area.", list(RADIO_CHANNEL_SUPPLY))
timeout = 10 SECONDS
var/bitrunners_alive = 0
var/island_brawl_exception = istype(generated_domain, /datum/lazy_template/virtual_domain/island_brawl)
for(var/datum/weakref/bitrunner_ref in avatar_connection_refs)
var/mob/living/bitrunner = astype(bitrunner_ref.resolve(), /datum/component/avatar_connection)?.parent
if(!bitrunner)
continue
if((bitrunner.stat > CONSCIOUS) || !bitrunner.client)
continue
if(island_brawl_exception)
timeout *= max(5 - generated_domain.main_crate_points, 1)
continue
bitrunners_alive++
timeout *= 5
if(bitrunners_alive)
to_chat(antag, span_warning("[bitrunners_alive] criminals still remain here, pilfering your domain. It will be more difficult to leave until they are handled."))
if(!do_after(antag, timeout) || QDELETED(chosen_forge) || QDELETED(antag) || QDELETED(src) || !is_ready || !is_operational)
chosen_forge.setup_particles()
return
@@ -52,6 +52,12 @@
var/secondary_loot_generated
/// Has this domain been beaten with high enough score to spawn a tech disk?
var/disk_reward_spawned = FALSE
/// The amount of points towards the spawning of the main crate, on maps using points.
var/main_crate_points = 0
/// The amount of points required to spawn the main crate, on maps using points.
var/main_crate_point_goal = 10
/// The location the crate will spawn when enough points are accumulated, on maps using points.
var/main_crate_loc
/**
* Modularity
@@ -99,7 +105,19 @@
/// Sends a point to any loot signals on the map
/datum/lazy_template/virtual_domain/proc/add_points(points_to_add = 1)
SEND_SIGNAL(src, COMSIG_BITRUNNER_GOAL_POINT, points_to_add)
main_crate_points += points_to_add
if(main_crate_points >= main_crate_point_goal)
reveal()
/datum/lazy_template/virtual_domain/proc/reveal()
if(!main_crate_loc)
return
var/turf/spawn_loc = get_turf(main_crate_loc)
playsound(spawn_loc, 'sound/effects/magic/blink.ogg', 50, TRUE)
var/obj/structure/closet/crate/secure/bitrunning/encrypted/crate = new()
crate.forceMove(spawn_loc) // Triggers any on-move effects on that turf
do_sparks(5, FALSE, spawn_loc, spark_type = /datum/effect_system/basic/spark_spread/quantum)
main_crate_loc = null
/// Loads the ghost candidates.
/datum/lazy_template/virtual_domain/proc/load_advanced_npcs(list/mob/lucky_ghosts)