[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>
This commit is contained in:
SkyratBot
2024-03-22 17:17:51 +01:00
committed by GitHub
parent 0c051e6102
commit 0a693b9dfa
36 changed files with 327 additions and 125 deletions

View File

@@ -63,5 +63,5 @@
/obj/machinery/byteforge/proc/start_to_spawn(obj/cache)
flicker()
addtimer(CALLBACK(src, PROC_REF(spawn_cache), cache), 1 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE)
addtimer(CALLBACK(src, PROC_REF(spawn_cache), cache), 1 SECONDS)

View File

@@ -22,6 +22,11 @@
name = "Bitrunning crate spawn"
icon_state = "crate"
/// Where you want secondary objectives to spawn
/obj/effect/landmark/bitrunning/curiosity_spawn
name = "Bitrunning curiosity spawn"
icon_state = "crate"
///Swaps the locations of an encrypted crate in the area with another randomly selected crate.
///Randomizes names, so you have to inspect crates manually.
/obj/effect/landmark/bitrunning/crate_replacer

View File

@@ -0,0 +1,53 @@
/obj/item/storage/lockbox/bitrunning
name = "base class curiosity"
desc = "Talk to a coder."
req_access = list(ACCESS_INACCESSIBLE)
icon_state = "bitrunning+l"
inhand_icon_state = "bitrunning"
base_icon_state = "bitrunning"
icon_locked = "bitrunning+l"
icon_closed = "bitrunning"
icon_broken = "bitrunning+b"
/obj/item/storage/lockbox/bitrunning/encrypted
name = "encrypted curiosity"
desc = "Needs to be decrypted at the safehouse to be opened."
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
/// Path for the loot we are assigned
var/loot_path
/obj/item/storage/lockbox/bitrunning/encrypted/emag_act(mob/user, obj/item/card/emag/emag_card)
return FALSE
/obj/item/storage/lockbox/bitrunning/decrypted
name = "decrypted curiosity"
desc = "Compiled from the virtual domain. An extra reward of a successful bitrunner."
/// What virtual domain did we come from.
var/datum/lazy_template/virtual_domain/source_domain
/obj/item/storage/lockbox/bitrunning/decrypted/Initialize(
mapload,
datum/lazy_template/virtual_domain/completed_domain,
)
if(isnull(completed_domain))
log_runtime("Decrypted curiosity was created with no source domain.")
return INITIALIZE_HINT_QDEL
if(!istype(completed_domain, /datum/lazy_template/virtual_domain)) // Check if this is a proper virtual domain before doing anything with it
log_runtime("Decrypted curiosity was created with an invalid source domain. [completed_domain.name] ([completed_domain.type]).")
return INITIALIZE_HINT_QDEL
source_domain = completed_domain
. = ..()
atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
atom_storage.max_slots = 1
atom_storage.max_total_storage = 3
atom_storage.locked = STORAGE_NOT_LOCKED
icon_state = icon_closed
playsound(src, 'sound/magic/blink.ogg', 50, TRUE)
/obj/item/storage/lockbox/bitrunning/decrypted/PopulateContents()
var/choice = SSbitrunning.pick_secondary_loot(source_domain)
new choice(src)

View File

@@ -42,11 +42,11 @@
if(isnull(completed_domain))
return
PopulateContents(completed_domain.reward_points, completed_domain.extra_loot, rewards_multiplier)
PopulateContents(completed_domain.reward_points, completed_domain.completion_loot, rewards_multiplier)
/obj/structure/closet/crate/secure/bitrunning/decrypted/PopulateContents(reward_points, list/extra_loot, rewards_multiplier)
/obj/structure/closet/crate/secure/bitrunning/decrypted/PopulateContents(reward_points, list/completion_loot, rewards_multiplier)
. = ..()
spawn_loot(extra_loot)
spawn_loot(completion_loot)
new /obj/item/stack/ore/iron(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_IRON))
new /obj/item/stack/ore/glass(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_GLASS))
@@ -70,16 +70,16 @@
var/random_sum = (rand() + 0.5) * base
return ROUND_UP(random_sum * ore_multiplier)
/// Handles spawning extra loot. This tries to handle bad flat and assoc lists
/obj/structure/closet/crate/secure/bitrunning/decrypted/proc/spawn_loot(list/extra_loot)
for(var/path in extra_loot)
/// Handles spawning completion loot. This tries to handle bad flat and assoc lists
/obj/structure/closet/crate/secure/bitrunning/decrypted/proc/spawn_loot(list/completion_loot)
for(var/path in completion_loot)
if(!ispath(path))
return FALSE
if(isnull(extra_loot[path]))
if(isnull(completion_loot[path]))
return FALSE
for(var/i in 1 to extra_loot[path])
for(var/i in 1 to completion_loot[path])
new path(src)
return TRUE

View File

@@ -56,7 +56,7 @@
if(isnull(server))
return data
data["available_domains"] = server.get_available_domains()
data["available_domains"] = SSbitrunning.get_available_domains(server.scanner_tier, server.points)
data["avatars"] = server.get_avatar_data()
return data