From 2543d885486ddf263f7f7055b3c1e82155bbb3ee Mon Sep 17 00:00:00 2001 From: ArrisFairburne Date: Tue, 11 Feb 2025 04:03:45 -0500 Subject: [PATCH] Punch Clock PDA Application/Modular Console (#2900) ## About The Pull Request Adds a new NTOS application to the game: "Plexagon Punch Clock", which functions similarly to the time clock in cryo. Using the app, crew members can clock out wherever they want. This will also create a locked briefcase containing certain job-related items; this can be unlocked by the player once they return to the shift, or by a relevant Command member. For later changes I'd like to be able to have this app be able to clock in/out a user via their DNA imprint. ## Why It's Good For The Game - It's easier to clock out before going for RP/ERP when done with work. - Placing job items in an easily-accessible box means that it's less annoying to return to work after finishing RP/ERP - Convenience ## Proof Of Testing
Screenshots/Videos ![GIF 12-Jan-25 6-22-47 PM](https://github.com/user-attachments/assets/2b90ccb6-a175-4e2a-80c2-bfe717f99358)
## Changelog :cl: ArrisFairburne, LT3 add: Added a new app to clock in and out from any NT OS-compatible device (Plexagon Punch Clock) qol: Your job items are now locked into a box instead of warped to cryo, when clocking out /:cl: --------- Co-authored-by: lessthanthree <83487515+lessthnthree@users.noreply.github.com> Co-authored-by: The Sharkening <95130227+StrangeWeirdKitten@users.noreply.github.com> --- .../IceBoxStation/Icebox_ntrep_office.dmm | 2 +- .../MetaStation/metastation_ntrep_office.dmm | 2 +- .../NebulaStation/nebulastation_arrivals.dmm | 2 +- .../NebulaStation/nebulastation_corridor.dmm | 2 +- .../NebulaStation/nebulastation_cryo.dmm | 2 +- .../nebulastation_ntrep_office.dmm | 2 +- .../kilostation/kilostation_cryo.dmm | 2 +- .../kilostation/kilostation_ert_bay.dmm | 2 +- .../tramstation/tramstation_ntrep_office.dmm | 2 +- _maps/map_files/BoxStation/BoxStation.dmm | 4 +- _maps/map_files/VoidRaptor/VoidRaptor.dmm | 2 +- _maps/map_files/biodome/biodome.dmm | 4 +- _maps/map_files/generic/CentCom_skyrat_z2.dmm | 2 +- _maps/map_files/moonstation/moonstation.dmm | 10 +- .../birdshot/birdshot_cryo(deprecated).dmm | 2 +- .../templates/birdshot/birdshot_cryo.dmm | 2 +- .../deltastation/deltastation_cryo.dmm | 2 +- .../templates/icebox/icebox_cryo.dmm | 2 +- .../kilostation/kilostation_cryo.dmm | 2 +- .../metastation/metastation_cryo.dmm | 2 +- .../templates/northstar/northstar_cryo.dmm | 2 +- .../tramstation/tramstation_cryo.dmm | 2 +- .../wawastation/wawastation_commons.dmm | 2 +- .../dcs/signals/signals_modular_computer.dm | 1 + code/__DEFINES/~~bubber_defines/jobs.dm | 59 ++++ code/__HELPERS/global_lists.dm | 2 +- .../computers/item/computer.dm | 1 + .../modular_computers/computers/item/pda.dm | 7 +- .../computers/item/computer.dm | 5 +- .../modules/research/designs/misc_designs.dm | 2 + .../modules/research/techweb/all_nodes.dm | 6 - modular_skyrat/modules/cryosleep/code/job.dm | 13 +- .../modules/time_clock/code/console.dm | 207 ------------ .../modules/time_clock/code/console_tgui.dm | 131 -------- .../modules/time_clock/code/mind.dm | 4 - .../modules/time_clock/code/sign.dm | 8 - .../time_clock/icons/machinery/console.dmi | Bin 862 -> 0 bytes .../modules/time_clock/icons/sign.dmi | Bin 978 -> 0 bytes .../effects/effects_system/effect_sparks.dm | 21 ++ .../icons/obj/machines/time_clock.dmi | Bin 0 -> 1106 bytes .../code/off_duty_component.dm | 3 + .../code/plexagon_selfserve.dm | 317 ++++++++++++++++++ .../plexagon_selfserve/code/shame_box.dm | 74 ++++ .../modules/plexagon_selfserve/code/sign.dm | 15 + .../plexagon_selfserve/code/time_clock.dm | 21 ++ .../plexagon_selfserve/icons/shame_box.dmi | Bin 0 -> 473 bytes .../modules/plexagon_selfserve/icons/sign.dmi | Bin 0 -> 1451 bytes tgstation.dme | 11 +- .../tgui/interfaces/NtosSelfServe.tsx | 146 ++++++++ .../Scripts_Bubber/2900_Time_Clock.txt | 1 + 50 files changed, 715 insertions(+), 398 deletions(-) delete mode 100644 modular_skyrat/modules/time_clock/code/console.dm delete mode 100644 modular_skyrat/modules/time_clock/code/console_tgui.dm delete mode 100644 modular_skyrat/modules/time_clock/code/mind.dm delete mode 100644 modular_skyrat/modules/time_clock/code/sign.dm delete mode 100644 modular_skyrat/modules/time_clock/icons/machinery/console.dmi delete mode 100644 modular_skyrat/modules/time_clock/icons/sign.dmi create mode 100644 modular_zubbers/code/game/objects/effects/effects_system/effect_sparks.dm create mode 100644 modular_zubbers/icons/obj/machines/time_clock.dmi rename {modular_skyrat/modules/time_clock => modular_zubbers/modules/plexagon_selfserve}/code/off_duty_component.dm (96%) create mode 100644 modular_zubbers/modules/plexagon_selfserve/code/plexagon_selfserve.dm create mode 100644 modular_zubbers/modules/plexagon_selfserve/code/shame_box.dm create mode 100644 modular_zubbers/modules/plexagon_selfserve/code/sign.dm create mode 100644 modular_zubbers/modules/plexagon_selfserve/code/time_clock.dm create mode 100644 modular_zubbers/modules/plexagon_selfserve/icons/shame_box.dmi create mode 100644 modular_zubbers/modules/plexagon_selfserve/icons/sign.dmi create mode 100644 tgui/packages/tgui/interfaces/NtosSelfServe.tsx create mode 100644 tools/UpdatePaths/Scripts_Bubber/2900_Time_Clock.txt diff --git a/_maps/bubber/automapper/templates/IceBoxStation/Icebox_ntrep_office.dmm b/_maps/bubber/automapper/templates/IceBoxStation/Icebox_ntrep_office.dmm index a53b9c3712e..45b4ae76dcc 100644 --- a/_maps/bubber/automapper/templates/IceBoxStation/Icebox_ntrep_office.dmm +++ b/_maps/bubber/automapper/templates/IceBoxStation/Icebox_ntrep_office.dmm @@ -6,7 +6,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, -/obj/machinery/time_clock/directional/west, +/obj/machinery/modular_computer/preset/time_clock/directional/west, /obj/structure/disposalpipe/trunk{ dir = 1 }, diff --git a/_maps/bubber/automapper/templates/MetaStation/metastation_ntrep_office.dmm b/_maps/bubber/automapper/templates/MetaStation/metastation_ntrep_office.dmm index 1f5c31bf21d..6ffe685f3d0 100644 --- a/_maps/bubber/automapper/templates/MetaStation/metastation_ntrep_office.dmm +++ b/_maps/bubber/automapper/templates/MetaStation/metastation_ntrep_office.dmm @@ -211,7 +211,7 @@ /turf/open/floor/carpet/green, /area/station/command/heads_quarters/nt_rep) "M" = ( -/obj/machinery/time_clock/directional/south, +/obj/machinery/modular_computer/preset/time_clock/directional/south, /turf/open/floor/iron, /area/station/hallway/primary/port) "N" = ( diff --git a/_maps/bubber/automapper/templates/NebulaStation/nebulastation_arrivals.dmm b/_maps/bubber/automapper/templates/NebulaStation/nebulastation_arrivals.dmm index e9378f5bfda..51cf2543d90 100644 --- a/_maps/bubber/automapper/templates/NebulaStation/nebulastation_arrivals.dmm +++ b/_maps/bubber/automapper/templates/NebulaStation/nebulastation_arrivals.dmm @@ -50,7 +50,7 @@ /obj/effect/turf_decal/stripes/corner{ dir = 8 }, -/obj/machinery/time_clock/directional/south, +/obj/machinery/modular_computer/preset/time_clock/directional/south, /turf/open/floor/iron, /area/station/hallway/primary/central) "C" = ( diff --git a/_maps/bubber/automapper/templates/NebulaStation/nebulastation_corridor.dmm b/_maps/bubber/automapper/templates/NebulaStation/nebulastation_corridor.dmm index 8d4dcdc5e9d..4651779e186 100644 --- a/_maps/bubber/automapper/templates/NebulaStation/nebulastation_corridor.dmm +++ b/_maps/bubber/automapper/templates/NebulaStation/nebulastation_corridor.dmm @@ -99,7 +99,7 @@ /turf/open/floor/grass/fairy, /area/station/common/cryopods/aux) "u" = ( -/obj/machinery/time_clock/directional/east, +/obj/machinery/modular_computer/preset/time_clock/directional/east, /obj/effect/turf_decal/tile/neutral/half/contrasted{ dir = 8 }, diff --git a/_maps/bubber/automapper/templates/NebulaStation/nebulastation_cryo.dmm b/_maps/bubber/automapper/templates/NebulaStation/nebulastation_cryo.dmm index c233a7b18d1..2243e84ab01 100644 --- a/_maps/bubber/automapper/templates/NebulaStation/nebulastation_cryo.dmm +++ b/_maps/bubber/automapper/templates/NebulaStation/nebulastation_cryo.dmm @@ -222,7 +222,7 @@ }, /area/station/commons/locker) "X" = ( -/obj/machinery/time_clock/directional/east, +/obj/machinery/modular_computer/preset/time_clock/directional/east, /obj/effect/turf_decal/siding/thinplating_new/dark{ dir = 5 }, diff --git a/_maps/bubber/automapper/templates/NebulaStation/nebulastation_ntrep_office.dmm b/_maps/bubber/automapper/templates/NebulaStation/nebulastation_ntrep_office.dmm index 5ddf9bf053a..fb63b944d2d 100644 --- a/_maps/bubber/automapper/templates/NebulaStation/nebulastation_ntrep_office.dmm +++ b/_maps/bubber/automapper/templates/NebulaStation/nebulastation_ntrep_office.dmm @@ -110,7 +110,7 @@ /turf/open/floor/plating, /area/station/command/heads_quarters/nt_rep) "v" = ( -/obj/machinery/time_clock/directional/south, +/obj/machinery/modular_computer/preset/time_clock/directional/south, /turf/template_noop, /area/station/hallway/primary/central) "w" = ( diff --git a/_maps/bubber/automapper/templates/kilostation/kilostation_cryo.dmm b/_maps/bubber/automapper/templates/kilostation/kilostation_cryo.dmm index d3035bcc07a..a9574027702 100644 --- a/_maps/bubber/automapper/templates/kilostation/kilostation_cryo.dmm +++ b/_maps/bubber/automapper/templates/kilostation/kilostation_cryo.dmm @@ -95,7 +95,7 @@ dir = 1 }, /obj/machinery/camera/directional/east, -/obj/machinery/time_clock/directional/east, +/obj/machinery/modular_computer/preset/time_clock/directional/east, /obj/item/kirbyplants/random, /turf/open/floor/iron/dark, /area/station/common/cryopods) diff --git a/_maps/bubber/automapper/templates/kilostation/kilostation_ert_bay.dmm b/_maps/bubber/automapper/templates/kilostation/kilostation_ert_bay.dmm index dfcfda5ec52..0d80052da7b 100644 --- a/_maps/bubber/automapper/templates/kilostation/kilostation_ert_bay.dmm +++ b/_maps/bubber/automapper/templates/kilostation/kilostation_ert_bay.dmm @@ -653,7 +653,7 @@ "nS" = ( /obj/effect/turf_decal/tile/green, /obj/machinery/camera/directional/south, -/obj/machinery/time_clock/directional/south, +/obj/machinery/modular_computer/preset/time_clock/directional/south, /turf/open/floor/iron/dark/corner, /area/station/hallway/primary/fore) "nW" = ( diff --git a/_maps/bubber/automapper/templates/tramstation/tramstation_ntrep_office.dmm b/_maps/bubber/automapper/templates/tramstation/tramstation_ntrep_office.dmm index bcd6ec3f0b0..654ffcd7838 100644 --- a/_maps/bubber/automapper/templates/tramstation/tramstation_ntrep_office.dmm +++ b/_maps/bubber/automapper/templates/tramstation/tramstation_ntrep_office.dmm @@ -167,7 +167,7 @@ /turf/open/floor/carpet/green, /area/station/command/heads_quarters/nt_rep) "u" = ( -/obj/machinery/time_clock, +/obj/machinery/modular_computer/preset/time_clock, /turf/closed/wall, /area/station/command/heads_quarters/nt_rep) "v" = ( diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index bef60ba776e..c7f439c240f 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -39167,7 +39167,7 @@ /turf/open/floor/iron, /area/station/hallway/primary/central) "gBW" = ( -/obj/machinery/time_clock/directional/north, +/obj/machinery/modular_computer/preset/time_clock/directional/north, /turf/open/floor/iron/dark/side{ dir = 1 }, @@ -56167,7 +56167,7 @@ /obj/effect/turf_decal/tile/green{ dir = 1 }, -/obj/machinery/time_clock/directional/north, +/obj/machinery/modular_computer/preset/time_clock/directional/north, /turf/open/floor/iron/dark, /area/station/common/cryopods) "rkn" = ( diff --git a/_maps/map_files/VoidRaptor/VoidRaptor.dmm b/_maps/map_files/VoidRaptor/VoidRaptor.dmm index a604de81071..f2fabdf478f 100644 --- a/_maps/map_files/VoidRaptor/VoidRaptor.dmm +++ b/_maps/map_files/VoidRaptor/VoidRaptor.dmm @@ -8959,7 +8959,7 @@ /area/station/tcommsat/server) "cHJ" = ( /obj/effect/turf_decal/siding/white, -/obj/machinery/time_clock/directional/north, +/obj/machinery/modular_computer/preset/time_clock/directional/north, /turf/open/floor/iron/dark/smooth_large, /area/station/common/cryopods) "cHR" = ( diff --git a/_maps/map_files/biodome/biodome.dmm b/_maps/map_files/biodome/biodome.dmm index e704ef1708e..3c9aba206b0 100644 --- a/_maps/map_files/biodome/biodome.dmm +++ b/_maps/map_files/biodome/biodome.dmm @@ -55617,7 +55617,7 @@ /obj/effect/turf_decal/trimline/brown/line{ dir = 8 }, -/obj/machinery/time_clock/directional/east, +/obj/machinery/modular_computer/preset/time_clock/directional/east, /obj/machinery/light/directional/east, /turf/open/floor/iron, /area/station/hallway/primary/central/aft) @@ -70621,7 +70621,7 @@ /turf/open/floor/iron/dark, /area/station/hallway/primary/aft) "yhC" = ( -/obj/machinery/time_clock/directional/north, +/obj/machinery/modular_computer/preset/time_clock/directional/north, /turf/open/floor/carpet/executive, /area/station/commons/locker) "yhE" = ( diff --git a/_maps/map_files/generic/CentCom_skyrat_z2.dmm b/_maps/map_files/generic/CentCom_skyrat_z2.dmm index 0b569b3357f..c1a5071250f 100644 --- a/_maps/map_files/generic/CentCom_skyrat_z2.dmm +++ b/_maps/map_files/generic/CentCom_skyrat_z2.dmm @@ -4738,7 +4738,7 @@ /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 8 }, -/obj/machinery/time_clock/directional/west, +/obj/machinery/modular_computer/preset/time_clock/directional/west, /turf/open/floor/iron/white, /area/centcom/interlink) "bGk" = ( diff --git a/_maps/map_files/moonstation/moonstation.dmm b/_maps/map_files/moonstation/moonstation.dmm index 0a39aa196e2..bc65ca80f66 100644 --- a/_maps/map_files/moonstation/moonstation.dmm +++ b/_maps/map_files/moonstation/moonstation.dmm @@ -28053,7 +28053,7 @@ dir = 8 }, /obj/effect/landmark/atmospheric_sanity/ignore_area, -/obj/machinery/time_clock/directional/west, +/obj/machinery/modular_computer/preset/time_clock/directional/west, /turf/open/floor/iron/showroomfloor, /area/station/terminal/cryo) "hHF" = ( @@ -40920,7 +40920,7 @@ /area/ruin/unpowered/ash_walkers) "lkQ" = ( /obj/machinery/computer/cryopod/directional/east, -/obj/machinery/time_clock/directional/south, +/obj/machinery/modular_computer/preset/time_clock/directional/south, /obj/effect/turf_decal/tile/green/anticorner/contrasted, /obj/item/kirbyplants/random, /turf/open/floor/iron/showroomfloor, @@ -72212,7 +72212,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, -/obj/machinery/time_clock/directional/north, +/obj/machinery/modular_computer/preset/time_clock/directional/north, /obj/structure/disposalpipe/segment{ dir = 4 }, @@ -72895,7 +72895,7 @@ /area/station/tcommsat/computer) "uaR" = ( /obj/machinery/computer/cryopod/directional/east, -/obj/machinery/time_clock/directional/south, +/obj/machinery/modular_computer/preset/time_clock/directional/south, /obj/effect/turf_decal/tile/green/anticorner/contrasted, /obj/item/kirbyplants/random, /turf/open/floor/iron/showroomfloor, @@ -76533,7 +76533,7 @@ /obj/effect/turf_decal/tile/neutral/half/contrasted{ dir = 8 }, -/obj/machinery/time_clock/directional/west, +/obj/machinery/modular_computer/preset/time_clock/directional/west, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark/corner{ dir = 1 diff --git a/_maps/skyrat/automapper/templates/birdshot/birdshot_cryo(deprecated).dmm b/_maps/skyrat/automapper/templates/birdshot/birdshot_cryo(deprecated).dmm index 5a33e0657ec..1ecccf5d0ba 100644 --- a/_maps/skyrat/automapper/templates/birdshot/birdshot_cryo(deprecated).dmm +++ b/_maps/skyrat/automapper/templates/birdshot/birdshot_cryo(deprecated).dmm @@ -138,7 +138,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/siding/thinplating_new/light/end, /obj/machinery/light/directional/north, -/obj/machinery/time_clock/directional/north, +/obj/machinery/modular_computer/preset/time_clock/directional/north, /turf/open/floor/iron/dark, /area/station/common/cryopods) "Y" = ( diff --git a/_maps/skyrat/automapper/templates/birdshot/birdshot_cryo.dmm b/_maps/skyrat/automapper/templates/birdshot/birdshot_cryo.dmm index 8572568a290..c68baf643ba 100644 --- a/_maps/skyrat/automapper/templates/birdshot/birdshot_cryo.dmm +++ b/_maps/skyrat/automapper/templates/birdshot/birdshot_cryo.dmm @@ -13,7 +13,7 @@ /obj/effect/turf_decal/siding/thinplating_new/light{ dir = 1 }, -/obj/machinery/time_clock/directional/north, +/obj/machinery/modular_computer/preset/time_clock/directional/north, /obj/machinery/cryopod, /obj/machinery/light/warm/directional/north, /turf/open/floor/iron/dark, diff --git a/_maps/skyrat/automapper/templates/deltastation/deltastation_cryo.dmm b/_maps/skyrat/automapper/templates/deltastation/deltastation_cryo.dmm index e2ade1d4387..145b8ae8bdc 100644 --- a/_maps/skyrat/automapper/templates/deltastation/deltastation_cryo.dmm +++ b/_maps/skyrat/automapper/templates/deltastation/deltastation_cryo.dmm @@ -4,7 +4,7 @@ /area/station/commons/fitness/recreation) "d" = ( /obj/effect/turf_decal/siding/white, -/obj/machinery/time_clock/directional/east, +/obj/machinery/modular_computer/preset/time_clock/directional/east, /turf/open/floor/iron/dark, /area/station/commons/fitness/recreation) "e" = ( diff --git a/_maps/skyrat/automapper/templates/icebox/icebox_cryo.dmm b/_maps/skyrat/automapper/templates/icebox/icebox_cryo.dmm index 46d36b10347..540cdada384 100644 --- a/_maps/skyrat/automapper/templates/icebox/icebox_cryo.dmm +++ b/_maps/skyrat/automapper/templates/icebox/icebox_cryo.dmm @@ -42,7 +42,7 @@ dir = 9 }, /obj/machinery/light/directional/east, -/obj/machinery/time_clock/directional/east, +/obj/machinery/modular_computer/preset/time_clock/directional/east, /turf/open/floor/iron/dark, /area/station/common/cryopods) "k" = ( diff --git a/_maps/skyrat/automapper/templates/kilostation/kilostation_cryo.dmm b/_maps/skyrat/automapper/templates/kilostation/kilostation_cryo.dmm index 4a343890ab1..c55a3d57ca8 100644 --- a/_maps/skyrat/automapper/templates/kilostation/kilostation_cryo.dmm +++ b/_maps/skyrat/automapper/templates/kilostation/kilostation_cryo.dmm @@ -95,7 +95,7 @@ dir = 1 }, /obj/machinery/camera/directional/east, -/obj/machinery/time_clock/directional/east, +/obj/machinery/modular_computer/preset/time_clock/directional/east, /obj/item/kirbyplants/random, /turf/open/floor/iron/dark, /area/station/common/cryopods) diff --git a/_maps/skyrat/automapper/templates/metastation/metastation_cryo.dmm b/_maps/skyrat/automapper/templates/metastation/metastation_cryo.dmm index 54bc572e412..fd353542e13 100644 --- a/_maps/skyrat/automapper/templates/metastation/metastation_cryo.dmm +++ b/_maps/skyrat/automapper/templates/metastation/metastation_cryo.dmm @@ -30,7 +30,7 @@ /area/station/common/cryopods) "p" = ( /obj/effect/turf_decal/siding/white, -/obj/machinery/time_clock/directional/north, +/obj/machinery/modular_computer/preset/time_clock/directional/north, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/iron/dark, /area/station/common/cryopods) diff --git a/_maps/skyrat/automapper/templates/northstar/northstar_cryo.dmm b/_maps/skyrat/automapper/templates/northstar/northstar_cryo.dmm index e77449ea97b..87c3cce8450 100644 --- a/_maps/skyrat/automapper/templates/northstar/northstar_cryo.dmm +++ b/_maps/skyrat/automapper/templates/northstar/northstar_cryo.dmm @@ -368,7 +368,7 @@ /area/station/commons/vacant_room/commissary) "zq" = ( /obj/machinery/computer/cryopod/directional/south, -/obj/machinery/time_clock/directional/east, +/obj/machinery/modular_computer/preset/time_clock/directional/east, /turf/open/floor/iron/dark, /area/station/common/cryopods) "Ao" = ( diff --git a/_maps/skyrat/automapper/templates/tramstation/tramstation_cryo.dmm b/_maps/skyrat/automapper/templates/tramstation/tramstation_cryo.dmm index 94883b8e91e..01ba5181ac9 100644 --- a/_maps/skyrat/automapper/templates/tramstation/tramstation_cryo.dmm +++ b/_maps/skyrat/automapper/templates/tramstation/tramstation_cryo.dmm @@ -246,7 +246,7 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 4 }, -/obj/machinery/time_clock/directional/west, +/obj/machinery/modular_computer/preset/time_clock/directional/west, /turf/open/floor/iron/dark, /area/station/common/cryopods) "M" = ( diff --git a/_maps/skyrat/automapper/templates/wawastation/wawastation_commons.dmm b/_maps/skyrat/automapper/templates/wawastation/wawastation_commons.dmm index 68e53ffc220..c57e2b8fe55 100644 --- a/_maps/skyrat/automapper/templates/wawastation/wawastation_commons.dmm +++ b/_maps/skyrat/automapper/templates/wawastation/wawastation_commons.dmm @@ -539,7 +539,7 @@ /turf/open/floor/carpet/purple, /area/station/service/library) "rI" = ( -/obj/machinery/time_clock/directional/east, +/obj/machinery/modular_computer/preset/time_clock/directional/east, /obj/effect/turf_decal/bot_blue, /obj/machinery/computer/cryopod/directional/south, /turf/open/floor/iron/dark/textured_large, diff --git a/code/__DEFINES/dcs/signals/signals_modular_computer.dm b/code/__DEFINES/dcs/signals/signals_modular_computer.dm index dd325e41984..055bdd4d176 100644 --- a/code/__DEFINES/dcs/signals/signals_modular_computer.dm +++ b/code/__DEFINES/dcs/signals/signals_modular_computer.dm @@ -16,6 +16,7 @@ /// From /obj/item/modular_computer/proc/InsertID: (inserting_id, user) #define COMSIG_MODULAR_COMPUTER_INSERTED_ID "comsig_computer_inserted_id" +#define COMSIG_MODULAR_COMPUTER_REMOVED_ID "comsig_computer_removed_id" // BUBBER EDIT ADDITION - Signal on ID removal /// From /datum/computer_file/program/on_start: (user) #define COMSIG_COMPUTER_PROGRAM_START "computer_program_start" diff --git a/code/__DEFINES/~~bubber_defines/jobs.dm b/code/__DEFINES/~~bubber_defines/jobs.dm index dd273bbb553..611d28b39f5 100644 --- a/code/__DEFINES/~~bubber_defines/jobs.dm +++ b/code/__DEFINES/~~bubber_defines/jobs.dm @@ -20,3 +20,62 @@ #define JOB_BLACKSMITH "Blacksmith" #define JOB_DISPLAY_ORDER_BLACKSMITH 48 + +/// Time after clocking out before you can clock in again +#define TIMECLOCK_COOLDOWN 5 MINUTES + +/// What items do we want to remove from the person clocking out? +#define SELF_SERVE_RETURN_ITEMS list( \ + /obj/item/melee/baton/security, \ + /obj/item/melee/baton/security/loaded, \ + /obj/item/melee/baton/telescopic, \ + /obj/item/melee/baton, \ + /obj/item/assembly/flash/handheld, \ + /obj/item/gun/energy/disabler, \ + /obj/item/megaphone/command, \ + /obj/item/door_remote/captain, \ + /obj/item/door_remote/chief_engineer, \ + /obj/item/door_remote/research_director, \ + /obj/item/door_remote/head_of_security, \ + /obj/item/door_remote/quartermaster, \ + /obj/item/door_remote/chief_medical_officer, \ + /obj/item/door_remote/civilian, \ + /obj/item/circuitboard/machine/techfab/department/engineering, \ + /obj/item/circuitboard/machine/techfab/department/service, \ + /obj/item/circuitboard/machine/techfab/department/security, \ + /obj/item/circuitboard/machine/techfab/department/medical, \ + /obj/item/circuitboard/machine/techfab/department/cargo, \ + /obj/item/circuitboard/machine/techfab/department/science, \ + /obj/item/blueprints, \ + /obj/item/pipe_dispenser/bluespace, \ + /obj/item/mod/control/pre_equipped/advanced, \ + /obj/item/clothing/shoes/magboots/advance, \ + /obj/item/shield/riot/tele, \ + /obj/item/storage/belt/security/full, \ + /obj/item/gun/energy/e_gun/hos, \ + /obj/item/pinpointer/nuke, \ + /obj/item/gun/energy/e_gun, \ + /obj/item/storage/toolbox/guncase/skyrat/pistol/trappiste_small_case/skild, \ + /obj/item/storage/belt/sabre, \ + /obj/item/mod/control/pre_equipped/magnate, \ + /obj/item/mod/control/pre_equipped/blueshield, \ + /obj/item/clothing/suit/armor/vest/warden, \ + /obj/item/clothing/glasses/hud/security/sunglasses, \ + /obj/item/clothing/gloves/krav_maga/sec, \ + /obj/item/clothing/suit/armor/vest/alt/sec, \ + /obj/item/storage/belt/holster/detective/full, \ + /obj/item/reagent_containers/spray/pepper, \ + /obj/item/detective_scanner, \ + /obj/item/gun/ballistic/revolver/c38/detective, \ + /obj/item/mod/control/pre_equipped/security, \ + /obj/item/mod/control/pre_equipped/safeguard, \ + /obj/item/gun/energy/cell_loaded/medigun/cmo, \ + /obj/item/defibrillator/compact/loaded, \ + /obj/item/storage/hypospraykit/cmo/preloaded, \ + /obj/item/mod/control/pre_equipped/rescue, \ + /obj/item/gun/ballistic/rifle/boltaction/sporterized, \ + /obj/item/clothing/glasses/hud/gun_permit/sunglasses, \ + /obj/item/card/id/departmental_budget/car, \ + /obj/item/clothing/suit/armor/reactive/teleport, \ + /obj/item/mod/control/pre_equipped/research, \ +) diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index e9973e6f671..3dd1f955537 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -188,7 +188,7 @@ GLOBAL_LIST_INIT(WALLITEMS_INTERIOR, typecacheof(list( /obj/machinery/status_display, /obj/machinery/ticket_machine, /obj/machinery/turretid, - /obj/machinery/time_clock, //SKYRAT EDIT TIME CLOCK + /obj/machinery/modular_computer/preset/time_clock, // BUBBER EDIT ADDITION - Punch Clock /obj/machinery/barsign, /obj/structure/extinguisher_cabinet, /obj/structure/fireaxecabinet, diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index de13d846230..9c505bfdc30 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -319,6 +319,7 @@ computer_id_slot.forceMove(drop_location()) computer_id_slot = null + SEND_SIGNAL(src, COMSIG_MODULAR_COMPUTER_REMOVED_ID, computer_id_slot, user) // BUBBER EDIT ADDITION - Signal on ID removal if(!silent && !isnull(user)) to_chat(user, span_notice("You remove the card from the card slot.")) diff --git a/code/modules/modular_computers/computers/item/pda.dm b/code/modules/modular_computers/computers/item/pda.dm index 2691c91275c..28fdc1049e2 100644 --- a/code/modules/modular_computers/computers/item/pda.dm +++ b/code/modules/modular_computers/computers/item/pda.dm @@ -38,10 +38,11 @@ /datum/computer_file/program/messenger, /datum/computer_file/program/nt_pay, /datum/computer_file/program/notepad, - // SKYRAT EDIT ADDITION START + /datum/computer_file/program/crew_manifest, + // BUBBER EDIT ADDITION START /datum/computer_file/program/maintenance/camera, // Adds camera to all base tablets - // SKRAT EDIT ADDITION END - /datum/computer_file/program/crew_manifest + /datum/computer_file/program/crew_self_serve, // Crew Self Serve + // BUBBER EDIT ADDITION END ) ///List of items that can be stored in a PDA var/static/list/contained_item = list( diff --git a/modular_skyrat/master_files/code/modules/modular_computers/computers/item/computer.dm b/modular_skyrat/master_files/code/modules/modular_computers/computers/item/computer.dm index 5a072fd075b..f1bfbb6331b 100644 --- a/modular_skyrat/master_files/code/modules/modular_computers/computers/item/computer.dm +++ b/modular_skyrat/master_files/code/modules/modular_computers/computers/item/computer.dm @@ -1,3 +1,6 @@ +// Extended PDA cells to compensate for increased round length /obj/item/modular_computer - // Extended PDA cell to compensate for increased round length + internal_cell = /obj/item/stock_parts/power_store/cell/upgraded + +/obj/item/modular_computer/processor internal_cell = /obj/item/stock_parts/power_store/cell/upgraded diff --git a/modular_skyrat/master_files/code/modules/research/designs/misc_designs.dm b/modular_skyrat/master_files/code/modules/research/designs/misc_designs.dm index 4d199f07931..d168d7a9e17 100644 --- a/modular_skyrat/master_files/code/modules/research/designs/misc_designs.dm +++ b/modular_skyrat/master_files/code/modules/research/designs/misc_designs.dm @@ -62,6 +62,7 @@ ) departmental_flags = DEPARTMENT_BITFLAG_MEDICAL +/* /datum/design/time_clock_frame name = "Time Clock Frame" desc = "A frame for a time clock console, contains all of the parts needed to build a new time clock" @@ -76,6 +77,7 @@ RND_CATEGORY_CONSTRUCTION + RND_SUBCATEGORY_CONSTRUCTION_MOUNTS, ) departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_SERVICE +*/ /datum/design/vox_gas_filter name = "Vox Gas Filter" diff --git a/modular_skyrat/master_files/code/modules/research/techweb/all_nodes.dm b/modular_skyrat/master_files/code/modules/research/techweb/all_nodes.dm index d79ec08dbac..36f3542343e 100644 --- a/modular_skyrat/master_files/code/modules/research/techweb/all_nodes.dm +++ b/modular_skyrat/master_files/code/modules/research/techweb/all_nodes.dm @@ -143,12 +143,6 @@ ////////////////////////Computer tech//////////////////////// -/datum/techweb_node/consoles/New() - design_ids += list( - "time_clock_frame", - ) - return ..() - /datum/techweb_node/hud/New() design_ids += list( "health_hud_prescription", diff --git a/modular_skyrat/modules/cryosleep/code/job.dm b/modular_skyrat/modules/cryosleep/code/job.dm index f7d9af2c6d0..97d268b181c 100644 --- a/modular_skyrat/modules/cryosleep/code/job.dm +++ b/modular_skyrat/modules/cryosleep/code/job.dm @@ -1,19 +1,26 @@ /datum/controller/subsystem/job/proc/FreeRole(rank) if(!rank) + stack_trace("FreeRole called to free job slot with no rank specified") return - job_debug("Freeing role: [rank]") var/datum/job/job = get_job(rank) if(!job) + stack_trace("FreeRole could not map rank [rank] to a job slot") return FALSE + log_econ("Modifying job slots of [job.title]. Existing slots: [job.current_positions]/[job.total_positions] New slots: [max(0, job.current_positions - 1)]/[job.total_positions]") job.current_positions = max(0, job.current_positions - 1) /// Used for clocking back in, re-claiming the previously freed role. Returns false if no slot is available. /datum/controller/subsystem/job/proc/OccupyRole(rank) if(!rank) + stack_trace("OccupyRole called to free job slot with no rank specified") return FALSE - job_debug("Occupying role: [rank]") var/datum/job/job = get_job(rank) - if(!job || job.current_positions >= job.total_positions) + if(!job) + stack_trace("FreeRole could not map rank [rank] to a job slot") return FALSE + if(job.current_positions >= job.total_positions) + log_econ("Modifying job slots of [job.title] failed due to no job slot being available. Current slots: [job.current_positions]/[job.total_positions]") + return FALSE + log_econ("Modifying job slots of [job.title]. Existing slots: [job.current_positions]/[job.total_positions] New slots: [job.current_positions + 1]/[job.total_positions]") job.current_positions = job.current_positions + 1 return TRUE diff --git a/modular_skyrat/modules/time_clock/code/console.dm b/modular_skyrat/modules/time_clock/code/console.dm deleted file mode 100644 index 791ad16cff2..00000000000 --- a/modular_skyrat/modules/time_clock/code/console.dm +++ /dev/null @@ -1,207 +0,0 @@ -#define CLOCK_IN_COOLDOWN 15 MINUTES - -/obj/machinery/time_clock - name = "time clock" - desc = "Allows employees to clock in and out of their jobs" - icon = 'modular_skyrat/modules/time_clock/icons/machinery/console.dmi' - icon_state = "timeclock" - density = FALSE - - ///What ID card is currently inside? - var/obj/item/card/id/inserted_id - ///What trim is applied to inserted IDs? - var/target_trim = /datum/id_trim/job/assistant - - //These variables are the same as the ones that the cryopods use to make annoucements - ///The radio that is used to announce when someone clocks in and clocks out. - var/obj/item/radio/headset/radio = /obj/item/radio/headset/silicon/pai - ///The channel that the radio broadcasts on. - var/announcement_channel = null - /// What alert level do we need to start preforming job checks at? - var/job_check_alert_level = SEC_LEVEL_RED - -MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/time_clock, 28) - -/obj/machinery/time_clock/Initialize(mapload) - . = ..() - radio = new radio(src) - -/obj/machinery/time_clock/Destroy() - . = ..() - if(inserted_id) - inserted_id.forceMove(drop_location()) - - if(radio) - QDEL_NULL(radio) - -/obj/machinery/time_clock/update_overlays() - . = ..() - if(machine_stat & (NOPOWER|BROKEN)) - return FALSE - - if(!inserted_id) - . += "[icon_state]_r_idle" - . += "[icon_state]_l_idle" - - else - . += "[icon_state]_r_card" - . += "[icon_state]_l_card" - -/obj/machinery/time_clock/attackby(obj/item/used_item, mob/user) - if(!istype(used_item, /obj/item/card/id)) - return ..() - - if(inserted_id) - to_chat(user, span_warning("There is already an ID card present!")) - return FALSE - - if(!user.transferItemToLoc(used_item)) - to_chat(user, span_warning("You are unable to put [used_item] inside of the [src]!")) - return FALSE - - inserted_id = used_item - update_appearance() - update_static_data_for_all_viewers() - to_chat(user, span_boldwarning("Before clocking out, please return any piece of job gear that is important or limited to your workplace.")) - - if(important_job_check()) - if(SSsecurity_level.get_current_level_as_number() >= job_check_alert_level) - to_chat(user, span_boldwarning("You are unable to clock out at the current alert level.")) - eject_inserted_id(user) - return FALSE - - if(tgui_alert(user, "You are a member of security and/or command, make sure that you ahelp before clocking out. If you decide to clock back in later, you will need to go to the Head of Personnel. Do you wish to continue?", "[src]", list("Yes", "No")) != "Yes") - eject_inserted_id(user) - return FALSE - - playsound(src, 'sound/machines/terminal/terminal_insert_disc.ogg', 50, FALSE) - return TRUE - -/obj/machinery/time_clock/click_alt(mob/user) - if(!eject_inserted_id(user)) - return CLICK_ACTION_BLOCKING - - return CLICK_ACTION_SUCCESS - -///Ejects the ID stored inside of the parent machine, if there is one. -/obj/machinery/time_clock/proc/eject_inserted_id(mob/recepient) - if(!inserted_id || !recepient) - return FALSE - - inserted_id.forceMove(drop_location()) - recepient.put_in_hands(inserted_id) - - inserted_id = FALSE - update_appearance() - update_static_data_for_all_viewers() - playsound(src, 'sound/machines/terminal/terminal_eject.ogg', 50, FALSE) - - return TRUE - -///Clocks out the currently inserted ID Card -/obj/machinery/time_clock/proc/clock_out() - if(!inserted_id) - return FALSE - - var/datum/component/off_duty_timer/timer_component = inserted_id.AddComponent(/datum/component/off_duty_timer, CLOCK_IN_COOLDOWN) - if(important_job_check()) - timer_component.hop_locked = TRUE - log_admin("[inserted_id.registered_name] clocked out as a head of staff and/or command") - - var/current_assignment = inserted_id.assignment - var/datum/id_trim/job/current_trim = inserted_id.trim - var/datum/job/clocked_out_job = current_trim.job - SSjob.FreeRole(clocked_out_job.title) - - radio.talk_into(src, "[inserted_id.registered_name], [current_assignment] has gone off-duty.", announcement_channel) - update_static_data_for_all_viewers() - - SSid_access.apply_trim_to_card(inserted_id, target_trim, TRUE) - inserted_id.assignment = "Off-Duty " + current_assignment - inserted_id.update_label() - - GLOB.manifest.modify(inserted_id.registered_name, inserted_id.assignment, inserted_id.get_trim_assignment()) - return TRUE - -///Clocks the currently inserted ID Card back in -/obj/machinery/time_clock/proc/clock_in() - if(!inserted_id) - return FALSE - - if(id_cooldown_check()) - return FALSE - - var/datum/component/off_duty_timer/id_component = inserted_id.GetComponent(/datum/component/off_duty_timer) - if(!id_component) - return FALSE - - var/datum/job/clocked_in_job = id_component.stored_trim.job - if(!SSjob.OccupyRole(clocked_in_job.title)) - say("[capitalize(clocked_in_job.title)] has no free slots available, unable to clock in!") - return FALSE - - - SSid_access.apply_trim_to_card(inserted_id, id_component.stored_trim.type, TRUE) - inserted_id.assignment = id_component.stored_assignment - - radio.talk_into(src, "[inserted_id.registered_name], [inserted_id.assignment] has returned to duty.", announcement_channel) - GLOB.manifest.modify(inserted_id.registered_name, inserted_id.assignment, inserted_id.get_trim_assignment()) - - qdel(id_component) - inserted_id.update_label() - update_static_data_for_all_viewers() - - return TRUE - -///Is the job of the inserted ID being worked by a job that in an important department? If so, this proc will return TRUE. -/obj/machinery/time_clock/proc/important_job_check() - if(!inserted_id) - return FALSE - - var/datum/id_trim/job/current_trim = inserted_id.trim - var/datum/job/clocked_in_job = current_trim.job - if((/datum/job_department/command in clocked_in_job.departments_list) || (/datum/job_department/security in clocked_in_job.departments_list)) - return TRUE - - return FALSE - -///Is the inserted ID on cooldown? returns TRUE if the ID has a cooldown -/obj/machinery/time_clock/proc/id_cooldown_check() - if(!inserted_id) - return FALSE - - var/datum/component/off_duty_timer/id_component = inserted_id.GetComponent(/datum/component/off_duty_timer) - if(!id_component) - return FALSE - - if(id_component.hop_locked) - return TRUE - - if(!id_component.on_cooldown) - return FALSE - - return TRUE - -///Is the inserted ID off-duty? Returns true if the ID is off-duty -/obj/machinery/time_clock/proc/off_duty_check() - if(!inserted_id) - return FALSE - - var/datum/component/off_duty_timer/id_component = inserted_id.GetComponent(/datum/component/off_duty_timer) - if(!id_component) - return FALSE - - return TRUE - -/obj/item/wallframe/time_clock - name = "time clock frame" - desc = "Contains all of the parts needed to assemble a wall-mounted time clock" - icon_state = "unanchoredstatusdisplay" - result_path = /obj/machinery/time_clock - pixel_shift = 28 - custom_materials = list( - /datum/material/iron = SHEET_MATERIAL_AMOUNT, - /datum/material/glass = SHEET_MATERIAL_AMOUNT * 2, - ) - -#undef CLOCK_IN_COOLDOWN diff --git a/modular_skyrat/modules/time_clock/code/console_tgui.dm b/modular_skyrat/modules/time_clock/code/console_tgui.dm deleted file mode 100644 index 3548accf753..00000000000 --- a/modular_skyrat/modules/time_clock/code/console_tgui.dm +++ /dev/null @@ -1,131 +0,0 @@ -///What items do we want to remove from the person clocking out? -#define TIME_CLOCK_RETURN_ITEMS list( \ - /obj/item/melee/baton/security, \ - /obj/item/melee/baton/security/loaded, \ - /obj/item/melee/baton/telescopic, \ - /obj/item/melee/baton, \ - /obj/item/assembly/flash/handheld, \ - /obj/item/gun/energy/disabler, \ - /obj/item/megaphone/command, \ - /obj/item/door_remote/captain, \ - /obj/item/door_remote/chief_engineer, \ - /obj/item/door_remote/research_director, \ - /obj/item/door_remote/head_of_security, \ - /obj/item/door_remote/quartermaster, \ - /obj/item/door_remote/chief_medical_officer, \ - /obj/item/door_remote/civilian, \ - /obj/item/circuitboard/machine/techfab/department/engineering, \ - /obj/item/circuitboard/machine/techfab/department/service, \ - /obj/item/circuitboard/machine/techfab/department/security, \ - /obj/item/circuitboard/machine/techfab/department/medical, \ - /obj/item/circuitboard/machine/techfab/department/cargo, \ - /obj/item/circuitboard/machine/techfab/department/science, \ - /obj/item/blueprints, \ - /obj/item/pipe_dispenser/bluespace, \ - /obj/item/mod/control/pre_equipped/advanced, \ - /obj/item/clothing/shoes/magboots/advance, \ - /obj/item/shield/riot/tele, \ - /obj/item/storage/belt/security/full, \ - /obj/item/gun/energy/e_gun/hos, \ - /obj/item/pinpointer/nuke, \ - /obj/item/gun/energy/e_gun, \ - /obj/item/storage/toolbox/guncase/skyrat/pistol/trappiste_small_case/skild, \ - /obj/item/storage/belt/sabre, \ - /obj/item/mod/control/pre_equipped/magnate, \ - /obj/item/mod/control/pre_equipped/blueshield, \ - /obj/item/clothing/suit/armor/vest/warden, \ - /obj/item/clothing/glasses/hud/security/sunglasses, \ - /obj/item/clothing/gloves/krav_maga/sec, \ - /obj/item/clothing/suit/armor/vest/alt/sec, \ - /obj/item/storage/belt/holster/detective/full, \ - /obj/item/reagent_containers/spray/pepper, \ - /obj/item/detective_scanner, \ - /obj/item/gun/ballistic/revolver/c38/detective, \ - /obj/item/mod/control/pre_equipped/security, \ - /obj/item/mod/control/pre_equipped/safeguard, \ - /obj/item/gun/energy/cell_loaded/medigun/cmo, \ - /obj/item/defibrillator/compact/loaded, \ - /obj/item/storage/hypospraykit/cmo/preloaded, \ - /obj/item/mod/control/pre_equipped/rescue, \ - /obj/item/gun/ballistic/rifle/boltaction/sporterized, \ - /obj/item/clothing/glasses/hud/gun_permit/sunglasses, \ - /obj/item/card/id/departmental_budget/car, \ - /obj/item/clothing/suit/armor/reactive/teleport, \ - /obj/item/mod/control/pre_equipped/research, \ -) - - -/obj/machinery/time_clock/ui_interact(mob/user, datum/tgui/ui) - . = ..() - if(machine_stat & (NOPOWER|BROKEN)) - return - - add_fingerprint(user) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "TimeClock", name) - ui.open() - - -/obj/machinery/time_clock/ui_state(mob/user) - return GLOB.conscious_state - -/obj/machinery/time_clock/ui_static_data(mob/user) - var/data = list() - data["inserted_id"] = inserted_id - data["station_alert_level"] = SSsecurity_level.get_current_level_as_text() - data["clock_status"] = off_duty_check() - - if(inserted_id) - data["id_holder_name"] = inserted_id.registered_name - data["id_job_title"] = inserted_id.assignment - - return data - -/obj/machinery/time_clock/ui_data(mob/user) - var/data = list() - data["current_time"] = station_time_timestamp() - - if(inserted_id) - data["insert_id_cooldown"] = id_cooldown_check() - - return data - -/obj/machinery/time_clock/ui_act(action, list/params) - . = ..() - if(.) - return - - switch(action) - if("clock_in_or_out") - if(off_duty_check()) - if(!(clock_in())) - return - log_admin("[key_name(usr)] clocked in as \an [inserted_id.assignment].") - - var/datum/mind/user_mind = usr.mind - if(user_mind) - user_mind.clocked_out_of_job = FALSE - - else - log_admin("[key_name(usr)] clocked out as \an [inserted_id.assignment].") - clock_out() - var/mob/living/carbon/human/human_user = usr - //skyrat edit begin - clocking out another person's ID no longer steals your items - if(inserted_id.registered_account.account_holder == human_user.real_name) - if(human_user) - human_user.return_items_to_console(TIME_CLOCK_RETURN_ITEMS) - - var/datum/mind/user_mind = usr.mind - if(user_mind) - user_mind.clocked_out_of_job = TRUE - //skyrat edit end - if(important_job_check()) - message_admins("[key_name(usr)] has clocked out as a head of staff. [ADMIN_JMP(src)]") - - playsound(src, 'sound/machines/ping.ogg', 50, FALSE) - - if("eject_id") - eject_inserted_id(usr) - -#undef TIME_CLOCK_RETURN_ITEMS diff --git a/modular_skyrat/modules/time_clock/code/mind.dm b/modular_skyrat/modules/time_clock/code/mind.dm deleted file mode 100644 index 244b699f2fc..00000000000 --- a/modular_skyrat/modules/time_clock/code/mind.dm +++ /dev/null @@ -1,4 +0,0 @@ -/datum/mind - /// Is our mind currently clocked out of their job? - var/clocked_out_of_job = FALSE - diff --git a/modular_skyrat/modules/time_clock/code/sign.dm b/modular_skyrat/modules/time_clock/code/sign.dm deleted file mode 100644 index 4c78f94818a..00000000000 --- a/modular_skyrat/modules/time_clock/code/sign.dm +++ /dev/null @@ -1,8 +0,0 @@ -/obj/structure/sign/poster/timeclock_psa - name = "HoP Moth - Time Clock" - desc = "This informational sign uses HoP Mothâ„¢ reminding the viewer to do their part in the station's Enterprise Resource Planning efforts, clocking out before periods of prolonged absence or leisure time." - icon = 'modular_skyrat/modules/time_clock/icons/sign.dmi' - icon_state = "moff-clockout" - anchored = TRUE - -MAPPING_DIRECTIONAL_HELPERS(/obj/structure/sign/poster/timeclock_psa, 32) diff --git a/modular_skyrat/modules/time_clock/icons/machinery/console.dmi b/modular_skyrat/modules/time_clock/icons/machinery/console.dmi deleted file mode 100644 index 51b0f5446fb8ee43a8f58daea9a116cc97eebcd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 862 zcmV-k1EKthP)V=-0C=2JR&a84 z_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRLOex6#a*U0*I5Sc+(=$pSoZ^zil2jm5sU$Nu zH903gIa`T~GbOXA7$|1Q#hF%=n41b=W2%fViqA~RNyVW7XlY7nPGTj9ZK#6*u^O0z z$3P2&dBz4h*bsITlM{Zb15sh`niB(006;YZOi9C zMKk~a0uxC@K~#90?c9q}gD?<4QK-~~sMVJL|5p=Uobx88Vk50CX@^x(e-ifVZKP+9N2L#_XQ399nrGJG8AorEjk z)3F7N>%SbdfUncFe=%Ked#`Dls#g@Z(cUWp00000U|Tc$^V#D~tmpo4Vp9L#%-cQr0*zNq7eI=%_>tNnL9E?R!H zyX?l71@o)@cd?>zEq{f$gj(WG!dLLA<3-nfkM!S%w*Aw_0RR910002&BB4JYzUe<9 z{&-&a)TX<4T}=7``hI-67fTd%(XyEx*5MKY#zexyus=00000006LyY|YoLWNW@|W$6O74UFuv oZ2@g1+ZNDP=-&eX0061J0V*~&_7!D!$^ZZW07*qoM6N<$f^9pC9smFU diff --git a/modular_skyrat/modules/time_clock/icons/sign.dmi b/modular_skyrat/modules/time_clock/icons/sign.dmi deleted file mode 100644 index 7fa733dea1b03391949187865f7fd3fb0f0c9594..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 978 zcmV;@11j&)X zK4pkEPkvrYbYM()V@-T#PlRevh;dYtTS;$SN^@XLcVbL?WKDl&Pl7NeGgn7yT1akO zNpfOLdT39DRYql2M`&G2bYV<*Wln%+PlHfIUsFY7Rz_%ANN-I-T2Mn?Qbl4_MrK$? zYGF)yWKDf$PJ!zfx_kft00DGTPE!Ct=GbNc0041%R9JLGWpiV4X>fFDZ*Bkpc$`yK zaB_9`^iy#0_2eo`Eh^5;&r`5fFwryM;w;ZhDainGjE%TBGg33tGfE(w;*!LYR3K9+ zH$N>+H#sLiIXl0!M2U+tC9|j)C~nBbnO2mTn+jnoE4cc(fQ<(LK*k+JANxj30004r zNkl2ydU zkkMxgR9s>LC!~Q=7q0-QtlVugffK9%S5)%-Rn-b6H6}=_K$KdKEZ1R7>b(*_Uju)v zfMB2B?@~x(Q$Pv^gGpflAwp<#ODkz>ud0?(5kW^MrCr@U)YIG7Zy%`ldfkK8K@AP7 zBXpFGjrd*RqVb79fY06vh^o>_s;b0=v62B09Em7Yi9|5burf8xhcW}R)?0jqXgWVf zzrBeMO#m86Mbo1dl@NwGfO!!tn4cFleQ9}R)#H)trq=QWpc{t4bY>X(`bG>kVGCdz z8by#4pKE7#Z~x%%koO6<3n0!+z~V=VV>scLI0cYJpfkqejOp>S^P%C3%gfl+wa=ds z+}z&5JwS*TiDm>3k5A7pi9|=|>)X2k{`fCG09|fR22jlR^Z)<=07*qoM6N<$g4xZd AUjP6A diff --git a/modular_zubbers/code/game/objects/effects/effects_system/effect_sparks.dm b/modular_zubbers/code/game/objects/effects/effects_system/effect_sparks.dm new file mode 100644 index 00000000000..1a1178de002 --- /dev/null +++ b/modular_zubbers/code/game/objects/effects/effects_system/effect_sparks.dm @@ -0,0 +1,21 @@ +/// A version of sparks for cosmetic purposes that doesn't set things on fire. +/proc/do_harmless_sparks(number, cardinal_only, datum/source) + var/datum/effect_system/spark_spread/quantum/harmless/sparks = new + sparks.set_up(number, cardinal_only, source) + sparks.autocleanup = TRUE + sparks.start() + +/obj/effect/particle_effect/sparks/quantum + light_color = LIGHT_COLOR_DARK_BLUE + +/obj/effect/particle_effect/sparks/quantum/harmless + name = "inert quantum sparks" + +/obj/effect/particle_effect/sparks/quantum/harmless/affect_location(turf/location, just_initialized = FALSE) + return + +/obj/effect/particle_effect/sparks/quantum/harmless/sparks_touched(datum/source, atom/singed) + return + +/datum/effect_system/spark_spread/quantum/harmless + effect_type = /obj/effect/particle_effect/sparks/quantum/harmless diff --git a/modular_zubbers/icons/obj/machines/time_clock.dmi b/modular_zubbers/icons/obj/machines/time_clock.dmi new file mode 100644 index 0000000000000000000000000000000000000000..ebf93332b8164fb84360e2e1e92585a0d89753c0 GIT binary patch literal 1106 zcmV-Y1g-mtP)V=-0C=2JR&a84 z_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRLOex6#a*U0*I5Sc+(=$pSoZ^zil2jm5DLFr{ zI6o&uGjv12I>ube z3a)-G;Ftjb0SRrbT1lWR0008{Nkl+Sn`J-GgoV&PnK`Nh#R0000@(|V{%fAY}QqmKdKHf#%gX}#%uTh!H~+kk!;>04ul z;da{jbWwC8imv6K(mw?BX0Rb9SU}Z9&6lM5Uj1W$RZXlwx-MG29In3!7(-$O5_L(g zFIod*jaY#+U9PV`2FxtS-k42+FRj~v?=#DBJnibyi~k=_{v2q!+sAWf`7u+KzP8x4 zKc8r$w-GZ<^SV%%4gdfE005`)eQB;rFYNC# zA1LkXJa9g6R)705@^(8;r(V4u;`#mLO&d|>19Gu{f1m;H0<{M3{P#!$C+7nf?to{$ zaOcm*8#v?dAJ_r!0OZgPOfv|@pO=IF{*^m0y+=~#1ETr&vRS~)avV>+dcSf+FYfO% zA1LncGao4J?=v4L?(Z`n0000004RpK_b+ImtiPX1d0!{Ffi!nG+1p%k z^9BD(#jodHpz1EKxcP#=fq2K@K_-R?^C1yXgR<(ru90t5cLnF@q0VO6&zX`JRd<2w^MUUEZtQP3&rE4r-E2Al00000000006yX8>e&nWqU00d>`_LWN%?18{ z{s!zN%;_$h;XQau`m7HzU1g6yZ$h_}@5s;Iz!m;|bO*D)g|6`LV^OV0RB1t Y0ziP5A!zf`umAu607*qoM6N<$g39m>r~m)} literal 0 HcmV?d00001 diff --git a/modular_skyrat/modules/time_clock/code/off_duty_component.dm b/modular_zubbers/modules/plexagon_selfserve/code/off_duty_component.dm similarity index 96% rename from modular_skyrat/modules/time_clock/code/off_duty_component.dm rename to modular_zubbers/modules/plexagon_selfserve/code/off_duty_component.dm index c2f26fb7347..c911dba9aea 100644 --- a/modular_skyrat/modules/time_clock/code/off_duty_component.dm +++ b/modular_zubbers/modules/plexagon_selfserve/code/off_duty_component.dm @@ -7,6 +7,8 @@ var/hop_locked = FALSE ///What was the name of the job the person was working when they clocked out? var/stored_assignment = "" + ///When was this timer added? + var/init_time /datum/component/off_duty_timer/Initialize(cooldown_timer = 0) . = ..() @@ -23,6 +25,7 @@ on_cooldown = TRUE addtimer(CALLBACK(src, PROC_REF(remove_cooldown)), cooldown_timer) + init_time = world.time RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(attempt_unlock)) /datum/component/off_duty_timer/Destroy(force, silent) diff --git a/modular_zubbers/modules/plexagon_selfserve/code/plexagon_selfserve.dm b/modular_zubbers/modules/plexagon_selfserve/code/plexagon_selfserve.dm new file mode 100644 index 00000000000..61e2305bd0c --- /dev/null +++ b/modular_zubbers/modules/plexagon_selfserve/code/plexagon_selfserve.dm @@ -0,0 +1,317 @@ +/datum/mind + /// Is our mind currently clocked out of their job? + var/clocked_out_of_job = FALSE + +/datum/computer_file/program/crew_self_serve + filename = "plexagonselfserve" + filedesc = "Plexagon Punch Clock" + downloader_category = PROGRAM_CATEGORY_SECURITY + program_open_overlay = "id" + extended_desc = "Allows crew members to remotely punch in or out of their job assignment, giving the impression they have a semblance of control over their lives." + program_flags = PROGRAM_ON_NTNET_STORE + size = 4 + tgui_id = "NtosSelfServe" + program_icon = "id-card" + /// The ID card used to authenticate. + var/obj/item/card/id/authenticated_card + /// The name of the registered user, related to `authenticated_card`. + var/authenticated_user + ///What trim is applied to inserted IDs? + var/target_trim = /datum/id_trim/job/assistant + +/datum/computer_file/program/crew_self_serve/on_start(mob/living/user) + . = ..() + if(!.) + return FALSE + + if(!computer) + stack_trace("[src] is running on a null computer!") + return FALSE + + computer.crew_manifest_update = TRUE + register_signals() + if(computer.computer_id_slot) + authenticate(id_card = computer.computer_id_slot) + + return TRUE + +/datum/computer_file/program/crew_self_serve/kill_program(mob/user) + UnregisterSignal(computer, COMSIG_MODULAR_COMPUTER_INSERTED_ID) + UnregisterSignal(computer, COMSIG_MODULAR_COMPUTER_REMOVED_ID) + return ..() + +/datum/computer_file/program/crew_self_serve/proc/register_signals() + RegisterSignal(computer, COMSIG_MODULAR_COMPUTER_INSERTED_ID, PROC_REF(id_changed)) + RegisterSignal(computer, COMSIG_MODULAR_COMPUTER_REMOVED_ID, PROC_REF(id_changed)) + +/datum/computer_file/program/crew_self_serve/proc/id_changed(source, obj/item/card/id/id_card, mob/user) + SIGNAL_HANDLER + authenticate(id_card = computer.computer_id_slot) + +/** + * Authenticates the program based on the specific ID card. + * + * Arguments: + * * auth_card - The ID card to attempt to authenticate under. + */ +/datum/computer_file/program/crew_self_serve/proc/authenticate(source, obj/item/card/id/id_card) + if(!id_card) + authenticated_card = null + authenticated_user = null + else + authenticated_card = id_card + authenticated_user = "[authenticated_card.name]" + + computer.update_static_data_for_all_viewers() + +/// Clocks out the currently inserted ID Card +/datum/computer_file/program/crew_self_serve/proc/clock_out() + if(!authenticated_card) + return FALSE + + var/important = job_is_CMD_or_SEC() + if(important) + if(tgui_alert(usr, "You are a member of security and/or command, make sure that you ahelp before punching out! If you decide to punch back in later, you will need to go to the Head of Personnel or Head of Security. Do you wish to continue?", "[src]", list("No", "Yes")) != "Yes") + return FALSE + + log_econ("[authenticated_card.registered_name] clocked out from role [authenticated_card.get_trim_assignment()]") + var/datum/component/off_duty_timer/timer_component = authenticated_card.AddComponent(/datum/component/off_duty_timer, TIMECLOCK_COOLDOWN) + if(important) + timer_component.hop_locked = TRUE + log_econ("[authenticated_card.registered_name] job slot [authenticated_card.get_trim_assignment()] has been locked from clocking back in") + message_admins("[ADMIN_LOOKUPFLW(usr)] clocked out from [span_comradio("restricted role")]: [authenticated_card.get_trim_assignment()].") + else + message_admins("[ADMIN_LOOKUPFLW(usr)] clocked out from role: [authenticated_card.get_trim_assignment()].") + + var/current_assignment = authenticated_card.assignment + var/datum/id_trim/job/current_trim = authenticated_card.trim + var/datum/job/clocked_out_job = current_trim.job + SSjob.FreeRole(clocked_out_job.title) + + var/obj/machinery/announcement_system/system = pick(GLOB.announcement_systems) + system.broadcast("[authenticated_card.registered_name], [current_assignment] has gone off-duty.", list()) + computer.update_static_data_for_all_viewers() + + SSid_access.apply_trim_to_card(authenticated_card, target_trim, TRUE) + authenticated_card.assignment = "Off-Duty " + current_assignment + authenticated_card.update_label() + + GLOB.manifest.modify(authenticated_card.registered_name, authenticated_card.assignment, authenticated_card.get_trim_assignment()) + return TRUE + +/// Clocks the currently inserted ID Card back in +/datum/computer_file/program/crew_self_serve/proc/clock_in() + if(!authenticated_card) + return FALSE + + if(id_cooldown_check()) + return FALSE + + var/datum/component/off_duty_timer/id_component = authenticated_card.GetComponent(/datum/component/off_duty_timer) + if(!id_component) + return FALSE + + var/datum/job/clocked_in_job = id_component.stored_trim.job + if(!SSjob.OccupyRole(clocked_in_job.title)) + computer.say("[capitalize(clocked_in_job.title)] has no free slots available, unable to punch in!") + return FALSE + + + SSid_access.apply_trim_to_card(authenticated_card, id_component.stored_trim.type, TRUE) + authenticated_card.assignment = id_component.stored_assignment + + log_econ("[authenticated_card.registered_name] clocked in to role [authenticated_card.get_trim_assignment()]") + message_admins("[ADMIN_LOOKUPFLW(usr)] clocked in to role: [authenticated_card.get_trim_assignment()].") + + var/obj/machinery/announcement_system/system = pick(GLOB.announcement_systems) + system.broadcast("[authenticated_card.registered_name] has returned to assignment [authenticated_card.assignment].", list()) + GLOB.manifest.modify(authenticated_card.registered_name, authenticated_card.assignment, authenticated_card.get_trim_assignment()) + + qdel(id_component) + authenticated_card.update_label() + computer.update_static_data_for_all_viewers() + + return TRUE + +/// Is the job of the inserted ID being worked by a job that in an important department? If so, this proc will return TRUE. +/datum/computer_file/program/crew_self_serve/proc/job_is_CMD_or_SEC() + if(!authenticated_card) + return FALSE + + var/datum/id_trim/job/current_trim = authenticated_card.trim + var/datum/job/clocked_in_job = current_trim.job + if((/datum/job_department/command in clocked_in_job.departments_list) || (/datum/job_department/security in clocked_in_job.departments_list)) + return TRUE + + return FALSE + +/// Is the inserted ID on cooldown? return -1 if invalid ID, 0 if ID is not on cooldown, and remaining time until cooldown ends otherwise. +/datum/computer_file/program/crew_self_serve/proc/id_cooldown_check() + if(!authenticated_card) + return -1 + + var/datum/component/off_duty_timer/id_component = authenticated_card.GetComponent(/datum/component/off_duty_timer) + if(!id_component) + return -1 + + if(!id_component.on_cooldown) + return 0 + + return max(TIMECLOCK_COOLDOWN - (world.time - id_component.init_time), 0) + +/// Returns the remaining time left for the ID, as a minutes:seconds string. +/datum/computer_file/program/crew_self_serve/proc/id_cooldown_minutes_seconds() + var/cooldownTics = id_cooldown_check() + if (cooldownTics == -1) + return "--:--" + + var/cooldownMinutes = num2text(floor(cooldownTics / (1 MINUTES))) + if (length(cooldownMinutes) == 1) + cooldownMinutes = addtext("0", cooldownMinutes) + var/cooldownSeconds = num2text(floor(cooldownTics / (1 SECONDS)) % (60)) + if (length(cooldownSeconds) == 1) + cooldownSeconds = addtext("0", cooldownSeconds) + + return addtext(cooldownMinutes, ":", cooldownSeconds) + +/// Is the inserted ID locked from clocking in? returns TRUE if the ID is locked +/datum/computer_file/program/crew_self_serve/proc/id_locked_check() + if(!authenticated_card) + return FALSE + + var/datum/component/off_duty_timer/id_component = authenticated_card.GetComponent(/datum/component/off_duty_timer) + if(!id_component) + return FALSE + + if(id_component.hop_locked) + return TRUE + + return FALSE + +/// Is the inserted ID off-duty? Returns true if the ID is off-duty +/datum/computer_file/program/crew_self_serve/proc/off_duty_check() + if(!authenticated_card) + return FALSE + + var/datum/component/off_duty_timer/id_component = authenticated_card.GetComponent(/datum/component/off_duty_timer) + if(!id_component) + return FALSE + + return TRUE + +/datum/computer_file/program/crew_self_serve/kill_program(mob/user) + computer.crew_manifest_update = FALSE + if(!isnull(authenticated_card)) + authenticated_card = null + + return ..() + +/// Places any items inside of the `eligible_items` list to a lockbox, to be opened by the player when they clock back in. +/datum/computer_file/program/crew_self_serve/proc/secure_items(mob/living/carbon/human/human_user, list/eligible_items) + var/obj/item/storage/lockbox/timeclock/shame_box = new /obj/item/storage/lockbox/timeclock(get_turf(authenticated_card), authenticated_card) + if(isnull(shame_box) || !istype(shame_box)) + stack_trace("Failed to create lockbox for [authenticated_card.registered_name] trim clock-out.") + return FALSE + + var/list/held_contents = human_user.get_contents() + if(!held_contents) + CRASH("Lockbox secure items: no items found on [authenticated_card.registered_name]. that's probably incorrect!") + + var/list/shamebox_items = list() + for(var/obj/item/found_item in held_contents) + if(!is_type_in_list(found_item, eligible_items)) + continue + human_user.transferItemToLoc(found_item, shame_box, force = TRUE, silent = TRUE) + LAZYADD(shamebox_items, "[found_item.name]") + + if(!length(shame_box.contents)) + qdel(shame_box) + return TRUE + + shame_box.locked_contents = english_list(shamebox_items) + do_harmless_sparks(number = 4, source = shame_box) + to_chat(human_user, span_warning("You feel weight lifted off your shoulders as items are teleported off your body!")) + to_chat(human_user, span_notice("Items moved to lockbox: [shame_box.locked_contents].")) + computer.say( + message = "A service contract between Nanotrasen and Lustwish stipulates that company issued batons, masks, restraints, and other equipment are not to be used for recreational purposes. Employees may purchase recreational provisions from an approved vendor. Your restricted items have been placed in a lockbox to be retrieved after punch in.", + forced = TRUE, + ) + return TRUE + +/datum/computer_file/program/crew_self_serve/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) + . = ..() + switch(action) + if("PRG_change_status") + if(!authenticated_card) + return + + if(off_duty_check()) + if(!authenticated_card) + return + + if(!clock_in()) + return + + var/datum/mind/user_mind = usr.mind + if(user_mind) + user_mind.clocked_out_of_job = FALSE + + computer.update_static_data_for_all_viewers() + playsound(computer, 'sound/machines/ping.ogg', 50, FALSE) + + else + if(!clock_out()) + return + + var/mob/living/carbon/human/human_user = usr + if(human_user) + secure_items(human_user, eligible_items = SELF_SERVE_RETURN_ITEMS) + + var/datum/mind/user_mind = usr.mind + if(user_mind) + user_mind.clocked_out_of_job = TRUE + + computer.update_static_data_for_all_viewers() + playsound(computer, 'sound/machines/ping.ogg', 50, FALSE) + computer.RemoveID(human_user, silent = TRUE) + authenticate(id_card = computer.computer_id_slot) + + return TRUE + + if("PRG_eject_id") + var/mob/living/carbon/human/human_user = usr + if(human_user) + computer.RemoveID(human_user, silent = TRUE) + authenticate(id_card = computer.computer_id_slot) + + return TRUE + +/datum/computer_file/program/crew_self_serve/ui_data(mob/user) + var/list/data = list() + data["authCard"] = authenticated_card ? authenticated_card.name : "-----" + data["authCardHOPLocked"] = id_locked_check() + data["authCardTimeLocked"] = id_cooldown_check() > 0 + data["authCardTimeRemaining"] = id_cooldown_minutes_seconds() + + return data + +/datum/computer_file/program/crew_self_serve/ui_static_data(mob/user) + var/list/data = list() + data["stationAlertLevel"] = SSsecurity_level.get_current_level_as_text() + if(authenticated_card) + data["authIDName"] = authenticated_card.registered_name ? authenticated_card.registered_name : "-----" + data["authIDRank"] = authenticated_card.assignment ? authenticated_card.assignment : "Unassigned" + data["authCardHOPLocked"] = id_locked_check() + data["trimClockedOut"] = off_duty_check() + if(authenticated_card.trim) + var/datum/id_trim/card_trim = authenticated_card.trim + data["trimAssignment"] = card_trim.assignment ? card_trim.assignment : "" + else + data["trimAssignment"] = "" + else + data["authIDName"] = "" + data["authIDRank"] = "" + data["trimClockedOut"] = FALSE + data["trimAssignment"] = "" + + return data diff --git a/modular_zubbers/modules/plexagon_selfserve/code/shame_box.dm b/modular_zubbers/modules/plexagon_selfserve/code/shame_box.dm new file mode 100644 index 00000000000..6feea502046 --- /dev/null +++ b/modular_zubbers/modules/plexagon_selfserve/code/shame_box.dm @@ -0,0 +1,74 @@ +/obj/item/storage/lockbox/timeclock + name = "crew equipment lockbox" + desc = "Holds a crew's restricted equipment while they are temporarily assigned off-duty. A service contract between Nanotrasen and Lustwish stipulates that company issued batons, masks, restraints, and other equipment are not to be used for recreational purposes. Employees may purchase recreational provisions from an approved vendor." + icon = 'modular_zubbers/modules/plexagon_selfserve/icons/shame_box.dmi' + icon_state = "crewbox+l" + icon_locked = "crewbox+l" + icon_closed = "crewbox" + icon_broken = "crewbox+b" + w_class = WEIGHT_CLASS_NORMAL + req_access = list(ACCESS_ALL_PERSONAL_LOCKERS) + /// The ID card associated with the box + var/obj/item/card/id/associated_card + /// A display formatted list of the locked contents + var/locked_contents = null + +/obj/item/storage/lockbox/timeclock/Initialize(mapload, obj/item/card/id/crew_id) + . = ..() + atom_storage.allow_big_nesting = TRUE + atom_storage.max_slots = 99 + atom_storage.max_specific_storage = WEIGHT_CLASS_GIGANTIC + atom_storage.max_total_storage = 99 + if(!isnull(crew_id) || !istype(crew_id)) + associated_card = crew_id + if(associated_card?.registered_name) + name = "[initial(name)] - [associated_card.registered_name]" + +/obj/item/storage/lockbox/timeclock/examine(mob/user) + . = ..() + if(!isnull(locked_contents)) + . += span_notice("The contents label reads: [locked_contents].") + +/obj/item/storage/lockbox/timeclock/can_unlock(mob/living/user, obj/item/card/id/id_card) + . = ..() + if(!.) + to_chat(user, span_warning("[src] can only be unlocked while on-duty or by the HoP, HoS, or Captain!")) + +/// Timeclock boxes can only be opened while the crew member is on duty, or by a command member with the proper access. +/obj/item/storage/lockbox/timeclock/check_access(obj/item/crew_id) + if(isnull(crew_id)) + return FALSE + + var/obj/item/card/id/access_card + if(istype(crew_id, /obj/item/modular_computer/pda)) + var/obj/item/modular_computer/pda/crew_pda = crew_id + access_card = crew_pda.computer_id_slot + else + access_card = crew_id + + if(isnull(access_card)) + return FALSE + if(!istype(access_card)) + return FALSE + if(check_access_list(access_card.GetAccess())) + release_contents() + return TRUE + if(access_card != associated_card) + return FALSE + + var/datum/id_trim/job/current_trim = access_card.trim + if(isnull(current_trim)) + return FALSE + if(istype(current_trim, /datum/id_trim/job/assistant)) + return FALSE + + release_contents() + return TRUE + +/// Timeclock boxes are one time use. When unlocked, release the contents and go away. +/obj/item/storage/lockbox/timeclock/proc/release_contents() + do_harmless_sparks(number = 6, source = src) + emptyStorage() + usr.visible_message(span_notice("[usr] activates the lockbox mechanism, releasing its contents before vanishing in a puff of bluespace smoke!")) + associated_card = null + qdel(src) diff --git a/modular_zubbers/modules/plexagon_selfserve/code/sign.dm b/modular_zubbers/modules/plexagon_selfserve/code/sign.dm new file mode 100644 index 00000000000..4cbae7ac45e --- /dev/null +++ b/modular_zubbers/modules/plexagon_selfserve/code/sign.dm @@ -0,0 +1,15 @@ +/obj/structure/sign/poster/timeclock_psa + name = "HoP Moth - punch clock" + desc = "This informational sign uses HoP Mothâ„¢ reminding the viewer to do their part in the station's Enterprise Resource Planning efforts, punching out before periods of prolonged absence or leisure time." + icon = 'modular_zubbers/modules/plexagon_selfserve/icons/sign.dmi' + icon_state = "moff-clockout" + anchored = TRUE + +/obj/structure/sign/poster/timeclock_psa/Initialize(mapload) + . = ..() + if(prob(30)) + name = "punch clock, punch shit" + icon_state = "punch-clock" + desc = "The informational sign for the punch clock is looking more aggressive than usual today. Better punch out before you punch shit!" + +MAPPING_DIRECTIONAL_HELPERS(/obj/structure/sign/poster/timeclock_psa, 32) diff --git a/modular_zubbers/modules/plexagon_selfserve/code/time_clock.dm b/modular_zubbers/modules/plexagon_selfserve/code/time_clock.dm new file mode 100644 index 00000000000..f02ae1ad621 --- /dev/null +++ b/modular_zubbers/modules/plexagon_selfserve/code/time_clock.dm @@ -0,0 +1,21 @@ +/obj/machinery/modular_computer/preset/time_clock + name = "punch clock" + desc = "Allows employees to punch in and out of their jobs. Figuratively, not literally... I hope." + icon = 'modular_zubbers/icons/obj/machines/time_clock.dmi' + density = FALSE + light_color = LIGHT_COLOR_DARK_BLUE + starting_programs = list( + /datum/computer_file/program/crew_self_serve, + ) + +MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/modular_computer/preset/time_clock, 28) + +/obj/machinery/modular_computer/preset/time_clock/Initialize(mapload) + . = ..() + SSticker.OnRoundstart(CALLBACK(src, PROC_REF(setup_starting_software))) + +/obj/machinery/modular_computer/preset/time_clock/proc/setup_starting_software() + var/datum/computer_file/program/crew_self_serve/punch_clock = cpu.find_file_by_name("plexagonselfserve") + cpu.active_program = punch_clock + punch_clock.register_signals() + set_light(light_strength) diff --git a/modular_zubbers/modules/plexagon_selfserve/icons/shame_box.dmi b/modular_zubbers/modules/plexagon_selfserve/icons/shame_box.dmi new file mode 100644 index 0000000000000000000000000000000000000000..8f1ec25a3a51ea393b61747e6dafef0e2c81b033 GIT binary patch literal 473 zcmV;~0Ve*5P)pq||?W>??R;EhT zu!}8NBEGanCu+5IYG1U7e@%GfV*;_&=NiPmCXu>kG9Biufc+k`dJZa6kAz@Id_!_oMzt!2bU! zf!F^C*#9sAY99Ci)c-hvKHUDt3G4xD2|)kj1fc(Mg4I(%{g250Pu6$>s!S2{EmsUi P00000NkvXXu0mjfk!s66 literal 0 HcmV?d00001 diff --git a/modular_zubbers/modules/plexagon_selfserve/icons/sign.dmi b/modular_zubbers/modules/plexagon_selfserve/icons/sign.dmi new file mode 100644 index 0000000000000000000000000000000000000000..0a41293152d1a9c4b2ed56e6b5b18bf36722a70f GIT binary patch literal 1451 zcmV;c1yuTpP)vvY1DlR>|BO`NFmKYi%3sSfMX#XQ4BXCoZ zfm^JDT(B7#8EsOGZ&QzZS)+bhr+{0l5D*Z`rig4(i*Hkobyk^pSDw|mqOXQxf?TaA zC@9vA00{{RYf*`AQjKy{m3&#Gep;wOMqUI21Zhx*ZBmPNR-1WPpLh($TS;+VOLg$v)9~EY?b_6DQ;=~~lyp^? zd03!>T(87|09imjEp%0xcvqc&TB(CwurDt!uX6x2JXE}U0BKN$c2=5vTBW&p09hI;iXs4HO@3xh zf@n{MY*C7LR-GUqAhUG6%{x*I4&+O8X6iBzk*r- z0004WQchCV=-0C=2JR&a84_w-Y6@%7{?OD!tS z%+FJ>RWQ*r;NmRLOex6#a*U0*I5Sc+(=$pSoZ^zil2jm5DK|eYO*c6wKRG+Uv_y%E zGbOXA7$|PY#hF%=n41b=!&MiQ<|Su9l;cvXtl;YB0(J@jsZlC9%b6Ka0008YNklL7Bsi;+P z;+}t`m(^T~eDr5OzI<}c==k;^iwG6i~8~VPKA60(Oq$khUp}cEVCXDWipwR%V0+AQ?_@BB#=D2!LED zrhsx%0O)|LqO1bk?g|$LRB{~2)HbC7@?ojK!>C9z;_I5J2X&_%2gX2S?6KaHpLdsjP05}{LPm19%_VTnM}%(oJ>j+*C*iy+yuA-n;)`YKrt@u*(Fh zQ0CE@LM%W^)&M#6aQYEECbypecuXM8WtIV_{&NP-0!Xqfr({`5J$=^K|9oa<^2N)R z09655$}~V-4^#>L9(eWo4ZH>DB;Oe|fms3|9U+UE0-$*+c=!Ip$4}GK-94Ybe6=iT z`dXSfumXSjU$Bj*)9G)OEXy{`R?XUq9N!&3>_638zW{C7)F)rj_<#Ta002ovPDHLk FV1mF+Wc&aC literal 0 HcmV?d00001 diff --git a/tgstation.dme b/tgstation.dme index 71885af112f..e1c44c42ebb 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -8586,11 +8586,6 @@ #include "modular_skyrat\modules\teshari\code\teshari_bodytype.dm" #include "modular_skyrat\modules\teshari\code\teshari_clothes.dm" #include "modular_skyrat\modules\ticket_counter\code\counter.dm" -#include "modular_skyrat\modules\time_clock\code\console.dm" -#include "modular_skyrat\modules\time_clock\code\console_tgui.dm" -#include "modular_skyrat\modules\time_clock\code\mind.dm" -#include "modular_skyrat\modules\time_clock\code\off_duty_component.dm" -#include "modular_skyrat\modules\time_clock\code\sign.dm" #include "modular_skyrat\modules\title_screen\code\_title_screen_defines.dm" #include "modular_skyrat\modules\title_screen\code\job_traits.dm" #include "modular_skyrat\modules\title_screen\code\new_player.dm" @@ -8803,6 +8798,7 @@ #include "modular_zubbers\code\game\machinery\pipe\construction.dm" #include "modular_zubbers\code\game\objects\effects\landmarks.dm" #include "modular_zubbers\code\game\objects\effects\decals\cleanable.dm" +#include "modular_zubbers\code\game\objects\effects\effects_system\effect_sparks.dm" #include "modular_zubbers\code\game\objects\effects\items\plushes.dm" #include "modular_zubbers\code\game\objects\effects\spawners\random\armory.dm" #include "modular_zubbers\code\game\objects\effects\spawners\random\moonstation_random.dm" @@ -9465,5 +9461,10 @@ #include "modular_zubbers\master_files\skyrat\modules\deforest_medical_items\code\cargo_packs.dm" #include "modular_zubbers\master_files\skyrat\modules\opposing_force\code\opposing_force_subsystem.dm" #include "modular_zubbers\master_files\skyrat\modules\verbs\code\subtle.dm" +#include "modular_zubbers\modules\plexagon_selfserve\code\off_duty_component.dm" +#include "modular_zubbers\modules\plexagon_selfserve\code\plexagon_selfserve.dm" +#include "modular_zubbers\modules\plexagon_selfserve\code\shame_box.dm" +#include "modular_zubbers\modules\plexagon_selfserve\code\sign.dm" +#include "modular_zubbers\modules\plexagon_selfserve\code\time_clock.dm" // END_INCLUDE diff --git a/tgui/packages/tgui/interfaces/NtosSelfServe.tsx b/tgui/packages/tgui/interfaces/NtosSelfServe.tsx new file mode 100644 index 00000000000..ec12f2b98e8 --- /dev/null +++ b/tgui/packages/tgui/interfaces/NtosSelfServe.tsx @@ -0,0 +1,146 @@ +import { capitalizeFirst } from 'common/string'; + +import { useBackend } from '../backend'; +import { Button, NoticeBox, Section, Stack } from '../components'; +import { NtosWindow } from '../layouts'; +import { NTOSData } from '../layouts/NtosWindow'; + +type Data = { + authCard: string; + authCardTimeRemaining: string; + authIDName: string; + authIDRank: string; + hasTrim: boolean; + trimAssignment: string; + stationAlertLevel: string; + trimClockedOut: boolean; + authCardHOPLocked: boolean; + authCardTimeLocked: boolean; + selfServeBlock: boolean; +} & NTOSData; + +export const NtosSelfServe = (props) => { + const { act, data } = useBackend(); + + return ( + + + + + + + + + + ); +}; + +const SelfServePage = (props) => { + const { act, data } = useBackend(); + const { + authCardTimeRemaining, + authIDName, + authIDRank, + authCardHOPLocked, + authCardTimeLocked, + stationAlertLevel, + trimClockedOut, + trimAssignment, + } = data; + + return ( +
+
+ + + Current Assignment: {trimAssignment || '-----'} + + + Job Title: {authIDRank || '-----'} + + + Current Status: {trimClockedOut ? 'Off-Duty' : 'Active Duty'} + + + Station Alert Level: {capitalizeFirst(stationAlertLevel) || '-----'} + + +
+ +
+ + + + + + + +
+
+ + {!trimClockedOut ? ( + + + Before punching out, please return any job gear that is + important or limited to your workplace. + + + While off-duty, any restricted items will be transferred to a + crew equipment lockbox, to be returned upon punching in. + + + ) : ( + '' + )} + {authCardHOPLocked ? ( + + + Assignment Locked! +
+
+ Security and Command members must visit an appropriate Command + member to punch in! +
+
+ ) : authCardTimeLocked ? ( + + + It is too early to return to your assignment! +
+ Time remaining: {authCardTimeRemaining} +
+
+ Please visit the HoP window or your departmental Command member + for an override. +
+
+ ) : ( + '' + )} +
+
+
+ ); +}; diff --git a/tools/UpdatePaths/Scripts_Bubber/2900_Time_Clock.txt b/tools/UpdatePaths/Scripts_Bubber/2900_Time_Clock.txt new file mode 100644 index 00000000000..15bb101e680 --- /dev/null +++ b/tools/UpdatePaths/Scripts_Bubber/2900_Time_Clock.txt @@ -0,0 +1 @@ +/obj/machinery/time_clock : /obj/machinery/modular_computer/preset/time_clock{@OLD}