[MIRROR] The Spectre-Meter App, also a bootleg data disk item for the black market. [MDB IGNORE] (#25717)

The Spectre-Meter App, also a bootleg data disk item for the black market.

Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
Co-authored-by: Gandalf <9026500+Gandalf2k15@users.noreply.github.com>
This commit is contained in:
SkyratBot
2023-12-25 00:25:23 +01:00
committed by GitHub
parent 67436cd148
commit cbaee82e73
14 changed files with 262 additions and 9 deletions
@@ -640,9 +640,9 @@
return SSmodular_computers.add_log("[src]: [text]")
/obj/item/modular_computer/proc/close_all_programs()
active_program = null
active_program?.kill_program()
for(var/datum/computer_file/program/idle as anything in idle_threads)
idle_threads.Remove(idle)
idle.kill_program()
/obj/item/modular_computer/proc/shutdown_computer(loud = TRUE)
close_all_programs()
@@ -14,6 +14,14 @@
/obj/item/computer_disk/maintenance/modsuit_control
starting_programs = list(/datum/computer_file/program/maintenance/modsuit_control)
///Returns A 'spookiness' value based on the number of ghastly creature and hauntium and their distance from the PC.
/obj/item/computer_disk/maintenance/spectre_meter
starting_programs = list(/datum/computer_file/program/maintenance/spectre_meter)
///A version of the arcade program with less HP/MP for the enemy and more for the player
/obj/item/computer_disk/maintenance/arcade
starting_programs = list(/datum/computer_file/program/arcade/eazy)
/obj/item/computer_disk/maintenance/theme/Initialize(mapload)
starting_programs = list(pick(subtypesof(/datum/computer_file/program/maintenance/theme)))
return ..()
@@ -9,3 +9,30 @@
/obj/item/computer_disk/syndicate/contractor
starting_programs = list(/datum/computer_file/program/contract_uplink)
/obj/item/computer_disk/black_market
desc = "Removable disk used to store data. This one has a smudged piece of paper glued to it, reading \"PC softwarez\"."
/obj/item/computer_disk/black_market/Initialize(mapload)
icon_state = "datadisk[rand(0, 10)]"
//Populated with programs not found in the verified downloader app or that require access to download (but not to run).
var/list/potential_programs = list(
/datum/computer_file/program/arcade/eazy,
/datum/computer_file/program/radar/lifeline,
/datum/computer_file/program/radar/custodial_locator,
/datum/computer_file/program/supermatter_monitor,
/datum/computer_file/program/newscaster,
/datum/computer_file/program/secureye,
/datum/computer_file/program/crew_manifest,
/datum/computer_file/program/status,
)
potential_programs += subtypesof(/datum/computer_file/program/maintenance) - /datum/computer_file/program/maintenance/theme
var/total_programs_size = 0
for(var/i in 1 to rand(2, 4))
var/datum/computer_file/program/to_add = pick_n_take(potential_programs)
total_programs_size += initial(to_add.size)
starting_programs += to_add
///Make sure the disk has enough space for all the programs
max_capacity = max(total_programs_size, max_capacity)
return ..()
@@ -187,8 +187,8 @@
if(src == computer.active_program)
computer.active_program = null
if(computer.enabled)
computer.update_tablet_open_uis(user)
if(!QDELETED(computer) && computer.enabled)
INVOKE_ASYNC(computer, TYPE_PROC_REF(/obj/item/modular_computer, update_tablet_open_uis), user)
if(src in computer.idle_threads)
computer.idle_threads.Remove(src)
@@ -211,5 +211,3 @@
computer.update_tablet_open_uis(usr)
computer.update_appearance(UPDATE_ICON)
return TRUE
#undef PROGRAM_BASIC_CELL_USE
@@ -23,6 +23,20 @@
///Determines which boss image to use on the UI.
var/boss_id = 1
///Lazy version of the arade that can be found in maintenance disks
/datum/computer_file/program/arcade/eazy
filename = "dsarcadeez"
filedesc = "Donksoft Micro Arcade Ez"
filetype = "MNT"
program_flags = PROGRAM_UNIQUE_COPY
extended_desc = "Some sort of fan-made conversion of the classic game 'Outbomb Cuban Pete'. This one has you fight the weaker 'George Melon' instead."
boss_hp = 40
boss_mp = 10
player_hp = 35
player_mp = 15
heads_up = "Are you a bad enough dude to grief the station?"
boss_name = "George Melon"
/datum/computer_file/program/arcade/proc/game_check(mob/user)
sleep(0.5 SECONDS)
user?.mind?.adjust_experience(/datum/skill/gaming, 1)
@@ -159,9 +173,9 @@
return TRUE
if("Start_Game")
game_active = TRUE
boss_hp = 45
player_hp = 30
player_mp = 10
boss_hp = initial(boss_hp)
player_hp = initial(player_hp)
player_mp = initial(player_mp)
heads_up = "You stand before [boss_name]! Prepare for battle!"
program_open_overlay = "arcade"
boss_id = rand(1,6)
@@ -33,6 +33,8 @@
if(internal_picture)
QDEL_NULL(internal_picture)
var/turf/our_turf = get_turf(tapped_atom)
var/spooky_camera = locate(/datum/computer_file/program/maintenance/spectre_meter) in computer.stored_files
internal_camera.see_ghosts = spooky_camera ? CAMERA_SEE_GHOSTS_BASIC : CAMERA_NO_GHOSTS
internal_picture = internal_camera.captureimage(our_turf, user, internal_camera.picture_size_x + 1, internal_camera.picture_size_y + 1)
picture_number++
computer.save_photo(internal_picture.picture_image)
@@ -28,6 +28,7 @@
return TRUE
/datum/computer_file/program/maintenance/modsuit_control/proc/unsync_modsuit(atom/source)
SIGNAL_HANDLER
UnregisterSignal(controlled_suit, COMSIG_QDELETING)
controlled_suit = null
@@ -0,0 +1,135 @@
#define SPOOK_VALUE_SAME_TURF_MULT 1.5
#define SPOOK_VALUE_LIVING_MULT 6
#define SPOOK_VALUE_DEF_MOB 10
#define SPOOK_VALUE_ICON_STATE_MAX 120
#define SPOOK_VALUE_SEGMENT 15
/datum/computer_file/program/maintenance/spectre_meter
filename = "spectre_meter"
filedesc = "Spectre-Meter"
power_cell_use = PROGRAM_BASIC_CELL_USE * 2
downloader_category = PROGRAM_CATEGORY_EQUIPMENT
extended_desc = "A program used to somehow detect nearby spectral presence. Combine with the camera app to take photos of ghosts."
size = 7
can_run_on_flags = PROGRAM_LAPTOP|PROGRAM_PDA
tgui_id = "NtosSpectreMeter"
program_icon = "ghost"
program_open_overlay = "spectre_meter_0"
/// The cooldown for manual scans
COOLDOWN_DECLARE(manual_scan_cd)
/// Whether the automatic scan mode is active or not
var/auto_mode = FALSE
/// The value reported by the last scan.
var/last_spook_value = 0
var/datum/looping_sound/spectre_meter/soundloop
/datum/computer_file/program/maintenance/spectre_meter/on_start(mob/user)
. = ..()
if(.)
soundloop = new()
/datum/computer_file/program/maintenance/spectre_meter/kill_program()
QDEL_NULL(soundloop)
auto_mode = FALSE
last_spook_value = 0
program_open_overlay = "spectre_meter_0"
power_cell_use = PROGRAM_BASIC_CELL_USE
STOP_PROCESSING(SSprocessing, src)
return ..()
/datum/computer_file/program/maintenance/spectre_meter/ui_data(mob/user)
var/list/data = list()
data["spook_value"] = last_spook_value
data["auto_mode"] = auto_mode
data["on_cooldown"] = !COOLDOWN_FINISHED(src, manual_scan_cd)
return data
/datum/computer_file/program/maintenance/spectre_meter/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
switch(action)
if("manual_scan")
if(COOLDOWN_FINISHED(src, manual_scan_cd))
INVOKE_ASYNC(src, PROC_REF(scan_surroundings))
COOLDOWN_START(src, manual_scan_cd, 2 SECONDS)
playsound(computer, 'sound/effects/ping_hit.ogg', vol = 40, vary = TRUE)
return TRUE
if("toggle_mode")
auto_mode = !auto_mode
if(auto_mode)
///We want SSprocess. It fires twice as fast than the standard SSobjs used by [computer_file/program/process_tick]
START_PROCESSING(SSprocessing, src)
soundloop.start(computer)
else
STOP_PROCESSING(SSprocessing, src)
soundloop.stop(TRUE)
power_cell_use = auto_mode ? PROGRAM_BASIC_CELL_USE * 3 : PROGRAM_BASIC_CELL_USE
return TRUE
/datum/computer_file/program/maintenance/spectre_meter/process(seconds_per_tick)
if(auto_mode)
INVOKE_ASYNC(src, PROC_REF(scan_surroundings))
///Return the "spook level" of the area the computer is in.
/datum/computer_file/program/maintenance/spectre_meter/proc/scan_surroundings()
var/spook_value = 0
var/turf/turf = get_turf(computer)
for(var/atom/atom as anything in range(5, turf))
var/spook_amount = 0
if(ismob(atom))
///ghastly mobs count toward spookiness more than observers.
var/spook_value_mult = 0
if(isliving(atom))
var/mob/living/living = atom
if(living.mob_biotypes & MOB_SPIRIT)
spook_value_mult = SPOOK_VALUE_LIVING_MULT
else if(isobserver(atom))
spook_value_mult = 1
spook_amount += SPOOK_VALUE_DEF_MOB * spook_value_mult
var/list/materials = atom.has_material_type(/datum/material/hauntium)
if(materials)
spook_amount += materials[/datum/material/hauntium]/SHEET_MATERIAL_AMOUNT
spook_amount += atom.reagents?.get_reagent_amount(/datum/reagent/hauntium)/20
if(!spook_amount)
continue
if(atom.loc == turf)
spook_amount *= SPOOK_VALUE_SAME_TURF_MULT
spook_value += spook_amount/max(get_dist(turf, atom), 1)
CHECK_TICK
soundloop.last_spook_value = last_spook_value = round(spook_value)
var/old_open_overlay = program_open_overlay
program_open_overlay = "spectre_meter_[min(FLOOR(last_spook_value, SPOOK_VALUE_SEGMENT), SPOOK_VALUE_ICON_STATE_MAX)]"
if(program_open_overlay != old_open_overlay)
computer.update_appearance(UPDATE_OVERLAYS)
/datum/looping_sound/spectre_meter
mid_sounds = /datum/looping_sound/geiger::mid_sounds
mid_length = 2
volume = 12
var/last_spook_value = 0
/datum/looping_sound/spectre_meter/get_sound()
var/index = 1
switch(last_spook_value)
if(0 to 14)
return null
if(14 to 40)
index = 1
if(40 to 65)
index = 2
if(65 to 90)
index = 3
else
index = 4
return ..(mid_sounds[index])
/datum/looping_sound/spectre_meter/stop(null_parent = FALSE)
last_spook_value = 0
return ..()
#undef SPOOK_VALUE_SAME_TURF_MULT
#undef SPOOK_VALUE_LIVING_MULT
#undef SPOOK_VALUE_DEF_MOB
#undef SPOOK_VALUE_ICON_STATE_MAX
#undef SPOOK_VALUE_SEGMENT