diff --git a/_maps/map_files/Delta/delta.dmm b/_maps/map_files/Delta/delta.dmm
index 9845389d9af..d27e2c18d96 100644
--- a/_maps/map_files/Delta/delta.dmm
+++ b/_maps/map_files/Delta/delta.dmm
@@ -10276,6 +10276,14 @@
/obj/effect/decal/warning_stripes/yellow/hollow,
/turf/simulated/floor/plasteel,
/area/quartermaster/storage)
+"aIg" = (
+/obj/structure/table/reinforced,
+/obj/item/eftpos/register{
+ dir = 1;
+ pixel_y = 9
+ },
+/turf/simulated/floor/plasteel/dark,
+/area/crew_quarters/bar)
"aIh" = (
/obj/machinery/conveyor/southeast{
id = "cargodelivery"
@@ -22791,6 +22799,9 @@
/obj/item/clipboard,
/obj/item/toy/figure/crew/chef,
/obj/effect/decal/warning_stripes/yellow/hollow,
+/obj/item/eftpos/register{
+ dir = 1
+ },
/turf/simulated/floor/plasteel,
/area/crew_quarters/kitchen)
"blq" = (
@@ -135594,7 +135605,7 @@ aFA
aGB
aMi
aJa
-aKs
+aIg
bsq
aOG
aOG
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index d68d05fe641..5c85dab4708 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -30013,6 +30013,9 @@
dir = 4
},
/obj/effect/turf_decal/tile/bar,
+/obj/item/eftpos/register{
+ dir = 8
+ },
/turf/simulated/floor/plasteel{
dir = 1;
icon_state = "whitecorner"
@@ -84982,6 +84985,13 @@
},
/turf/simulated/floor/plasteel,
/area/toxins/xenobiology)
+"udl" = (
+/obj/structure/table/reinforced,
+/obj/item/eftpos/register,
+/turf/simulated/floor/plasteel{
+ icon_state = "bar"
+ },
+/area/crew_quarters/bar)
"udB" = (
/obj/machinery/atmospherics/unary/vent_scrubber/on,
/turf/simulated/floor/plasteel,
@@ -126318,7 +126328,7 @@ mZL
bCv
bEv
bHO
-bGd
+udl
bJH
bLx
lUc
diff --git a/_maps/map_files/cerestation/cerestation.dmm b/_maps/map_files/cerestation/cerestation.dmm
index 9d8a2e88acc..3c79a95ddde 100644
--- a/_maps/map_files/cerestation/cerestation.dmm
+++ b/_maps/map_files/cerestation/cerestation.dmm
@@ -11816,6 +11816,7 @@
/obj/structure/table,
/obj/item/reagent_containers/glass/beaker,
/obj/item/reagent_containers/food/condiment/enzyme,
+/obj/item/eftpos/register,
/turf/simulated/floor/plasteel{
icon_state = "cafeteria"
},
@@ -53916,7 +53917,9 @@
/area/hallway/secondary/exit)
"iWD" = (
/obj/structure/table/glass/reinforced,
-/obj/item/phone/pos,
+/obj/item/eftpos/register{
+ dir = 8
+ },
/turf/simulated/floor/wood,
/area/crew_quarters/bar)
"iWF" = (
diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm
index c90e10014e1..60e208618b6 100644
--- a/_maps/map_files/cyberiad/cyberiad.dmm
+++ b/_maps/map_files/cyberiad/cyberiad.dmm
@@ -24748,6 +24748,10 @@
"bkP" = (
/obj/structure/table/reinforced,
/obj/item/reagent_containers/glass/rag,
+/obj/item/eftpos/register{
+ dir = 1;
+ pixel_y = 11
+ },
/turf/simulated/floor/plasteel{
icon_state = "grimy"
},
@@ -28145,6 +28149,7 @@
},
/obj/structure/table,
/obj/item/book/manual/wiki/sop_service,
+/obj/item/eftpos/register,
/turf/simulated/floor/plasteel{
icon_state = "cafeteria"
},
@@ -41520,7 +41525,7 @@
pixel_y = 7;
pixel_x = -8
},
-/obj/item/phone/pos,
+/obj/item/eftpos/register,
/turf/simulated/floor/plating,
/area/maintenance/apmaint)
"caq" = (
@@ -52687,7 +52692,9 @@
/area/maintenance/apmaint2)
"cFL" = (
/obj/structure/table/reinforced,
-/obj/item/phone/pos,
+/obj/item/eftpos/register{
+ dir = 8
+ },
/turf/simulated/floor/wood,
/area/maintenance/apmaint2)
"cFM" = (
@@ -62955,7 +62962,6 @@
dir = 4
},
/obj/structure/table/reinforced,
-/obj/item/phone/pos,
/turf/simulated/floor/plasteel{
icon_state = "grimy"
},
@@ -67152,7 +67158,7 @@
"eIN" = (
/obj/structure/table/reinforced,
/obj/effect/spawner/lootdrop/maintenance,
-/obj/item/phone/pos,
+/obj/item/eftpos/register,
/turf/simulated/floor/plating,
/area/maintenance/aft)
"eJo" = (
diff --git a/code/__DEFINES/tools.dm b/code/__DEFINES/tools.dm
index 62422f4b4d8..70af463f7dd 100644
--- a/code/__DEFINES/tools.dm
+++ b/code/__DEFINES/tools.dm
@@ -64,6 +64,8 @@ GLOBAL_LIST_INIT(surgery_tool_behaviors, list(
//Wrench messages
#define WRENCH_ANCHOR_MESSAGE user.visible_message("[user] tightens the bolts on [src]!", "You tighten the bolts on [src]!", "You hear ratcheting.")
#define WRENCH_UNANCHOR_MESSAGE user.visible_message("[user] loosens the bolts on [src]!", "You loosen the bolts on [src]!", "You hear ratcheting.")
+#define WRENCH_ATTEMPT_ANCHOR_MESSAGE user.visible_message("[user] begins tightening the bolts on [src]...", "You begin tightening the bolts on [src]...", "You hear ratcheting.")
+#define WRENCH_ATTEMPT_UNANCHOR_MESSAGE user.visible_message("[user] begins loosening the bolts on [src]...", "You begin loosening the bolts on [src]...", "You hear ratcheting.")
#define WRENCH_UNANCHOR_WALL_MESSAGE user.visible_message("[user] unwrenches [src] from the wall!", "You unwrench [src] from the wall!", "You hear ratcheting.")
#define WRENCH_ANCHOR_TO_WALL_MESSAGE user.visible_message("[user] affixes [src] to the wall!", "You affix [src] to the wall!", "You hear ratcheting.")
diff --git a/code/game/objects/items/weapons/misc_items.dm b/code/game/objects/items/weapons/misc_items.dm
index a4793b43e27..a560f0e8f87 100644
--- a/code/game/objects/items/weapons/misc_items.dm
+++ b/code/game/objects/items/weapons/misc_items.dm
@@ -145,10 +145,3 @@
if(cooldown < world.time - 20)
playsound(user.loc, 'sound/weapons/ring.ogg', 50, 1)
cooldown = world.time
-
-/obj/item/phone/pos
- name = "point of sale"
- desc = "Also known as a cash register, or, more commonly, \"robbery magnet\". It's old and rusty, clearly non-functional and decorative only."
- icon = 'icons/obj/machines/pos.dmi'
- icon_state = "pos"
- attack_verb = list("bounced a check off", "checked-out", "tipped")
diff --git a/code/modules/economy/economy_machinery/eftpos.dm b/code/modules/economy/economy_machinery/eftpos.dm
index 2ad7da6fc43..c810a6a5f72 100644
--- a/code/modules/economy/economy_machinery/eftpos.dm
+++ b/code/modules/economy/economy_machinery/eftpos.dm
@@ -12,6 +12,7 @@
var/transaction_amount = 0
var/transaction_purpose = "Default charge"
var/access_code
+ var/transaction_sound = 'sound/machines/chime.ogg'
///linked money account database to this EFTPOS
var/datum/money_account_database/account_database
@@ -94,7 +95,7 @@
if(account_database)
var/attempt_account_num = input("Enter account number to pay EFTPOS charges into", "New account number") as num
var/attempt_pin = input("Enter pin code", "Account pin") as num
- if(!Adjacent(user))
+ if(!check_user_position(user))
return
var/datum/money_account/target_account = GLOB.station_money_database.find_user_account(attempt_account_num, include_departments = TRUE)
if(!target_account)
@@ -110,13 +111,13 @@
to_chat(user, "[bicon(src)]Unable to connect to accounts database.")
if("trans_purpose")
var/purpose = clean_input("Enter reason for EFTPOS transaction", "Transaction purpose", transaction_purpose)
- if(!Adjacent(user))
+ if(!check_user_position(user))
return
if(purpose)
transaction_purpose = purpose
if("trans_value")
var/try_num = input("Enter amount for EFTPOS transaction", "Transaction amount", transaction_amount) as num
- if(!Adjacent(user))
+ if(!check_user_position(user))
return
if(try_num < 0)
alert("That is not a valid amount!")
@@ -128,7 +129,7 @@
if("toggle_lock")
if(transaction_locked)
var/attempt_code = input("Enter EFTPOS access code", "Reset Transaction") as num
- if(!Adjacent(user))
+ if(!check_user_position(user))
return
if(attempt_code == access_code)
transaction_locked = FALSE
@@ -160,10 +161,10 @@
to_chat(user, "[bicon(src)]Access code reset to 0.")
-/obj/item/eftpos/proc/scan_card(obj/item/card/id/C, mob/user)
+/obj/item/eftpos/proc/scan_card(obj/item/card/id/C, mob/user, secured = TRUE)
visible_message("[user] swipes a card through [src].")
- if(!transaction_locked || transaction_paid)
+ if(!transaction_locked || transaction_paid || !secured)
return
if(!linked_account)
@@ -190,7 +191,7 @@
to_chat(user, "[bicon(src)]Insufficient credits in your account!")
return
GLOB.station_money_database.credit_account(linked_account, transaction_amount, transaction_purpose, machine_name, FALSE)
- playsound(src, 'sound/machines/chime.ogg', 50, 1)
+ playsound(src, transaction_sound, 50, TRUE)
visible_message("[src] chimes!")
transaction_paid = TRUE
@@ -218,3 +219,80 @@
R.forceMove(D)
D.wrapped = R
D.name = "small parcel - 'EFTPOS access code'"
+
+/obj/item/eftpos/proc/check_user_position(mob/user)
+ return Adjacent(user)
+
+/obj/item/eftpos/register
+ name = "point of sale"
+ desc = "Also known as a cash register, or, more commonly, \"robbery magnet\". It's old and rusty, and had an EFTPOS module fitted in it."
+ icon = 'icons/obj/machines/pos.dmi'
+ icon_state = "pos"
+ force = 10
+ throwforce = 10
+ throw_speed = 1.5
+ throw_range = 7
+ anchored = TRUE
+ w_class = WEIGHT_CLASS_BULKY
+ hitsound = 'sound/weapons/ringslam.ogg'
+ drop_sound = 'sound/items/handling/register_drop.ogg'
+ pickup_sound = 'sound/items/handling/toolbox_pickup.ogg'
+ transaction_sound = 'sound/machines/checkout.ogg'
+ attack_verb = list("bounced a check off", "checked-out", "tipped")
+
+/obj/item/eftpos/register/examine(mob/user)
+ . = ..()
+ if(!anchored)
+ . += "Alt-click to rotate it."
+ else
+ . += "It is secured in place."
+
+/obj/item/eftpos/register/AltClick(mob/user)
+ if(user.incapacitated())
+ to_chat(user, "You can't do that right now!")
+ return
+ if(!Adjacent(user))
+ return
+ if(anchored)
+ to_chat(user, "[src] is secured in place!")
+ return
+ setDir(turn(dir, 90))
+
+/obj/item/eftpos/register/attack_hand(mob/user)
+ if(anchored)
+ if(!check_user_position(user))
+ to_chat(user, "You need to be behind [src] to use it!")
+ return
+ add_fingerprint(user)
+ ui_interact(user, state = GLOB.human_adjacent_state)
+ return TRUE
+ return ..()
+
+/obj/item/eftpos/register/attack_self(mob/user)
+ to_chat(user, "[src] has to be set down and secured to be used.")
+
+/obj/item/eftpos/register/check_user_position(mob/user)
+ if(!..())
+ return FALSE
+ var/user_loc = get_dir(src, user)
+ if(!user_loc || user_loc & dir)
+ return TRUE
+ return FALSE
+
+/obj/item/eftpos/register/scan_card(obj/item/card/id/C, mob/user)
+ ..(C, user, anchored)
+
+/obj/item/eftpos/register/wrench_act(mob/user, obj/item/I)
+ . = TRUE
+ if(anchored)
+ WRENCH_ATTEMPT_UNANCHOR_MESSAGE
+ else
+ WRENCH_ATTEMPT_ANCHOR_MESSAGE
+ if(!I.use_tool(src, user, 5 SECONDS, volume = I.tool_volume))
+ return
+ anchored = !anchored
+ if(anchored)
+ WRENCH_ANCHOR_MESSAGE
+ else
+ WRENCH_UNANCHOR_MESSAGE
+ SStgui.close_uis(src)
diff --git a/sound/items/handling/register_drop.ogg b/sound/items/handling/register_drop.ogg
new file mode 100644
index 00000000000..9827dd52cc7
Binary files /dev/null and b/sound/items/handling/register_drop.ogg differ
diff --git a/sound/machines/checkout.ogg b/sound/machines/checkout.ogg
new file mode 100644
index 00000000000..e082a67a4d1
Binary files /dev/null and b/sound/machines/checkout.ogg differ
diff --git a/sound/weapons/ringslam.ogg b/sound/weapons/ringslam.ogg
new file mode 100644
index 00000000000..5c2d7f339b6
Binary files /dev/null and b/sound/weapons/ringslam.ogg differ