mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-29 08:08:49 +01:00
[MIRROR] Feature: bitrunner, a new supply role (READY) [MDB IGNORE] (#23865)
* Feature: bitrunner, a new supply role (READY) * Delete bepis.dm * Conflicts * Update dynamic_rulesets_midround.dm * Fixing this invalid icon file path It was trying to use the aesthetics one * Bepis is dead * New digi sprites courtesy of CandleJaxx!! Now in the correct branch! * Fixing merge conflict * bitrunning hotfixes [NO GBP] * Modular health adjustments * Revert "Modular health adjustments" This reverts commit 0ff3c48d398f6c1aac51cdf8fecaf869491bbc86. * Modular health adjustments Only this one should be necessary * The screenshot test * Bitrunner den for voidraptor (FOR #23865) (#23891) * no shower in sight * lets bitrunners actually get to their room and spawn there * New digi sprites courtesy of CandleJaxx!! * Revert "New digi sprites courtesy of CandleJaxx!!" This reverts commit eea9f47de256dd407c78450bc8f2a09b814f93e9. --------- Co-authored-by: Giz <13398309+vinylspiders@users.noreply.github.com> * Removes bitrunning unit tests (#78607) ## About The Pull Request Removes the fraction of unit tests I thought would be safe. Not thrilled that I have to exclude ALL unit tests now, but hey. The issue is that atmos attempts to process on a turf which hasn't initialized yet. ## Why It's Good For The Game Other PRs can pass checks now ## Changelog N/A * Update birdshot.dmm * Tweaks the BEPIS category of the bitrunning order console * Adds back the flashdark that we had skyrat edited in * Update tgstation.dme * Fixes Voidraptor bitrunning den not being connected to the powergrid --------- Co-authored-by: Jeremiah <42397676+jlsnow301@users.noreply.github.com> Co-authored-by: Giz <13398309+vinylspiders@users.noreply.github.com> Co-authored-by: Paxilmaniac <82386923+Paxilmaniac@users.noreply.github.com> Co-authored-by: Profakos <profakos@gmail.com> Co-authored-by: GoldenAlpharex <jerego1234@hotmail.com>
This commit is contained in:
co-authored by
Jeremiah
Giz
Paxilmaniac
Profakos
GoldenAlpharex
parent
ebebe387d9
commit
964fc99589
@@ -0,0 +1,86 @@
|
||||
#define CREDIT_TYPE_BITRUNNING "np"
|
||||
|
||||
/obj/machinery/computer/order_console/bitrunning
|
||||
name = "bitrunning supplies order console"
|
||||
desc = "NexaCache(tm)! Dubiously authentic gear for the digital daredevil."
|
||||
icon = 'icons/obj/machines/bitrunning.dmi'
|
||||
icon_state = "vendor"
|
||||
icon_keyboard = null
|
||||
icon_screen = null
|
||||
circuit = /obj/item/circuitboard/computer/order_console/bitrunning
|
||||
cooldown_time = 10 SECONDS
|
||||
cargo_cost_multiplier = 0.65
|
||||
express_cost_multiplier = 1
|
||||
purchase_tooltip = @{"Your purchases will arrive at cargo,
|
||||
and hopefully get delivered by them.
|
||||
35% cheaper than express delivery."}
|
||||
express_tooltip = @{"Sends your purchases instantly."}
|
||||
credit_type = CREDIT_TYPE_BITRUNNING
|
||||
|
||||
order_categories = list(
|
||||
CATEGORY_BITRUNNING_FLAIR,
|
||||
CATEGORY_BITRUNNING_TECH,
|
||||
CATEGORY_BEPIS,
|
||||
)
|
||||
blackbox_key = "bitrunning"
|
||||
|
||||
/obj/machinery/computer/order_console/bitrunning/subtract_points(final_cost, obj/item/card/id/card)
|
||||
if(final_cost <= card.registered_account.bitrunning_points)
|
||||
card.registered_account.bitrunning_points -= final_cost
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/computer/order_console/bitrunning/order_groceries(mob/living/purchaser, obj/item/card/id/card, list/groceries)
|
||||
var/list/things_to_order = list()
|
||||
for(var/datum/orderable_item/item as anything in groceries)
|
||||
things_to_order[item.item_path] = groceries[item]
|
||||
|
||||
var/datum/supply_pack/bitrunning/pack = new(
|
||||
purchaser = purchaser, \
|
||||
cost = get_total_cost(), \
|
||||
contains = things_to_order,
|
||||
)
|
||||
|
||||
var/datum/supply_order/new_order = new(
|
||||
pack = pack,
|
||||
orderer = purchaser,
|
||||
orderer_rank = "Bitrunning Vendor",
|
||||
orderer_ckey = purchaser.ckey,
|
||||
reason = "",
|
||||
paying_account = card.registered_account,
|
||||
department_destination = null,
|
||||
coupon = null,
|
||||
charge_on_purchase = FALSE,
|
||||
manifest_can_fail = FALSE,
|
||||
cost_type = credit_type,
|
||||
can_be_cancelled = FALSE,
|
||||
)
|
||||
say("Thank you for your purchase! It will arrive on the next cargo shuttle!")
|
||||
radio.talk_into(src, "A bitrunner has ordered equipment which will arrive on the cargo shuttle! Please make sure it gets to them as soon as possible!", radio_channel)
|
||||
SSshuttle.shopping_list += new_order
|
||||
|
||||
/obj/machinery/computer/order_console/bitrunning/retrieve_points(obj/item/card/id/id_card)
|
||||
return round(id_card.registered_account.bitrunning_points)
|
||||
|
||||
/obj/machinery/computer/order_console/bitrunning/ui_act(action, params)
|
||||
. = ..()
|
||||
if(!.)
|
||||
flick("vendor_off", src)
|
||||
|
||||
/obj/machinery/computer/order_console/bitrunning/update_icon_state()
|
||||
icon_state = "[initial(icon_state)][powered() ? null : "_off"]"
|
||||
return ..()
|
||||
|
||||
/datum/supply_pack/bitrunning
|
||||
name = "bitrunning order"
|
||||
hidden = TRUE
|
||||
crate_name = "bitrunning delivery crate"
|
||||
access = list(ACCESS_BIT_DEN)
|
||||
|
||||
/datum/supply_pack/bitrunning/New(purchaser, cost, list/contains)
|
||||
. = ..()
|
||||
name = "[purchaser]'s Bitrunning Order"
|
||||
src.cost = cost
|
||||
src.contains = contains
|
||||
|
||||
#undef CREDIT_TYPE_BITRUNNING
|
||||
@@ -0,0 +1,9 @@
|
||||
/obj/item/clothing/glasses/sunglasses/oval
|
||||
name = "oval sunglasses"
|
||||
desc = "Vintage wrap around sunglasses. Provides a little protection."
|
||||
icon_state = "jensenshades"
|
||||
|
||||
/obj/item/clothing/suit/jacket/trenchcoat
|
||||
name = "trenchcoat"
|
||||
desc = "A long, black trenchcoat. Makes you feel like you're the one, but you're not."
|
||||
icon_state = "trenchcoat"
|
||||
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* Bitrunning tech disks which let you load items or programs into the vdom on first avatar generation.
|
||||
* For the record: Balance shouldn't be a primary concern.
|
||||
* You can make the custom cheese spells you've always wanted.
|
||||
* Just make it fun and engaging, it's PvE content.
|
||||
*/
|
||||
/obj/item/bitrunning_disk
|
||||
name = "generic bitrunning program"
|
||||
desc = "A disk containing source code."
|
||||
icon = 'icons/obj/assemblies/module.dmi'
|
||||
base_icon_state = "datadisk"
|
||||
icon_state = "datadisk0"
|
||||
/// Name of the choice made
|
||||
var/choice_made
|
||||
|
||||
/obj/item/bitrunning_disk/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
icon_state = "[base_icon_state][rand(0, 7)]"
|
||||
update_icon()
|
||||
RegisterSignal(src, COMSIG_ATOM_EXAMINE, PROC_REF(on_examined))
|
||||
|
||||
/obj/item/bitrunning_disk/proc/on_examined(datum/source, mob/examiner, list/examine_text)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
examine_text += span_infoplain("This disk must be carried on your person into a netpod to be used.")
|
||||
|
||||
if(isnull(choice_made))
|
||||
examine_text += span_notice("To make a selection, toggle the disk in hand.")
|
||||
return
|
||||
|
||||
examine_text += span_info("It has been used to select: <b>[choice_made]</b>.")
|
||||
examine_text += span_notice("It cannot make another selection.")
|
||||
|
||||
/obj/item/bitrunning_disk/ability
|
||||
desc = "A disk containing source code. It can be used to preload abilities into the virtual domain."
|
||||
/// The selected ability that this grants
|
||||
var/datum/action/granted_action
|
||||
/// The list of actions that this can grant
|
||||
var/list/datum/action/selectable_actions = list()
|
||||
|
||||
/obj/item/bitrunning_disk/ability/attack_self(mob/user, modifiers)
|
||||
. = ..()
|
||||
|
||||
if(choice_made)
|
||||
return
|
||||
|
||||
var/names = list()
|
||||
for(var/datum/action/thing as anything in selectable_actions)
|
||||
names += initial(thing.name)
|
||||
|
||||
var/choice = tgui_input_list(user, message = "Select an ability", title = "Bitrunning Program", items = names)
|
||||
if(isnull(choice))
|
||||
return
|
||||
|
||||
for(var/datum/action/thing as anything in selectable_actions)
|
||||
if(initial(thing.name) == choice)
|
||||
granted_action = thing
|
||||
|
||||
if(isnull(granted_action))
|
||||
return
|
||||
|
||||
balloon_alert(user, "selected")
|
||||
playsound(user, 'sound/items/click.ogg', 50, TRUE)
|
||||
choice_made = choice
|
||||
|
||||
/// Tier 1 programs. Simple, funny, or helpful.
|
||||
/obj/item/bitrunning_disk/ability/tier1
|
||||
name = "bitrunning program: basic"
|
||||
selectable_actions = list(
|
||||
/datum/action/cooldown/spell/conjure/cheese,
|
||||
/datum/action/cooldown/spell/basic_heal,
|
||||
)
|
||||
|
||||
/// Tier 2 programs. More complex, powerful, or useful.
|
||||
/obj/item/bitrunning_disk/ability/tier2
|
||||
name = "bitrunning program: complex"
|
||||
selectable_actions = list(
|
||||
/datum/action/cooldown/spell/pointed/projectile/fireball,
|
||||
/datum/action/cooldown/spell/pointed/projectile/lightningbolt,
|
||||
/datum/action/cooldown/spell/forcewall,
|
||||
)
|
||||
|
||||
/// Tier 3 abilities. Very powerful, game breaking.
|
||||
/obj/item/bitrunning_disk/ability/tier3
|
||||
name = "bitrunning program: elite"
|
||||
selectable_actions = list(
|
||||
/datum/action/cooldown/spell/shapeshift/dragon,
|
||||
/datum/action/cooldown/spell/shapeshift/polar_bear,
|
||||
)
|
||||
|
||||
/obj/item/bitrunning_disk/item
|
||||
desc = "A disk containing source code. It can be used to preload items into the virtual domain."
|
||||
/// The selected item that this grants
|
||||
var/obj/granted_item
|
||||
/// The list of actions that this can grant
|
||||
var/list/obj/selectable_items = list()
|
||||
|
||||
/obj/item/bitrunning_disk/item/attack_self(mob/user, modifiers)
|
||||
. = ..()
|
||||
|
||||
if(choice_made)
|
||||
return
|
||||
|
||||
var/names = list()
|
||||
for(var/obj/thing as anything in selectable_items)
|
||||
names += initial(thing.name)
|
||||
|
||||
var/choice = tgui_input_list(user, message = "Select an ability", title = "Bitrunning Program", items = names)
|
||||
if(isnull(choice))
|
||||
return
|
||||
|
||||
for(var/obj/thing as anything in selectable_items)
|
||||
if(initial(thing.name) == choice)
|
||||
granted_item = thing
|
||||
|
||||
balloon_alert(user, "selected")
|
||||
playsound(user, 'sound/items/click.ogg', 50, TRUE)
|
||||
choice_made = choice
|
||||
|
||||
/// Tier 1 items. Simple, funny, or helpful.
|
||||
/obj/item/bitrunning_disk/item/tier1
|
||||
name = "bitrunning gear: simple"
|
||||
selectable_items = list(
|
||||
/obj/item/pizzabox/infinite,
|
||||
/obj/item/gun/medbeam,
|
||||
/obj/item/grenade/c4,
|
||||
)
|
||||
|
||||
/// Tier 2 items. More complex, powerful, or useful.
|
||||
/obj/item/bitrunning_disk/item/tier2
|
||||
name = "bitrunning gear: complex"
|
||||
selectable_items = list(
|
||||
/obj/item/chainsaw,
|
||||
/obj/item/gun/ballistic/automatic/pistol,
|
||||
/obj/item/melee/energy/blade/hardlight,
|
||||
)
|
||||
|
||||
/// Tier 3 items. Very powerful, game breaking.
|
||||
/obj/item/bitrunning_disk/item/tier3
|
||||
name = "bitrunning gear: advanced"
|
||||
selectable_items = list(
|
||||
/obj/item/gun/energy/tesla_cannon,
|
||||
/obj/item/dualsaber/green,
|
||||
/obj/item/melee/beesword,
|
||||
)
|
||||
@@ -0,0 +1,51 @@
|
||||
/obj/structure/hololadder
|
||||
name = "hololadder"
|
||||
|
||||
anchored = TRUE
|
||||
desc = "An abstract representation of the means to disconnect from the virtual domain."
|
||||
icon = 'icons/obj/structures.dmi'
|
||||
icon_state = "ladder11"
|
||||
obj_flags = BLOCK_Z_OUT_DOWN
|
||||
/// Time req to disconnect properly
|
||||
var/travel_time = 3 SECONDS
|
||||
|
||||
/obj/structure/hololadder/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
RegisterSignal(loc, COMSIG_ATOM_ENTERED, PROC_REF(on_enter))
|
||||
|
||||
/obj/structure/hololadder/attack_hand(mob/user, list/modifiers)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
if(!in_range(src, user) || DOING_INTERACTION(user, DOAFTER_SOURCE_CLIMBING_LADDER))
|
||||
return
|
||||
|
||||
disconnect(user)
|
||||
|
||||
/// If there's a pilot ref- send the disconnect signal
|
||||
/obj/structure/hololadder/proc/disconnect(mob/user)
|
||||
if(isnull(user.mind))
|
||||
return
|
||||
|
||||
if(!HAS_TRAIT(user, TRAIT_TEMPORARY_BODY))
|
||||
balloon_alert(user, "no connection detected.")
|
||||
return
|
||||
|
||||
balloon_alert(user, "disconnecting...")
|
||||
if(do_after(user, travel_time, src))
|
||||
SEND_SIGNAL(user, COMSIG_BITRUNNER_SAFE_DISCONNECT)
|
||||
|
||||
/// Helper for times when you dont have hands (gondola??)
|
||||
/obj/structure/hololadder/proc/on_enter(datum/source, atom/movable/arrived, turf/old_loc)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!isliving(arrived))
|
||||
return
|
||||
|
||||
var/mob/living/user = arrived
|
||||
if(isnull(user.mind))
|
||||
return
|
||||
|
||||
INVOKE_ASYNC(src, PROC_REF(disconnect), user)
|
||||
@@ -0,0 +1,33 @@
|
||||
/obj/item/bitrunning_host_monitor
|
||||
name = "host monitor"
|
||||
|
||||
custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT * 2)
|
||||
desc = "A complex medical device that, when attached to an avatar's data stream, can detect the user of their host's health."
|
||||
flags_1 = CONDUCT_1
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "gps-b"
|
||||
inhand_icon_state = "electronic"
|
||||
item_flags = NOBLUDGEON
|
||||
lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi'
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
throw_range = 7
|
||||
throw_speed = 3
|
||||
throwforce = 3
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
worn_icon_state = "electronic"
|
||||
|
||||
/obj/item/bitrunning_host_monitor/attack_self(mob/user, modifiers)
|
||||
. = ..()
|
||||
|
||||
var/datum/component/avatar_connection/connection = user.GetComponent(/datum/component/avatar_connection)
|
||||
if(isnull(connection))
|
||||
balloon_alert(user, "data not recognized")
|
||||
return
|
||||
|
||||
var/mob/living/pilot = connection.old_body_ref?.resolve()
|
||||
if(isnull(pilot))
|
||||
balloon_alert(user, "host not recognized")
|
||||
return
|
||||
|
||||
to_chat(user, span_notice("Current host health: [pilot.health / pilot.maxHealth * 100]%"))
|
||||
@@ -0,0 +1,70 @@
|
||||
/obj/effect/landmark/bitrunning
|
||||
name = "Generic bitrunning effect"
|
||||
icon = 'icons/effects/bitrunning.dmi'
|
||||
icon_state = "crate"
|
||||
|
||||
/// In case you want to gate the crate behind a special condition.
|
||||
/obj/effect/landmark/bitrunning/loot_signal
|
||||
name = "Mysterious aura"
|
||||
/// The amount required to spawn a crate
|
||||
var/points_goal = 10
|
||||
/// A special condition limits this from spawning a crate
|
||||
var/points_received = 0
|
||||
/// Finished the special condition
|
||||
var/revealed = FALSE
|
||||
|
||||
/obj/effect/landmark/bitrunning/loot_signal/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
RegisterSignal(src, COMSIG_BITRUNNER_GOAL_POINT, PROC_REF(on_add_point))
|
||||
|
||||
/// Listens for points to be added which will eventually spawn a crate.
|
||||
/obj/effect/landmark/bitrunning/loot_signal/proc/on_add_point(datum/source, points_to_add)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(revealed)
|
||||
return
|
||||
|
||||
points_received += points_to_add
|
||||
|
||||
if(points_received < points_goal)
|
||||
return
|
||||
|
||||
reveal()
|
||||
|
||||
/// Spawns the crate with some effects
|
||||
/obj/effect/landmark/bitrunning/loot_signal/proc/reveal()
|
||||
playsound(src, 'sound/magic/blink.ogg', 50, TRUE)
|
||||
|
||||
var/turf/tile = get_turf(src)
|
||||
var/obj/structure/closet/crate/secure/bitrunning/encrypted/loot = new(tile)
|
||||
var/datum/effect_system/spark_spread/quantum/sparks = new(tile)
|
||||
sparks.set_up(5, 1, get_turf(loot))
|
||||
sparks.start()
|
||||
|
||||
qdel(src)
|
||||
|
||||
/// Where the crates get ported to station
|
||||
/obj/effect/landmark/bitrunning/station_reward_spawn
|
||||
name = "Bitrunning rewards spawn"
|
||||
icon_state = "station"
|
||||
|
||||
/// Where the exit hololadder spawns
|
||||
/obj/effect/landmark/bitrunning/hololadder_spawn
|
||||
name = "Bitrunning hololadder spawn"
|
||||
icon_state = "hololadder"
|
||||
|
||||
/// Where the crates need to be taken
|
||||
/obj/effect/landmark/bitrunning/cache_goal_turf
|
||||
name = "Bitrunning goal turf"
|
||||
icon_state = "goal"
|
||||
|
||||
/// Where you want the crate to spawn
|
||||
/obj/effect/landmark/bitrunning/cache_spawn
|
||||
name = "Bitrunning crate spawn"
|
||||
icon_state = "spawn"
|
||||
|
||||
/// Where the safehouse will spawn
|
||||
/obj/effect/landmark/bitrunning/safehouse_spawn
|
||||
name = "Bitrunning safehouse spawn"
|
||||
icon_state = "safehouse"
|
||||
@@ -0,0 +1,91 @@
|
||||
#define ORE_MULTIPLIER_IRON 3
|
||||
#define ORE_MULTIPLIER_GLASS 2
|
||||
#define ORE_MULTIPLIER_PLASMA 1
|
||||
#define ORE_MULTIPLIER_SILVER 0.7
|
||||
#define ORE_MULTIPLIER_GOLD 0.6
|
||||
#define ORE_MULTIPLIER_TITANIUM 0.5
|
||||
#define ORE_MULTIPLIER_URANIUM 0.4
|
||||
#define ORE_MULTIPLIER_DIAMOND 0.3
|
||||
#define ORE_MULTIPLIER_BLUESPACE_CRYSTAL 0.2
|
||||
|
||||
/obj/structure/closet/crate/secure/bitrunning // Base class. Do not spawn this.
|
||||
name = "base class cache"
|
||||
desc = "Talk to a coder."
|
||||
|
||||
/// The virtual domain - side of the bitrunning crate. Deliver to the send location.
|
||||
/obj/structure/closet/crate/secure/bitrunning/encrypted
|
||||
name = "encrypted cache"
|
||||
desc = "Needs decrypted at the safehouse to be opened."
|
||||
locked = TRUE
|
||||
|
||||
/obj/structure/closet/crate/secure/bitrunning/encrypted/can_unlock(mob/living/user, obj/item/card/id/player_id, obj/item/card/id/registered_id)
|
||||
return FALSE
|
||||
|
||||
/// The bitrunner den - side of the bitrunning crate. Appears in the receive location.
|
||||
/obj/structure/closet/crate/secure/bitrunning/decrypted
|
||||
name = "decrypted cache"
|
||||
desc = "Compiled from the virtual domain. The reward of a successful bitrunner."
|
||||
locked = FALSE
|
||||
|
||||
/obj/structure/closet/crate/secure/bitrunning/decrypted/Initialize(
|
||||
mapload,
|
||||
datum/lazy_template/virtual_domain/completed_domain,
|
||||
rewards_multiplier = 1,
|
||||
)
|
||||
. = ..()
|
||||
playsound(src, 'sound/magic/blink.ogg', 50, TRUE)
|
||||
|
||||
if(isnull(completed_domain))
|
||||
return
|
||||
|
||||
PopulateContents(completed_domain.reward_points, completed_domain.extra_loot, rewards_multiplier)
|
||||
|
||||
/obj/structure/closet/crate/secure/bitrunning/decrypted/PopulateContents(reward_points, list/extra_loot, rewards_multiplier)
|
||||
. = ..()
|
||||
spawn_loot(extra_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))
|
||||
|
||||
if(reward_points > 1)
|
||||
new /obj/item/stack/ore/silver(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_SILVER))
|
||||
new /obj/item/stack/ore/titanium(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_TITANIUM))
|
||||
|
||||
if(reward_points > 2)
|
||||
new /obj/item/stack/ore/plasma(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_PLASMA))
|
||||
new /obj/item/stack/ore/gold(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_GOLD))
|
||||
new /obj/item/stack/ore/uranium(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_URANIUM))
|
||||
|
||||
if(reward_points > 3)
|
||||
new /obj/item/stack/ore/diamond(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_DIAMOND))
|
||||
new /obj/item/stack/ore/bluespace_crystal(src, calculate_loot(reward_points, rewards_multiplier, ORE_MULTIPLIER_BLUESPACE_CRYSTAL))
|
||||
|
||||
/// Handles generating random numbers & calculating loot totals
|
||||
/obj/structure/closet/crate/secure/bitrunning/decrypted/proc/calculate_loot(reward_points, rewards_multiplier, ore_multiplier)
|
||||
var/base = 1 * (rewards_multiplier + reward_points)
|
||||
var/random_sum = (rand() * 1.0 + 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)
|
||||
if(!ispath(path))
|
||||
continue
|
||||
|
||||
if(isnull(extra_loot[path]))
|
||||
return FALSE
|
||||
|
||||
for(var/i in 1 to extra_loot[path])
|
||||
new path(src)
|
||||
|
||||
return TRUE
|
||||
|
||||
#undef ORE_MULTIPLIER_IRON
|
||||
#undef ORE_MULTIPLIER_GLASS
|
||||
#undef ORE_MULTIPLIER_PLASMA
|
||||
#undef ORE_MULTIPLIER_SILVER
|
||||
#undef ORE_MULTIPLIER_GOLD
|
||||
#undef ORE_MULTIPLIER_TITANIUM
|
||||
#undef ORE_MULTIPLIER_URANIUM
|
||||
#undef ORE_MULTIPLIER_DIAMOND
|
||||
#undef ORE_MULTIPLIER_BLUESPACE_CRYSTAL
|
||||
@@ -0,0 +1,476 @@
|
||||
#define BASE_DISCONNECT_DAMAGE 40
|
||||
|
||||
/obj/machinery/netpod
|
||||
name = "netpod"
|
||||
|
||||
base_icon_state = "netpod"
|
||||
circuit = /obj/item/circuitboard/machine/netpod
|
||||
desc = "A link to the netverse. It has an assortment of cables to connect yourself to a virtual domain."
|
||||
icon = 'icons/obj/machines/bitrunning.dmi'
|
||||
icon_state = "netpod"
|
||||
max_integrity = 300
|
||||
obj_flags = BLOCKS_CONSTRUCTION
|
||||
state_open = TRUE
|
||||
/// Whether we have an ongoing connection
|
||||
var/connected = FALSE
|
||||
/// A player selected outfit by clicking the netpod
|
||||
var/datum/outfit/netsuit = /datum/outfit/job/bitrunner
|
||||
/// Holds this to see if it needs to generate a new one
|
||||
var/datum/weakref/avatar_ref
|
||||
/// The linked quantum server
|
||||
var/datum/weakref/server_ref
|
||||
/// The amount of brain damage done from force disconnects
|
||||
var/disconnect_damage
|
||||
/// Static list of outfits to select from
|
||||
var/list/cached_outfits = list()
|
||||
|
||||
/obj/machinery/netpod/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/netpod/LateInitialize()
|
||||
. = ..()
|
||||
|
||||
disconnect_damage = BASE_DISCONNECT_DAMAGE
|
||||
|
||||
RegisterSignals(src, list(
|
||||
COMSIG_QDELETING,
|
||||
COMSIG_MACHINERY_BROKEN,
|
||||
COMSIG_MACHINERY_POWER_LOST,
|
||||
),
|
||||
PROC_REF(on_broken),
|
||||
)
|
||||
RegisterSignal(src, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
|
||||
RegisterSignal(src, COMSIG_ATOM_TAKE_DAMAGE, PROC_REF(on_take_damage))
|
||||
|
||||
register_context()
|
||||
update_appearance()
|
||||
|
||||
/obj/machinery/netpod/Destroy()
|
||||
. = ..()
|
||||
cached_outfits.Cut()
|
||||
|
||||
/obj/machinery/netpod/add_context(atom/source, list/context, obj/item/held_item, mob/user)
|
||||
. = ..()
|
||||
|
||||
if(isnull(held_item))
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Select Outfit"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
if(istype(held_item, /obj/item/crowbar) && occupant)
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Pry Open"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
/obj/machinery/netpod/update_icon_state()
|
||||
if(!is_operational)
|
||||
icon_state = base_icon_state
|
||||
return ..()
|
||||
|
||||
if(state_open)
|
||||
icon_state = base_icon_state + "_open_active"
|
||||
return ..()
|
||||
|
||||
if(panel_open)
|
||||
icon_state = base_icon_state + "_panel"
|
||||
return ..()
|
||||
|
||||
icon_state = base_icon_state + "_closed"
|
||||
if(occupant)
|
||||
icon_state += "_active"
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/netpod/MouseDrop_T(mob/target, mob/user)
|
||||
var/mob/living/carbon/player = user
|
||||
if(!iscarbon(player))
|
||||
return
|
||||
|
||||
if((HAS_TRAIT(player, TRAIT_UI_BLOCKED) && !player.resting) || !Adjacent(player) || !player.Adjacent(target) || !ISADVANCEDTOOLUSER(player) || !is_operational)
|
||||
return
|
||||
|
||||
close_machine(target)
|
||||
|
||||
/obj/machinery/netpod/crowbar_act(mob/living/user, obj/item/tool)
|
||||
if(user.combat_mode)
|
||||
attack_hand(user)
|
||||
return TOOL_ACT_TOOLTYPE_SUCCESS
|
||||
|
||||
if(default_pry_open(tool, user) || default_deconstruction_crowbar(tool))
|
||||
return TOOL_ACT_TOOLTYPE_SUCCESS
|
||||
|
||||
/obj/machinery/netpod/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
if(occupant)
|
||||
balloon_alert(user, "in use!")
|
||||
return TOOL_ACT_TOOLTYPE_SUCCESS
|
||||
|
||||
if(state_open)
|
||||
balloon_alert(user, "close first.")
|
||||
return TOOL_ACT_TOOLTYPE_SUCCESS
|
||||
|
||||
if(default_deconstruction_screwdriver(user, "[base_icon_state]_panel", "[base_icon_state]_closed", tool))
|
||||
update_appearance() // sometimes icon doesnt properly update during flick()
|
||||
ui_close(user)
|
||||
return TOOL_ACT_TOOLTYPE_SUCCESS
|
||||
|
||||
/obj/machinery/netpod/attack_hand(mob/living/user, list/modifiers)
|
||||
. = ..()
|
||||
if(!state_open && user == occupant)
|
||||
container_resist_act(user)
|
||||
|
||||
/obj/machinery/netpod/Exited(atom/movable/gone, direction)
|
||||
. = ..()
|
||||
if(!state_open && gone == occupant)
|
||||
container_resist_act(gone)
|
||||
|
||||
/obj/machinery/netpod/Exited(atom/movable/gone, direction)
|
||||
. = ..()
|
||||
if(!state_open && gone == occupant)
|
||||
container_resist_act(gone)
|
||||
|
||||
/obj/machinery/netpod/relaymove(mob/living/user, direction)
|
||||
if(!state_open)
|
||||
container_resist_act(user)
|
||||
|
||||
/obj/machinery/netpod/container_resist_act(mob/living/user)
|
||||
user.visible_message(span_notice("[occupant] emerges from [src]!"),
|
||||
span_notice("You climb out of [src]!"),
|
||||
span_notice("With a hiss, you hear a machine opening."))
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/netpod/open_machine(drop = TRUE, density_to_set = FALSE)
|
||||
unprotect_and_signal()
|
||||
playsound(src, 'sound/machines/tramopen.ogg', 60, TRUE, frequency = 65000)
|
||||
flick("[base_icon_state]_opening", src)
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/netpod/close_machine(mob/user, density_to_set = TRUE)
|
||||
if(!state_open || panel_open || !is_operational || !iscarbon(user))
|
||||
return
|
||||
|
||||
playsound(src, 'sound/machines/tramclose.ogg', 60, TRUE, frequency = 65000)
|
||||
flick("[base_icon_state]_closing", src)
|
||||
..()
|
||||
|
||||
if(!iscarbon(occupant))
|
||||
open_machine()
|
||||
return
|
||||
|
||||
enter_matrix()
|
||||
|
||||
/obj/machinery/netpod/default_pry_open(obj/item/crowbar, mob/living/pryer)
|
||||
if(isnull(occupant) || !iscarbon(occupant))
|
||||
if(!state_open)
|
||||
if(panel_open)
|
||||
return FALSE
|
||||
open_machine()
|
||||
else
|
||||
shut_pod()
|
||||
|
||||
return TRUE
|
||||
|
||||
pryer.visible_message(
|
||||
span_danger("[pryer] starts prying open [src]!"),
|
||||
span_notice("You start to pry open [src]."),
|
||||
span_notice("You hear loud prying on metal.")
|
||||
)
|
||||
playsound(src, 'sound/machines/airlock_alien_prying.ogg', 100, TRUE)
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_BITRUNNER_CROWBAR_ALERT, pryer)
|
||||
|
||||
if(do_after(pryer, 15 SECONDS, src))
|
||||
if(!state_open)
|
||||
open_machine()
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/netpod/ui_interact(mob/user, datum/tgui/ui)
|
||||
if(!is_operational)
|
||||
return
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "NetpodOutfits")
|
||||
ui.set_autoupdate(FALSE)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/netpod/ui_data()
|
||||
var/list/data = list()
|
||||
|
||||
data["netsuit"] = netsuit
|
||||
return data
|
||||
|
||||
/obj/machinery/netpod/ui_static_data()
|
||||
var/list/data = list()
|
||||
|
||||
if(!length(cached_outfits))
|
||||
cached_outfits += make_outfit_collection("Jobs", subtypesof(/datum/outfit/job))
|
||||
|
||||
data["collections"] = cached_outfits
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/netpod/ui_act(action, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return TRUE
|
||||
switch(action)
|
||||
if("select_outfit")
|
||||
var/datum/outfit/new_suit = resolve_outfit(params["outfit"])
|
||||
if(new_suit)
|
||||
netsuit = new_suit
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/// Disconnects the occupant after a certain time so they aren't just hibernating in netpod stasis. A balance change
|
||||
/obj/machinery/netpod/proc/auto_disconnect()
|
||||
if(isnull(occupant) || state_open || connected)
|
||||
return
|
||||
|
||||
if(!iscarbon(occupant))
|
||||
open_machine()
|
||||
return
|
||||
|
||||
var/mob/living/carbon/player = occupant
|
||||
|
||||
player.playsound_local(src, 'sound/effects/splash.ogg', 60, TRUE)
|
||||
to_chat(player, span_notice("The machine disconnects itself and begins to drain."))
|
||||
open_machine()
|
||||
|
||||
/**
|
||||
* ### Disconnect occupant
|
||||
* If this goes smoothly, should reconnect a receiving mind to the occupant's body
|
||||
*
|
||||
* This is the second stage of the process - if you want to disconn avatars start at the mind first
|
||||
*/
|
||||
/obj/machinery/netpod/proc/disconnect_occupant(forced = FALSE)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(isnull(occupant) || !isliving(occupant))
|
||||
return
|
||||
|
||||
connected = FALSE
|
||||
|
||||
if(mob_occupant.stat == DEAD)
|
||||
open_machine()
|
||||
return
|
||||
|
||||
mob_occupant.playsound_local(src, "sound/magic/blink.ogg", 25, TRUE)
|
||||
mob_occupant.set_static_vision(2 SECONDS)
|
||||
mob_occupant.set_temp_blindness(1 SECONDS)
|
||||
mob_occupant.Paralyze(2 SECONDS)
|
||||
|
||||
var/heal_time = 1
|
||||
if(mob_occupant.health < mob_occupant.maxHealth)
|
||||
heal_time = (mob_occupant.stat + 2) * 5
|
||||
addtimer(CALLBACK(src, PROC_REF(auto_disconnect)), heal_time SECONDS, TIMER_UNIQUE|TIMER_STOPPABLE|TIMER_DELETE_ME)
|
||||
|
||||
if(!forced)
|
||||
return
|
||||
|
||||
mob_occupant.flash_act(override_blindness_check = TRUE, visual = TRUE)
|
||||
mob_occupant.adjustOrganLoss(ORGAN_SLOT_BRAIN, disconnect_damage)
|
||||
INVOKE_ASYNC(mob_occupant, TYPE_PROC_REF(/mob/living, emote), "scream")
|
||||
to_chat(mob_occupant, span_danger("You've been forcefully disconnected from your avatar! Your thoughts feel scrambled!"))
|
||||
|
||||
/**
|
||||
* ### Enter Matrix
|
||||
* Finds any current avatars from this chair - or generates a new one
|
||||
*
|
||||
* New avatars cost 1 attempt, and this will eject if there's none left
|
||||
*
|
||||
* Connects the mind to the avatar if everything is ok
|
||||
*/
|
||||
/obj/machinery/netpod/proc/enter_matrix()
|
||||
var/mob/living/carbon/human/neo = occupant
|
||||
if(!ishuman(neo) || neo.stat == DEAD || isnull(neo.mind))
|
||||
balloon_alert(neo, "invalid occupant.")
|
||||
return
|
||||
|
||||
var/obj/machinery/quantum_server/server = find_server()
|
||||
if(isnull(server))
|
||||
balloon_alert(neo, "no server connected!")
|
||||
return
|
||||
|
||||
var/datum/lazy_template/virtual_domain/generated_domain = server.generated_domain
|
||||
if(isnull(generated_domain) || !server.is_ready)
|
||||
balloon_alert(neo, "nothing loaded!")
|
||||
return
|
||||
|
||||
var/mob/living/carbon/current_avatar = avatar_ref?.resolve()
|
||||
var/obj/structure/hololadder/wayout
|
||||
if(isnull(current_avatar) || current_avatar.stat != CONSCIOUS) // We need a viable avatar
|
||||
wayout = server.generate_hololadder()
|
||||
if(isnull(wayout))
|
||||
balloon_alert(neo, "out of bandwidth!")
|
||||
return
|
||||
current_avatar = server.generate_avatar(wayout, netsuit)
|
||||
avatar_ref = WEAKREF(current_avatar)
|
||||
server.stock_gear(current_avatar, neo)
|
||||
|
||||
neo.set_static_vision(3 SECONDS)
|
||||
protect_occupant(occupant)
|
||||
if(!do_after(neo, 2 SECONDS, src))
|
||||
return
|
||||
|
||||
// Very invalid
|
||||
if(QDELETED(neo) || QDELETED(current_avatar) || QDELETED(src))
|
||||
return
|
||||
|
||||
// Invalid
|
||||
if(occupant != neo || isnull(neo.mind) || neo.stat == DEAD || current_avatar.stat == DEAD)
|
||||
return
|
||||
|
||||
current_avatar.AddComponent( \
|
||||
/datum/component/avatar_connection, \
|
||||
old_mind = neo.mind, \
|
||||
old_body = neo, \
|
||||
server = server, \
|
||||
pod = src, \
|
||||
help_text = generated_domain.help_text, \
|
||||
)
|
||||
|
||||
connected = TRUE
|
||||
|
||||
/// Finds a server and sets the server_ref
|
||||
/obj/machinery/netpod/proc/find_server()
|
||||
var/obj/machinery/quantum_server/server = server_ref?.resolve()
|
||||
if(server)
|
||||
return server
|
||||
|
||||
server = locate(/obj/machinery/quantum_server) in oview(4, src)
|
||||
if(isnull(server))
|
||||
return
|
||||
|
||||
server_ref = WEAKREF(server)
|
||||
RegisterSignal(server, COMSIG_BITRUNNER_SERVER_UPGRADED, PROC_REF(on_server_upgraded), override = TRUE)
|
||||
RegisterSignal(server, COMSIG_BITRUNNER_DOMAIN_COMPLETE, PROC_REF(on_domain_complete), override = TRUE)
|
||||
|
||||
return server
|
||||
|
||||
/// Creates a list of outfit entries for the UI.
|
||||
/obj/machinery/netpod/proc/make_outfit_collection(identifier, list/outfit_list)
|
||||
var/list/collection = list(
|
||||
"name" = identifier,
|
||||
"outfits" = list()
|
||||
)
|
||||
|
||||
for(var/path as anything in outfit_list)
|
||||
var/datum/outfit/outfit = path
|
||||
|
||||
var/outfit_name = initial(outfit.name)
|
||||
if(findtext(outfit_name, "(") != 0 || findtext(outfit_name, "-") != 0) // No special variants please
|
||||
continue
|
||||
|
||||
collection["outfits"] += list(list("path" = path, "name" = outfit_name))
|
||||
|
||||
return list(collection)
|
||||
|
||||
/// Machine has been broken - handles signals and reverting sprites
|
||||
/obj/machinery/netpod/proc/on_broken(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!state_open)
|
||||
open_machine()
|
||||
|
||||
if(occupant)
|
||||
unprotect_and_signal()
|
||||
|
||||
/// Puts points on the current occupant's card account
|
||||
/obj/machinery/netpod/proc/on_domain_complete(datum/source, atom/movable/crate, reward_points)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(isnull(occupant) || !connected || !iscarbon(occupant))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/player = occupant
|
||||
|
||||
var/datum/bank_account/account = player.get_bank_account()
|
||||
if(isnull(account))
|
||||
return
|
||||
|
||||
account.bitrunning_points += reward_points * 100
|
||||
|
||||
/obj/machinery/netpod/proc/on_examine(datum/source, mob/examiner, list/examine_text)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
examine_text += span_infoplain("Drag yourself into the pod to engage the link.")
|
||||
examine_text += span_infoplain("It has limited resuscitation capabilities. Remaining in the pod can heal some injuries.")
|
||||
examine_text += span_infoplain("It has a security system that will alert the occupant if it is tampered with.")
|
||||
|
||||
if(isnull(occupant))
|
||||
examine_text += span_notice("It is currently unoccupied.")
|
||||
return
|
||||
|
||||
examine_text += span_notice("It is currently occupied by [occupant].")
|
||||
examine_text += span_notice("It can be pried open with a crowbar, but its safety mechanisms will alert the occupant.")
|
||||
|
||||
/// On unbuckle or break, make sure the occupant ref is null
|
||||
/obj/machinery/netpod/proc/unprotect_and_signal()
|
||||
unprotect_occupant(occupant)
|
||||
SEND_SIGNAL(src, COMSIG_BITRUNNER_SEVER_AVATAR, src)
|
||||
|
||||
/// When the server is upgraded, drops brain damage a little
|
||||
/obj/machinery/netpod/proc/on_server_upgraded(datum/source, servo_rating)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
disconnect_damage = BASE_DISCONNECT_DAMAGE * (1 - servo_rating)
|
||||
|
||||
/// Checks the integrity, alerts occupants
|
||||
/obj/machinery/netpod/proc/on_take_damage(datum/source, damage_amount)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(isnull(occupant))
|
||||
return
|
||||
|
||||
var/total = max_integrity - damage_amount
|
||||
var/integrity = (atom_integrity / total) * 100
|
||||
if(integrity > 50)
|
||||
return
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_BITRUNNER_NETPOD_INTEGRITY)
|
||||
|
||||
/// Puts the occupant in netpod stasis, basically short-circuiting environmental conditions
|
||||
/obj/machinery/netpod/proc/protect_occupant(mob/living/target)
|
||||
if(target != occupant)
|
||||
return
|
||||
|
||||
target.AddComponent(/datum/component/netpod_healing, \
|
||||
brute_heal = 4, \
|
||||
burn_heal = 4, \
|
||||
toxin_heal = 4, \
|
||||
clone_heal = 4, \
|
||||
blood_heal = 4, \
|
||||
)
|
||||
|
||||
target.playsound_local(src, 'sound/effects/submerge.ogg', 20, TRUE)
|
||||
target.extinguish_mob()
|
||||
update_use_power(ACTIVE_POWER_USE)
|
||||
|
||||
/// Removes the occupant from netpod stasis
|
||||
/obj/machinery/netpod/proc/unprotect_occupant(mob/living/target)
|
||||
var/datum/component/netpod_healing/healing_eff = target?.GetComponent(/datum/component/netpod_healing)
|
||||
if(healing_eff)
|
||||
qdel(healing_eff)
|
||||
|
||||
update_use_power(IDLE_POWER_USE)
|
||||
|
||||
/// Resolves a path to an outfit.
|
||||
/obj/machinery/netpod/proc/resolve_outfit(text)
|
||||
var/path = text2path(text)
|
||||
if(ispath(path, /datum/outfit))
|
||||
return path
|
||||
|
||||
/// Closes the machine without shoving in an occupant
|
||||
/obj/machinery/netpod/proc/shut_pod()
|
||||
state_open = FALSE
|
||||
playsound(src, 'sound/machines/tramclose.ogg', 60, TRUE, frequency = 65000)
|
||||
flick("[base_icon_state]_closing", src)
|
||||
set_density(TRUE)
|
||||
|
||||
update_appearance()
|
||||
|
||||
#undef BASE_DISCONNECT_DAMAGE
|
||||
@@ -0,0 +1,110 @@
|
||||
/obj/machinery/computer/quantum_console
|
||||
name = "quantum console"
|
||||
|
||||
circuit = /obj/item/circuitboard/computer/quantum_console
|
||||
icon_keyboard = "mining"
|
||||
icon_screen = "bitrunning"
|
||||
req_access = list(ACCESS_MINING)
|
||||
/// The server this console is connected to.
|
||||
var/datum/weakref/server_ref
|
||||
|
||||
/obj/machinery/computer/quantum_console/Initialize(mapload, obj/item/circuitboard/circuit)
|
||||
. = ..()
|
||||
desc = "Even in the distant year [CURRENT_STATION_YEAR], Nanostrasen is still using REST APIs. How grim."
|
||||
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/computer/quantum_console/LateInitialize()
|
||||
. = ..()
|
||||
|
||||
if(isnull(server_ref))
|
||||
find_server()
|
||||
|
||||
/obj/machinery/computer/quantum_console/ui_interact(mob/user, datum/tgui/ui)
|
||||
. = ..()
|
||||
|
||||
if(!is_operational)
|
||||
return
|
||||
|
||||
if(isnull(server_ref))
|
||||
find_server()
|
||||
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "QuantumConsole")
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/quantum_console/ui_data()
|
||||
var/list/data = list()
|
||||
|
||||
var/obj/machinery/quantum_server/server = find_server()
|
||||
if(isnull(server))
|
||||
data["connected"] = FALSE
|
||||
return data
|
||||
|
||||
data["connected"] = TRUE
|
||||
data["generated_domain"] = server.generated_domain?.key
|
||||
data["occupants"] = length(server.avatar_connection_refs)
|
||||
data["points"] = server.points
|
||||
data["randomized"] = server.domain_randomized
|
||||
data["ready"] = server.is_ready && server.is_operational
|
||||
data["scanner_tier"] = server.scanner_tier
|
||||
data["retries_left"] = length(server.exit_turfs) - server.retries_spent
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/quantum_console/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
var/obj/machinery/quantum_server/server = find_server()
|
||||
if(isnull(server))
|
||||
return data
|
||||
|
||||
data["available_domains"] = server.get_available_domains()
|
||||
data["avatars"] = server.get_avatar_data()
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/quantum_console/ui_act(action, list/params, datum/tgui/ui)
|
||||
. = ..()
|
||||
if(.)
|
||||
return TRUE
|
||||
|
||||
var/obj/machinery/quantum_server/server = find_server()
|
||||
if(isnull(server))
|
||||
return FALSE
|
||||
|
||||
switch(action)
|
||||
if("random_domain")
|
||||
var/map_id = server.get_random_domain_id()
|
||||
if(!map_id)
|
||||
return TRUE
|
||||
|
||||
server.cold_boot_map(usr, map_id)
|
||||
return TRUE
|
||||
if("refresh")
|
||||
ui.send_full_update()
|
||||
return TRUE
|
||||
if("set_domain")
|
||||
server.cold_boot_map(usr, params["id"])
|
||||
return TRUE
|
||||
if("stop_domain")
|
||||
server.begin_shutdown(usr)
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/// Attempts to find a quantum server.
|
||||
/obj/machinery/computer/quantum_console/proc/find_server()
|
||||
var/obj/machinery/quantum_server/server = server_ref?.resolve()
|
||||
if(server)
|
||||
return server
|
||||
|
||||
for(var/direction in GLOB.cardinals)
|
||||
var/obj/machinery/quantum_server/nearby_server = locate(/obj/machinery/quantum_server, get_step(src, direction))
|
||||
if(nearby_server)
|
||||
server_ref = WEAKREF(nearby_server)
|
||||
nearby_server.console_ref = WEAKREF(src)
|
||||
return nearby_server
|
||||
|
||||
return
|
||||
Reference in New Issue
Block a user