feat: new floppy disk sprites; most disks are now under the /item/disk type; adds disk stacking, uqinue styling and wrapping (#94112)

## About The Pull Request

Floppy disks received a sprite upgrade, as well as unique wraps:

<img width="364" height="150" alt="image"
src="https://github.com/user-attachments/assets/0ac433e3-7432-4c06-bec2-aeae00b6852f"
/>

<img width="786" height="527" alt="image"
src="https://github.com/user-attachments/assets/0f36bd0d-0362-4431-8131-49060a2fe348"
/>

You can now stack floppy disks! They also scatter around when thrown.
The video also showcases new styling options with a selection of
stickers! You can also write something on the disk instead of selecting
an icon:


https://github.com/user-attachments/assets/ff0a8542-9d79-4108-ae46-672ca5d620a2

MOST disks now inherit the `/item/disk` type to properly stack and do...
stuff. An updatepaths script included.

## Why It's Good For The Game

Old school is cool. Stacking disks makes them feel more authentic, while
styling allows for more crearivity!

## Changelog

🆑
add: New unique wraps for floppy disks
qol: Floppy disks can now be stacked
image: New sprites and stickers for floppy disks
map: Added and ran an updatepaths script
refactor: Most disks are now under the base disk item type
/🆑

---------

Co-authored-by: The-Tyrant <tyrantofgaming@gmail.com>
This commit is contained in:
mcbalaam
2026-01-04 08:52:18 +13:00
committed by GitHub
co-authored by The-Tyrant
parent d16ac25c1b
commit 3799968eb3
81 changed files with 694 additions and 342 deletions
@@ -19,7 +19,7 @@
///The alt slot, only used by certain UIs like the access app.
var/obj/item/card/id/alt_stored_id
///The disk in this PDA. If set, this will be inserted on Initialize.
var/obj/item/computer_disk/inserted_disk
var/obj/item/disk/computer/inserted_disk
///The power cell the computer uses to run on.
var/obj/item/stock_parts/power_store/internal_cell = /obj/item/stock_parts/power_store/cell
///A pAI currently loaded into the modular computer.
@@ -927,7 +927,7 @@
if(istype(tool, /obj/item/paper_bin))
return paper_bin_act(user, tool)
if(istype(tool, /obj/item/computer_disk))
if(istype(tool, /obj/item/disk/computer))
return computer_disk_act(user, tool)
return NONE
@@ -999,7 +999,7 @@
bin.update_appearance()
return ITEM_INTERACT_SUCCESS
/obj/item/modular_computer/proc/computer_disk_act(mob/user, obj/item/computer_disk/disk)
/obj/item/modular_computer/proc/computer_disk_act(mob/user, obj/item/disk/computer/disk)
if(!user.transferItemToLoc(disk, src))
return ITEM_INTERACT_BLOCKING
if(inserted_disk)
@@ -74,7 +74,7 @@
* the same filename (disregarding extension), will return it.
* If a computer disk is passed instead, it will check the disk over the computer.
*/
/obj/item/modular_computer/proc/find_file_by_name(filename, obj/item/computer_disk/target_disk)
/obj/item/modular_computer/proc/find_file_by_name(filename, obj/item/disk/computer/target_disk)
if(!istext(filename))
return null
if(isnull(target_disk))
@@ -94,7 +94,7 @@
* A file's uid is always unique to them, so this proc is sometimes preferable over find_file_by_name.
* If a computer disk is passed instead, it will check the disk over the computer.
*/
/obj/item/modular_computer/proc/find_file_by_uid(uid, obj/item/computer_disk/target_disk)
/obj/item/modular_computer/proc/find_file_by_uid(uid, obj/item/disk/computer/target_disk)
if(!isnum(uid))
return null
if(isnull(target_disk))
@@ -1,26 +1,21 @@
/obj/item/computer_disk
name = "data disk"
desc = "Removable disk used to store data."
icon = 'icons/obj/devices/circuitry_n_data.dmi'
icon_state = "datadisk6"
w_class = WEIGHT_CLASS_TINY
///The amount of storage space is on the disk
/obj/item/disk/computer
/// The amount of free storage space
var/max_capacity = 16
///The amount of storage space we've got filled
/// The amount of storage space occupied
var/used_capacity = 0
///List of stored files on this drive. DO NOT MODIFY DIRECTLY!
/// List of stored files on this drive. Do NOT directly modify; use setters instead.
var/list/datum/computer_file/stored_files = list()
///List of all programs that the disk should start with.
/// List of all programs that the disk should start with
var/list/datum/computer_file/starting_programs = list()
/obj/item/computer_disk/Initialize(mapload)
/obj/item/disk/computer/Initialize(mapload)
. = ..()
for(var/programs in starting_programs)
var/datum/computer_file/program_type = new programs
add_file(program_type)
/obj/item/computer_disk/Destroy(force)
/obj/item/disk/computer/Destroy(force)
. = ..()
QDEL_LIST(stored_files)
@@ -29,7 +24,7 @@
*
* Attempts to add an already existing file to the computer disk, then adds that capacity to the used capicity.
*/
/obj/item/computer_disk/proc/add_file(datum/computer_file/file)
/obj/item/disk/computer/proc/add_file(datum/computer_file/file)
if((file.size + used_capacity) > max_capacity)
return FALSE
stored_files.Add(file)
@@ -42,7 +37,7 @@
*
* Removes an app from the stored_files list, then removes their size from the capacity.
*/
/obj/item/computer_disk/proc/remove_file(datum/computer_file/file)
/obj/item/disk/computer/proc/remove_file(datum/computer_file/file)
if(!(file in stored_files))
return FALSE
stored_files.Remove(file)
@@ -50,12 +45,12 @@
qdel(file)
return TRUE
/obj/item/computer_disk/advanced
/obj/item/disk/computer/advanced
name = "advanced data disk"
icon_state = "datadisk5"
max_capacity = 64
/obj/item/computer_disk/super
/obj/item/disk/computer/super
name = "super data disk"
desc = "Removable disk used to store large amounts of data."
icon_state = "datadisk3"
@@ -1,30 +1,30 @@
/obj/item/computer_disk/maintenance
/obj/item/disk/computer/maintenance
name = "maintenance data disk"
desc = "A data disk forgotten in the depths of maintenance, might have some useful program on it."
/// Medical health analyzer app
/obj/item/computer_disk/maintenance/scanner
/obj/item/disk/computer/maintenance/scanner
starting_programs = list(/datum/computer_file/program/maintenance/phys_scanner)
///Camera app, forced to always have largest image size
/obj/item/computer_disk/maintenance/camera
/obj/item/disk/computer/maintenance/camera
starting_programs = list(/datum/computer_file/program/maintenance/camera)
///MODsuit UI, in your PDA!
/obj/item/computer_disk/maintenance/modsuit_control
/obj/item/disk/computer/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
/obj/item/disk/computer/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
/obj/item/disk/computer/maintenance/arcade
starting_programs = list(/datum/computer_file/program/arcade/eazy)
/obj/item/computer_disk/maintenance/theme/Initialize(mapload)
/obj/item/disk/computer/maintenance/theme/Initialize(mapload)
starting_programs = list(pick(subtypesof(/datum/computer_file/program/maintenance/theme)))
return ..()
/obj/item/computer_disk/maintenance/cool_sword
/obj/item/disk/computer/maintenance/cool_sword
starting_programs = list(/datum/computer_file/program/maintenance/cool_sword)
@@ -1,7 +1,7 @@
/**
* Command
*/
/obj/item/computer_disk/command
/obj/item/disk/computer/command
icon_state = "datadisk7"
max_capacity = 32
///Static list of programss ALL command tablets have.
@@ -10,13 +10,13 @@
/datum/computer_file/program/status,
)
/obj/item/computer_disk/command/Initialize(mapload)
/obj/item/disk/computer/command/Initialize(mapload)
. = ..()
for(var/programs in command_programs)
var/datum/computer_file/program/program_type = new programs
add_file(program_type)
/obj/item/computer_disk/command/captain
/obj/item/disk/computer/command/captain
name = "captain data disk"
desc = "Removable disk used to download essential Captain tablet apps."
icon_state = "datadisk10"
@@ -25,21 +25,21 @@
/datum/computer_file/program/records/medical,
)
/obj/item/computer_disk/command/cmo
/obj/item/disk/computer/command/cmo
name = "chief medical officer data disk"
desc = "Removable disk used to download essential CMO tablet apps."
starting_programs = list(
/datum/computer_file/program/records/medical,
)
/obj/item/computer_disk/command/rd
/obj/item/disk/computer/command/rd
name = "research director data disk"
desc = "Removable disk used to download essential RD tablet apps."
starting_programs = list(
/datum/computer_file/program/signal_commander,
)
/obj/item/computer_disk/command/hos
/obj/item/disk/computer/command/hos
name = "head of security data disk"
desc = "Removable disk used to download essential HoS tablet apps."
icon_state = "datadisk9"
@@ -47,7 +47,7 @@
/datum/computer_file/program/records/security,
)
/obj/item/computer_disk/command/hop
/obj/item/disk/computer/command/hop
name = "head of personnel data disk"
desc = "Removable disk used to download essential HoP tablet apps."
starting_programs = list(
@@ -55,7 +55,7 @@
/datum/computer_file/program/job_management,
)
/obj/item/computer_disk/command/ce
/obj/item/disk/computer/command/ce
name = "chief engineer data disk"
desc = "Removable disk used to download essential CE tablet apps."
starting_programs = list(
@@ -67,7 +67,7 @@
/**
* Security
*/
/obj/item/computer_disk/security
/obj/item/disk/computer/security
name = "security officer data disk"
desc = "Removable disk used to download security-related tablet apps."
icon_state = "datadisk9"
@@ -78,7 +78,7 @@
/**
* Medical
*/
/obj/item/computer_disk/medical
/obj/item/disk/computer/medical
name = "medical doctor data disk"
desc = "Removable disk used to download medical-related tablet apps."
icon_state = "datadisk7"
@@ -89,10 +89,10 @@
/**
* Supply
*/
/obj/item/computer_disk/quartermaster
/obj/item/disk/computer/quartermaster
name = "cargo data disk"
desc = "Removable disk used to download cargo-related tablet apps."
icon_state = "cargodisk"
icon_state = "datadisk12"
starting_programs = list(
/datum/computer_file/program/shipping,
/datum/computer_file/program/budgetorders,
@@ -102,7 +102,7 @@
/**
* Science
*/
/obj/item/computer_disk/ordnance
/obj/item/disk/computer/ordnance
name = "ordnance data disk"
desc = "Removable disk used to download ordnance-related tablet apps."
icon_state = "datadisk5"
@@ -114,7 +114,7 @@
/**
* Engineering
*/
/obj/item/computer_disk/engineering
/obj/item/disk/computer/engineering
name = "engineering data disk"
desc = "Removable disk used to download engineering-related tablet apps."
icon_state = "datadisk6"
@@ -1,19 +1,27 @@
/obj/item/computer_disk/syndicate
/obj/item/disk/computer/syndicate
name = "golden data disk"
desc = "A data disk with some high-tech programs, probably expensive as hell."
icon_state = "datadisk8"
icon_state = "datadisk9"
custom_materials = list(/datum/material/gold = SMALL_MATERIAL_AMOUNT)
/obj/item/computer_disk/syndicate/camera_app
/obj/item/disk/computer/syndicate/Initialize(mapload)
. = ..()
add_overlay("o_syndicate")
/obj/item/disk/computer/syndicate/camera_app
starting_programs = list(/datum/computer_file/program/secureye/syndicate)
/obj/item/computer_disk/syndicate/contractor
/obj/item/disk/computer/syndicate/contractor
starting_programs = list(/datum/computer_file/program/contract_uplink)
/obj/item/computer_disk/black_market
/obj/item/disk/computer/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)
/obj/item/disk/computer/black_market/Initialize(mapload)
. = ..()
add_overlay("o_code")
/obj/item/disk/computer/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(
@@ -2,14 +2,14 @@
* Virus disk
* Can't hold apps, instead does unique actions.
*/
/obj/item/computer_disk/virus
/obj/item/disk/computer/virus
name = "\improper generic virus disk"
icon_state = "virusdisk"
max_capacity = 0
///How many charges the virus has left
var/charges = 5
/obj/item/computer_disk/virus/proc/send_virus(obj/item/modular_computer/pda/source, obj/item/modular_computer/pda/target, mob/living/user, message)
/obj/item/disk/computer/virus/proc/send_virus(obj/item/modular_computer/pda/source, obj/item/modular_computer/pda/target, mob/living/user, message)
if(charges <= 0)
to_chat(user, span_notice("ERROR: Out of charges."))
return FALSE
@@ -23,10 +23,10 @@
* Makes people's PDA honk
* Can also be used on open panel airlocks to make them honk on opening.
*/
/obj/item/computer_disk/virus/clown
/obj/item/disk/computer/virus/clown
name = "\improper H.O.N.K. disk"
/obj/item/computer_disk/virus/clown/send_virus(obj/item/modular_computer/pda/source, obj/item/modular_computer/pda/target, mob/living/user, message)
/obj/item/disk/computer/virus/clown/send_virus(obj/item/modular_computer/pda/source, obj/item/modular_computer/pda/target, mob/living/user, message)
. = ..()
if(!.)
return FALSE
@@ -40,10 +40,10 @@
* Mime virus
* Makes PDA's silent, removing their ringtone.
*/
/obj/item/computer_disk/virus/mime
/obj/item/disk/computer/virus/mime
name = "\improper sound of silence disk"
/obj/item/computer_disk/virus/mime/send_virus(obj/item/modular_computer/pda/source, obj/item/modular_computer/pda/target, mob/living/user, message)
/obj/item/disk/computer/virus/mime/send_virus(obj/item/modular_computer/pda/source, obj/item/modular_computer/pda/target, mob/living/user, message)
. = ..()
if(!.)
return FALSE
@@ -60,11 +60,11 @@
* Detomatix virus
* Sends a false message, and blows the PDA up if the target responds to it (or opens their messenger before a timer)
*/
/obj/item/computer_disk/virus/detomatix
/obj/item/disk/computer/virus/detomatix
name = "\improper D.E.T.O.M.A.T.I.X. disk"
charges = 6
/obj/item/computer_disk/virus/detomatix/send_virus(obj/item/modular_computer/pda/source, obj/item/modular_computer/pda/target, mob/living/user, message)
/obj/item/disk/computer/virus/detomatix/send_virus(obj/item/modular_computer/pda/source, obj/item/modular_computer/pda/target, mob/living/user, message)
. = ..()
if(!.)
return FALSE
@@ -101,7 +101,7 @@
* Creates and opens a false uplink on someone's PDA
* Can be loaded with TC to show up on the false uplink.
*/
/obj/item/computer_disk/virus/frame
/obj/item/disk/computer/virus/frame
name = "\improper F.R.A.M.E. disk"
///How many telecrystals the uplink should have
@@ -109,7 +109,7 @@
///How much progression should be shown in the uplink, set on purchase of the item.
var/current_progression = 0
/obj/item/computer_disk/virus/frame/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers)
/obj/item/disk/computer/virus/frame/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers)
. = ..()
if(!istype(attacking_item, /obj/item/stack/telecrystal))
return
@@ -122,7 +122,7 @@
telecrystal_stack.use(telecrystal_stack.amount)
/obj/item/computer_disk/virus/frame/send_virus(obj/item/modular_computer/pda/source, obj/item/modular_computer/pda/target, mob/living/user, message)
/obj/item/disk/computer/virus/frame/send_virus(obj/item/modular_computer/pda/source, obj/item/modular_computer/pda/target, mob/living/user, message)
. = ..()
if(!.)
return FALSE
@@ -112,9 +112,9 @@
if(!target_machine.panel_open && !istype(target, /obj/machinery/computer))
return ..()
if(!istype(inserted_disk, /obj/item/computer_disk/virus/clown))
if(!istype(inserted_disk, /obj/item/disk/computer/virus/clown))
return ..()
var/obj/item/computer_disk/virus/clown/installed_cartridge = inserted_disk
var/obj/item/disk/computer/virus/clown/installed_cartridge = inserted_disk
if(!installed_cartridge.charges)
to_chat(user, span_notice("Out of virus charges."))
return ..()
@@ -225,7 +225,7 @@
if(current_turf)
current_turf.hotspot_expose(700,125)
if(istype(inserted_disk, /obj/item/computer_disk/virus/detomatix))
if(istype(inserted_disk, /obj/item/disk/computer/virus/detomatix))
explosion(src, devastation_range = -1, heavy_impact_range = 1, light_impact_range = 3, flash_range = 4)
else
explosion(src, devastation_range = -1, heavy_impact_range = -1, light_impact_range = 2, flash_range = 3)
@@ -326,7 +326,7 @@
icon = 'icons/obj/devices/modular_pda.dmi'
icon_state = "pda-clown"
post_init_icon_state = null
inserted_disk = /obj/item/computer_disk/virus/clown
inserted_disk = /obj/item/disk/computer/virus/clown
greyscale_config = null
greyscale_colors = null
inserted_item = /obj/item/toy/crayon/rainbow
@@ -358,7 +358,7 @@
/obj/item/modular_computer/pda/clown/proc/AfterSlip(mob/living/carbon/human/M)
if (istype(M) && (M.real_name != saved_identification))
var/obj/item/computer_disk/virus/clown/cart = inserted_disk
var/obj/item/disk/computer/virus/clown/cart = inserted_disk
if(istype(cart) && cart.charges < 5)
cart.charges++
playsound(src,'sound/machines/ping.ogg',30,TRUE)
@@ -368,7 +368,7 @@
/obj/item/modular_computer/pda/mime
name = "mime PDA"
inserted_disk = /obj/item/computer_disk/virus/mime
inserted_disk = /obj/item/disk/computer/virus/mime
icon_state = "/obj/item/modular_computer/pda/mime"
greyscale_config = /datum/greyscale_config/tablet/mime
greyscale_colors = "#FAFAFA#EA3232"