Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handheld EFTPOS offering #27978

Merged
merged 3 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions code/__DEFINES/status_effects.dm
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@

#define STATUS_EFFECT_HIGHFIVE /datum/status_effect/high_five
#define STATUS_EFFECT_DAP /datum/status_effect/high_five/dap
#define STATUS_EFFECT_OFFERING_EFTPOS /datum/status_effect/high_five/offering_eftpos
#define STATUS_EFFECT_HANDSHAKE /datum/status_effect/high_five/handshake
#define STATUS_EFFECT_RPS /datum/status_effect/high_five/rps

Expand Down
23 changes: 23 additions & 0 deletions code/datums/status_effects/neutral.dm
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,29 @@
/datum/status_effect/high_five/dap/get_missed_message()
return "sadly can't find anybody to give daps to, and daps [owner.p_themselves()]. Shameful."

/datum/status_effect/high_five/offering_eftpos
id = "offering_eftpos"
request = "holds out an EFTPOS device."
item_path = /obj/item/eftpos

/datum/status_effect/high_five/offering_eftpos/get_missed_message()
return "pulls back the EFTPOS device."

/datum/status_effect/high_five/offering_eftpos/on_apply()
owner.custom_emote(EMOTE_VISIBLE, request)
owner.create_point_bubble_from_path(item_path, FALSE)
RegisterSignal(owner, COMSIG_ATOM_RANGED_ATTACKED, PROC_REF(on_ranged_attack))
return TRUE

/datum/status_effect/high_five/offering_eftpos/on_remove()
UnregisterSignal(owner, COMSIG_ATOM_RANGED_ATTACKED)

/datum/status_effect/high_five/offering_eftpos/proc/on_ranged_attack(mob/living/me, mob/living/carbon/human/attacker)
SIGNAL_HANDLER // COMSIG_ATOM_RANGED_ATTACKED
if(get_dist(me, attacker) <= 2)
to_chat(attacker, "<span class='warning'>You need to have your ID in hand to scan it!</span>")
return COMPONENT_CANCEL_ATTACK_CHAIN

/datum/status_effect/high_five/handshake
id = "handshake"
critical_success = "give each other an EPIC handshake!"
Expand Down
21 changes: 21 additions & 0 deletions code/game/objects/items/weapons/cards_ids.dm
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,27 @@
if(can_id_flash)
flash_card(user)

/obj/item/card/id/interact_with_atom(atom/target, mob/living/user, list/modifiers)
if(!isliving(target))
return NONE
return shared_interact(target, user)

/obj/item/card/id/ranged_interact_with_atom(atom/target, mob/living/user, list/modifiers)
if(isliving(target) && get_dist(target, user) <= 2)
return shared_interact(target, user)
return NONE

/obj/item/card/id/proc/shared_interact(mob/living/victim, mob/living/user)
if(victim.has_status_effect(STATUS_EFFECT_OFFERING_EFTPOS))
var/obj/item/eftpos/eftpos = victim.is_holding_item_of_type(/obj/item/eftpos)
if(!eftpos || !eftpos.can_offer)
to_chat(user, "<span class='warning'>They don't seem to have it in hand anymore.</span>")
return ITEM_INTERACT_COMPLETE
victim.remove_status_effect(STATUS_EFFECT_OFFERING_EFTPOS)
eftpos.scan_card(src, user)
return ITEM_INTERACT_COMPLETE
return NONE

/obj/item/card/id/proc/UpdateName()
name = "[registered_name]'s ID Card ([assignment])"

Expand Down
26 changes: 18 additions & 8 deletions code/modules/economy/economy_machinery/eftpos.dm
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
var/datum/money_account_database/main_station/account_database
///Current money account the EFTPOS is depositing to
var/datum/money_account/linked_account
///Is this a portable unit that you can offer with *payme?
var/can_offer = TRUE

/obj/item/eftpos/Initialize(mapload)
machine_name = "EFTPOS #[rand(101, 999)]"
Expand Down Expand Up @@ -80,6 +82,7 @@
)
data["available_accounts"] += list(account_data)

data["can_offer"] = can_offer

return data

Expand Down Expand Up @@ -148,21 +151,27 @@
else if(istype(I, /obj/item/card/emag))
access_code = 0
to_chat(user, "[bicon(src)]<span class='notice'>Access code reset to 0.</span>")
if("offer")
if(can_offer)
offer(user)

/obj/item/eftpos/proc/offer(mob/living/user)
user.apply_status_effect(STATUS_EFFECT_OFFERING_EFTPOS)

/obj/item/eftpos/proc/scan_card(obj/item/card/id/C, mob/user, secured = TRUE)
visible_message("<span class='notice'>[user] swipes a card through [src].</span>")

if(!transaction_locked || transaction_paid || !secured)
visible_message("<span class='notice'>[user] swipes a card through [src], but nothing happens.</span>")
return

visible_message("<span class='notice'>[user] swipes a card through [src].</span>")

if(!linked_account)
to_chat(user, "[bicon(src)]<span class='warning'>EFTPOS is not connected to an account.</span>")
visible_message("[bicon(src)]<span class='warning'>[src] buzzes as its display flashes \"EFTPOS is not connected to an account.\"</span>", "<span class='notice'>You hear something buzz.</span>")
return

var/datum/money_account/D = GLOB.station_money_database.find_user_account(C.associated_account_number, include_departments = FALSE)
if(!D)
to_chat(user, "<span class='warning'>Your currently in use card is not connected to a money account.</span>")
visible_message("[bicon(src)]<span class='warning'>[src] buzzes as its display flashes \"Card is not connected to an account.\"</span>", "<span class='notice'>You hear something buzz.</span>")
return
//if security level high enough, prompt for pin
var/attempt_pin
Expand All @@ -172,19 +181,19 @@
return
//given the credentials, can the associated account be accessed right now?
if(!GLOB.station_money_database.try_authenticate_login(D, attempt_pin, restricted_bypass = FALSE))
to_chat(user, "[bicon(src)]<span class='warning'>Unable to access account, insufficient access.</span>")
visible_message("[bicon(src)]<span class='warning'>[src] buzzes as its display flashes \"Access denied.\"</span>", "<span class='notice'>You hear something buzz.</span>")
return
if(tgui_alert(user, "Are you sure you want to pay $[transaction_amount] to: [linked_account.account_name]", "Confirm transaction", list("Yes", "No")) != "Yes")
return
if(!Adjacent(user))
if(!Adjacent(user) && !(can_offer && get_dist(user, src) <= 2))
return
//attempt to charge account money
if(!GLOB.station_money_database.charge_account(D, transaction_amount, transaction_purpose, machine_name, FALSE, FALSE))
to_chat(user, "[bicon(src)]<span class='warning'>Insufficient credits in your account!</span>")
visible_message("[bicon(src)]<span class='warning'>[src] buzzes as its display flashes \"Insufficient funds.\"</span>", "<span class='notice'>You hear something buzz.</span>")
return
GLOB.station_money_database.credit_account(linked_account, transaction_amount, transaction_purpose, machine_name, FALSE)
playsound(src, transaction_sound, 50, TRUE)
visible_message("<span class='notice'>[src] chimes!</span>")
visible_message("[bicon(src)]<span class='notice'>[src] chimes as its display reads \"Transaction successful!\"</span>", "<span class='notice'>You hear something chime.</span>")
transaction_paid = TRUE
addtimer(VARSET_CALLBACK(src, transaction_paid, FALSE), 5 SECONDS)

Expand Down Expand Up @@ -232,6 +241,7 @@
pickup_sound = 'sound/items/handling/toolbox_pickup.ogg'
transaction_sound = 'sound/machines/checkout.ogg'
attack_verb = list("bounced a check off", "checked-out", "tipped")
can_offer = FALSE

/obj/item/eftpos/register/examine(mob/user)
. = ..()
Expand Down
5 changes: 4 additions & 1 deletion code/modules/mob/living/carbon/carbon_procs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,10 @@
return
// If it has any of the highfive statuses, dap, handshake, etc
var/datum/status_effect/effect = has_status_effect_type(STATUS_EFFECT_HIGHFIVE)
if(effect)
if(istype(effect, STATUS_EFFECT_OFFERING_EFTPOS))
to_chat(M, "<span class='warning'>You need to have your ID in hand to scan it!</span>")
return
else if(effect)
M.apply_status_effect(effect.type)
return
// BEGIN HUGCODE - N3X
Expand Down
25 changes: 25 additions & 0 deletions code/modules/mob/living/carbon/human/human_emote.dm
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,31 @@
status = STATUS_EFFECT_DAP
key_third_person = "daps"

/datum/emote/living/carbon/human/highfive/payme
key = "payme"
status = STATUS_EFFECT_OFFERING_EFTPOS

/datum/emote/living/carbon/human/highfive/payme/run_emote(mob/living/user, params, type_override, intentional)
var/obj/item/eftpos/eftpos = user.is_holding_item_of_type(/obj/item/eftpos)
if(!eftpos)
to_chat(user, "<span class='warning'>You must be holding an EFTPOS to do that!</span>")
return TRUE
if(!eftpos.can_offer)
to_chat(user, "<span class='warning'>[eftpos] is too bulky to hold out to someone!</span>")
return TRUE
if(!eftpos.transaction_locked)
to_chat(user, "<span class='warning'>You must lock [eftpos] before it can accept payments.</span>")
return TRUE
if(user.has_status_effect(status))
user.visible_message("<span class='notice'>[user.name] shakes [eftpos] around slightly, impatiently waiting for someone to scan their card.</span>")
return TRUE

var/datum/result = set_status(user)
if(QDELETED(result))
return TRUE

return TRUE

/datum/emote/living/carbon/human/highfive/handshake
key = "handshake"
key_third_person = "handshakes"
Expand Down
10 changes: 8 additions & 2 deletions tgui/packages/tgui/interfaces/EFTPOS.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const EFTPOS = (props, context) => {

const LockedView = (props, context) => {
const { act, data } = useBackend(context);
const { transaction_amount, transaction_paid } = data;
const { transaction_amount, transaction_paid, can_offer } = data;
return (
<>
<Box
Expand All @@ -56,14 +56,20 @@ const LockedView = (props, context) => {
? 'This transaction has been processed successfully '
: 'Swipe your card to finish this transaction.'}
</Box>
{(can_offer && (
<Box mt={0.5} fontSize="1.25rem" align="center" justify="center">
<Button content="Request Payment" icon="credit-card" onClick={() => act('offer')} />
</Box>
)) ||
''}
</>
);
};

const UnlockedView = (props, context) => {
const { act, data } = useBackend(context);
const [searchText, setSearchText] = useLocalState(context, 'searchText', '');
const { transaction_purpose, transaction_amount, linked_account, available_accounts } = data;
const { transaction_purpose, transaction_amount, linked_account, available_accounts, can_offer } = data;

let accountMap = [];
available_accounts.map((account) => (accountMap[account.name] = account.UID));
Expand Down
144 changes: 72 additions & 72 deletions tgui/public/tgui.bundle.js

Large diffs are not rendered by default.

Loading