mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 17:52:36 +00:00
The Coupon Master PDA app (#80240)
## About The Pull Request This PR adds a new PDA program to the supply category, which allows users to redeems coupons for various cargo packs (mostly goodies), like the ones also found at the bottom of cig packs. How it works is fairly simple: - Once installed, the modular computer subsystem will periodically, at a 3-5 minutes interval, generate a coupon code datum associated to a plain text code, which is sent out to everyone with the program installed. - The user can then open the program and insert the text into an input box to redeem the coupon code, which is then associated with their bank account. - He will then have to find a photocopier, and tap it with the PDA to print the coupon. Only one coupon can be printed. Photocopier fees apply, so it'd cost 5 creds to the average assistant to print the coupon. - He can then insert the coupon in a cargo console and order/reuest the associated pack (same deal as cig coupons). - Some coupon codes however, especially those with juicer discounts, will expire after a while if not printed. Albeit mostly innocuous, the program provides negative Detomatix resistance, slowly fills the computer file storage with trash files with each redeemed coupon, and halves the download speed of new apps. Not really the cleanest ware out there. This PR also extends coupons to several non-goody packs, since they have been privately buyable for over the last couple years now. Some packs get discounts less frequently however, with those in the uncommon category being roughly 1 in a 12 chance and the rare being 1 in 50. Here's a screenshot of the UI (outdated, I've reduced the height from 500 to 400 and the notice box tip to specify the right click):  Fun fact: Right now, the odds of a 75% discount coming from the Coupon Master for the 1.000.000 credits bycycle pack are roughly 0.0012%, while that of a 50% for the same pack, from a cig pack coupon are 0.0042%. ## Why It's Good For The Game These last couple days I've been wanting to test myself at making simple UIs, as well as contributing to the modular computers feature, which has started to become pretty neat ever since PDAs were reworked into a subtype of it. Beside, coupons are a very small feature limited to the bottom of cigarette packs (also possibly cursed) in the current state of affairs. Cargo is filled with packs that are niche or fluff. Modular computers also has those little things that, while interesting, do not contribute a whole lot. Maybe this is one of them, but I guess free* coupons are always a big W. ## Changelog 🆑 add: Added the 'Coupon Master' program for the PDA. Install it to receive periodical, redeemable coupons for several cargo packs. Requires NTnet connection and the messenger enabled to work. add: Coupons are no longer only limited to goodies, but may also apply discount to some other packs as well. /🆑 <sup>*minus the photocopier fee</sup> --------- Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com>
This commit is contained in:
@@ -53,21 +53,14 @@
|
||||
/// Universal Scanner mode for using the price tagger.
|
||||
#define SCAN_PRICE_TAG 3
|
||||
|
||||
GLOBAL_LIST_EMPTY(supplypod_loading_bays)
|
||||
///Used by coupons to define that they're cursed
|
||||
#define COUPON_OMEN "omen"
|
||||
|
||||
GLOBAL_LIST_INIT(podstyles, list(\
|
||||
list(POD_SHAPE_NORML, "pod", TRUE, "default", "yellow", RUBBLE_NORMAL, "supply pod", "A Nanotrasen supply drop pod."),\
|
||||
list(POD_SHAPE_NORML, "advpod", TRUE, "bluespace", "blue", RUBBLE_NORMAL, "bluespace supply pod" , "A Nanotrasen Bluespace supply pod. Teleports back to CentCom after delivery."),\
|
||||
list(POD_SHAPE_NORML, "advpod", TRUE, "centcom", "blue", RUBBLE_NORMAL, "\improper CentCom supply pod", "A Nanotrasen supply pod, this one has been marked with Central Command's designations. Teleports back to CentCom after delivery."),\
|
||||
list(POD_SHAPE_NORML, "darkpod", TRUE, "syndicate", "red", RUBBLE_NORMAL, "blood-red supply pod", "An intimidating supply pod, covered in the blood-red markings of the Syndicate. It's probably best to stand back from this."),\
|
||||
list(POD_SHAPE_NORML, "darkpod", TRUE, "deathsquad", "blue", RUBBLE_NORMAL, "\improper Deathsquad drop pod", "A Nanotrasen drop pod. This one has been marked the markings of Nanotrasen's elite strike team."),\
|
||||
list(POD_SHAPE_NORML, "pod", TRUE, "cultist", "red", RUBBLE_NORMAL, "bloody supply pod", "A Nanotrasen supply pod covered in scratch-marks, blood, and strange runes."),\
|
||||
list(POD_SHAPE_OTHER, "missile", FALSE, FALSE, FALSE, RUBBLE_THIN, "cruise missile", "A big ass missile that didn't seem to fully detonate. It was likely launched from some far-off deep space missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\
|
||||
list(POD_SHAPE_OTHER, "smissile", FALSE, FALSE, FALSE, RUBBLE_THIN, "\improper Syndicate cruise missile", "A big ass, blood-red missile that didn't seem to fully detonate. It was likely launched from some deep space Syndicate missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\
|
||||
list(POD_SHAPE_OTHER, "box", TRUE, FALSE, FALSE, RUBBLE_WIDE, "\improper Aussec supply crate", "An incredibly sturdy supply crate, designed to withstand orbital re-entry. Has 'Aussec Armory - 2532' engraved on the side."),\
|
||||
list(POD_SHAPE_NORML, "clownpod", TRUE, "clown", "green", RUBBLE_NORMAL, "\improper HONK pod", "A brightly-colored supply pod. It likely originated from the Clown Federation."),\
|
||||
list(POD_SHAPE_OTHER, "orange", TRUE, FALSE, FALSE, RUBBLE_NONE, "\improper Orange", "An angry orange."),\
|
||||
list(POD_SHAPE_OTHER, FALSE, FALSE, FALSE, FALSE, RUBBLE_NONE, "\improper S.T.E.A.L.T.H. pod MKVII", "A supply pod that, under normal circumstances, is completely invisible to conventional methods of detection. How are you even seeing this?"),\
|
||||
list(POD_SHAPE_OTHER, "gondola", FALSE, FALSE, FALSE, RUBBLE_NONE, "gondola", "The silent walker. This one seems to be part of a delivery agency."),\
|
||||
list(POD_SHAPE_OTHER, FALSE, FALSE, FALSE, FALSE, RUBBLE_NONE, FALSE, FALSE, "rl_click", "give_po")\
|
||||
))
|
||||
///Discount categories for coupons. This one is for anything that isn't discountable.
|
||||
#define SUPPLY_PACK_NOT_DISCOUNTABLE null
|
||||
///Discount category for the standard stuff, mostly goodies.
|
||||
#define SUPPLY_PACK_STD_DISCOUNTABLE "standard_discount"
|
||||
///Discount category for stuff that's mostly niche and/or that might be useful.
|
||||
#define SUPPLY_PACK_UNCOMMON_DISCOUNTABLE "uncommon_discount"
|
||||
///Discount category for the silly, overpriced, joke content, sometimes useful or plain bad.
|
||||
#define SUPPLY_PACK_RARE_DISCOUNTABLE "rare_discount"
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
///This app grants a larger protection against being PDA bombed if installed.
|
||||
///(can sometimes prevent it from being sent, while wasting a PDA bomb from the sender).
|
||||
#define DETOMATIX_RESIST_MAJOR 2
|
||||
///This app gives a diminished protection against being PDA bombed if installed.
|
||||
#define DETOMATIX_RESIST_MALUS -4
|
||||
|
||||
/**
|
||||
* NTNet transfer speeds, used when downloading/uploading a file/program.
|
||||
|
||||
@@ -782,10 +782,12 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
/// Trait applied when an integrated circuit opens a UI on a player (see list pick component)
|
||||
#define TRAIT_CIRCUIT_UI_OPEN "circuit_ui_open"
|
||||
|
||||
/// PDA Traits. This one makes PDAs explode if the user opens the messages menu
|
||||
/// PDA/ModPC Traits. This one makes PDAs explode if the user opens the messages menu
|
||||
#define TRAIT_PDA_MESSAGE_MENU_RIGGED "pda_message_menu_rigged"
|
||||
/// This one denotes a PDA has received a rigged message and will explode when the user tries to reply to a rigged PDA message
|
||||
#define TRAIT_PDA_CAN_EXPLODE "pda_can_explode"
|
||||
///The download speeds of programs from the dowloader is halved.
|
||||
#define TRAIT_MODPC_HALVED_DOWNLOAD_SPEED "modpc_halved_download_speed"
|
||||
|
||||
/// If present on a [/mob/living/carbon], will make them appear to have a medium level disease on health HUDs.
|
||||
#define TRAIT_DISEASELIKE_SEVERITY_MEDIUM "diseaselike_severity_medium"
|
||||
|
||||
34
code/_globalvars/lists/cargo.dm
Normal file
34
code/_globalvars/lists/cargo.dm
Normal file
@@ -0,0 +1,34 @@
|
||||
GLOBAL_LIST_INIT(discountable_packs, init_discountable_packs())
|
||||
|
||||
/proc/init_discountable_packs()
|
||||
var/list/packs = list()
|
||||
for(var/datum/supply_pack/prototype as anything in subtypesof(/datum/supply_pack))
|
||||
var/discountable = initial(prototype.discountable)
|
||||
if(discountable)
|
||||
LAZYADD(packs[discountable], prototype)
|
||||
return packs
|
||||
|
||||
GLOBAL_LIST_INIT(pack_discount_odds, list(
|
||||
SUPPLY_PACK_STD_DISCOUNTABLE = 45,
|
||||
SUPPLY_PACK_UNCOMMON_DISCOUNTABLE = 4,
|
||||
SUPPLY_PACK_RARE_DISCOUNTABLE = 1,
|
||||
))
|
||||
|
||||
GLOBAL_LIST_EMPTY(supplypod_loading_bays)
|
||||
|
||||
GLOBAL_LIST_INIT(podstyles, list(\
|
||||
list(POD_SHAPE_NORML, "pod", TRUE, "default", "yellow", RUBBLE_NORMAL, "supply pod", "A Nanotrasen supply drop pod."),\
|
||||
list(POD_SHAPE_NORML, "advpod", TRUE, "bluespace", "blue", RUBBLE_NORMAL, "bluespace supply pod" , "A Nanotrasen Bluespace supply pod. Teleports back to CentCom after delivery."),\
|
||||
list(POD_SHAPE_NORML, "advpod", TRUE, "centcom", "blue", RUBBLE_NORMAL, "\improper CentCom supply pod", "A Nanotrasen supply pod, this one has been marked with Central Command's designations. Teleports back to CentCom after delivery."),\
|
||||
list(POD_SHAPE_NORML, "darkpod", TRUE, "syndicate", "red", RUBBLE_NORMAL, "blood-red supply pod", "An intimidating supply pod, covered in the blood-red markings of the Syndicate. It's probably best to stand back from this."),\
|
||||
list(POD_SHAPE_NORML, "darkpod", TRUE, "deathsquad", "blue", RUBBLE_NORMAL, "\improper Deathsquad drop pod", "A Nanotrasen drop pod. This one has been marked the markings of Nanotrasen's elite strike team."),\
|
||||
list(POD_SHAPE_NORML, "pod", TRUE, "cultist", "red", RUBBLE_NORMAL, "bloody supply pod", "A Nanotrasen supply pod covered in scratch-marks, blood, and strange runes."),\
|
||||
list(POD_SHAPE_OTHER, "missile", FALSE, FALSE, FALSE, RUBBLE_THIN, "cruise missile", "A big ass missile that didn't seem to fully detonate. It was likely launched from some far-off deep space missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\
|
||||
list(POD_SHAPE_OTHER, "smissile", FALSE, FALSE, FALSE, RUBBLE_THIN, "\improper Syndicate cruise missile", "A big ass, blood-red missile that didn't seem to fully detonate. It was likely launched from some deep space Syndicate missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\
|
||||
list(POD_SHAPE_OTHER, "box", TRUE, FALSE, FALSE, RUBBLE_WIDE, "\improper Aussec supply crate", "An incredibly sturdy supply crate, designed to withstand orbital re-entry. Has 'Aussec Armory - 2532' engraved on the side."),\
|
||||
list(POD_SHAPE_NORML, "clownpod", TRUE, "clown", "green", RUBBLE_NORMAL, "\improper HONK pod", "A brightly-colored supply pod. It likely originated from the Clown Federation."),\
|
||||
list(POD_SHAPE_OTHER, "orange", TRUE, FALSE, FALSE, RUBBLE_NONE, "\improper Orange", "An angry orange."),\
|
||||
list(POD_SHAPE_OTHER, FALSE, FALSE, FALSE, FALSE, RUBBLE_NONE, "\improper S.T.E.A.L.T.H. pod MKVII", "A supply pod that, under normal circumstances, is completely invisible to conventional methods of detection. How are you even seeing this?"),\
|
||||
list(POD_SHAPE_OTHER, "gondola", FALSE, FALSE, FALSE, RUBBLE_NONE, "gondola", "The silent walker. This one seems to be part of a delivery agency."),\
|
||||
list(POD_SHAPE_OTHER, FALSE, FALSE, FALSE, FALSE, RUBBLE_NONE, FALSE, FALSE, "rl_click", "give_po")\
|
||||
))
|
||||
@@ -527,6 +527,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_COMPONENT_MMI" = TRAIT_COMPONENT_MMI,
|
||||
),
|
||||
/obj/item/modular_computer = list(
|
||||
"TRAIT_MODPC_HALVED_DOWNLOAD_SPEED" = TRAIT_MODPC_HALVED_DOWNLOAD_SPEED,
|
||||
"TRAIT_PDA_CAN_EXPLODE" = TRAIT_PDA_CAN_EXPLODE,
|
||||
"TRAIT_PDA_MESSAGE_MENU_RIGGED" = TRAIT_PDA_MESSAGE_MENU_RIGGED,
|
||||
),
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
///The maximum amount of logs that can be generated before they start overwriting eachother.
|
||||
s///The maximum amount of logs that can be generated before they start overwriting eachother.
|
||||
#define MAX_LOG_COUNT 300
|
||||
|
||||
SUBSYSTEM_DEF(modular_computers)
|
||||
name = "Modular Computers"
|
||||
flags = SS_NO_FIRE
|
||||
|
||||
wait = 1 MINUTES
|
||||
runlevels = RUNLEVEL_GAME
|
||||
|
||||
///List of all logs generated by ModPCs through the round.
|
||||
///Stops at MAX_LOG_COUNT and must be purged to keep logging.
|
||||
@@ -22,11 +24,94 @@ SUBSYSTEM_DEF(modular_computers)
|
||||
var/intrusion_detection_alarm = FALSE
|
||||
var/next_picture_id = 0
|
||||
|
||||
///Lazylist of coupons used by the Coupon Master PDA app. e.g. "COUPONCODE25" = coupon_code
|
||||
var/list/discount_coupons
|
||||
///When will the next coupon drop?
|
||||
var/next_discount = 0
|
||||
|
||||
/datum/controller/subsystem/modular_computers/Initialize()
|
||||
build_software_lists()
|
||||
initialized = TRUE
|
||||
return SS_INIT_SUCCESS
|
||||
|
||||
/datum/controller/subsystem/modular_computers/fire(resumed = FALSE)
|
||||
if(discount_coupons && world.time >= next_discount)
|
||||
announce_coupon()
|
||||
|
||||
///Generate new coupon codes that can be redeemed with the Coupon Master App
|
||||
/datum/controller/subsystem/modular_computers/proc/announce_coupon()
|
||||
//If there's no way to announce the coupon, we may as well skip it.
|
||||
if(!length(GLOB.announcement_systems))
|
||||
return
|
||||
var/obj/machinery/announcement_system/announcement_system = pick(GLOB.announcement_systems)
|
||||
|
||||
var/static/list/discounts = list("0.10" = 7, "0.15" = 16, "0.20" = 20, "0.25" = 16, "0.50" = 8, "0.66" = 1)
|
||||
var/static/list/flash_discounts = list("0.30" = 3, "0.40" = 8, "0.50" = 8, "0.66" = 2, "0.75" = 1)
|
||||
///Eliminates non-alphanumeri characters, as well as the word "Single-Pack" or "Pack" or "Crate" from the coupon code
|
||||
var/static/regex/strip_pack_name = regex("\[^a-zA-Z0-9]|(Single-)?Pack|Crate", "g")
|
||||
|
||||
var/datum/supply_pack/discounted_pack = pick(GLOB.discountable_packs[pick_weight(GLOB.pack_discount_odds)])
|
||||
var/pack_name = initial(discounted_pack.name)
|
||||
var/chosen_discount
|
||||
var/expires_in = 0
|
||||
if(prob(75))
|
||||
chosen_discount = text2num(pick_weight(discounts))
|
||||
if(prob(20))
|
||||
expires_in = rand(8,10)
|
||||
else
|
||||
chosen_discount = text2num(pick_weight(flash_discounts))
|
||||
expires_in = rand(2, 4)
|
||||
var/coupon_code = "[uppertext(strip_pack_name.Replace(pack_name, ""))][chosen_discount*100]"
|
||||
|
||||
var/list/targets = list()
|
||||
for (var/messenger_ref in GLOB.pda_messengers)
|
||||
var/datum/computer_file/program/messenger/messenger = GLOB.pda_messengers[messenger_ref]
|
||||
if(locate(/datum/computer_file/program/coupon) in messenger?.computer.stored_files)
|
||||
targets += messenger
|
||||
|
||||
///Don't go any further if the same coupon code has been done alrady or if there's no recipient for the 'promo'.
|
||||
if((coupon_code in discount_coupons) || !length(targets))
|
||||
return
|
||||
|
||||
var/datum/coupon_code/coupon = new(chosen_discount, discounted_pack, expires_in)
|
||||
|
||||
discount_coupons[coupon_code] = coupon
|
||||
|
||||
///pda message code here
|
||||
var/static/list/promo_messages = list(
|
||||
"A new discount has dropped for %GOODY: %DISCOUNT.",
|
||||
"Check this new offer out: %GOODY, now %DISCOUNT off.",
|
||||
"Now on sales: %GOODY, at %DISCOUNT discount!",
|
||||
"This item is now on sale (%DISCOUNT off): %GOODY.",
|
||||
"Would you look at that! A %DISCOUNT discount on %GOODY!",
|
||||
"Exclusive offer for %GOODY. Only %DISCOUNT! Get it now:",
|
||||
"%GOODY is now %DISCOUNT off.",
|
||||
"*RING* A new discount has dropped: %GOODY, %DISCOUNT off.",
|
||||
"%GOODY - %DISCOUNT off."
|
||||
)
|
||||
var/static/list/code_messages = list(
|
||||
"Here's the code",
|
||||
"Use this code to redeem it",
|
||||
"Open the app to redeem it",
|
||||
"Code",
|
||||
"Redeem it now",
|
||||
"Buy it now",
|
||||
)
|
||||
|
||||
var/chosen_promo_message = replacetext(replacetext(pick(promo_messages), "%GOODY", pack_name), "%DISCOUNT", "[chosen_discount*100]%")
|
||||
var/datum/signal/subspace/messaging/tablet_message/signal = new(announcement_system, list(
|
||||
"fakename" = "Coupon Master",
|
||||
"fakejob" = "Goodies Promotion",
|
||||
"message" = "[chosen_promo_message] [pick(code_messages)]: [coupon_code][expires_in ? " (EXPIRES IN [expires_in] MINUTES)" : ""].",
|
||||
"targets" = targets,
|
||||
"automated" = TRUE,
|
||||
))
|
||||
|
||||
signal.send_to_receivers()
|
||||
|
||||
next_discount = world.time + rand(3, 5) MINUTES
|
||||
|
||||
|
||||
///Finds all downloadable programs and adds them to their respective downloadable list.
|
||||
/datum/controller/subsystem/modular_computers/proc/build_software_lists()
|
||||
for(var/datum/computer_file/program/prog as anything in subtypesof(/datum/computer_file/program))
|
||||
|
||||
@@ -213,7 +213,7 @@
|
||||
balloon_alert(user, "ooh, free coupon")
|
||||
var/obj/item/coupon/attached_coupon = new
|
||||
user.put_in_hands(attached_coupon)
|
||||
attached_coupon.generate(rigged_omen)
|
||||
attached_coupon.generate(rigged_omen ? COUPON_OMEN : null)
|
||||
attached_coupon = null
|
||||
spawn_coupon = FALSE
|
||||
name = "discarded cigarette packet"
|
||||
|
||||
@@ -1,4 +1,49 @@
|
||||
#define COUPON_OMEN "omen"
|
||||
///datum used by the Coupon Master PDA app to generate coupon items redeemed by a bank account.
|
||||
/datum/coupon_code
|
||||
///The pack that'll receive the discount
|
||||
var/datum/supply_pack/discounted_pack
|
||||
///The discount of the pack, on a 0 to 1 range.
|
||||
var/discount
|
||||
/**
|
||||
* If set, copies of the coupon code will delete itself after a while if not printed.
|
||||
* The ones SSmodular_computer.discount_coupons stay intact.
|
||||
*/
|
||||
var/expires_in
|
||||
///Has the coupon been printed. Dictates in which section it's shown, and that it cannot be printed again.
|
||||
var/printed = FALSE
|
||||
///The timerid for deletion if expires_in is set.
|
||||
var/timerid
|
||||
///Reference to the associated bank account, since we need to clear refs on deletion.
|
||||
var/datum/bank_account/associated_account
|
||||
|
||||
/datum/coupon_code/New(discount, discounted_pack, expires_in)
|
||||
..()
|
||||
src.discounted_pack = discounted_pack
|
||||
src.discount = discount
|
||||
if(expires_in)
|
||||
src.expires_in = world.time + expires_in
|
||||
|
||||
/datum/coupon_code/Destroy()
|
||||
if(associated_account)
|
||||
associated_account.redeemed_coupons -= src
|
||||
associated_account = null
|
||||
return ..()
|
||||
|
||||
/datum/coupon_code/proc/copy(datum/bank_account/account)
|
||||
var/datum/coupon_code/copy = new(discount, discounted_pack, expires_in)
|
||||
copy.associated_account = account
|
||||
if(account)
|
||||
LAZYADD(account.redeemed_coupons, src)
|
||||
if(expires_in)
|
||||
copy.timerid = QDEL_IN_STOPPABLE(copy, expires_in - world.time)
|
||||
|
||||
/datum/coupon_code/proc/generate()
|
||||
var/obj/item/coupon/coupon = new()
|
||||
coupon.generate(discount, discounted_pack)
|
||||
printed = TRUE
|
||||
deltimer(timerid)
|
||||
timerid = null
|
||||
return coupon
|
||||
|
||||
/obj/item/coupon
|
||||
name = "coupon"
|
||||
@@ -12,18 +57,15 @@
|
||||
var/obj/machinery/computer/cargo/inserted_console
|
||||
|
||||
/// Choose what our prize is :D
|
||||
/obj/item/coupon/proc/generate(rig_omen=FALSE)
|
||||
discounted_pack = pick(subtypesof(/datum/supply_pack/goody))
|
||||
var/list/chances = list("0.10" = 4, "0.15" = 8, "0.20" = 10, "0.25" = 8, "0.50" = 4, COUPON_OMEN = 1)
|
||||
|
||||
if(rig_omen)
|
||||
discount_pct_off = COUPON_OMEN
|
||||
else
|
||||
discount_pct_off = pick_weight(chances)
|
||||
/obj/item/coupon/proc/generate(discount, datum/supply_pack/discounted_pack)
|
||||
src.discounted_pack = discounted_pack || pick(GLOB.discountable_packs[pick_weight(GLOB.pack_discount_odds)])
|
||||
var/static/list/chances = list("0.10" = 4, "0.15" = 8, "0.20" = 10, "0.25" = 8, "0.50" = 4, COUPON_OMEN = 1)
|
||||
discount_pct_off = discount || pick_weight(chances)
|
||||
|
||||
if(discount_pct_off != COUPON_OMEN)
|
||||
discount_pct_off = text2num(discount_pct_off)
|
||||
name = "coupon - [round(discount_pct_off * 100)]% off [initial(discounted_pack.name)]"
|
||||
if(!discount) // the discount arg should be a number already, while the keys in the chances list cannot be numbers
|
||||
discount_pct_off = text2num(discount_pct_off)
|
||||
name = "coupon - [round(discount_pct_off * 100)]% off [initial(src.discounted_pack.name)]"
|
||||
return
|
||||
|
||||
name = "coupon - fuck you"
|
||||
@@ -71,5 +113,3 @@
|
||||
LAZYREMOVE(inserted_console.loaded_coupons, src)
|
||||
inserted_console = null
|
||||
. = ..()
|
||||
|
||||
#undef COUPON_OMEN
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
access = NONE
|
||||
group = "Goodies"
|
||||
goody = TRUE
|
||||
discountable = SUPPLY_PACK_STD_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/goody/clear_pda
|
||||
name = "Mint Condition Nanotrasen Clear PDA"
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
var/admin_spawned = FALSE
|
||||
/// Goodies can only be purchased by private accounts and can have coupons apply to them. They also come in a lockbox instead of a full crate, so the 700 min doesn't apply
|
||||
var/goody = FALSE
|
||||
/// Can coupons target this pack? If so, how rarely?
|
||||
var/discountable = SUPPLY_PACK_NOT_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/New()
|
||||
id = type
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
)
|
||||
crate_name = "collectable hats crate"
|
||||
crate_type = /obj/structure/closet/crate/wooden
|
||||
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/costumes_toys/formalwear
|
||||
name = "Formalwear Crate"
|
||||
@@ -70,6 +71,7 @@
|
||||
contains = list(/obj/item/firing_pin/clown)
|
||||
crate_name = "toy crate" // It's /technically/ a toy. For the clown, at least.
|
||||
crate_type = /obj/structure/closet/crate/wooden
|
||||
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/costumes_toys/lasertag
|
||||
name = "Laser Tag Crate"
|
||||
@@ -232,6 +234,7 @@
|
||||
cost = 1000
|
||||
contains = list()
|
||||
crate_name = "booster pack pack"
|
||||
discountable = SUPPLY_PACK_STD_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/costumes_toys/randomised/tcg/fill(obj/structure/closet/crate/C)
|
||||
var/cardpacktype
|
||||
@@ -244,6 +247,7 @@
|
||||
desc = "This crate contains a random assortment of stickers."
|
||||
cost = CARGO_CRATE_VALUE * 3
|
||||
contains = list()
|
||||
discountable = SUPPLY_PACK_STD_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/costumes_toys/stickers/fill(obj/structure/closet/crate/crate)
|
||||
for(var/i in 1 to rand(1,2))
|
||||
@@ -262,3 +266,4 @@
|
||||
)
|
||||
crate_name = "corgi pinata kit"
|
||||
crate_type = /obj/structure/closet/crate/wooden
|
||||
discountable = SUPPLY_PACK_STD_DISCOUNTABLE
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/datum/supply_pack/emergency
|
||||
group = "Emergency"
|
||||
discountable = SUPPLY_PACK_UNCOMMON_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/emergency/bio
|
||||
name = "Biological Emergency Crate"
|
||||
|
||||
@@ -271,6 +271,7 @@
|
||||
crate_name = "supermatter shard crate"
|
||||
crate_type = /obj/structure/closet/crate/secure/radiation
|
||||
dangerous = TRUE
|
||||
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/engine/tesla_coils
|
||||
name = "Tesla Coil Crate"
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
/obj/item/toner = 2)
|
||||
crate_name = "tattoo crate"
|
||||
crate_type = /obj/structure/closet/crate/wooden
|
||||
discountable = SUPPLY_PACK_STD_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/misc/bicycle
|
||||
name = "Bicycle"
|
||||
@@ -33,6 +34,7 @@
|
||||
contains = list(/obj/vehicle/ridden/bicycle)
|
||||
crate_name = "bicycle crate"
|
||||
crate_type = /obj/structure/closet/crate/large
|
||||
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/misc/bigband
|
||||
name = "Big Band Instrument Collection"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
cost = CARGO_CRATE_VALUE * 2
|
||||
contains = list(/obj/item/gun/ballistic/shotgun/toy = 8)
|
||||
crate_name = "foam force crate"
|
||||
discountable = SUPPLY_PACK_STD_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/imports/foamforce/bonus
|
||||
name = "Foam Force Pistols Crate"
|
||||
@@ -37,6 +38,7 @@
|
||||
contains = list(/obj/item/storage/backpack/meat)
|
||||
crate_name = "MEAT MEAT MEAT MEAT MEAT"
|
||||
crate_type = /obj/structure/closet/crate/necropolis
|
||||
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/imports/duct_spider
|
||||
name = "Duct Spider Crate"
|
||||
@@ -45,6 +47,7 @@
|
||||
contains = list(/mob/living/basic/spider/maintenance)
|
||||
crate_name = "duct spider crate"
|
||||
crate_type = /obj/structure/closet/crate/critter
|
||||
discountable = SUPPLY_PACK_UNCOMMON_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/imports/duct_spider/dangerous
|
||||
name = "Duct Spider Crate?"
|
||||
@@ -66,6 +69,7 @@
|
||||
cost = CARGO_CRATE_VALUE * 100
|
||||
contains = list(/obj/item/stack/sheet/mineral/bananium)
|
||||
crate_name = "bananium sheet crate"
|
||||
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/imports/naturalbait
|
||||
name = "Freshness Jars full of Natural Bait"
|
||||
@@ -226,6 +230,7 @@
|
||||
/obj/item/clothing/suit/armor/vest/russian_coat,
|
||||
/obj/item/storage/toolbox/guncase/soviet = 2,
|
||||
)
|
||||
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/imports/russian/fill(obj/structure/closet/crate/our_crate)
|
||||
for(var/items in 1 to 10)
|
||||
@@ -268,6 +273,7 @@
|
||||
crate_name = "abandoned crate"
|
||||
contraband = TRUE
|
||||
dangerous = TRUE //these are literally bombs so....
|
||||
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/imports/shambler_evil
|
||||
name = "Shamber's Juice Eldritch Energy! Crate"
|
||||
|
||||
@@ -222,6 +222,7 @@
|
||||
cost = CARGO_CRATE_VALUE * 20
|
||||
contains = list(/mob/living/basic/garden_gnome)
|
||||
crate_name = "garden gnome crate"
|
||||
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/critter/garden_gnome/generate()
|
||||
. = ..()
|
||||
|
||||
@@ -189,3 +189,4 @@
|
||||
cost = CARGO_CRATE_VALUE * 6
|
||||
contains = list(/obj/item/organ/internal/cyberimp/arm/muscle = 2)
|
||||
crate_name = "Strong-Arm implant crate"
|
||||
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
|
||||
|
||||
@@ -125,6 +125,7 @@
|
||||
access = ACCESS_THEATRE
|
||||
access_view = ACCESS_THEATRE
|
||||
crate_type = /obj/structure/closet/crate/secure
|
||||
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/organic/hydroponics
|
||||
name = "Hydroponics Crate"
|
||||
@@ -306,6 +307,7 @@
|
||||
/obj/machinery/grill/unwrenched,
|
||||
)
|
||||
crate_name = "grilling starter kit crate"
|
||||
discountable = SUPPLY_PACK_UNCOMMON_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/organic/grillfuel
|
||||
name = "Grilling Fuel Kit"
|
||||
@@ -317,6 +319,7 @@
|
||||
/obj/item/reagent_containers/cup/soda_cans/monkey_energy,
|
||||
)
|
||||
crate_name = "grilling fuel kit crate"
|
||||
discountable = SUPPLY_PACK_UNCOMMON_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/organic/tiziran_supply
|
||||
name = "Tiziran Supply Box"
|
||||
|
||||
@@ -140,6 +140,7 @@
|
||||
/obj/item/clothing/mask/gas/sechailer,
|
||||
)
|
||||
crate_name = "security clothing crate"
|
||||
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/security/baton
|
||||
name = "Stun Batons Crate"
|
||||
@@ -168,6 +169,7 @@
|
||||
/obj/item/clothing/mask/whistle,
|
||||
/obj/item/conversion_kit,
|
||||
)
|
||||
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
|
||||
|
||||
/// Armory packs
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
contains = list(/obj/item/stack/tile/carpet/fifty = 2,
|
||||
/obj/item/stack/tile/carpet/black/fifty = 2)
|
||||
crate_name = "premium carpet crate"
|
||||
discountable = SUPPLY_PACK_UNCOMMON_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/service/carpet_exotic
|
||||
name = "Exotic Carpet Crate"
|
||||
@@ -119,6 +120,7 @@
|
||||
/obj/item/stack/tile/carpet/royalblack/fifty = 2,
|
||||
)
|
||||
crate_name = "exotic carpet crate"
|
||||
discountable = SUPPLY_PACK_UNCOMMON_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/service/carpet_neon
|
||||
name = "Simple Neon Carpet Crate"
|
||||
@@ -140,6 +142,7 @@
|
||||
/obj/item/stack/tile/carpet/neon/simple/pink/sixty = 2,
|
||||
)
|
||||
crate_name = "neon carpet crate"
|
||||
discountable = SUPPLY_PACK_UNCOMMON_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/service/lightbulbs
|
||||
name = "Replacement Lights"
|
||||
@@ -243,6 +246,7 @@
|
||||
)
|
||||
crate_name = "\improper Ready-Donk crate"
|
||||
crate_type = /obj/structure/closet/crate/freezer/food
|
||||
discountable = SUPPLY_PACK_UNCOMMON_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/service/randomized/ready_donk/fill(obj/structure/closet/crate/C)
|
||||
for(var/i in 1 to 3)
|
||||
@@ -265,6 +269,7 @@
|
||||
/obj/item/reagent_containers/cup/bottle/syrup_bottle/caramel, //one extra syrup as a treat
|
||||
)
|
||||
crate_name = "coffee equipment crate"
|
||||
discountable = SUPPLY_PACK_UNCOMMON_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/service/coffeemaker
|
||||
name = "Impressa Coffeemaker Crate"
|
||||
@@ -273,6 +278,7 @@
|
||||
contains = list(/obj/machinery/coffeemaker/impressa)
|
||||
crate_name = "coffeemaker crate"
|
||||
crate_type = /obj/structure/closet/crate/large
|
||||
discountable = SUPPLY_PACK_UNCOMMON_DISCOUNTABLE
|
||||
|
||||
/datum/supply_pack/service/aquarium_kit
|
||||
name = "Aquarium Kit"
|
||||
@@ -287,6 +293,7 @@
|
||||
)
|
||||
crate_name = "aquarium kit crate"
|
||||
crate_type = /obj/structure/closet/crate/wooden
|
||||
discountable = SUPPLY_PACK_UNCOMMON_DISCOUNTABLE
|
||||
|
||||
/// Spare bar sign wallmount
|
||||
/datum/supply_pack/service/bar_sign
|
||||
@@ -295,3 +302,4 @@
|
||||
cost = CARGO_CRATE_VALUE * 14
|
||||
contains = list(/obj/item/wallframe/barsign/all_access)
|
||||
crate_name = "bar sign crate"
|
||||
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
var/pay_token
|
||||
///List with a transaction history for NT pay app
|
||||
var/list/transaction_history = list()
|
||||
///A lazylist of coupons redeemed with the Coupon Master pda app associated with this account.
|
||||
var/list/redeemed_coupons
|
||||
|
||||
/datum/bank_account/New(newname, job, modifier = 1, player_account = TRUE)
|
||||
account_holder = newname
|
||||
@@ -47,6 +49,7 @@
|
||||
/datum/bank_account/Destroy()
|
||||
if(add_to_accounts)
|
||||
SSeconomy.bank_accounts_by_id -= "[account_id]"
|
||||
QDEL_LIST(redeemed_coupons)
|
||||
return ..()
|
||||
|
||||
/**
|
||||
|
||||
119
code/modules/modular_computers/file_system/programs/coupon.dm
Normal file
119
code/modules/modular_computers/file_system/programs/coupon.dm
Normal file
@@ -0,0 +1,119 @@
|
||||
#define COUPON_PAPER_USE 1
|
||||
#define COUPON_TONER_USE 0.250
|
||||
|
||||
///A program that enables the user to redeem randomly generated coupons for several cargo packs (mostly goodies).
|
||||
/datum/computer_file/program/coupon
|
||||
filename = "couponmaster"
|
||||
filedesc = "Coupon Master"
|
||||
downloader_category = PROGRAM_CATEGORY_SUPPLY
|
||||
extended_desc = "Program for receiving discounts for several cargo goodies. After redeeming a coupon, hit a photocopier with your PDA to print it."
|
||||
program_flags = PROGRAM_ON_NTNET_STORE | PROGRAM_REQUIRES_NTNET
|
||||
size = 5
|
||||
tgui_id = "NtosCouponMaster"
|
||||
program_icon = "ticket"
|
||||
can_run_on_flags = PROGRAM_PDA //It relies on the PDA messenger to let you know of new codes
|
||||
detomatix_resistance = DETOMATIX_RESIST_MALUS
|
||||
|
||||
/datum/computer_file/program/coupon/on_install()
|
||||
. = ..()
|
||||
///set the discount_coupons list, which means SSmodular_computers will now begin to periodically produce new coupon codes.
|
||||
LAZYINITLIST(SSmodular_computers.discount_coupons)
|
||||
ADD_TRAIT(computer, TRAIT_MODPC_HALVED_DOWNLOAD_SPEED, REF(src)) //All that glitters is not gold
|
||||
|
||||
/datum/computer_file/program/coupon/Destroy()
|
||||
if(computer)
|
||||
REMOVE_TRAIT(computer, TRAIT_MODPC_HALVED_DOWNLOAD_SPEED, REF(src))
|
||||
return ..()
|
||||
|
||||
/datum/computer_file/program/coupon/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["printed_coupons"] = list()
|
||||
data["redeemed_coupons"] = list()
|
||||
data["valid_id"] = FALSE
|
||||
var/obj/item/card/id/user_id = computer.computer_id_slot
|
||||
if(user_id?.registered_account.add_to_accounts)
|
||||
for(var/datum/coupon_code/coupon as anything in user_id.registered_account.redeemed_coupons)
|
||||
var/list/coupon_data = list(
|
||||
"goody" = initial(coupon.discounted_pack.name),
|
||||
"discount" = coupon.discount*100,
|
||||
)
|
||||
if(coupon.printed)
|
||||
data["printed_coupons"] += list(coupon_data)
|
||||
else
|
||||
data["redeemed_coupons"] += list(coupon_data)
|
||||
data["valid_id"] = TRUE
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/coupon/ui_act(action, params, datum/tgui/ui)
|
||||
var/obj/item/card/id/user_id = computer.computer_id_slot
|
||||
if(!(user_id?.registered_account.add_to_accounts))
|
||||
return TRUE
|
||||
switch(action)
|
||||
if("redeem")
|
||||
var/code = params["code"]
|
||||
if(!length(code))
|
||||
return TRUE
|
||||
var/datum/coupon_code/coupon = SSmodular_computers.discount_coupons[code]
|
||||
if(isnull(coupon))
|
||||
user_id.registered_account.bank_card_talk("Invalid coupon code.", TRUE)
|
||||
return TRUE
|
||||
if(coupon.expires_in && coupon.expires_in < world.time)
|
||||
user_id.registered_account.bank_card_talk("Expired coupon code.", TRUE)
|
||||
return TRUE
|
||||
if(coupon in user_id.registered_account.redeemed_coupons)
|
||||
user_id.registered_account.bank_card_talk("Coupon [code] already redeemed.", TRUE)
|
||||
return TRUE
|
||||
coupon.copy(user_id.registered_account)
|
||||
var/static/list/goodbye = list(
|
||||
"Have a wonderful day.",
|
||||
"Don't forget to print it.",
|
||||
"Time to get shopping!",
|
||||
"Enjoy your discount!",
|
||||
"Congratulations!",
|
||||
"Bye Bye~.",
|
||||
)
|
||||
user_id.registered_account.bank_card_talk("Coupon [code] redeemed. [pick(goodbye)]", TRUE)
|
||||
//Well, guess you're redeeming something else too.
|
||||
if(prob(40) && computer.used_capacity < computer.max_capacity)
|
||||
var/datum/computer_file/warez = new()
|
||||
warez.filename = random_string(rand(6, 12), GLOB.alphabet + GLOB.alphabet_upper + GLOB.numerals)
|
||||
warez.filetype = pick("DAT", "XXX", "TMP", "FILE", "MNT", "MINER", "SYS", "PNG.EXE")
|
||||
warez.size = min(rand(1, 4), computer.max_capacity - computer.used_capacity)
|
||||
if(prob(25))
|
||||
warez.undeletable = TRUE
|
||||
computer.store_file(warez)
|
||||
|
||||
/**
|
||||
* Normally, modular PCs can be print paper already, but I find this additional step
|
||||
* to be less lazy and fitting to the "I gotta go print it before it expires" aspect of it.
|
||||
*/
|
||||
/datum/computer_file/program/coupon/tap(atom/tapped_atom, mob/living/user, params)
|
||||
if(!istype(tapped_atom, /obj/machinery/photocopier))
|
||||
return FALSE
|
||||
var/obj/item/card/id/user_id = computer.computer_id_slot
|
||||
if(!(user_id?.registered_account))
|
||||
computer.balloon_alert(user, "no bank account found!")
|
||||
return TRUE
|
||||
var/obj/machinery/photocopier/copier = tapped_atom
|
||||
if(copier.check_busy(user))
|
||||
return TRUE
|
||||
var/num_coupons = 0
|
||||
for(var/datum/coupon_code/coupon as anything in user_id.registered_account.redeemed_coupons)
|
||||
if(!coupon.printed)
|
||||
num_coupons++
|
||||
if(!num_coupons)
|
||||
computer.balloon_alert(user, "no coupon available!")
|
||||
return TRUE
|
||||
copier.do_copies(CALLBACK(src, PROC_REF(print_coupon), user_id.registered_account), user, COUPON_PAPER_USE, COUPON_TONER_USE, num_coupons)
|
||||
return TRUE
|
||||
|
||||
/datum/computer_file/program/coupon/proc/print_coupon(datum/bank_account/account)
|
||||
var/datum/coupon_code/coupon
|
||||
for(var/datum/coupon_code/possible_coupon as anything in account.redeemed_coupons)
|
||||
if(!possible_coupon.printed)
|
||||
coupon = possible_coupon
|
||||
break
|
||||
return coupon?.generate()
|
||||
|
||||
#undef COUPON_PAPER_USE
|
||||
#undef COUPON_TONER_USE
|
||||
@@ -100,6 +100,8 @@
|
||||
if(NTNET_ETHERNET_SIGNAL)
|
||||
download_netspeed = NTNETSPEED_ETHERNET
|
||||
if(download_netspeed)
|
||||
if(HAS_TRAIT(computer, TRAIT_MODPC_HALVED_DOWNLOAD_SPEED))
|
||||
download_netspeed *= 0.5
|
||||
download_completion += download_netspeed
|
||||
|
||||
/datum/computer_file/program/ntnetdownload/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
|
||||
@@ -283,6 +283,9 @@ GLOBAL_LIST_INIT(paper_blanks, init_paper_blanks())
|
||||
|
||||
/// Will invoke `do_copy_loop` asynchronously. Passes the supplied arguments on to it.
|
||||
/obj/machinery/photocopier/proc/do_copies(datum/callback/copy_cb, mob/user, paper_use, toner_use, copies_amount)
|
||||
if(machine_stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
|
||||
busy = TRUE
|
||||
update_use_power(ACTIVE_POWER_USE)
|
||||
// fucking god proc
|
||||
|
||||
@@ -512,6 +512,7 @@
|
||||
#include "code\_globalvars\lists\achievements.dm"
|
||||
#include "code\_globalvars\lists\ambience.dm"
|
||||
#include "code\_globalvars\lists\canisters.dm"
|
||||
#include "code\_globalvars\lists\cargo.dm"
|
||||
#include "code\_globalvars\lists\client.dm"
|
||||
#include "code\_globalvars\lists\color.dm"
|
||||
#include "code\_globalvars\lists\crafting.dm"
|
||||
@@ -5012,6 +5013,7 @@
|
||||
#include "code\modules\modular_computers\file_system\programs\budgetordering.dm"
|
||||
#include "code\modules\modular_computers\file_system\programs\card.dm"
|
||||
#include "code\modules\modular_computers\file_system\programs\cargoship.dm"
|
||||
#include "code\modules\modular_computers\file_system\programs\coupon.dm"
|
||||
#include "code\modules\modular_computers\file_system\programs\crewmanifest.dm"
|
||||
#include "code\modules\modular_computers\file_system\programs\emojipedia.dm"
|
||||
#include "code\modules\modular_computers\file_system\programs\file_browser.dm"
|
||||
|
||||
61
tgui/packages/tgui/interfaces/NtosCouponMaster.tsx
Normal file
61
tgui/packages/tgui/interfaces/NtosCouponMaster.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import { BooleanLike } from 'common/react';
|
||||
|
||||
import { useBackend } from '../backend';
|
||||
import { Box, Input, NoticeBox, Section } from '../components';
|
||||
import { NtosWindow } from '../layouts';
|
||||
|
||||
type Data = {
|
||||
valid_id: BooleanLike;
|
||||
redeemed_coupons: CouponData[];
|
||||
printed_coupons: CouponData[];
|
||||
};
|
||||
|
||||
type CouponData = {
|
||||
goody: string;
|
||||
discount: number;
|
||||
};
|
||||
|
||||
export const NtosCouponMaster = (props) => {
|
||||
const { act, data } = useBackend<Data>();
|
||||
const { valid_id, redeemed_coupons = [], printed_coupons = [] } = data;
|
||||
return (
|
||||
<NtosWindow width={400} height={400}>
|
||||
<NtosWindow.Content scrollable>
|
||||
{!valid_id ? (
|
||||
<NoticeBox danger>
|
||||
No valid bank account detected. Insert a valid ID.
|
||||
</NoticeBox>
|
||||
) : (
|
||||
<>
|
||||
<NoticeBox info>
|
||||
You can print redeemed coupons by right-clicking a photocopier.
|
||||
</NoticeBox>
|
||||
<Input
|
||||
fontSize={1.2}
|
||||
placeholder="Insert your coupon code here"
|
||||
onEnter={(e, value) =>
|
||||
act('redeem', {
|
||||
code: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
<Section title="Redeemed Coupons">
|
||||
{redeemed_coupons.map((coupon, index) => (
|
||||
<Box key={index} className="candystripe">
|
||||
{coupon.goody} ({coupon.discount}% OFF)
|
||||
</Box>
|
||||
))}
|
||||
</Section>
|
||||
<Section title="Printed Coupons">
|
||||
{printed_coupons.map((coupon, index) => (
|
||||
<Box key={index} className="candystripe">
|
||||
{coupon.goody} ({coupon.discount}% OFF)
|
||||
</Box>
|
||||
))}
|
||||
</Section>
|
||||
</>
|
||||
)}
|
||||
</NtosWindow.Content>
|
||||
</NtosWindow>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user