mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-30 02:52:30 +00:00
* Making the fuck you coupon trigger only once, take two (#81953) ## About The Pull Request So a previous pr attempted to fix the fuck you coupon, by adding 1 to the arguments. ```dm (tgstation/code/modules/cargo/coupon.dm, line 87) cursed.AddComponent(/datum/component/omen, 1) ``` But this was setting the `vessel` rather than the `incidents_left` argument to 1. ```dm (tgstation/code/datums/components/omen.dm, line 20) /datum/component/omen/Initialize(obj/vessel, incidents_left, luck_mod, damage_mod) ``` Moving this argument over one fixes the issue. ```dm cursed.AddComponent(/datum/component/omen, null, 1) ``` However! We're now skipping over the `vessel` value, which is used to burn up a curse's vessel once the curse is expended. Setting this to `src` rather than `null` means the fuck you coupon actually gets 'expended', which I think it better than just using `null` or `incidents_left = 1`. The coupon's useless once it's done, and this way it's cooler anyway. For consistency, we then also add this behaviour to when the coupon gives you a heart attack instead. Then! I noticed there was a _second_ bug with fuck you coupons, where it would stop prematurely if the location wasn't a mob. ```dm (tgstation/code/modules/cargo/coupon.dm, line 80-81) if(!ismob(loc)) return FALSE ``` However, this also happens when you don't have a free hand for it to put the coupon in, and thus entirely negating the curse and just giving you a useless fuck you coupon. We fix this by just adding a `user` argument to `generate`, which it prefers to use when available, and is set to the user ripping off the coupon in the first place. ## Why It's Good For The Game Fixes #81946. As fuck you coupons are pretty much useless after expending their curse, and we have to add the vessel value anyway, I thought it'd be more fitting to add the coupon as the vessel rather than just putting in null. Then, for consistency, I felt it'd be best to make them *also* burn when giving you a heart attack when you already have a curse. Y'know, it's expending the coupon for it's one-time fuck you! Also fixes fuck you coupons not actually applying their curse if you didn't have any free hands for it to put the coupon in when ripping it off. ## Changelog 🆑 fix: Fuck you coupons ACTUALLY trigger only once again. As a consequence, they also burn up when expended for their one-time fuck you. fix: Fuck you coupons work regardless of whether you had a free hand or not. /🆑 * Making the fuck you coupon trigger only once, take two --------- Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com>
133 lines
4.6 KiB
Plaintext
133 lines
4.6 KiB
Plaintext
///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"
|
|
desc = "It doesn't matter if you didn't want it before, what matters now is that you've got a coupon for it!"
|
|
icon_state = "data_1"
|
|
icon = 'icons/obj/card.dmi'
|
|
item_flags = NOBLUDGEON
|
|
w_class = WEIGHT_CLASS_TINY
|
|
var/datum/supply_pack/discounted_pack
|
|
var/discount_pct_off = 0.05
|
|
var/obj/machinery/computer/cargo/inserted_console
|
|
|
|
/obj/item/coupon/Initialize(mapload)
|
|
. = ..()
|
|
|
|
if(discounted_pack)
|
|
update_name()
|
|
|
|
/// Choose what our prize is :D
|
|
/obj/item/coupon/proc/generate(discount, datum/supply_pack/discounted_pack, mob/user)
|
|
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)
|
|
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)
|
|
update_name()
|
|
return
|
|
|
|
name = "coupon - fuck you"
|
|
desc = "The small text reads, 'You will be slaughtered'... That doesn't sound right, does it?"
|
|
|
|
var/mob/cursed = user || loc
|
|
if(!ismob(cursed))
|
|
return FALSE
|
|
|
|
to_chat(cursed, span_warning("The coupon reads '<b>fuck you</b>' in large, bold text... is- is that a prize, or?"))
|
|
|
|
if(!cursed.GetComponent(/datum/component/omen))
|
|
cursed.AddComponent(/datum/component/omen, src, 1)
|
|
return TRUE
|
|
if(HAS_TRAIT(cursed, TRAIT_CURSED))
|
|
to_chat(cursed, span_warning("What a horrible night... To have a curse!"))
|
|
addtimer(CALLBACK(src, PROC_REF(curse_heart), cursed), 5 SECONDS, TIMER_UNIQUE | TIMER_STOPPABLE)
|
|
|
|
/obj/item/coupon/update_name()
|
|
name = "coupon - [round(discount_pct_off * 100)]% off [initial(discounted_pack.name)]"
|
|
return ..()
|
|
|
|
/// Play stupid games, win stupid prizes
|
|
/obj/item/coupon/proc/curse_heart(mob/living/cursed)
|
|
if(!iscarbon(cursed))
|
|
cursed.gib(DROP_ALL_REMAINS)
|
|
burn_evilly()
|
|
return TRUE
|
|
|
|
var/mob/living/carbon/player = cursed
|
|
INVOKE_ASYNC(player, TYPE_PROC_REF(/mob, emote), "scream")
|
|
to_chat(player, span_mind_control("What could that coupon mean?"))
|
|
to_chat(player, span_userdanger("...The suspense is killing you!"))
|
|
player.set_heartattack(status = TRUE)
|
|
burn_evilly()
|
|
|
|
/obj/item/coupon/proc/burn_evilly()
|
|
visible_message(span_warning("[src] burns up in a sinister flash, taking an evil energy with it..."))
|
|
burn()
|
|
|
|
/obj/item/coupon/attack_atom(obj/O, mob/living/user, params)
|
|
if(!istype(O, /obj/machinery/computer/cargo))
|
|
return ..()
|
|
if(discount_pct_off == COUPON_OMEN)
|
|
to_chat(user, span_warning("\The [O] validates the coupon as authentic, but refuses to accept it..."))
|
|
O.say("Coupon fulfillment already in progress...")
|
|
return
|
|
|
|
inserted_console = O
|
|
LAZYADD(inserted_console.loaded_coupons, src)
|
|
inserted_console.say("Coupon for [initial(discounted_pack.name)] applied!")
|
|
forceMove(inserted_console)
|
|
|
|
/obj/item/coupon/Destroy()
|
|
if(inserted_console)
|
|
LAZYREMOVE(inserted_console.loaded_coupons, src)
|
|
inserted_console = null
|
|
. = ..()
|