[Ready for review]Adds credit holochips to replace magic cash (#40462)

cl XDTM
add: Added credit holochips, a form of semi-physical currency to use in transactions. They can be generated by id cards by drawing from bank accounts and can be used to make payments.
add: There is no limit to the amount of credits that can be stored on a holochip, but being holograms they are vulnerable to electromagnetic pulses, and may disappear if exposed to one!
add: Holochips can be split with alt-click, and can be merged by clicking on another holochip.
/cl

Inserting physical cash into ids and printing it on the go is really jarring, and since we're on a sci-fi universe i think that hard-light hologram chips with encrypted credits sounds more believable.

As a plus, they don't have to deal with messy stack calculations with different denominations, and simply have a credits var that holds their amount. They change color based on the amount of cash for easy recognizability.
This commit is contained in:
XDTM
2018-09-26 00:35:02 +02:00
committed by yogstation13-bot
parent 19ed135b4b
commit 5a4e5b8090
11 changed files with 160 additions and 43 deletions

View File

@@ -8,6 +8,7 @@
var/obj/item/radio/radio var/obj/item/radio/radio
var/radio_channel = "Common" var/radio_channel = "Common"
var/minimum_time_between_warnings = 400 var/minimum_time_between_warnings = 400
var/syphoning_credits = 0
/obj/machinery/computer/bank_machine/Initialize() /obj/machinery/computer/bank_machine/Initialize()
. = ..() . = ..()
@@ -25,6 +26,9 @@
if(istype(I, /obj/item/stack/spacecash)) if(istype(I, /obj/item/stack/spacecash))
var/obj/item/stack/spacecash/C = I var/obj/item/stack/spacecash/C = I
value = C.value * C.amount value = C.value * C.amount
else if(istype(I, /obj/item/holochip))
var/obj/item/holochip/H = I
value = H.credits
if(value) if(value)
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D) if(D)
@@ -40,14 +44,15 @@
if(siphoning) if(siphoning)
if (stat & (BROKEN|NOPOWER)) if (stat & (BROKEN|NOPOWER))
say("Insufficient power. Halting siphon.") say("Insufficient power. Halting siphon.")
siphoning = FALSE end_syphon()
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(!D.has_money(200)) if(!D.has_money(200))
say("Cargo budget depleted. Halting siphon.") say("Cargo budget depleted. Halting siphon.")
siphoning = FALSE end_syphon()
return return
new /obj/item/stack/spacecash/c200(drop_location()) // will autostack
playsound(src, 'sound/items/poster_being_created.ogg', 100, 1) playsound(src, 'sound/items/poster_being_created.ogg', 100, 1)
syphoning_credits += 200
D.adjust_money(-200) D.adjust_money(-200)
if(next_warning < world.time && prob(15)) if(next_warning < world.time && prob(15))
var/area/A = get_area(loc) var/area/A = get_area(loc)
@@ -85,4 +90,9 @@
siphoning = TRUE siphoning = TRUE
if(href_list["halt"]) if(href_list["halt"])
say("Station credit withdrawal halted.") say("Station credit withdrawal halted.")
siphoning = FALSE end_syphon()
/obj/machinery/computer/bank_machine/proc/end_syphon()
siphoning = FALSE
new /obj/item/holochip(drop_location(), syphoning_credits) //get the loot
syphoning_credits = 0

View File

@@ -142,14 +142,12 @@
update_label() update_label()
/obj/item/card/id/attackby(obj/item/W, mob/user, params) /obj/item/card/id/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/stack/spacecash)) if(istype(W, /obj/item/holochip))
var/obj/item/stack/spacecash/vbucks = W var/obj/item/holochip/holochip = W
if(registered_account) if(registered_account)
var/fortnite_money = vbucks.value * vbucks.amount registered_account.adjust_money(holochip.credits)
registered_account.adjust_money(fortnite_money) to_chat(user, "You insert [holochip] into [src], adding [holochip.credits] credits to your account.")
to_chat(user, "You insert [vbucks] into [src], adding $[fortnite_money] to your account.") qdel(holochip)
qdel(vbucks)
/obj/item/card/id/attack_self(mob/user) /obj/item/card/id/attack_self(mob/user)
if(!registered_account) if(!registered_account)
@@ -170,10 +168,9 @@
if(!amount_to_remove || amount_to_remove < 0) if(!amount_to_remove || amount_to_remove < 0)
return return
if(registered_account.adjust_money(-amount_to_remove)) if(registered_account.adjust_money(-amount_to_remove))
var/obj/item/stack/spacecash/c1/dosh = new /obj/item/stack/spacecash/c1(get_turf(user)) var/obj/item/holochip/holochip = new (get_turf(user), amount_to_remove)
dosh.amount = amount_to_remove user.put_in_hands(holochip)
user.put_in_hands(dosh) to_chat(user, "You withdraw [amount_to_remove] credits into a holochip.")
to_chat(user, "You withdraw $[amount_to_remove].")
return return
else else
to_chat(user, "You don't have the funds for that.") to_chat(user, "You don't have the funds for that.")
@@ -187,8 +184,8 @@
var/datum/bank_account/D = SSeconomy.get_dep_account(registered_account.account_job.paycheck_department) var/datum/bank_account/D = SSeconomy.get_dep_account(registered_account.account_job.paycheck_department)
if(D) if(D)
to_chat(user, "The [D.account_holder] reports a balance of $[D.account_balance].") to_chat(user, "The [D.account_holder] reports a balance of $[D.account_balance].")
to_chat(user, "Use your ID in-hand to pull money from your account in the form of cash.") to_chat(user, "Use your ID in-hand to pull money from your account in the form of holochips.")
to_chat(user, "You can insert cash into your account by smashing the money against the ID.") to_chat(user, "You can insert credits into your account by pressing holochips against the ID.")
to_chat(user, "If you lose this ID card, you can reclaim your account by using a blank ID card inhand and punching in the account ID.") to_chat(user, "If you lose this ID card, you can reclaim your account by using a blank ID card inhand and punching in the account ID.")
if(mining_points) if(mining_points)

View File

@@ -0,0 +1,83 @@
/obj/item/holochip
name = "credit holochip"
desc = "A hard-light chip encoded with an amount of credits. It is a modern replacement for physical money that can be directly converted to virtual currency and viceversa. Keep away from magnets."
icon = 'icons/obj/economy.dmi'
icon_state = "holochip_1"
throwforce = 0
force = 0
w_class = WEIGHT_CLASS_TINY
var/credits = 0
/obj/item/holochip/Initialize(mapload, amount)
. = ..()
credits = amount
update_icon()
/obj/item/holochip/examine(mob/user)
. = ..()
to_chat(user, "<span class='notice'>It's loaded with [credits] credit[( credits > 1 ) ? "s" : ""]</span>")
to_chat(user, "<span class='notice'>Alt-Click to split.</span>")
/obj/item/holochip/update_icon()
switch(credits)
if(1 to 9)
icon_state = "holochip_1"
if(10 to 99)
icon_state = "holochip_10"
if(100 to 999)
icon_state = "holochip_100"
if(1000 to 9999)
icon_state = "holochip_1k"
if(10000 to 999999)
icon_state = "holochip_10k"
if(1000000 to 999999999)
icon_state = "holochip_million"
if(1000000000 to INFINITY)
icon_state = "holochip_billion"
/obj/item/holochip/proc/spend(amount, pay_anyway = FALSE)
if(credits >= amount)
credits -= amount
if(credits == 0)
qdel(src)
update_icon()
return amount
else if(pay_anyway)
qdel(src)
return credits
else
return 0
/obj/item/holochip/attackby(obj/item/I, mob/user, params)
..()
if(istype(I, /obj/item/holochip))
var/obj/item/holochip/H = I
credits += H.credits
to_chat(user, "<span class='notice'>You insert the credits into [src].</span>")
update_icon()
qdel(H)
/obj/item/holochip/AltClick(mob/user)
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
var/split_amount = round(input(user,"How many credits do you want to extract from the holochip?") as null|num)
if(split_amount == null || split_amount <= 0 || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
else
var/new_credits = spend(split_amount, TRUE)
var/obj/item/holochip/H = new(user ? user : drop_location(), new_credits)
if(user)
if(!user.put_in_hands(H))
H.forceMove(user.drop_location())
add_fingerprint(user)
H.add_fingerprint(user)
to_chat(user, "<span class='notice'>You extract [split_amount] credits into a new holochip.</span>")
/obj/item/holochip/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
var/wipe_chance = 60 / severity
if(prob(wipe_chance))
visible_message("<span class='warning'>[src] fizzles and disappears!</span>")
qdel(src) //rip cash

View File

@@ -15,6 +15,7 @@
STR.max_items = 4 STR.max_items = 4
STR.can_hold = typecacheof(list( STR.can_hold = typecacheof(list(
/obj/item/stack/spacecash, /obj/item/stack/spacecash,
/obj/item/holochip,
/obj/item/card, /obj/item/card,
/obj/item/clothing/mask/cigarette, /obj/item/clothing/mask/cigarette,
/obj/item/flashlight/pen, /obj/item/flashlight/pen,
@@ -75,6 +76,5 @@
icon_state = "random_wallet" icon_state = "random_wallet"
/obj/item/storage/wallet/random/PopulateContents() /obj/item/storage/wallet/random/PopulateContents()
var/obj/item/stack/spacecash/c10/cash = new /obj/item/stack/spacecash/c10(src) new /obj/item/holochip(src, rand(5,30))
cash.amount = rand(1,5)
update_icon() update_icon()

View File

@@ -28,8 +28,7 @@
var/obj/item/card/id/vbucks = W var/obj/item/card/id/vbucks = W
if(vbucks.registered_account) if(vbucks.registered_account)
if(vbucks.registered_account.adjust_money(-price)) if(vbucks.registered_account.adjust_money(-price))
my_card.registered_account.adjust_money(price) purchase(vbucks.registered_account.account_holder)
my_card.registered_account.bank_card_talk("Purchase made at your vendor by [vbucks.registered_account.account_holder] for $[price].")
to_chat(user, "Thanks for purchasing! The vendor has been informed.") to_chat(user, "Thanks for purchasing! The vendor has been informed.")
return return
else else
@@ -38,6 +37,15 @@
else else
to_chat(user, "You're going to need an actual bank account for that one, buddy.") to_chat(user, "You're going to need an actual bank account for that one, buddy.")
return return
if(istype(W, /obj/item/holochip))
var/obj/item/holochip/H = W
if(H.spend(price, FALSE))
purchase(user)
to_chat(user, "Thanks for purchasing! The vendor has been informed.")
return
else
to_chat(user, "You trying to punk me, kid? Come back when you have the cash.")
return
if(istype(W, /obj/item/stack/spacecash)) if(istype(W, /obj/item/stack/spacecash))
to_chat(user, "What is this, the 2000s? We only take card here.") to_chat(user, "What is this, the 2000s? We only take card here.")
return return
@@ -57,4 +65,9 @@
else if(default_deconstruction_crowbar(W)) else if(default_deconstruction_crowbar(W))
return return
else else
return ..() return ..()
/obj/machinery/paystand/proc/purchase(buyer)
my_card.registered_account.adjust_money(price)
my_card.registered_account.bank_card_talk("Purchase made at your vendor by [buyer] for [price] credits.")

View File

@@ -146,15 +146,9 @@
new /obj/effect/temp_visual/emp(get_turf(S)) new /obj/effect/temp_visual/emp(get_turf(S))
/obj/machinery/shuttle_scrambler/proc/dump_loot(mob/user) /obj/machinery/shuttle_scrambler/proc/dump_loot(mob/user)
if(credits_stored < 200) new /obj/item/holochip(drop_location(), credits_stored)
to_chat(user,"<span class='notice'>Not enough credits to retrieve.</span>")
return
while(credits_stored >= 200)
new /obj/item/stack/spacecash/c200(drop_location())
credits_stored -= 200
to_chat(user,"<span class='notice'>You retrieve the siphoned credits!</span>") to_chat(user,"<span class='notice'>You retrieve the siphoned credits!</span>")
/obj/machinery/shuttle_scrambler/proc/send_notification() /obj/machinery/shuttle_scrambler/proc/send_notification()
priority_announce("Data theft signal detected, source registered on local gps units.") priority_announce("Data theft signal detected, source registered on local gps units.")
@@ -458,4 +452,13 @@
/datum/export/pirate/cash/get_amount(obj/O) /datum/export/pirate/cash/get_amount(obj/O)
var/obj/item/stack/spacecash/C = O var/obj/item/stack/spacecash/C = O
return ..() * C.amount * C.value return ..() * C.amount * C.value
/datum/export/pirate/holochip
cost = 1
unit_name = "holochip"
export_types = list(/obj/item/holochip)
/datum/export/pirate/holochip/get_cost(atom/movable/AM)
var/obj/item/holochip/H = AM
return H.credits

View File

@@ -15,7 +15,7 @@
STR.max_w_class = WEIGHT_CLASS_NORMAL STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_items = 40 STR.max_items = 40
STR.max_combined_w_class = 40 STR.max_combined_w_class = 40
STR.can_hold = typecacheof(list(/obj/item/coin, /obj/item/stack/spacecash)) STR.can_hold = typecacheof(list(/obj/item/coin, /obj/item/stack/spacecash, /obj/item/holochip))
/obj/item/storage/bag/money/vault/PopulateContents() /obj/item/storage/bag/money/vault/PopulateContents()
new /obj/item/coin/silver(src) new /obj/item/coin/silver(src)

View File

@@ -232,25 +232,35 @@
var/list/counted_money = list() var/list/counted_money = list()
for(var/obj/item/coin/C in AM.GetAllContents()) for(var/obj/item/coin/C in AM.GetAllContents())
payees[AM] += C.value
counted_money += C
if(payees[AM] >= threshold) if(payees[AM] >= threshold)
break break
payees[AM] += C.value
counted_money += C
for(var/obj/item/stack/spacecash/S in AM.GetAllContents()) for(var/obj/item/stack/spacecash/S in AM.GetAllContents())
if(payees[AM] >= threshold)
break
payees[AM] += S.value * S.amount payees[AM] += S.value * S.amount
counted_money += S counted_money += S
for(var/obj/item/holochip/H in AM.GetAllContents())
if(payees[AM] >= threshold) if(payees[AM] >= threshold)
break break
payees[AM] += H.credits
counted_money += H
if(istype(AM.pulling, /obj/item/coin)) if(payees[AM] < threshold && istype(AM.pulling, /obj/item/coin))
var/obj/item/coin/C = AM.pulling var/obj/item/coin/C = AM.pulling
payees[AM] += C.value payees[AM] += C.value
counted_money += C counted_money += C
else if(istype(AM.pulling, /obj/item/stack/spacecash)) else if(payees[AM] < threshold && istype(AM.pulling, /obj/item/stack/spacecash))
var/obj/item/stack/spacecash/S = AM.pulling var/obj/item/stack/spacecash/S = AM.pulling
payees[AM] += S.value * S.amount payees[AM] += S.value * S.amount
counted_money += S counted_money += S
else if(payees[AM] < threshold && istype(AM.pulling, /obj/item/holochip))
var/obj/item/holochip/H = AM.pulling
payees[AM] += H.credits
counted_money += H
if(ishuman(AM)) if(ishuman(AM))
var/mob/living/carbon/human/H = AM var/mob/living/carbon/human/H = AM

View File

@@ -16,14 +16,14 @@
for(var/mob/living/carbon/C in targets) for(var/mob/living/carbon/C in targets)
if(user.dropItemToGround(user.get_active_held_item())) if(user.dropItemToGround(user.get_active_held_item()))
var/obj/item = pick( var/obj/item = pick(
new /obj/item/coin/gold(user.loc), new /obj/item/coin/gold(user.drop_location()),
new /obj/item/coin/diamond(user.loc), new /obj/item/coin/diamond(user.drop_location()),
new /obj/item/coin/silver(user.loc), new /obj/item/coin/silver(user.drop_location()),
new /obj/item/clothing/accessory/medal/gold(user.loc), new /obj/item/clothing/accessory/medal/gold(user.drop_location()),
new /obj/item/stack/sheet/mineral/gold(user.loc), new /obj/item/stack/sheet/mineral/gold(user.drop_location()),
new /obj/item/stack/sheet/mineral/silver(user.loc), new /obj/item/stack/sheet/mineral/silver(user.drop_location()),
new /obj/item/stack/sheet/mineral/diamond(user.loc), new /obj/item/stack/sheet/mineral/diamond(user.drop_location()),
new /obj/item/stack/spacecash/c1000(user.loc)) new /obj/item/holochip(user.drop_location(), 1000))
C.put_in_hands(item) C.put_in_hands(item)
/obj/effect/proc_holder/spell/targeted/view_range /obj/effect/proc_holder/spell/targeted/view_range

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -769,6 +769,7 @@
#include "code\game\objects\items\cosmetics.dm" #include "code\game\objects\items\cosmetics.dm"
#include "code\game\objects\items\courtroom.dm" #include "code\game\objects\items\courtroom.dm"
#include "code\game\objects\items\crayons.dm" #include "code\game\objects\items\crayons.dm"
#include "code\game\objects\items\credit_holochip.dm"
#include "code\game\objects\items\defib.dm" #include "code\game\objects\items\defib.dm"
#include "code\game\objects\items\dehy_carp.dm" #include "code\game\objects\items\dehy_carp.dm"
#include "code\game\objects\items\dice.dm" #include "code\game\objects\items\dice.dm"