Files
Bubberstation/code/modules/bitrunning/server/map_handling.dm
SkyratBot 0a693b9dfa [MIRROR] Bitrunning 1.5: Secondary Objectives (#26821)
* Bitrunning 1.5: Secondary Objectives (#81828)

## About The Pull Request

Added secondary objective lockboxes to bitrunning. These pull from a
list of secondary objective loot on the domain, with a limited quantity
of items. Once there are no items left to pull, the secondary objective
disappears. If multiple secondary objective markers are placed, they
will be placed until all markers have been used, or all the items in the
loot pool are already spoken for.

To support this functionality, adds SSbitrunning, which stores all
domains as instances, instead of checking the hardcoded types as
previously. SSbitrunning manages listing domains for the quantum
console, and rolling secondary loot.

As an example of this functionality, added a side path to Glacier Grind
with a polar bear and some loot.

## Why It's Good For The Game

Secondary objectives give mappers ways to encourage players to venture
into a wider range of domains by offering non-trivial loot beyond the
fluff items given in the main caches. The absolute limit on the number
of items available ensures these items can't be farmed.

As well as supporting secondary objectives, SSbitrunning allows for
future support of features relying on mid-round modification of domains,
for instance adding custom domains.

## Changelog
🆑
add: Added secondary objectives to bitrunning!
add: Pick up encrypted curiosities and return them to the safehouse to
claim their contents.
add: Glacier Grind has been given a secondary objective, look out for
the limited edition hat.
add: Bitrunning domains can now be modified during the round by admins.
/🆑

* Bitrunning 1.5: Secondary Objectives

* Update virtual_domain.dm

---------

Co-authored-by: Thunder12345 <Thunder12345@users.noreply.github.com>
Co-authored-by: Pinta <68373373+softcerv@users.noreply.github.com>
2024-03-22 12:17:51 -04:00

174 lines
5.4 KiB
Plaintext

/// Gives all current occupants a notification that the server is going down
/obj/machinery/quantum_server/proc/begin_shutdown(mob/user)
if(isnull(generated_domain))
return
if(!length(avatar_connection_refs))
balloon_alert_to_viewers("powering down domain...")
playsound(src, 'sound/machines/terminal_off.ogg', 40, vary = TRUE)
reset()
return
balloon_alert_to_viewers("notifying clients...")
playsound(src, 'sound/machines/terminal_alert.ogg', 100, vary = TRUE)
user.visible_message(
span_danger("[user] begins depowering the server!"),
span_notice("You start disconnecting clients..."),
span_danger("You hear frantic keying on a keyboard."),
)
SEND_SIGNAL(src, COMSIG_BITRUNNER_SHUTDOWN_ALERT, user)
if(!do_after(user, 20 SECONDS, src))
return
reset()
/// Links all the loading processes together - does validation for booting a map
/obj/machinery/quantum_server/proc/cold_boot_map(map_key)
if(!is_ready)
return FALSE
if(isnull(map_key))
balloon_alert_to_viewers("no domain specified.")
return FALSE
if(generated_domain)
balloon_alert_to_viewers("stop the current domain first.")
return FALSE
if(length(avatar_connection_refs))
balloon_alert_to_viewers("all clients must disconnect!")
return FALSE
is_ready = FALSE
playsound(src, 'sound/machines/terminal_processing.ogg', 30, 2)
/// If any one of these fail, it reverts the entire process
if(!load_domain(map_key) || !load_map_items() || !load_mob_segments())
balloon_alert_to_viewers("initialization failed.")
scrub_vdom()
is_ready = TRUE
return FALSE
is_ready = TRUE
if(prob(clamp((threat * glitch_chance), 1, 10)))
setup_glitch()
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 30, vary = TRUE)
balloon_alert_to_viewers("domain loaded.")
generated_domain.start_time = world.time
points -= generated_domain.cost
update_use_power(ACTIVE_POWER_USE)
update_appearance()
return TRUE
/// Initializes a new domain if the given key is valid and the user has enough points
/obj/machinery/quantum_server/proc/load_domain(map_key)
for(var/datum/lazy_template/virtual_domain/available in SSbitrunning.all_domains)
if(map_key == available.key && points >= available.cost)
generated_domain = available
RegisterSignal(generated_domain, COMSIG_LAZY_TEMPLATE_LOADED, PROC_REF(on_template_loaded))
generated_domain.lazy_load()
return TRUE
return FALSE
/// Loads in necessary map items like hololadder spawns, caches, etc
/obj/machinery/quantum_server/proc/load_map_items()
var/turf/goal_turfs = list()
var/turf/cache_turfs = list()
var/turf/curiosity_turfs = list()
for(var/obj/effect/landmark/bitrunning/thing in GLOB.landmarks_list)
if(istype(thing, /obj/effect/landmark/bitrunning/hololadder_spawn))
exit_turfs += get_turf(thing)
qdel(thing) // i'm worried about multiple servers getting confused so lets clean em up
continue
if(istype(thing, /obj/effect/landmark/bitrunning/cache_goal_turf))
var/turf/tile = get_turf(thing)
goal_turfs += tile
RegisterSignal(tile, COMSIG_ATOM_ENTERED, PROC_REF(on_goal_turf_entered))
RegisterSignal(tile, COMSIG_ATOM_EXAMINE, PROC_REF(on_goal_turf_examined))
qdel(thing)
continue
if(istype(thing, /obj/effect/landmark/bitrunning/cache_spawn))
cache_turfs += get_turf(thing)
qdel(thing)
continue
if(istype(thing, /obj/effect/landmark/bitrunning/curiosity_spawn))
curiosity_turfs += get_turf(thing)
qdel(thing)
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)
qdel(thing)
if(!length(exit_turfs))
CRASH("Failed to find exit turfs on generated domain.")
if(!length(goal_turfs))
CRASH("Failed to find send turfs on generated domain.")
if(!attempt_spawn_cache(cache_turfs))
return FALSE
while(length(curiosity_turfs))
var/turf/picked_turf = attempt_spawn_curiosity(curiosity_turfs)
if(!picked_turf)
break
generated_domain.secondary_loot_generated += 1
curiosity_turfs -= picked_turf
return TRUE
/// Stops the current virtual domain and disconnects all users
/obj/machinery/quantum_server/proc/reset(fast = FALSE)
is_ready = FALSE
sever_connections()
if(!fast)
notify_spawned_threats()
addtimer(CALLBACK(src, PROC_REF(scrub_vdom)), 15 SECONDS, TIMER_UNIQUE|TIMER_STOPPABLE)
else
scrub_vdom() // used in unit testing, no need to wait for callbacks
addtimer(CALLBACK(src, PROC_REF(cool_off)), ROUND_UP(server_cooldown_time * capacitor_coefficient), TIMER_UNIQUE|TIMER_STOPPABLE|TIMER_DELETE_ME)
update_appearance()
update_use_power(IDLE_POWER_USE)
domain_randomized = FALSE
retries_spent = 0
/// Tries to clean up everything in the domain
/obj/machinery/quantum_server/proc/scrub_vdom()
sever_connections() /// just in case someone's connected
SEND_SIGNAL(src, COMSIG_BITRUNNER_DOMAIN_SCRUBBED) // avatar cleanup just in case
if(length(generated_domain.reservations))
var/datum/turf_reservation/res = generated_domain.reservations[1]
res.Release()
var/list/creatures = spawned_threat_refs + mutation_candidate_refs
for(var/datum/weakref/creature_ref as anything in creatures)
var/mob/living/creature = creature_ref?.resolve()
if(isnull(creature))
continue
creature.dust(just_ash = TRUE, force = TRUE) // sometimes mobs just don't die
generated_domain.secondary_loot_generated = 0
avatar_connection_refs.Cut()
exit_turfs = list()
generated_domain = null
mutation_candidate_refs.Cut()
spawned_threat_refs.Cut()