diff --git a/_maps/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm b/_maps/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm index 2e6a25bdab3..caf994011d8 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm @@ -1075,7 +1075,7 @@ /turf/closed/wall/mineral/sandstone, /area/ruin/powered/beach) "NJ" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /turf/open/floor/wood, /area/ruin/powered/beach) "NK" = ( diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm index b79b3650238..4a71ef27f78 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm @@ -4099,6 +4099,7 @@ "Ue" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/computer/slot_machine/syndicate, /turf/open/floor/iron/dark, /area/ruin/syndicate_lava_base/bar) "Um" = ( diff --git a/_maps/RandomRuins/SpaceRuins/listeningstation.dmm b/_maps/RandomRuins/SpaceRuins/listeningstation.dmm index cb069a04b11..0ce9d1fb7c4 100644 --- a/_maps/RandomRuins/SpaceRuins/listeningstation.dmm +++ b/_maps/RandomRuins/SpaceRuins/listeningstation.dmm @@ -186,6 +186,10 @@ /obj/machinery/hydroponics/soil, /turf/open/floor/iron, /area/ruin/space/has_grav/listeningstation) +"iN" = ( +/obj/machinery/computer/slot_machine/syndicate, +/turf/open/floor/plating, +/area/ruin/space/has_grav/listeningstation) "jr" = ( /obj/machinery/power/port_gen/pacman{ anchored = 1 @@ -1346,7 +1350,7 @@ FV ca BX dW -We +iN JB vI vI diff --git a/_maps/RandomZLevels/SnowCabin.dmm b/_maps/RandomZLevels/SnowCabin.dmm index 52579ccdacc..d164796beab 100644 --- a/_maps/RandomZLevels/SnowCabin.dmm +++ b/_maps/RandomZLevels/SnowCabin.dmm @@ -639,7 +639,7 @@ /turf/open/floor/wood, /area/awaymission/cabin) "cN" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /turf/open/floor/carpet, /area/awaymission/cabin) "cO" = ( diff --git a/_maps/RandomZLevels/TheBeach.dmm b/_maps/RandomZLevels/TheBeach.dmm index 1cecb4bebfe..3eb04da8ee6 100644 --- a/_maps/RandomZLevels/TheBeach.dmm +++ b/_maps/RandomZLevels/TheBeach.dmm @@ -4026,7 +4026,7 @@ /obj/structure/sign/directions/medical/directional/north{ pixel_y = 29 }, -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /turf/open/floor/wood/large, /area/awaymission/beach) "Zt" = ( diff --git a/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm b/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm index fe79d7aa3aa..3ad6324e364 100644 --- a/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm +++ b/_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm @@ -10861,7 +10861,7 @@ /turf/open/floor/iron, /area/station/hallway/secondary/construction) "cOJ" = ( -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /obj/effect/decal/cleanable/glitter, @@ -24017,7 +24017,7 @@ "goW" = ( /obj/effect/decal/cleanable/cobweb/cobweb2, /obj/effect/decal/cleanable/dirt, -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /turf/open/floor/wood, @@ -31604,7 +31604,7 @@ "itr" = ( /obj/effect/turf_decal/siding/thinplating_new/dark, /obj/structure/extinguisher_cabinet/directional/south, -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /turf/open/floor/iron/dark/smooth_large, @@ -33224,7 +33224,7 @@ /turf/open/floor/iron/white, /area/station/hallway/secondary/entry) "iPv" = ( -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /obj/effect/decal/cleanable/dirt, @@ -60940,7 +60940,7 @@ /turf/open/floor/iron, /area/station/maintenance/starboard/aft) "qjy" = ( -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /turf/open/floor/iron, @@ -63099,7 +63099,7 @@ /turf/open/floor/iron/dark/textured, /area/station/cargo/sorting) "qNo" = ( -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /obj/effect/decal/cleanable/blood/oil, @@ -65052,7 +65052,7 @@ /turf/open/floor/iron, /area/station/science/research) "rpq" = ( -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /turf/open/floor/plating, @@ -79748,7 +79748,7 @@ /turf/open/floor/iron/dark, /area/station/service/chapel) "vgV" = ( -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /obj/effect/decal/cleanable/dirt, @@ -84488,7 +84488,7 @@ /turf/open/floor/iron, /area/station/cargo/storage) "wtN" = ( -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /obj/effect/decal/cleanable/vomit/old, diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index ab953026673..c9d741ff81e 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -3868,7 +3868,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/neutral/half/contrasted{ dir = 1 @@ -56213,7 +56213,7 @@ /obj/structure/disposalpipe/segment{ dir = 10 }, -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 1dc2cef08cc..ddd0b28d8f1 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -17243,7 +17243,7 @@ /obj/machinery/camera/directional/east{ c_tag = "Service - Gambling Lounge" }, -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ name = "two-armed bandit" }, /turf/open/floor/wood/large, @@ -28771,7 +28771,7 @@ /area/station/security/prison/rec) "ibJ" = ( /obj/item/radio/intercom/directional/east, -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ name = "two-armed bandit" }, /turf/open/floor/wood/large, @@ -52934,7 +52934,7 @@ /turf/open/floor/iron/grimy, /area/station/maintenance/aft/greater) "oMP" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /turf/open/floor/wood, /area/station/command/meeting_room) "oMR" = ( diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index fcfef778c10..0b681656f74 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -11658,7 +11658,7 @@ /turf/open/floor/iron, /area/station/service/hydroponics) "ebG" = ( -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /obj/effect/mapping_helpers/broken_floor, @@ -12536,7 +12536,7 @@ /turf/open/floor/wood, /area/station/commons/lounge) "eov" = ( -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /obj/effect/mapping_helpers/broken_floor, @@ -22916,7 +22916,7 @@ /turf/open/floor/engine, /area/station/science/xenobiology) "hWj" = ( -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /turf/open/floor/wood, @@ -40886,7 +40886,7 @@ /area/station/command/bridge) "nXG" = ( /obj/machinery/newscaster/directional/north, -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /obj/effect/turf_decal/tile/bar/opposingcorners, @@ -51307,7 +51307,7 @@ /area/station/security/interrogation) "rzi" = ( /obj/machinery/airalarm/directional/north, -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /obj/effect/turf_decal/tile/bar/opposingcorners, diff --git a/_maps/map_files/NebulaStation/NebulaStation.dmm b/_maps/map_files/NebulaStation/NebulaStation.dmm index 39dc26cc6e4..0060c13dc5a 100644 --- a/_maps/map_files/NebulaStation/NebulaStation.dmm +++ b/_maps/map_files/NebulaStation/NebulaStation.dmm @@ -90828,7 +90828,7 @@ /obj/effect/turf_decal/siding/wood{ dir = 6 }, -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /obj/effect/turf_decal/siding/wood/corner{ dir = 1 }, @@ -137223,7 +137223,7 @@ /obj/effect/turf_decal/siding/wood{ dir = 5 }, -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /obj/effect/turf_decal/siding/wood/corner{ dir = 8 }, @@ -139659,7 +139659,7 @@ /turf/open/floor/wood, /area/station/security/courtroom) "uFM" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /obj/effect/turf_decal/siding/wood{ dir = 6 }, @@ -150211,7 +150211,7 @@ /turf/open/floor/wood/large, /area/station/service/library/upper) "wiG" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /obj/effect/turf_decal/siding/wood{ dir = 10 }, diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index 6edd7fc9d11..bc99abb402b 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -12214,7 +12214,7 @@ /turf/open/floor/iron/dark, /area/station/medical/morgue) "dds" = ( -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /obj/machinery/light/cold/directional/north, @@ -12503,7 +12503,7 @@ /turf/open/floor/iron/dark, /area/station/ai/satellite/foyer) "diN" = ( -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /turf/open/floor/iron/dark, @@ -67354,7 +67354,7 @@ /turf/open/floor/wood, /area/station/service/bar/backroom) "wwj" = ( -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /obj/machinery/light/cold/directional/south, diff --git a/_maps/map_files/wawastation/wawastation.dmm b/_maps/map_files/wawastation/wawastation.dmm index 2a439748deb..5ce45523ec0 100644 --- a/_maps/map_files/wawastation/wawastation.dmm +++ b/_maps/map_files/wawastation/wawastation.dmm @@ -5627,7 +5627,7 @@ "bXx" = ( /obj/machinery/camera/autoname/directional/south, /obj/machinery/airalarm/directional/south, -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /turf/open/floor/wood, @@ -6753,7 +6753,7 @@ /turf/open/floor/glass/reinforced, /area/station/security/prison) "ctP" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /obj/effect/decal/cleanable/dirt/dust, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/grimy, @@ -39342,7 +39342,7 @@ /turf/closed/wall/r_wall, /area/station/maintenance/central/greater) "nzw" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /obj/effect/turf_decal/sand/plating, /turf/open/floor/plating, /area/station/maintenance/central/greater) @@ -41216,7 +41216,7 @@ /turf/open/floor/iron, /area/station/hallway/primary/central) "olC" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /obj/effect/decal/cleanable/dirt/dust, /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/directional/west, @@ -62694,7 +62694,7 @@ "vxl" = ( /obj/machinery/power/apc/auto_name/directional/south, /obj/structure/cable, -/obj/machinery/computer/slot_machine{ +/obj/effect/spawner/random/entertainment/slot_machine{ pixel_y = 2 }, /turf/open/floor/wood, @@ -63653,7 +63653,7 @@ /turf/open/floor/iron/white/smooth_large, /area/station/science/research) "vNT" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron/grimy, /area/station/maintenance/central/lesser) diff --git a/_maps/shuttles/emergency_casino.dmm b/_maps/shuttles/emergency_casino.dmm index 1bfe4744198..e4521dc80b6 100644 --- a/_maps/shuttles/emergency_casino.dmm +++ b/_maps/shuttles/emergency_casino.dmm @@ -33,7 +33,7 @@ /turf/open/floor/wood, /area/shuttle/escape) "bT" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /obj/structure/window/reinforced/spawner/directional/west, /obj/structure/window/reinforced/spawner/directional/north, /turf/open/floor/carpet/green, @@ -431,7 +431,7 @@ /turf/open/floor/carpet/royalblue, /area/shuttle/escape) "mx" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /obj/structure/window/reinforced/spawner/directional/east, /obj/structure/window/reinforced/spawner/directional/north, /turf/open/floor/carpet/green, @@ -509,7 +509,7 @@ /turf/open/floor/mineral/plastitanium/red, /area/shuttle/escape/brig) "oB" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /obj/structure/window/reinforced/spawner/directional/north, /turf/open/floor/carpet/green, /area/shuttle/escape) @@ -739,7 +739,7 @@ /turf/open/floor/sepia, /area/shuttle/escape) "we" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /obj/effect/turf_decal/siding/thinplating{ dir = 8 }, @@ -911,7 +911,7 @@ /turf/open/floor/mineral/plastitanium/red, /area/shuttle/escape/brig) "Bf" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /turf/open/floor/carpet/green, /area/shuttle/escape) "Bj" = ( diff --git a/_maps/shuttles/emergency_discoinferno.dmm b/_maps/shuttles/emergency_discoinferno.dmm index d6dedd686af..73a76ec0556 100644 --- a/_maps/shuttles/emergency_discoinferno.dmm +++ b/_maps/shuttles/emergency_discoinferno.dmm @@ -122,7 +122,7 @@ /turf/open/floor/wood, /area/shuttle/escape) "C" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /obj/machinery/light/directional/west, /turf/open/floor/wood, /area/shuttle/escape) @@ -160,7 +160,7 @@ /turf/open/floor/wood, /area/shuttle/escape) "I" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /turf/open/floor/wood, /area/shuttle/escape) "J" = ( diff --git a/_maps/shuttles/hunter_psyker.dmm b/_maps/shuttles/hunter_psyker.dmm index b16650013c9..3aff0d2eed0 100644 --- a/_maps/shuttles/hunter_psyker.dmm +++ b/_maps/shuttles/hunter_psyker.dmm @@ -273,7 +273,7 @@ /area/shuttle/hunter) "lD" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /obj/effect/decal/cleanable/wrapping, /turf/open/floor/iron/grimy, /area/shuttle/hunter) diff --git a/_maps/templates/lazy_templates/nukie_base.dmm b/_maps/templates/lazy_templates/nukie_base.dmm index 7d87dc7d4e6..537fe8fda84 100644 --- a/_maps/templates/lazy_templates/nukie_base.dmm +++ b/_maps/templates/lazy_templates/nukie_base.dmm @@ -3633,6 +3633,7 @@ /area/centcom/syndicate_mothership/control) "Ni" = ( /obj/machinery/light/small/directional/north, +/obj/machinery/computer/slot_machine/syndicate, /turf/open/floor/wood/tile, /area/centcom/syndicate_mothership/control) "No" = ( diff --git a/_maps/virtual_domains/beach_bar.dmm b/_maps/virtual_domains/beach_bar.dmm index e3e4a09e96b..a41b0c87d93 100644 --- a/_maps/virtual_domains/beach_bar.dmm +++ b/_maps/virtual_domains/beach_bar.dmm @@ -1006,7 +1006,7 @@ /turf/open/floor/wood, /area/virtual_domain/fullbright) "VA" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /turf/open/floor/wood, /area/virtual_domain/fullbright) "VE" = ( diff --git a/_maps/virtual_domains/fredingtonfastingbear.dmm b/_maps/virtual_domains/fredingtonfastingbear.dmm index e28813d8c94..24174de946b 100644 --- a/_maps/virtual_domains/fredingtonfastingbear.dmm +++ b/_maps/virtual_domains/fredingtonfastingbear.dmm @@ -362,7 +362,7 @@ /turf/open/floor/iron/kitchen, /area/virtual_domain) "sk" = ( -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /turf/open/floor/iron/kitchen, /area/virtual_domain) "sl" = ( diff --git a/_maps/virtual_domains/island_brawl.dmm b/_maps/virtual_domains/island_brawl.dmm index 31a65f790ab..4688e496bbf 100644 --- a/_maps/virtual_domains/island_brawl.dmm +++ b/_maps/virtual_domains/island_brawl.dmm @@ -2228,7 +2228,7 @@ /obj/structure/sign/directions/medical/directional/north{ pixel_y = 29 }, -/obj/machinery/computer/slot_machine, +/obj/effect/spawner/random/entertainment/slot_machine, /turf/open/floor/wood/large, /area/virtual_domain) "BW" = ( diff --git a/code/game/machinery/slotmachine.dm b/code/game/machinery/slotmachine.dm index cd61dcebac0..4ff3d99a004 100644 --- a/code/game/machinery/slotmachine.dm +++ b/code/game/machinery/slotmachine.dm @@ -16,7 +16,6 @@ #define PRIZE_JACKPOT 10000 #define SPIN_TIME 4 SECONDS #define REEL_DEACTIVATE_DELAY 0.4 SECONDS -#define JACKPOT_SEVENS FA_ICON_7 #define HOLOCHIP 1 #define COIN 2 @@ -29,8 +28,8 @@ icon_screen = "slots_screen" density = TRUE circuit = /obj/item/circuitboard/computer/slot_machine - light_color = LIGHT_COLOR_BROWN interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON // don't need to be literate to play slots + light_color = LIGHT_COLOR_BROWN var/money = 3000 // How much money it has CONSUMED var/plays = 0 var/working = FALSE @@ -39,17 +38,35 @@ var/jackpots = 0 var/paymode = HOLOCHIP // toggles between HOLOCHIP/COIN, defined above var/cointype = /obj/item/coin/iron //default cointype - /// Icons that can be displayed by the slot machine. - var/static/list/icons = list( - FA_ICON_LEMON, - FA_ICON_STAR, - FA_ICON_BOMB, - FA_ICON_BIOHAZARD, - FA_ICON_APPLE_WHOLE, - FA_ICON_7, - FA_ICON_DOLLAR_SIGN, + + /// The optional bank account used as the machine's bank. Player losses are deposited here, while payouts and jackpots are deducted from its balance + var/datum/bank_account/house_bank_account + + /// Typepaths representing the symbols shown on this machine's reels + var/list/symbol_paths = list( + /obj/item/storage/bag/money, + /obj/item/food/grown/cherry_bomb, + /obj/item/grenade/flashbang, + /obj/item/poker_chip, + /obj/item/food/grown/chili, + /obj/item/clothing/neck/necklace/dope, + /obj/item/stack/spacecash/c20, ) + /// Used to determine the 1st name of the slot machine. Name = "[adjective] [noun]" + var/list/slot_adjectives = list("Blazing", "Bonus", "Grand", "Greedy", "Jumbo", "Platinum", "Lucky", "Mega", "Robust", "Super", "Turbo", "Wild") + /// Used to determine the 2nd name of the slot machine. Name = "[adjective] [noun]" + var/list/slot_nouns = list("Bankroll", "Cashout", "Fortune", "Jackpot", "Luck", "Money", "Payday", "Reels", "Riches", "Spinner", "Spins", "Strike", "Treasure", "Spess") + + /// The symbol typepath that pays out the jackpot when it lines up five wide + var/jackpot_path = /obj/item/food/grown/cherry_bomb + + /// The symbol typepath that activates a trap when it lines up five wide (set to null to disable) + var/trap_path = /obj/item/grenade/flashbang + + /// Cached list of symbol data (id/name/icon/icon_state) sent to ui_static_data + var/list/symbol_data + var/static/list/coinvalues var/list/reels = list( list("", "", ""), @@ -58,13 +75,21 @@ list("", "", ""), list("", "", ""), ) - var/static/list/ray_filter = list(type = "rays", y = 16, size = 40, density = 4, color = COLOR_RED_LIGHT, factor = 15, flags = FILTER_OVERLAY) + var/static/list/ray_filter = list(type = "rays", y = 14, size = 40, density = 4, color = COLOR_RED_LIGHT, factor = 15, flags = FILTER_OVERLAY) /obj/machinery/computer/slot_machine/Initialize(mapload) . = ..() jackpots = rand(1, 4) //false hope plays = rand(75, 200) + name = make_machine_name() + + if(jackpot_path && !(jackpot_path in symbol_paths)) + stack_trace("[type] has jackpot_path [jackpot_path] not present in symbol_paths!") + if(trap_path && !(trap_path in symbol_paths)) + stack_trace("[type] has trap_path [trap_path] not present in symbol_paths!") + + build_symbol_data() // Populate the reels randomize_reels() @@ -76,6 +101,26 @@ coinvalues["[cointype]"] = C.get_item_credit_value() qdel(C) //Sigh +/obj/machinery/computer/slot_machine/Destroy() + house_bank_account = null + . = ..() + +/// Generates a randomised slot name by pulling an adjective and a noun +/// Produces things like "Lucky Sevens", "Robust Payday", "Honking Bonanza", etc. +/obj/machinery/computer/slot_machine/proc/make_machine_name() + var/adjective = pick(slot_adjectives) + var/noun = pick(slot_nouns) + return "[adjective] [noun]" + +/// Builds symbol_data from symbol_paths to be used for DmIcon in TGUI +/obj/machinery/computer/slot_machine/proc/build_symbol_data() + symbol_data = list() + for(var/obj/symbol as anything in symbol_paths) + symbol_data += list(list( + "id" = "[symbol]", + "icon_id" = sanitize_css_class_name("[symbol::icon][symbol::icon_state]") + )) + /obj/machinery/computer/slot_machine/on_deconstruction(disassembled) if(balance) give_payout(balance) @@ -138,6 +183,35 @@ balloon_alert(user, "coins only!") return ITEM_INTERACT_BLOCKING + var/obj/item/card/id/id_card = inserted.GetID() + if(isidcard(id_card)) + if(house_bank_account) + say("Already linked to [house_bank_account.account_holder]!") + playsound(src, 'sound/machines/buzz/buzz-two.ogg', 30, TRUE) + return ITEM_INTERACT_BLOCKING + + var/datum/bank_account/id_bank_account = id_card.registered_account + + if(!id_bank_account) + say("No bank account detected on id card!") + playsound(src, 'sound/machines/buzz/buzz-two.ogg', 30, TRUE) + return ITEM_INTERACT_BLOCKING + + if(!id_bank_account.has_money(PRIZE_SMALL)) + say("Insufficent funds for potential payout. Minimum of [PRIZE_SMALL] credits needed!") + playsound(src, 'sound/machines/buzz/buzz-two.ogg', 30, TRUE) + return ITEM_INTERACT_BLOCKING + + var/msg = tgui_input_text(user, "Name of your slot machine (optional)", "Slot Customization", "Slot Machine", max_length = MAX_NAME_LEN) + if(msg) + name = msg + + playsound(src, 'sound/machines/terminal/terminal_success.ogg', 50, TRUE) + desc = "Owned by [id_bank_account.account_holder], draws directly from [user.p_their()] account." + house_bank_account = id_bank_account + to_chat(user, span_notice("You link the slot machine to [id_bank_account.account_holder]'s account.")) + return ITEM_INTERACT_SUCCESS + return NONE /obj/machinery/computer/slot_machine/multitool_act(mob/living/user, obj/item/tool) @@ -163,6 +237,11 @@ balloon_alert(user, "machine rigged") return TRUE +/obj/machinery/computer/slot_machine/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet_batched/slot_machines), + ) + /obj/machinery/computer/slot_machine/ui_interact(mob/living/user, datum/tgui/ui) . = ..() ui = SStgui.try_update_ui(user, src, ui) @@ -172,9 +251,12 @@ /obj/machinery/computer/slot_machine/ui_static_data(mob/user) var/list/data = list() - data["icons"] = icons + data["symbols"] = symbol_data data["cost"] = SPIN_PRICE data["jackpot"] = PRIZE_JACKPOT + data["jackpot_id"] = "[jackpot_path]" + if(trap_path) + data["trap_id"] = "[trap_path]" return data /obj/machinery/computer/slot_machine/ui_data(mob/user) @@ -182,7 +264,7 @@ var/list/_reels = list() for(var/reel in reels) _reels += list(list( - "icons" = reel, + "symbols" = reel, )) data["reels"] = _reels data["balance"] = balance @@ -224,10 +306,25 @@ money -= max(0, give_payout(min(rand(-50, 100 * severity_ascending)), money)) //This starts at -50 because it shouldn't always dispense coins yo spin() +/// Returns TRUE if the owner has enough funds to payout +/obj/machinery/computer/slot_machine/proc/has_funds_to_pay(payout) + if(!house_bank_account) // no owner so NT is paying + return TRUE + + if(house_bank_account.has_money(payout)) + return TRUE + + say("The bank account of [house_bank_account.account_holder] does not have enough funds to pay out the potential prize, contact them to fill up their account or lower your bet!") + playsound(src, 'sound/machines/buzz/buzz-two.ogg', 30, TRUE) + return FALSE + /obj/machinery/computer/slot_machine/proc/spin(mob/user) if(!can_spin(user)) return + if(!has_funds_to_pay(PRIZE_SMALL)) + return + if(!use_energy(active_power_usage, force = FALSE)) say("Not enough energy!") return @@ -244,6 +341,12 @@ balance -= SPIN_PRICE money += SPIN_PRICE + + if(house_bank_account) + // Since big jackpots & free games aren't deducted directly from the account holder NT takes a 40% cut of profit + // Also discourages infinite money exploits since people playing slot machines they own will cause them to slowly lose money + house_bank_account.adjust_money(SPIN_PRICE * 0.60, "Slot Machine: Spin") + plays += 1 working = TRUE @@ -284,28 +387,44 @@ /// Randomize the states of all reels /obj/machinery/computer/slot_machine/proc/randomize_reels() - for(var/reel in reels) - reel[1] = pick(icons) - reel[2] = pick(icons) - reel[3] = pick(icons) + for(var/list/reel in reels) + reel[1] = "[pick(symbol_paths)]" + reel[2] = "[pick(symbol_paths)]" + reel[3] = "[pick(symbol_paths)]" + +/// Triggers a negative effect for a slot machine if all trap icons are lined up in the middle +/obj/machinery/computer/slot_machine/proc/activate_trap(mob/living/user) + visible_message("[src] says, 'Big Loser! Prepare for your special prize!'") + + switch(trap_path) + if(/obj/item/restraints/handcuffs) + if(iscarbon(user)) + var/mob/living/carbon/carbon_user = user + playsound(loc, 'sound/items/weapons/handcuffs.ogg', 30, TRUE, -2) + carbon_user.set_handcuffed(new /obj/item/restraints/handcuffs(user)) + if(/obj/item/suspiciousphone) + playsound(loc, 'sound/items/dump_it.ogg', 30, TRUE, -2) + balance = 0 + if(/obj/singularity) + user.electrocute_act(80, src, flags = SHOCK_ILLUSION | SHOCK_NOGLOVES) + else // gibonite, syndicate bombs, flashbangs, etc. + var/obj/item/grenade/flashbang/bang = new(get_turf(src)) + bang.arm_grenade(null, 1 SECONDS) /// Checks if any prizes have been won, and pays them out -/obj/machinery/computer/slot_machine/proc/give_prizes(usrname, mob/user) +/obj/machinery/computer/slot_machine/proc/give_prizes(usrname, mob/living/user) var/linelength = get_lines() var/did_player_win = TRUE - if(check_jackpot(FA_ICON_BOMB)) - var/obj/item/grenade/flashbang/bang = new(get_turf(src)) - bang.arm_grenade(null, 1 SECONDS) + if(trap_path && check_middle_row_all(trap_path)) + activate_trap(user) - else if(check_jackpot(JACKPOT_SEVENS)) + else if(check_middle_row_all(jackpot_path)) winning = WINNING_JACKPOT var/prize = money + PRIZE_JACKPOT visible_message("[src] says, 'JACKPOT! You win [prize] [MONEY_NAME]!'") priority_announce("Congratulations to [user ? user.real_name : usrname] for winning the jackpot at the slot machine in [get_area(src)]!") - if(isliving(user) && (user in viewers(src))) - var/mob/living/living_user = user - living_user.add_mood_event("slots", /datum/mood_event/slots/win/jackpot) + user.add_mood_event("slots", /datum/mood_event/slots/win/jackpot) jackpots += 1 money = 0 if(paymode == HOLOCHIP) @@ -322,17 +441,13 @@ winning = WINNING_BIG visible_message("[src] says, 'Big Winner! You win a thousand [MONEY_NAME]!'") give_money(PRIZE_BIG) - if(isliving(user) && (user in viewers(src))) - var/mob/living/living_user = user - living_user.add_mood_event("slots", /datum/mood_event/slots/win/big) + user.add_mood_event("slots", /datum/mood_event/slots/win/big) else if(linelength == 4) winning = WINNING_SMALL visible_message("[src] says, 'Winner! You win four hundred [MONEY_NAME]!'") give_money(PRIZE_SMALL) - if(isliving(user) && (user in viewers(src))) - var/mob/living/living_user = user - living_user.add_mood_event("slots", /datum/mood_event/slots/win) + user.add_mood_event("slots", /datum/mood_event/slots/win) else if(linelength == 3) winning = WINNING_FREESPIN @@ -344,9 +459,7 @@ winning = WINNING_NOTHING balloon_alert(user, "no luck!") did_player_win = FALSE - if(isliving(user) && (user in viewers(src))) - var/mob/living/living_user = user - living_user.add_mood_event("slots", /datum/mood_event/slots/loss) + user.add_mood_event("slots", /datum/mood_event/slots/loss) playsound(src, 'sound/machines/lever/lever_stop.ogg', 50) @@ -362,30 +475,31 @@ /obj/machinery/computer/slot_machine/proc/clear_winning() winning = WINNING_NOTHING -/// Checks for a jackpot (5 matching icons in the middle row) with the given icon name -/obj/machinery/computer/slot_machine/proc/check_jackpot(name) - for(var/reel in reels) - if(reel[2] != name) +/// Checks for a jackpot (5 matching symbols in the middle row) for the given symbol typepath +/obj/machinery/computer/slot_machine/proc/check_middle_row_all(symbol_path) + var/symbol_id = "[symbol_path]" + for(var/list/reel in reels) + if(reel[2] != symbol_id) return FALSE return TRUE /// Finds the largest number of consecutive matching icons in a row /obj/machinery/computer/slot_machine/proc/get_lines() - var/amountthesame + var/amountthesame = 0 - for(var/i in 1 to 3) - var/inputtext = reels[1][i] + reels[2][i] + reels[3][i] + reels[4][i] + reels[5][i] - for(var/icon in icons) - var/j = 3 //The lowest value we have to check for. - var/symboltext = icon + icon + icon - while(j <= 5) - if(findtext(inputtext, symboltext)) - amountthesame = max(j, amountthesame) - j++ - symboltext += icon + for(var/row in 1 to 3) + var/current_symbol = null + var/current_run = 0 - if(amountthesame) - break + for(var/list/reel in reels) + var/symbol = reel[row] + if(symbol == current_symbol) + current_run++ + else + current_symbol = symbol + current_run = 1 + if(current_run >= 3) + amountthesame = max(amountthesame, current_run) return amountthesame @@ -396,6 +510,9 @@ money -= amount_to_give balance += surplus + if(house_bank_account) + house_bank_account.adjust_money(-amount_to_give, "Slot Machine: Payout") + /// Pay out the specified amount in either coins or holochips /obj/machinery/computer/slot_machine/proc/give_payout(amount) if(paymode == HOLOCHIP) @@ -436,6 +553,204 @@ playsound(src, pick(list('sound/machines/coindrop.ogg', 'sound/machines/coindrop2.ogg')), 50, TRUE) return amount +/obj/machinery/computer/slot_machine/command + name = "command slot machine" + desc = "The handle is made of solid gold, and the screen is polished with the tears of overworked assistants." + symbol_paths = list( + /obj/item/disk/nuclear, + /obj/item/clothing/accessory/medal/gold, + /obj/item/hand_tele, + /mob/living/basic/pet/dog/corgi, + /obj/item/card/id/advanced/gold, + /obj/item/melee/sabre, + /obj/item/grenade/syndieminibomb + ) + jackpot_path = /obj/item/clothing/accessory/medal/gold + trap_path = /obj/item/grenade/syndieminibomb + +/obj/machinery/computer/slot_machine/command/Initialize(mapload) + slot_adjectives += list("Royal", "Regal", "Golden", "Captain's", "Glorious") + slot_nouns += list("Medal", "Ransom", "Authority", "Command") + . = ..() + +/obj/machinery/computer/slot_machine/security + name = "security slot machine" + desc = "Repurposed from a confiscated syndicate gambling ring. Losing is a crime. Winning is also a crime." + symbol_paths = list( + /obj/item/food/donut/berry, + /mob/living/simple_animal/bot/secbot/beepsky, + /obj/item/melee/baton/security/loaded, + /obj/item/gun/energy/disabler, + /obj/vehicle/sealed/mecha/ripley/paddy, + /obj/item/book/manual/wiki/security_space_law, + /obj/item/grown/bananapeel + ) + jackpot_path = /obj/item/food/donut/berry + trap_path = /obj/item/grown/bananapeel + +/obj/machinery/computer/slot_machine/security/Initialize(mapload) + slot_adjectives += list("Stunned", "Flashed", "Confiscated", "Loyal", "Arrested") + slot_nouns += list("Baton", "Donut", "Contraband", "Brig", "Security") + . = ..() + +/obj/machinery/computer/slot_machine/medical + name = "medical slot machine" + desc = "A miracle of modern medicine! It cures boredom, but causes acute financial necrosis." + symbol_paths = list( + /obj/item/storage/medkit/brute, + /obj/vehicle/sealed/mecha/odysseus, + /obj/item/clothing/glasses/hud/health, + /mob/living/basic/pet/cat/runtime, + /obj/item/plunger, + /obj/item/clothing/neck/stethoscope, + /obj/machinery/syndicatebomb, + ) + jackpot_path = /obj/item/clothing/neck/stethoscope + trap_path = /obj/machinery/syndicatebomb + +/obj/machinery/computer/slot_machine/medical/Initialize(mapload) + slot_adjectives += list("Mutated", "Overdosed", "Infectious", "Healing", "Husked") + slot_nouns += list("Medkit", "Defib", "Patient", "Doctor", "Cure") + . = ..() + +/obj/machinery/computer/slot_machine/engineering + name = "engineering slot machine" + desc = "Gambling for those who think wearing insulated gloves makes them invincible. Ground yourself before playing." + symbol_paths = list( + /obj/item/storage/toolbox/mechanical, + /obj/item/blueprints, + /obj/item/clothing/gloves/color/yellow, + /obj/item/clothing/head/utility/welding, + /obj/item/clothing/glasses/meson, + /mob/living/basic/parrot/poly, + /obj/singularity, + ) + jackpot_path = /obj/item/blueprints + trap_path = /obj/singularity + +/obj/machinery/computer/slot_machine/engineering/Initialize(mapload) + slot_adjectives += list("Supercharged", "Pressurized", "Radioactive", "Overloaded", "Delaminating", "Insulated") + slot_nouns += list("Toolbox", "Emitter", "Supermatter") + . = ..() + +/obj/machinery/computer/slot_machine/cargo + name = "cargo slot machine" + desc = "Every credit spent here is a credit that won't be spent on 'useless' things, like food or medicine." + symbol_paths = list( + /obj/item/bounty_cube, + /obj/item/clipboard, + /obj/item/universal_scanner, + /mob/living/basic/sloth, + /obj/item/multitool, + /obj/vehicle/sealed/mecha/ripley, + /obj/item/suspiciousphone, + ) + jackpot_path = /obj/item/bounty_cube + trap_path = /obj/item/suspiciousphone + +/obj/machinery/computer/slot_machine/cargo/Initialize(mapload) + slot_adjectives += list("Express", "Smuggled", "Stolen", "Overdue", "Subsidized", "Manifested") + slot_nouns += list("Bounty", "Crate", "Manifest", "MULE", "Profit") + . = ..() + +/obj/machinery/computer/slot_machine/service + name = "service slot machine" + desc = "The handle is a repurposed rolling pin. Every loss is just another ingredient for the daily special." + symbol_paths = list( + /obj/item/clothing/head/hats/tophat, + /obj/item/reagent_containers/cup/watering_can, + /obj/item/clothing/shoes/galoshes, + /mob/living/basic/goat/pete, + /obj/item/book/bible, + /obj/item/kitchen/rollingpin, + /obj/item/seeds/random, + ) + jackpot_path = /obj/item/seeds/random + trap_path = /mob/living/basic/goat/pete + +/obj/machinery/computer/slot_machine/service/Initialize(mapload) + slot_adjectives += list("Fermented", "Seasoned", "Tipsy", "Cleaned", "Organic", "Culinary", "Refreshing", "Divine", "Holy") + slot_nouns += list("Recipe", "Cocktail", "Harvest", "Scrubber") + . = ..() + +/obj/machinery/computer/slot_machine/science + name = "research slot machine" + desc = "The reels seem to exist in multiple dimensions at once. It still takes your money in all of them." + symbol_paths = list( + /obj/item/stack/sheet/mineral/gold, + /obj/item/stack/sheet/mineral/silver, + /obj/item/stack/sheet/mineral/uranium, + /obj/item/stack/sheet/mineral/plasma, + /obj/item/stack/sheet/mineral/runite, + /obj/item/clothing/mask/facehugger/lamarr, + /obj/item/gibtonite, + ) + jackpot_path = /obj/item/stack/sheet/mineral/runite + trap_path = /obj/item/gibtonite + +/obj/machinery/computer/slot_machine/science/Initialize(mapload) + slot_adjectives += list("Atomic", "Bluespace", "Cosmic", "Golden", "Diamond", "Silver", "Uranium", "Quantum", "Anomalous", "Plasma", "Experimental", "Robotic") + slot_nouns += list("Anomaly", "Artifact", "Slime", "Extract", "Circuit", "Discovery", "Explosion") + . = ..() + +/obj/machinery/computer/slot_machine/clown + desc = "Gambling is fun! Smells like bananas, wet shoes, and regret. HONK!" + symbol_paths = list( + /obj/item/food/grown/banana, + /obj/item/toy/crayon/spraycan/lubecan, + /obj/item/card/id/advanced/rainbow, + /obj/vehicle/sealed/mecha/honker, + /obj/item/clothing/mask/gas/clown_hat, + /obj/item/storage/backpack/clown, + /obj/item/restraints/handcuffs, + ) + jackpot_path = /obj/vehicle/sealed/mecha/honker + trap_path = /obj/item/restraints/handcuffs + +/obj/machinery/computer/slot_machine/clown/Initialize(mapload) + slot_adjectives += list("Honking", "Slippery", "Pranked", "Squeaky", "Hilarious", "Giggling") + slot_nouns += list("Banana", "Peel", "Prank", "Joke", "Punchline", "Candy", "Honk") + . = ..() + +/obj/machinery/computer/slot_machine/mime + desc = "Gambling is a silent tragedy. The machine stares back at you with a cold indifference." + symbol_paths = list( + /obj/item/book/granter/action/spell/mime/mimery, + /obj/item/clothing/mask/gas/mime, + /obj/item/toy/crayon/spraycan/mimecan, + /obj/item/reagent_containers/cup/glass/bottle/bottleofnothing, + /obj/item/clothing/gloves/color/white, + /obj/item/storage/backpack/mime, + /obj/item/restraints/handcuffs, + ) + jackpot_path = /obj/item/book/granter/action/spell/mime/mimery + trap_path = /obj/item/restraints/handcuffs + +/obj/machinery/computer/slot_machine/mime/Initialize(mapload) + slot_adjectives += list("Silent", "Transparent", "Unspeakable", "Voiceless", "Quiet", "Hushed", "Invisible", "Imaginary", "Empty") + slot_nouns += list("Silence", "Mute", "Introvert", "Nothing", "Baguette") + . = ..() + +/obj/machinery/computer/slot_machine/syndicate + name = "syndicate slot machine" + desc = "Gambling for the operative who's already lost everything. Death to Nanotrasen, and death to your wallet." + symbol_paths = list( + /obj/machinery/nuclearbomb, + /obj/item/card/emag, + /obj/item/storage/toolbox/syndicate, + /obj/vehicle/sealed/mecha/gygax/dark, + /obj/item/soap/syndie, + /obj/item/gun/energy/recharge/ebow, + /obj/item/restraints/handcuffs, + ) + jackpot_path = /obj/machinery/nuclearbomb + trap_path = /obj/item/restraints/handcuffs + +/obj/machinery/computer/slot_machine/syndicate/Initialize(mapload) + slot_adjectives += list("Covert", "Nuclear", "Suspicious", "Bloody", "Syndie", "Sabotaged", "Clandestine", "Illicit", "Traitorous") + slot_nouns += list("Telecrystal", "Uplink", "Bomb", "Operative", "Disk", "Nuke", "Syndicate", "Traitor") + . = ..() + #undef SPIN_PRICE #undef WINNING_NOTHING #undef WINNING_FREESPIN @@ -447,6 +762,5 @@ #undef PRIZE_JACKPOT #undef SPIN_TIME #undef REEL_DEACTIVATE_DELAY -#undef JACKPOT_SEVENS #undef HOLOCHIP #undef COIN diff --git a/code/game/objects/effects/spawners/random/entertainment.dm b/code/game/objects/effects/spawners/random/entertainment.dm index ddc3dd790dc..fc766d6bd36 100644 --- a/code/game/objects/effects/spawners/random/entertainment.dm +++ b/code/game/objects/effects/spawners/random/entertainment.dm @@ -12,6 +12,23 @@ /obj/machinery/computer/arcade/amputation = 2, ) +/obj/effect/spawner/random/entertainment/slot_machine + name = "spawn random slot machine" + desc = "Automagically transforms into a random slot machine. If you see this while in a shift, please create a bug report." + icon_state = "arcade" + loot = list( // syndie slots omitted + /obj/machinery/computer/slot_machine = 20, + /obj/machinery/computer/slot_machine/security = 10, + /obj/machinery/computer/slot_machine/medical = 10, + /obj/machinery/computer/slot_machine/engineering = 10, + /obj/machinery/computer/slot_machine/cargo = 10, + /obj/machinery/computer/slot_machine/service = 10, + /obj/machinery/computer/slot_machine/science = 10, + /obj/machinery/computer/slot_machine/command = 10, + /obj/machinery/computer/slot_machine/clown = 5, + /obj/machinery/computer/slot_machine/mime = 5, + ) + /obj/effect/spawner/random/entertainment/musical_instrument name = "musical instrument spawner" icon_state = "eguitar" diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm index b1a7e0bb445..8dd950e3a6c 100644 --- a/code/game/objects/items/circuitboards/computer_circuitboards.dm +++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm @@ -313,6 +313,50 @@ name = "Slot Machine" greyscale_colors = CIRCUIT_COLOR_GENERIC build_path = /obj/machinery/computer/slot_machine + desc = "You can change the theme using a screwdriver." + /// List of pickable slot machines + var/static/list/slot_themes = list( + "Default" = /obj/machinery/computer/slot_machine, + "Command" = /obj/machinery/computer/slot_machine/command, + "Security" = /obj/machinery/computer/slot_machine/security, + "Medical" = /obj/machinery/computer/slot_machine/medical, + "Engineering" = /obj/machinery/computer/slot_machine/engineering, + "Cargo" = /obj/machinery/computer/slot_machine/cargo, + "Service" = /obj/machinery/computer/slot_machine/service, + "Science" = /obj/machinery/computer/slot_machine/science, + "Clown" = /obj/machinery/computer/slot_machine/clown, + "Mime" = /obj/machinery/computer/slot_machine/mime, + ) + +/obj/item/circuitboard/computer/slot_machine/examine(mob/user) + . = ..() + var/current_theme = "Unknown" + for(var/theme_name in slot_themes) + if(slot_themes[theme_name] == build_path) + current_theme = theme_name + break + . += span_info("[src] is set to the [current_theme] theme. You can use a screwdriver to reconfigure it.") + +/obj/item/circuitboard/computer/slot_machine/screwdriver_act(mob/living/user, obj/item/tool) + if(obj_flags & EMAGGED) + balloon_alert(user, "board mode is broken!") + return FALSE + + var/choice = tgui_input_list(user, "Choose a slot machine theme", "Theme Selection", slot_themes) + if(isnull(choice)) + return ITEM_INTERACT_BLOCKING + build_path = slot_themes[choice] + to_chat(user, span_notice("You set the board to the [choice] theme.")) + return ITEM_INTERACT_SUCCESS + +/obj/item/circuitboard/computer/slot_machine/emag_act(mob/user, obj/item/card/emag/emag_card) + if(obj_flags & EMAGGED) + return FALSE + + obj_flags |= EMAGGED + build_path = /obj/machinery/computer/slot_machine/syndicate + balloon_alert(user, "illegal slot machine loaded") + return TRUE /obj/item/circuitboard/computer/swfdoor name = "Magix" diff --git a/code/modules/asset_cache/assets/slot_machines.dm b/code/modules/asset_cache/assets/slot_machines.dm new file mode 100644 index 00000000000..c3210bb3672 --- /dev/null +++ b/code/modules/asset_cache/assets/slot_machines.dm @@ -0,0 +1,24 @@ +/datum/asset/spritesheet_batched/slot_machines + name = "slotmachines" + +/datum/asset/spritesheet_batched/slot_machines/create_spritesheets() + // initialising the list of items we need + var/list/target_items = list() + for(var/obj/machinery/computer/slot_machine/slot_machine as anything in typesof(/obj/machinery/computer/slot_machine)) + slot_machine = new slot_machine() + target_items |= slot_machine.symbol_paths // no dupes + qdel(slot_machine) + + for(var/atom/atom as anything in target_items) + var/icon = initial(atom.icon) + var/icon_state = initial(atom.icon_state) + var/id = sanitize_css_class_name("[icon][icon_state]") + + var/has_gags = atom::greyscale_config && atom::greyscale_colors + var/has_color = atom::color && icon_state + // GAGS and colored icons must be pregenerated so blacklist them for now + if(has_gags || has_color) + stack_trace("[atom] is either using GAGS or colored icons which is not supported for slot machine reels") + continue + + insert_icon(id, uni_icon(icon, icon_state)) diff --git a/icons/effects/random_spawners.dmi b/icons/effects/random_spawners.dmi index 3450f6754c2..4d816c6df80 100644 Binary files a/icons/effects/random_spawners.dmi and b/icons/effects/random_spawners.dmi differ diff --git a/tgstation.dme b/tgstation.dme index ca737cae21b..247820c849f 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3716,6 +3716,7 @@ #include "code\modules\asset_cache\assets\safe.dm" #include "code\modules\asset_cache\assets\seeds.dm" #include "code\modules\asset_cache\assets\sheetmaterials.dm" +#include "code\modules\asset_cache\assets\slot_machines.dm" #include "code\modules\asset_cache\assets\supplypods.dm" #include "code\modules\asset_cache\assets\tcomms.dm" #include "code\modules\asset_cache\assets\tgfont.dm" diff --git a/tgui/packages/tgui/interfaces/SlotMachine.tsx b/tgui/packages/tgui/interfaces/SlotMachine.tsx index 54045ecfac1..784e6b98d57 100644 --- a/tgui/packages/tgui/interfaces/SlotMachine.tsx +++ b/tgui/packages/tgui/interfaces/SlotMachine.tsx @@ -1,12 +1,12 @@ -import { useEffect, useRef, useState } from 'react'; -import { Blink, Box, Button, Icon, Section, Stack } from 'tgui-core/components'; +import { useEffect, useMemo, useRef, useState } from 'react'; +import { Blink, Box, Button, Section, Stack } from 'tgui-core/components'; import { formatMoney } from 'tgui-core/format'; import { classes } from 'tgui-core/react'; import { useBackend } from '../backend'; import { Window } from '../layouts'; type Data = { - icons: string[]; + symbols: SlotSymbol[]; reels: Reel[]; balance: number; working: number; @@ -17,36 +17,24 @@ type Data = { jackpots: number; jackpot: number; paymode: number; + jackpot_id: string; + trap_id: string; +}; + +type SlotSymbol = { + id: string; + icon_id: string; }; type Reel = { - icons: string[]; - spinning: number; -}; - -type IconMeta = { - color: string; -}; - -const iconMetaByName: Record = { - 'fa-7': { color: '#b22' }, - 'fa-star': { color: '#fd6' }, - 'fa-lemon': { color: '#ce0' }, - 'fa-apple-whole': { color: '#d64' }, - 'fa-biohazard': { color: '#2c0' }, - 'fa-dollar-sign': { color: '#08b' }, - 'fa-bomb': { color: '#876' }, + symbols: string[]; }; const pluralS = (amount: number) => { return amount === 1 ? '' : 's'; }; -const slotIconToColor = (iconName: string): string => { - return iconMetaByName[iconName]?.color || '#f0f'; -}; - -const pickRandomMany = (items: T[], n: number) => { +const pickRandomMany = (items: T[], n: number) => { const result: T[] = []; for (let i = 0; i < n; i += 1) { result.push(pickRandom(items)); @@ -54,17 +42,28 @@ const pickRandomMany = (items: T[], n: number) => { return result; }; -const pickRandom = (items: T[]) => { +const pickRandom = (items: T[]) => { return items[Math.floor(Math.random() * items.length)]; }; export const SlotMachine = () => { const { act, data } = useBackend(); - const { icons, cost, reels, balance } = data; + const { symbols, cost, reels, balance } = data; const spinning = data.working === 1; + const symbolsById = useMemo(() => { + const map: Record = {}; + for (const symbol of symbols) { + map[symbol.id] = symbol; + } + return map; + }, [symbols]); + + const jackpotSymbol = symbolsById[data.jackpot_id]; + const trapSymbol = data.trap_id ? symbolsById[data.trap_id] : null; + return ( - +
@@ -72,43 +71,82 @@ export const SlotMachine = () => { {reels.map((reel, i) => (
))}
- - -
act('payout')} disabled={balance <= 0}> - Refund - - } - > - - {formatMoney(balance)} cr + + +
+ + Jackpot: + {jackpotSymbol && ( + + )} + + {trapSymbol && ( + <> + + Trap: + + + + )}
-
- -
+ + +
act('payout')} + disabled={balance <= 0} + > + Refund + + } + > + + {formatMoney(balance)} cr + +
+
+ +
+ +
+
+
@@ -301,30 +339,32 @@ const BannerStats = () => { const ICON_STRIP_LENGTH = 30; type IconStripProps = { - icons: string[]; - iconsNeeded: string[]; + symbols: SlotSymbol[]; + symbolsById: Record; + symbolsNeeded: string[]; spinning?: boolean; }; const IconStrip = (props: IconStripProps) => { - const { icons, iconsNeeded, spinning } = props; + const { symbols, symbolsById, symbolsNeeded, spinning } = props; + const symbolIds = useMemo(() => symbols.map((s) => s.id), [symbols]); - const [drawnIcons, setDrawnIcons] = useState([ - ...pickRandomMany(icons, ICON_STRIP_LENGTH - 3), - ...iconsNeeded, + const [drawnSymbols, setDrawnSymbols] = useState([ + ...pickRandomMany(symbolIds, ICON_STRIP_LENGTH - 3), + ...symbolsNeeded, ]); useEffect(() => { if (spinning) { - setDrawnIcons((drawnIcons) => [ - ...drawnIcons.slice(-3), - ...pickRandomMany(icons, ICON_STRIP_LENGTH - 6), - ...iconsNeeded, + setDrawnSymbols((drawn) => [ + ...drawn.slice(-3), + ...pickRandomMany(symbolIds, ICON_STRIP_LENGTH - 6), + ...symbolsNeeded, ]); } else { - setDrawnIcons([ - ...pickRandomMany(icons, ICON_STRIP_LENGTH - 3), - ...iconsNeeded, + setDrawnSymbols([ + ...pickRandomMany(symbolIds, ICON_STRIP_LENGTH - 3), + ...symbolsNeeded, ]); } }, [spinning]); @@ -336,18 +376,16 @@ const IconStrip = (props: IconStripProps) => { spinning && 'SlotMachine__IconStrip--spinning', ])} > - {drawnIcons.map((icon, i) => ( - - ))} + {drawnSymbols.map((symbolId, i) => { + const symbol = symbolsById[symbolId]; + return ( +
+ {symbol && ( + + )} +
+ ); + })} ); }; diff --git a/tgui/packages/tgui/styles/interfaces/SlotMachine.scss b/tgui/packages/tgui/styles/interfaces/SlotMachine.scss index 82599f53d22..48583d4d982 100644 --- a/tgui/packages/tgui/styles/interfaces/SlotMachine.scss +++ b/tgui/packages/tgui/styles/interfaces/SlotMachine.scss @@ -152,15 +152,6 @@ transform: translateY(calc(-60px * 27)); // animation-duration: 3.5s; text-align: center; - // animation: scroll-up 2s linear infinite; - // animation-play-state: paused; - // transform: translateY(0px); - text-shadow: - 2px 2px 6px #000, - 0 2px #000, - 0 -2px #000, - 2px 0 #000, - -2px 0 #000; } .SlotMachine__IconStrip--spinning { @@ -171,6 +162,20 @@ animation-timing-function: cubic-bezier(1, 1.26, 0.88, 0.96); } +.SlotMachine__Symbol { + height: 60px; + display: flex; + align-items: center; + justify-content: center; + + .slotmachines32x32 { + width: 32px; + height: 32px; + image-rendering: pixelated; + filter: drop-shadow(1px 1px 1px black); + } +} + @keyframes SlotMachine__Spin { 0% { transform: translateY(0);