[MIRROR] The Curse Of The Slot Machine - Now Clone-less [MDB IGNORE] (#23380)

* The Curse Of The Slot Machine - Now Clone-less

* The copy paste really needs to be gutted to the essentials

* Update burns.dm

---------

Co-authored-by: san7890 <the@san7890.com>
Co-authored-by: Giz <13398309+vinylspiders@users.noreply.github.com>
This commit is contained in:
SkyratBot
2023-08-28 02:51:46 -04:00
committed by GitHub
co-authored by san7890 Giz
parent 8a36d51fc5
commit d7cd5e2456
9 changed files with 354 additions and 90 deletions
@@ -462,3 +462,15 @@
/// from /obj/plunger_act when an object is being plungered
#define COMSIG_PLUNGER_ACT "plunger_act"
/// from /obj/structure/cursed_slot_machine/handle_status_effect() when someone pulls the handle on the slot machine
#define COMSIG_CURSED_SLOT_MACHINE_USE "cursed_slot_machine_use"
#define SLOT_MACHINE_USE_CANCEL (1<<0) //! we've used up the number of times we may use this slot machine. womp womp.
#define SLOT_MACHINE_USE_POSTPONE (1<<1) //! we haven't used up all our attempts to gamble away our life but we should chill for a few seconds
/// from /obj/structure/cursed_slot_machine/determine_victor() when someone loses.
#define COMSIG_CURSED_SLOT_MACHINE_LOST "cursed_slot_machine_lost"
/// from /obj/structure/cursed_slot_machine/determine_victor() when someone finally wins.
#define COMSIG_GLOB_CURSED_SLOT_MACHINE_WON "cursed_slot_machine_won"
@@ -205,3 +205,4 @@
/atom/movable/screen/alert/status_effect/Destroy()
attached_effect = null //Don't keep a ref now
return ..()
@@ -0,0 +1,193 @@
#define DEFAULT_MAX_CURSE_COUNT 5
/// Status effect that gives the target miscellanous debuffs while throwing a status alert and causing them to smoke from the damage they're incurring.
/// Purposebuilt for cursed slot machines.
/datum/status_effect/grouped/cursed
id = "cursed"
alert_type = /atom/movable/screen/alert/status_effect/cursed
/// The max number of curses a target can incur with this status effect.
var/max_curse_count = DEFAULT_MAX_CURSE_COUNT
/// The amount of times we have been "applied" to the target.
var/curse_count = 0
/// Raw probability we have to deal damage this tick.
var/damage_chance = 10
/// Are we currently in the process of sending a monologue?
var/monologuing = FALSE
/// The hand we are branded to.
var/obj/item/bodypart/branded_hand = null
/// The cached path of the particles we're using to smoke
var/smoke_path = null
/datum/status_effect/grouped/cursed/on_apply()
RegisterSignal(owner, COMSIG_MOB_STATCHANGE, PROC_REF(on_stat_changed))
RegisterSignal(owner, COMSIG_LIVING_DEATH, PROC_REF(on_death))
RegisterSignal(owner, COMSIG_CURSED_SLOT_MACHINE_USE, PROC_REF(check_curses))
RegisterSignal(owner, COMSIG_CURSED_SLOT_MACHINE_LOST, PROC_REF(update_curse_count))
RegisterSignal(SSdcs, COMSIG_GLOB_CURSED_SLOT_MACHINE_WON, PROC_REF(clear_curses))
return ..()
/datum/status_effect/grouped/cursed/Destroy()
UnregisterSignal(SSdcs, COMSIG_GLOB_CURSED_SLOT_MACHINE_WON)
branded_hand = null
return ..()
/// Checks the number of curses we have and returns information back to the slot machine. `max_curse_amount` is set by the slot machine itself.
/datum/status_effect/grouped/cursed/proc/check_curses(max_curse_amount)
SIGNAL_HANDLER
if(curse_count >= max_curse_amount)
return SLOT_MACHINE_USE_CANCEL
if(monologuing)
to_chat(owner, span_warning("Your arm is resisting your attempts to pull the lever!")) // listening to kitschy monologues to postpone your powergaming is the true curse here.
return SLOT_MACHINE_USE_POSTPONE
/// Handles the debuffs of this status effect and incrementing the number of curses we have.
/datum/status_effect/grouped/cursed/proc/update_curse_count()
SIGNAL_HANDLER
curse_count++
linked_alert?.update_appearance() // we may have not initialized it yet
addtimer(CALLBACK(src, PROC_REF(handle_after_effects), 1 SECONDS)) // give it a second to let the failure sink in before we exact our toll
/// Makes a nice lorey message about the curse level we're at. I think it's nice
/datum/status_effect/grouped/cursed/proc/handle_after_effects()
if(QDELETED(src))
return
monologuing = TRUE
var/list/messages = list()
switch(curse_count)
if(1) // basically your first is a "freebie" that will still require urgent medical attention and will leave you smoking forever but could be worse tbh
if(ishuman(owner))
var/mob/living/carbon/human/human_owner = owner
playsound(human_owner, SFX_SEAR, 50, TRUE)
var/obj/item/bodypart/affecting = human_owner.get_active_hand()
branded_hand = affecting
affecting.force_wound_upwards(/datum/wound/burn/severe/cursed_brand, wound_source = "curse of the slot machine")
messages += span_boldwarning("Your hand burns, and you quickly let go of the lever! You feel a little sick as the nerves deaden in your hand...")
messages += span_boldwarning("Some smoke appears to be coming out of your hand now, but it's not too bad...")
messages += span_boldwarning("Fucking stupid machine.")
if(2)
messages += span_boldwarning("The machine didn't burn you this time, it must be some arcane work of the brand recognizing a source...")
messages += span_boldwarning("Blisters and boils start to appear over your skin. Each one hissing searing hot steam out of its own pocket...")
messages += span_boldwarning("You understand that the machine tortures you with its simplistic allure. It can kill you at any moment, but it derives a sick satisfaction at forcing you to keep going.")
messages += span_boldwarning("If you could get away from here, you might be able to live with some medical supplies. Is it too late to stop now?")
messages += span_boldwarning("As you shut your eyes to dwell on this conundrum, the brand surges in pain. You shudder to think what might happen if you go unconscious.")
if(3)
owner.emote("cough")
messages += span_boldwarning("Your throat becomes to feel like it's slowly caking up with sand and dust. You eject the contents of the back of your throat onto your sleeve.")
messages += span_boldwarning("It is sand. Crimson red. You've never felt so thirsty in your life, yet you don't trust your own hand to carry the glass to your lips.")
messages += span_boldwarning("You get the sneaking feeling that if someone else were to win, that it might clear your curse too. Saving your life is a noble cause.")
messages += span_boldwarning("Of course, you might have to not speak on the nature of this machine, in case they scamper off to leave you to die.")
messages += span_boldwarning("Is it truly worth it to condemn someone to this fate to cure the manifestation of your own hedonistic urges? You'll have to decide quickly.")
if(4)
messages += span_boldwarning("A migraine swells over your head as your thoughts become hazy. Your hand desperately inches closer towards the slot machine for one final pull...")
messages += span_boldwarning("The ultimate test of mind over matter. You can jerk your own muscle back in order to prevent a terrible fate, but your life already is worth so little now.")
messages += span_boldwarning("This is what they want, is it not? To witness your failure against itself? The compulsion carries you forward as a sinking feeling of dread fills your stomach.")
messages += span_boldwarning("Paradoxically, where there is hopelessness, there is elation. Elation at the fact that there's still enough power in you for one more pull.")
messages += span_boldwarning("Your legs desperate wish to jolt away on the thought of running away from this wretched machination, but your own arm remains complacent in the thought of seeing spinning wheels.")
messages += span_userdanger("The toll has already been exacted. There is no longer death on 'your' terms. Is your dignity worth more than your life?")
if(5 to INFINITY)
if(max_curse_count != DEFAULT_MAX_CURSE_COUNT) // this probably will only happen through admin schenanigans letting people stack up infinite curses or something
to_chat(owner, span_boldwarning("Do you <i>still</i> think you're in control?"))
return
to_chat(owner, span_userdanger("Why couldn't I get one more try?!"))
owner.investigate_log("has been gibbed by the cursed status effect after accumulating [curse_count] curses.", INVESTIGATE_DEATHS)
owner.gib()
qdel(src)
return
for(var/message in messages)
to_chat(owner, message)
sleep(1.5 SECONDS) // yes yes a bit fast but it can be a lot of text and i want the whole thing to send before the cooldown on the slot machine might expire
monologuing = FALSE
/// Cleans ourselves up and removes our curses. Meant to be done in a "positive" way, when the curse is broken. Directly use qdel otherwise.
/datum/status_effect/grouped/cursed/proc/clear_curses()
SIGNAL_HANDLER
if(!isnull(branded_hand))
var/datum/wound/brand = branded_hand.get_wound_type(/datum/wound/burn/severe/cursed_brand)
brand?.remove_wound()
owner.visible_message(
span_notice("The smoke slowly clears from [owner.name]..."),
span_notice("Your skin finally settles down and your throat no longer feels as dry... The brand disappearing confirms that the curse has been lifted."),
)
QDEL_NULL(particle_effect)
qdel(src)
/// If our owner's stat changes, rapidly surge the damage chance.
/datum/status_effect/grouped/cursed/proc/on_stat_changed()
SIGNAL_HANDLER
if(owner.stat == CONSCIOUS || owner.stat == DEAD) // reset on these two states
damage_chance = initial(damage_chance)
return
to_chat(owner, span_userdanger("As your body crumbles, you feel the curse of the slot machine surge through your body!"))
damage_chance += 75 //ruh roh raggy
/// If our owner dies without getting gibbed (as in of other causes), stop smoking because we've "expended all the life energy".
/datum/status_effect/grouped/cursed/proc/on_death(mob/living/source, gibbed)
SIGNAL_HANDLER
if(gibbed)
return
QDEL_NULL(particle_effect)
/datum/status_effect/grouped/cursed/update_particles()
var/particle_path = /particles/smoke/steam/mild
switch(curse_count)
if(2 to 3)
particle_path = /particles/smoke/steam
if(4 to INFINITY)
particle_path = /particles/smoke/steam/bad
if(smoke_path == particle_path)
return
QDEL_NULL(particle_effect)
smoke_path = particle_path
particle_effect = new(owner, particle_path)
/datum/status_effect/grouped/cursed/tick(seconds_between_ticks)
if(curse_count <= 1)
return // you get one "freebie" (single damage) to nudge you into thinking this is a bad idea before the house begins to win.
// the house won.
var/ticked_coefficient = (rand(15, 40) / 100)
var/effective_percentile_chance = ((curse_count == 2 ? 1 : curse_count) * damage_chance * ticked_coefficient)
if(SPT_PROB(effective_percentile_chance, seconds_between_ticks))
owner.apply_damages(
brute = (curse_count * ticked_coefficient),
burn = (curse_count * ticked_coefficient),
oxy = (curse_count * ticked_coefficient),
)
/atom/movable/screen/alert/status_effect/cursed
name = "Cursed!"
desc = "The brand on your hand reminds you of your greed, yet you seem to be okay otherwise."
icon_state = "cursed_by_slots"
/atom/movable/screen/alert/status_effect/cursed/update_desc()
. = ..()
var/datum/status_effect/grouped/cursed/linked_effect = attached_effect
var/curses = linked_effect.curse_count
switch(curses)
if(2)
desc = "Your greed is catching up to you..."
if(3)
desc = "You really don't feel good right now... But why stop now?"
if(4 to INFINITY)
desc = "Real winners quit before they reach the ultimate prize."
#undef DEFAULT_MAX_CURSE_COUNT
+10
View File
@@ -315,4 +315,14 @@
desc = "Patient is suffering extreme burns from a strange brand marking, creating serious risk of infection and greatly reduced limb integrity."
examine_desc = "appears to have holy symbols painfully branded into their flesh, leaving severe burns."
occur_text = "chars rapidly into a strange pattern of holy symbols, burned into the flesh."
/// special severe wound caused by the cursed slot machine.
/datum/wound/burn/severe/cursed_brand
name = "Ancient Brand"
desc = "Patient is suffering extreme burns with oddly ornate brand markings, creating serious risk of infection and greatly reduced limb integrity."
examine_desc = "appears to have ornate symbols painfully branded into their flesh, leaving severe burns"
occur_text = "chars rapidly into a pattern that can only be described as an agglomeration of several financial symbols, burned into the flesh"
/datum/wound/burn/severe/cursed_brand/get_limb_examine_description()
return span_warning("The flesh on this limb has several ornate symbols burned into it, with pitting throughout.")
*/
@@ -0,0 +1,126 @@
/// Greed's slot machine: Used in the Greed ruin. Deals damage on each use, with a successful use giving a d20 of fate.
/obj/structure/cursed_slot_machine
name = "greed's slot machine"
desc = "High stakes, high rewards."
icon = 'icons/obj/machines/computer.dmi'
icon_state = "slots"
anchored = TRUE
density = TRUE
/// Variable that tracks the screen we display.
var/icon_screen = "slots_screen"
/// Should we be emitting light?
var/brightness_on = TRUE
/// The probability the player has to win.
var/win_prob = 5
/// The maximum amount of curses we will allow a player to have before disallowing them to use the machine.
var/max_curse_amount = 5
/// machine's reward when you hit jackpot
var/prize = /obj/structure/cursed_money
/// should we be applying the cursed status effect?
var/status_effect_on_roll = TRUE
/// Length of the cooldown between the machine being used and being able to spin the machine again.
var/cooldown_length = 15 SECONDS
/// Are we currently in use? Anti-spam prevention measure.
var/in_use = FALSE
/// Cooldown between pulls of the cursed slot machine.
COOLDOWN_DECLARE(spin_cooldown)
/obj/structure/cursed_slot_machine/Initialize(mapload)
. = ..()
update_appearance()
set_light(brightness_on)
/obj/structure/cursed_slot_machine/interact(mob/user)
if(!ishuman(user))
return
var/mob/living/carbon/human/human_user = user
if(in_use)
balloon_alert(human_user, "already spinning!")
return
if(!COOLDOWN_FINISHED(src, spin_cooldown))
to_chat(human_user, span_danger("The machine doesn't engage. You get the compulsion to try again in a few seconds."))
return
in_use = TRUE
var/signal_value = SEND_SIGNAL(human_user, COMSIG_CURSED_SLOT_MACHINE_USE, max_curse_amount)
if(signal_value & SLOT_MACHINE_USE_POSTPONE)
return
if(signal_value & SLOT_MACHINE_USE_CANCEL) // failsafe in case we don't want to let the machine be used for some reason (like if we're maxed out on curses but not getting gibbed)
say("We're sorry, but we can no longer serve you at this establishment.")
return
user.visible_message(
span_warning("[human_user] pulls [src]'s lever with a glint in [user.p_their()] eyes!"),
span_warning("You feel a draining as you pull the lever, but you know it'll be worth it."),
)
icon_screen = "slots_screen_working"
update_appearance()
playsound(src, 'sound/lavaland/cursed_slot_machine.ogg', 50, FALSE)
addtimer(CALLBACK(src, PROC_REF(determine_victor), human_user), 5 SECONDS)
/obj/structure/cursed_slot_machine/update_overlays()
. = ..()
var/overlay_state = icon_screen
. += mutable_appearance(icon, overlay_state)
. += emissive_appearance(icon, overlay_state, src)
/obj/structure/cursed_slot_machine/proc/determine_victor(mob/living/user)
icon_screen = initial(icon_screen)
update_appearance()
in_use = FALSE
COOLDOWN_START(src, spin_cooldown, cooldown_length)
if(!prob(win_prob))
if(status_effect_on_roll && isnull(user.has_status_effect(/datum/status_effect/grouped/cursed)))
user.apply_status_effect(/datum/status_effect/grouped/cursed)
SEND_SIGNAL(user, COMSIG_CURSED_SLOT_MACHINE_LOST)
playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE)
balloon_alert_to_viewers("you lost!")
return
playsound(src, 'sound/lavaland/cursed_slot_machine_jackpot.ogg', 50, FALSE)
new prize(get_turf(src))
if(user)
to_chat(user, span_boldwarning("You've hit the jackpot!!! Laughter echoes around you as your reward appears in the machine's place."))
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CURSED_SLOT_MACHINE_WON)
qdel(src)
/// Prize given out by the cursed slot machine that will give the user one Die of Fate and then delete itself.
/obj/structure/cursed_money
name = "bag of money"
desc = "RICH! YES! YOU KNEW IT WAS WORTH IT! YOU'RE RICH! RICH! RICH!"
icon = 'icons/obj/storage/storage.dmi'
icon_state = "moneybag"
anchored = FALSE
density = TRUE
/obj/structure/cursed_money/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, PROC_REF(collapse)), 1 MINUTES)
/obj/structure/cursed_money/proc/collapse()
if(QDELETED(src))
return
visible_message(span_warning("[src] falls in on itself, with the canvas rotting away and contents vanishing."))
qdel(src)
/obj/structure/cursed_money/attack_hand(mob/living/user, list/modifiers)
. = ..()
if(.)
return
user.visible_message(
span_warning("[user] opens the bag and removes a die."),
span_warning("[span_boldwarning("You open the bag...!")] But all you see is a bag full of dice. Confused, you take one..."),
)
var/turf/location = get_turf(user)
var/obj/item/dice/d20/fate/one_use/critical_fail = new(location)
user.put_in_hands(critical_fail)
collapse()
@@ -1,95 +1,5 @@
//These objects are used in the cardinal sin-themed ruins (i.e. Gluttony, Pride...)
/obj/structure/cursed_slot_machine //Greed's slot machine: Used in the Greed ruin. Deals clone damage on each use, with a successful use giving a d20 of fate.
name = "greed's slot machine"
desc = "High stakes, high rewards."
icon = 'icons/obj/machines/computer.dmi'
icon_state = "slots"
var/icon_screen = "slots_screen"
var/brightness_on = 1
anchored = TRUE
density = TRUE
var/win_prob = 5
/// clone damaged dealt each roll
var/damage_on_roll = 20
/// machine's reward when you hit jackpot
var/prize = /obj/structure/cursed_money
/obj/structure/cursed_slot_machine/Initialize(mapload)
. = ..()
update_appearance()
set_light(brightness_on)
/obj/structure/cursed_slot_machine/interact(mob/living/carbon/human/user)
if(!istype(user))
return
if(obj_flags & IN_USE)
return
obj_flags |= IN_USE
user.adjustCloneLoss(damage_on_roll)
if(user.stat)
to_chat(user, span_userdanger("No... just one more try..."))
user.investigate_log("has been gibbed by [src].", INVESTIGATE_DEATHS)
user.gib()
else
user.visible_message(span_warning("[user] pulls [src]'s lever with a glint in [user.p_their()] eyes!"), "<span class='warning'>You feel a draining as you pull the lever, but you \
know it'll be worth it.</span>")
icon_screen = "slots_screen_working"
update_appearance()
playsound(src, 'sound/lavaland/cursed_slot_machine.ogg', 50, FALSE)
addtimer(CALLBACK(src, PROC_REF(determine_victor), user), 50)
/obj/structure/cursed_slot_machine/proc/determine_victor(mob/living/user)
icon_screen = "slots_screen"
update_appearance()
obj_flags &= ~IN_USE
if(prob(win_prob))
playsound(src, 'sound/lavaland/cursed_slot_machine_jackpot.ogg', 50, FALSE)
new prize(get_turf(src))
if(user)
to_chat(user, span_boldwarning("You've hit jackpot. Laughter echoes around you as your reward appears in the machine's place."))
qdel(src)
else
if(user)
to_chat(user, span_boldwarning("Fucking machine! Must be rigged. Still... one more try couldn't hurt, right?"))
/obj/structure/cursed_slot_machine/update_overlays()
. = ..()
var/overlay_state = icon_screen
. += mutable_appearance(icon, overlay_state)
. += emissive_appearance(icon, overlay_state, src)
/obj/structure/cursed_money
name = "bag of money"
desc = "RICH! YES! YOU KNEW IT WAS WORTH IT! YOU'RE RICH! RICH! RICH!"
icon = 'icons/obj/storage/storage.dmi'
icon_state = "moneybag"
anchored = FALSE
density = TRUE
/obj/structure/cursed_money/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, PROC_REF(collapse)), 600)
/obj/structure/cursed_money/proc/collapse()
visible_message("<span class='warning'>[src] falls in on itself, \
canvas rotting away and contents vanishing.</span>")
qdel(src)
/obj/structure/cursed_money/attack_hand(mob/living/user, list/modifiers)
. = ..()
if(.)
return
user.visible_message("<span class='warning'>[user] opens the bag and \
and removes a die. The bag then vanishes.</span>",
"[span_boldwarning("You open the bag...!")]\n\
<span class='danger'>And see a bag full of dice. Confused, \
you take one... and the bag vanishes.</span>")
var/turf/T = get_turf(user)
var/obj/item/dice/d20/fate/one_use/critical_fail = new(T)
user.put_in_hands(critical_fail)
qdel(src)
/obj/effect/gluttony //Gluttony's wall: Used in the Gluttony ruin. Only lets the overweight through.
name = "gluttony's wall"
desc = "Only those who truly indulge may pass."
Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 135 KiB

@@ -299,3 +299,13 @@
desc = "Patient is suffering extreme burns from a strange brand marking, creating serious risk of infection and greatly reduced limb integrity."
examine_desc = "appears to have holy symbols painfully branded into their flesh, leaving severe burns."
occur_text = "chars rapidly into a strange pattern of holy symbols, burned into the flesh."
/// special severe wound caused by the cursed slot machine.
/datum/wound/burn/severe/cursed_brand
name = "Ancient Brand"
desc = "Patient is suffering extreme burns with oddly ornate brand markings, creating serious risk of infection and greatly reduced limb integrity."
examine_desc = "appears to have ornate symbols painfully branded into their flesh, leaving severe burns"
occur_text = "chars rapidly into a pattern that can only be described as an agglomeration of several financial symbols, burned into the flesh"
/datum/wound/burn/severe/cursed_brand/get_limb_examine_description()
return span_warning("The flesh on this limb has several ornate symbols burned into it, with pitting throughout.")
+2
View File
@@ -1627,6 +1627,7 @@
#include "code\datums\status_effects\debuffs\blindness.dm"
#include "code\datums\status_effects\debuffs\choke.dm"
#include "code\datums\status_effects\debuffs\confusion.dm"
#include "code\datums\status_effects\debuffs\cursed.dm"
#include "code\datums\status_effects\debuffs\debuffs.dm"
#include "code\datums\status_effects\debuffs\decloning.dm"
#include "code\datums\status_effects\debuffs\dizziness.dm"
@@ -4080,6 +4081,7 @@
#include "code\modules\mapfluff\ruins\lavalandruin_code\surface.dm"
#include "code\modules\mapfluff\ruins\lavalandruin_code\syndicate_base.dm"
#include "code\modules\mapfluff\ruins\objects_and_mobs\ash_walker_den.dm"
#include "code\modules\mapfluff\ruins\objects_and_mobs\cursed_slot_machine.dm"
#include "code\modules\mapfluff\ruins\objects_and_mobs\necropolis_gate.dm"
#include "code\modules\mapfluff\ruins\objects_and_mobs\sin_ruins.dm"
#include "code\modules\mapfluff\ruins\spaceruin_code\allamericandiner.dm"