diff --git a/code/__DEFINES/actionspeed_modification.dm b/code/__DEFINES/actionspeed_modification.dm index 40fbd3fe26d..c3d288e907f 100644 --- a/code/__DEFINES/actionspeed_modification.dm +++ b/code/__DEFINES/actionspeed_modification.dm @@ -1,2 +1,3 @@ //ids #define ACTIONSPEED_ID_SANITY "sanity_component" +#define ACTIONSPEED_ID_STIMULANTS "stimulant_withdrawal" diff --git a/code/__DEFINES/movespeed_modification.dm b/code/__DEFINES/movespeed_modification.dm index 104965dc8db..c4300d96606 100644 --- a/code/__DEFINES/movespeed_modification.dm +++ b/code/__DEFINES/movespeed_modification.dm @@ -7,6 +7,7 @@ //ids #define MOVESPEED_ID_SANITY "sanity_component" +#define MOVESPEED_ID_STIMULANTS "movespeed_stimulants" #define MOVESPEED_ID_MOB_GRAB_STATE "mob_grab_state" #define MOVESPEED_ID_MOB_WALK_RUN "mob_walk_run" diff --git a/code/__DEFINES/reagents.dm b/code/__DEFINES/reagents.dm index 0c593ebea55..64518f73b46 100644 --- a/code/__DEFINES/reagents.dm +++ b/code/__DEFINES/reagents.dm @@ -47,41 +47,52 @@ //Used in holder.dm/equlibrium.dm to set values and volume limits ///stops floating point errors causing issues with checking reagent amounts -#define CHEMICAL_QUANTISATION_LEVEL 0.0001 +#define CHEMICAL_QUANTISATION_LEVEL 0.0001 ///The smallest amount of volume allowed - prevents tiny numbers -#define CHEMICAL_VOLUME_MINIMUM 0.001 +#define CHEMICAL_VOLUME_MINIMUM 0.001 ///Round to this, to prevent extreme decimal magic and to keep reagent volumes in line with perceived values. -#define CHEMICAL_VOLUME_ROUNDING 0.01 +#define CHEMICAL_VOLUME_ROUNDING 0.01 ///Default pH for reagents datum -#define CHEMICAL_NORMAL_PH 7.000 +#define CHEMICAL_NORMAL_PH 7.000 //reagent bitflags, used for altering how they works ///allows on_mob_dead() if present in a dead body -#define REAGENT_DEAD_PROCESS (1<<0) +#define REAGENT_DEAD_PROCESS (1<<0) ///Do not split the chem at all during processing - ignores all purity effects -#define REAGENT_DONOTSPLIT (1<<1) +#define REAGENT_DONOTSPLIT (1<<1) ///Doesn't appear on handheld health analyzers. -#define REAGENT_INVISIBLE (1<<2) +#define REAGENT_INVISIBLE (1<<2) ///When inverted, the inverted chem uses the name of the original chem -#define REAGENT_SNEAKYNAME (1<<3) +#define REAGENT_SNEAKYNAME (1<<3) ///Retains initial volume of chem when splitting for purity effects -#define REAGENT_SPLITRETAINVOL (1<<4) +#define REAGENT_SPLITRETAINVOL (1<<4) //Lets a given reagent be synthesized important for random reagents and things like the odysseus syringe gun(Replaces the old can_synth variable) -#define REAGENT_CAN_BE_SYNTHESIZED (1<<5) +#define REAGENT_CAN_BE_SYNTHESIZED (1<<5) //Chemical reaction flags, for determining reaction specialties ///Convert into impure/pure on reaction completion -#define REACTION_CLEAR_IMPURE (1<<0) +#define REACTION_CLEAR_IMPURE (1<<0) ///Convert into inverse on reaction completion when purity is low enough -#define REACTION_CLEAR_INVERSE (1<<1) +#define REACTION_CLEAR_INVERSE (1<<1) ///Clear converted chems retain their purities/inverted purities. Requires 1 or both of the above. -#define REACTION_CLEAR_RETAIN (1<<2) +#define REACTION_CLEAR_RETAIN (1<<2) ///Used to create instant reactions -#define REACTION_INSTANT (1<<3) +#define REACTION_INSTANT (1<<3) ///Used to force reactions to create a specific amount of heat per 1u created. So if thermic_constant = 5, for 1u of reagent produced, the heat will be forced up arbitarily by 5 irresepective of other reagents. If you use this, keep in mind standard thermic_constant values are 100x what it should be with this enabled. -#define REACTION_HEAT_ARBITARY (1<<4) +#define REACTION_HEAT_ARBITARY (1<<4) ///Used to bypass the chem_master transfer block (This is needed for competitive reactions unless you have an end state programmed). More stuff might be added later. When defining this, please add in the comments the associated reactions that it competes with -#define REACTION_COMPETITIVE (1<<5) +#define REACTION_COMPETITIVE (1<<5) ///Used to force an equlibrium to end a reaction in reaction_step() (i.e. in a reaction_step() proc return END_REACTION to end it) -#define END_REACTION "end_reaction" +#define END_REACTION "end_reaction" + +///Minimum requirement for addiction buzz to be met +#define MIN_ADDICTION_REAGENT_AMOUNT 2 +#define MAX_ADDICTION_POINTS 1000 + +///Addiction start/ends +#define WITHDRAWAL_STAGE1_START_CYCLE 1 +#define WITHDRAWAL_STAGE1_END_CYCLE 60 +#define WITHDRAWAL_STAGE2_START_CYCLE 61 +#define WITHDRAWAL_STAGE2_END_CYCLE 120 +#define WITHDRAWAL_STAGE3_START_CYCLE 121 diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index fa52b9ae5d5..b65ed11c421 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -93,6 +93,17 @@ #define STATUS_EFFECT_CLOUDSTRUCK /datum/status_effect/cloudstruck //blinds and applies an overlay. +///Raises click cooldowns for everything you do. +#define STATUS_EFFECT_WOOZY /datum/status_effect/woozy + +///Makes you bleed harder +#define STATUS_EFFECT_HIGHBLOODPRESSURE /datum/status_effect/high_blood_pressure + + +/// makes you seize up. reminds me of this video https://www.youtube.com/watch?v=wvkHIZg_954 +#define STATUS_EFFECT_SEIZURE /datum/status_effect/seizure + + /// Makes the mob move randomly. /// Read the documentation for /datum/status_effect/confusion for more information. #define STATUS_EFFECT_CONFUSION /datum/status_effect/confusion diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index beaff0b1adf..e6f9f7bc7c3 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -240,6 +240,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_CANT_RIDE "cant_ride" #define TRAIT_BLOODY_MESS "bloody_mess" //from heparin, makes open bleeding wounds rapidly spill more blood #define TRAIT_COAGULATING "coagulating" //from coagulant reagents, this doesn't affect the bleeding itself but does affect the bleed warning messages +/// From anti-convulsant medication against seizures. +#define TRAIT_ANTICONVULSANT "anticonvulsant" /// The holder of this trait has antennae or whatever that hurt a ton when noogied #define TRAIT_ANTENNAE "antennae" /// Blowing kisses actually does damage to the victim diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 2501a1e8b7a..7759fe4a394 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -22,13 +22,15 @@ #define LAZYLEN(L) length(L) ///Sets a list to null #define LAZYNULL(L) L = null -#define LAZYADDASSOC(L, K, V) if(!L) { L = list(); } L[K] += list(V); +#define LAZYADDASSOC(L, K, V) if(!L) { L = list(); } L[K] += V; +///This is used to add onto lazy assoc list when the value you're adding is a /list/. This one has extra safety over lazyaddassoc because the value could be null (and thus cant be used to += objects) +#define LAZYADDASSOCLIST(L, K, V) if(!L) { L = list(); } L[K] += list(V); #define LAZYREMOVEASSOC(L, K, V) if(L) { if(L[K]) { L[K] -= V; if(!length(L[K])) L -= K; } if(!length(L)) L = null; } #define LAZYACCESSASSOC(L, I, K) L ? L[I] ? L[I][K] ? L[I][K] : null : null : null #define QDEL_LAZYLIST(L) for(var/I in L) qdel(I); L = null; //These methods don't null the list #define LAZYCOPY(L) (L ? L.Copy() : list() ) //Use LAZYLISTDUPLICATE instead if you want it to null with no entries -#define LAZYCLEARLIST(L) if(L) L.Cut() // Consider LAZYNULL instead +#define LAZYCLEARLIST(L) if(L) L.Cut() // Consider LAZYNULL instead #define SANITIZE_LIST(L) ( islist(L) ? L : list() ) #define reverseList(L) reverseRange(L.Copy()) diff --git a/code/controllers/subsystem/addiction.dm b/code/controllers/subsystem/addiction.dm new file mode 100644 index 00000000000..39caf101b8e --- /dev/null +++ b/code/controllers/subsystem/addiction.dm @@ -0,0 +1,19 @@ +/*! +This subsystem mostly exists to populate and manage the withdrawal singletons. +*/ + +SUBSYSTEM_DEF(addiction) + name = "Addiction" + flags = SS_NO_FIRE + ///Dictionary of addiction.type || addiction ref + var/list/all_addictions = list() + +/datum/controller/subsystem/addiction/Initialize(timeofday) + InitializeAddictions() + return ..() + +///Ran on initialize, populates the addiction dictionary +/datum/controller/subsystem/addiction/proc/InitializeAddictions() + for(var/type in subtypesof(/datum/addiction)) + var/datum/addiction/ref = new type + all_addictions[type] = ref diff --git a/code/datums/chatmessage.dm b/code/datums/chatmessage.dm index 2827c08364d..0a0d35559cb 100644 --- a/code/datums/chatmessage.dm +++ b/code/datums/chatmessage.dm @@ -202,7 +202,7 @@ message.maptext = MAPTEXT(complete_text) // View the message - LAZYADDASSOC(owned_by.seen_messages, message_loc, src) + LAZYADDASSOCLIST(owned_by.seen_messages, message_loc, src) owned_by.images |= message animate(message, alpha = 255, time = CHAT_MESSAGE_SPAWN_TIME) diff --git a/code/datums/components/mood.dm b/code/datums/components/mood.dm index 55714a3415f..2c3460663ec 100644 --- a/code/datums/components/mood.dm +++ b/code/datums/components/mood.dm @@ -257,6 +257,8 @@ add_event(null, "jolly", /datum/mood_event/jolly) + + ///Sets sanity to the specified amount and applies effects. /datum/component/mood/proc/setSanity(amount, minimum=SANITY_INSANE, maximum=SANITY_GREAT, override = FALSE) // If we're out of the acceptable minimum-maximum range move back towards it in steps of 0.7 @@ -478,5 +480,18 @@ add_event(null, "slipped", /datum/mood_event/slipped) +/datum/component/mood/proc/HandleAddictions() + if(!iscarbon(parent)) + return + + var/mob/living/carbon/affected_carbon = parent + + if(sanity < SANITY_GREAT) ///Sanity is low, stay addicted. + return + + for(var/addiction_type in affected_carbon.mind.addiction_points) + var/datum/addiction/addiction_to_remove = SSaddiction.all_addictions[type] + affected_carbon.mind.remove_addiction_points(type, addiction_to_remove.high_sanity_addiction_loss) //If true was returned, we lost the addiction! + #undef MINOR_INSANITY_PEN #undef MAJOR_INSANITY_PEN diff --git a/code/datums/elements/climbable.dm b/code/datums/elements/climbable.dm index 0c00018d746..1f50665101e 100644 --- a/code/datums/elements/climbable.dm +++ b/code/datums/elements/climbable.dm @@ -62,7 +62,7 @@ adjusted_climb_time *= 0.25 //aliens are terrifyingly fast if(HAS_TRAIT(user, TRAIT_FREERUNNING)) //do you have any idea how fast I am??? adjusted_climb_time *= 0.8 - LAZYADDASSOC(current_climbers, climbed_thing, user) + LAZYADDASSOCLIST(current_climbers, climbed_thing, user) if(do_after(user, adjusted_climb_time, climbed_thing)) if(QDELETED(climbed_thing)) //Checking if structure has been destroyed return diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 1a1a11b4ece..d86d60d5812 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -83,6 +83,11 @@ /// A lazy list of statuses to add next to this mind in the traitor panel var/list/special_statuses + ///Assoc list of addiction values, key is the type of withdrawal (as singleton type), and the value is the amount of addiction points (as number) + var/list/addiction_points + ///Assoc list of key active addictions and value amount of cycles that it has been active. + var/list/active_addictions + /datum/mind/New(_key) key = _key martial_art = default_martial_art @@ -826,6 +831,18 @@ return martial_art return FALSE +///Adds addiction points to the specified addiction +/datum/mind/proc/add_addiction_points(type, amount) + LAZYSET(addiction_points, type, min(LAZYACCESS(addiction_points, type) + amount, MAX_ADDICTION_POINTS)) + var/datum/addiction/affected_addiction = SSaddiction.all_addictions[type] + return affected_addiction.on_gain_addiction_points(src) + +///Adds addiction points to the specified addiction +/datum/mind/proc/remove_addiction_points(type, amount) + LAZYSET(addiction_points, type, max(LAZYACCESS(addiction_points, type) - amount, 0)) + var/datum/addiction/affected_addiction = SSaddiction.all_addictions[type] + return affected_addiction.on_lose_addiction_points(src) + /mob/dead/new_player/sync_mind() return diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index 60305055556..fc5f07bee1c 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -128,6 +128,10 @@ description = "It sure is dark around here...\n" mood_change = -3 +/datum/mood_event/bright_light + description = "I hate it in the light...I need to find a darker place...\n" + mood_change = -12 + /datum/mood_event/family_heirloom_missing description = "I'm missing my family heirloom...\n" mood_change = -4 diff --git a/code/datums/progressbar.dm b/code/datums/progressbar.dm index 67051686b7d..64e033539f4 100644 --- a/code/datums/progressbar.dm +++ b/code/datums/progressbar.dm @@ -37,7 +37,7 @@ bar.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA user = User - LAZYADDASSOC(user.progressbars, bar_loc, src) + LAZYADDASSOCLIST(user.progressbars, bar_loc, src) var/list/bars = user.progressbars[bar_loc] listindex = bars.len diff --git a/code/datums/quirks/good.dm b/code/datums/quirks/good.dm index 52374440f84..ebc2e62efa3 100644 --- a/code/datums/quirks/good.dm +++ b/code/datums/quirks/good.dm @@ -173,7 +173,7 @@ var/obj/item/organ/eyes/eyes = H.getorgan(/obj/item/organ/eyes) if(!eyes || eyes.lighting_alpha) return - eyes.Insert(H) //refresh their eyesight and vision + eyes.refresh() //refresh their eyesight and vision /datum/quirk/selfaware name = "Self-Aware" diff --git a/code/datums/quirks/negative.dm b/code/datums/quirks/negative.dm index 81654a2ac87..19d3e9004ba 100644 --- a/code/datums/quirks/negative.dm +++ b/code/datums/quirks/negative.dm @@ -583,7 +583,8 @@ if (!reagent_type) reagent_type = pick(drug_list) reagent_instance = new reagent_type() - LAZYADD(H.reagents.addiction_list, reagent_instance) + for(var/addiction in reagent_instance.addiction_types) + H.mind.add_addiction_points(addiction, 1000) ///Max that shit out var/current_turf = get_turf(quirk_holder) if (!drug_container_type) drug_container_type = /obj/item/storage/pill_bottle @@ -615,7 +616,8 @@ /datum/quirk/junkie/remove() if(quirk_holder && reagent_instance) - quirk_holder.reagents.remove_addiction(reagent_instance) //chat feedback here. No need of lose_text. + for(var/addiction_type in subtypesof(/datum/addiction)) + quirk_holder.mind.remove_addiction_points(addiction_type, MAX_ADDICTION_POINTS) //chat feedback here. No need of lose_text. /datum/quirk/junkie/proc/announce_drugs() to_chat(quirk_holder, "There is a [initial(drug_container_type.name)] of [initial(reagent_type.name)] [where_drug]. Better hope you don't run out...") @@ -627,13 +629,17 @@ if(world.time > next_process) next_process = world.time + process_interval var/deleted = QDELETED(reagent_instance) - if(deleted || !LAZYFIND(H.reagents.addiction_list, reagent_instance)) + var/missing_addiction = FALSE + for(var/addiction_type in reagent_instance.addiction_types) + if(!LAZYACCESS(H.mind.active_addictions, addiction_type)) + missing_addiction = TRUE + if(deleted || missing_addiction) if(deleted) reagent_instance = new reagent_type() - else - reagent_instance.addiction_stage = 0 - LAZYADD(H.reagents.addiction_list, reagent_instance) - to_chat(quirk_holder, "You thought you kicked it, but you suddenly feel like you need [reagent_instance.name] again...") + to_chat(quirk_holder, "You thought you kicked it, but you feel like you're falling back onto bad habits..") + for(var/addiction in reagent_instance.addiction_types) + H.mind.add_addiction_points(addiction, 1000) ///Max that shit out + /datum/quirk/junkie/smoker name = "Smoker" diff --git a/code/datums/status_effects/drug_effects.dm b/code/datums/status_effects/drug_effects.dm new file mode 100644 index 00000000000..d9c37e1c711 --- /dev/null +++ b/code/datums/status_effects/drug_effects.dm @@ -0,0 +1,60 @@ +/datum/status_effect/woozy + id = "woozy" + tick_interval = -1 + status_type = STATUS_EFFECT_UNIQUE + alert_type = /atom/movable/screen/alert/status_effect/woozy + + +/datum/status_effect/woozy/nextmove_modifier() + return 1.5 + +/atom/movable/screen/alert/status_effect/woozy + name = "Woozy" + desc = "You feel a bit slower than usual, it seems doing things with your hands takes longer than it usually does" + icon_state = "woozy" + + +/datum/status_effect/high_blood_pressure + id = "high_blood_pressure" + tick_interval = -1 + status_type = STATUS_EFFECT_UNIQUE + alert_type = /atom/movable/screen/alert/status_effect/high_blood_pressure + +/datum/status_effect/high_blood_pressure/on_apply() + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.physiology.bleed_mod *= 1.25 + +/datum/status_effect/high_blood_pressure/on_remove() + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.physiology.bleed_mod /= 1.25 + +/atom/movable/screen/alert/status_effect/high_blood_pressure + name = "High blood pressure" + desc = "This stuff is driving my blood pressure up the wall...I'll probably bleed like crazy." + icon_state = "highbloodpressure" + + + +/datum/status_effect/seizure + id = "seizure" + tick_interval = -1 + status_type = STATUS_EFFECT_UNIQUE + alert_type = /atom/movable/screen/alert/status_effect/seizure + +/datum/status_effect/seizure/on_apply() + if(!iscarbon(owner)) + return FALSE + var/amplitude = rand(1 SECONDS, 3 SECONDS) + duration = amplitude + owner.Jitter(50) + owner.Paralyze(duration) + owner.visible_message("[owner] drops to the ground as [owner.p_they()] start seizing up.", \ + "[pick("You can't collect your thoughts...", "You suddenly feel extremely dizzy...", "You cant think straight...","You can't move your face properly anymore...")]") + return TRUE + +/atom/movable/screen/alert/status_effect/seizure + name = "Seizure" + desc = "FJOIWEHUWQEFGYUWDGHUIWHUIDWEHUIFDUWGYSXQHUIODSDBNJKVBNKDML <--- this is you right now" + icon_state = "paralysis" diff --git a/code/game/machinery/medical_kiosk.dm b/code/game/machinery/medical_kiosk.dm index 04c6a07374f..1d81dae7480 100644 --- a/code/game/machinery/medical_kiosk.dm +++ b/code/game/machinery/medical_kiosk.dm @@ -252,9 +252,9 @@ var/bit_vol = bit.volume - belly.food_reagents[bit.type] if(bit_vol > 0) chemical_list += list(list("name" = bit.name, "volume" = round(bit_vol, 0.01))) - for(var/a in altPatient.reagents.addiction_list) - var/datum/reagent/addiction = a - addict_list += list(list("name" = addiction.name)) + for(var/datum/addiction/addiction_type as anything in altPatient.mind.active_addictions) + addict_list += list(list("name" = initial(addiction_type.name))) + if (altPatient.hallucinating()) hallucination_status = "Subject appears to be hallucinating. Suggested treatments: bedrest, mannitol or psicodine." diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 76bbf00ae81..897b40f27db 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -41,7 +41,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark) . = ..() GLOB.start_landmarks_list += src if(jobspawn_override) - LAZYADDASSOC(GLOB.jobspawn_overrides, name, src) + LAZYADDASSOCLIST(GLOB.jobspawn_overrides, name, src) if(name != "start") tag = "start*[name]" diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index f3ff12f122c..26f8eadd194 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -452,13 +452,12 @@ GENE SCANNER else render_list += "Subject contains no reagents in their stomach.\n" - if(LAZYLEN(M.reagents.addiction_list)) - render_list += "Subject is addicted to the following reagents:\n" - for(var/a in M.reagents.addiction_list) - var/datum/reagent/addiction = a - render_list += "[addiction.name]\n" + if(LAZYLEN(M.mind.active_addictions)) + render_list += "Subject is addicted to the following types of drug:\n" + for(var/datum/addiction/addiction_type as anything in M.mind.active_addictions) + render_list += "[initial(addiction_type.name)]\n" else - render_list += "Subject is not addicted to any reagents.\n" + render_list += "Subject is not addicted to any types of drug.\n" to_chat(user, jointext(render_list, ""), trailing_newline = FALSE) // we handled the last
so we don't need handholding diff --git a/code/modules/actionspeed/modifiers/addiction.dm b/code/modules/actionspeed/modifiers/addiction.dm new file mode 100644 index 00000000000..a37693329a0 --- /dev/null +++ b/code/modules/actionspeed/modifiers/addiction.dm @@ -0,0 +1,3 @@ +/datum/actionspeed_modifier/stimulants + multiplicative_slowdown = 0.25 + id = ACTIONSPEED_ID_STIMULANTS diff --git a/code/modules/antagonists/gang/gang.dm b/code/modules/antagonists/gang/gang.dm index c429896ba10..56670d0972d 100644 --- a/code/modules/antagonists/gang/gang.dm +++ b/code/modules/antagonists/gang/gang.dm @@ -411,7 +411,7 @@ free_clothes = list(/obj/item/clothing/mask/bandana/gold, /obj/item/clothing/under/color/yellow, /obj/item/toy/crayon/spraycan) - gang_objective = "Orders from up high. We need to up our drug operation. Ensure that at least 25% of the station is addicted to meth." + gang_objective = "Orders from up high. We need to up our drug operation. Ensure that at least 25% of the station is addicted to stimulants." antag_hud_name = "Vagos" /datum/antagonist/gang/vagos/check_gang_objective() @@ -423,9 +423,8 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M people_on_station++ - for(var/R in H.reagents.addiction_list) - if(istype(R, /datum/reagent/drug/methamphetamine)) - people_on_crack++ + if(H.mind.active_addictions[/datum/addiction/stimulants]) + people_on_crack++ if(0.25*people_on_station > people_on_crack) return FALSE return TRUE diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 68c99fe1013..be1411902c5 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -284,8 +284,8 @@ Works together with spawning an observer, noted above. SStgui.on_transfer(src, ghost) // Transfer NanoUIs. ghost.can_reenter_corpse = can_reenter_corpse ghost.key = key - ghost.client.init_verbs() - if(!can_reenter_corpse) // Disassociates observer mind from the body mind + ghost.client?.init_verbs() + if(!can_reenter_corpse)// Disassociates observer mind from the body mind ghost.mind = null return ghost diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 644cb810330..5f2baccb41a 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -898,8 +898,9 @@ /mob/living/carbon/fully_heal(admin_revive = FALSE) if(reagents) reagents.clear_reagents() - for(var/addi in reagents.addiction_list) - reagents.remove_addiction(addi) + if(mind) + for(var/addiction_type in subtypesof(/datum/addiction)) + mind.remove_addiction_points(addiction_type, MAX_ADDICTION_POINTS) //Remove the addiction! for(var/O in internal_organs) var/obj/item/organ/organ = O organ.setOrganDamage(0) @@ -918,8 +919,6 @@ for(var/obj/item/restraints/R in contents) //actually remove cuffs from inventory qdel(R) update_handcuffed() - if(reagents) - reagents.addiction_list = list() cure_all_traumas(TRAUMA_RESILIENCE_MAGIC) ..() diff --git a/code/modules/mob/living/carbon/init_signals.dm b/code/modules/mob/living/carbon/init_signals.dm index 4bd32b22a73..12ccd3cbbf3 100644 --- a/code/modules/mob/living/carbon/init_signals.dm +++ b/code/modules/mob/living/carbon/init_signals.dm @@ -33,12 +33,7 @@ */ /mob/living/carbon/proc/on_nometabolism_trait_gain(datum/source) SIGNAL_HANDLER + for(var/addiction_type in subtypesof(/datum/addiction)) + mind.remove_addiction_points(addiction_type, MAX_ADDICTION_POINTS) //Remove the addiction! - if(reagents.addiction_list) - to_chat(source, "You feel like you've gotten over your need for drugs.") - for(var/a in reagents.addiction_list) - var/datum/reagent/R = a - SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "[R.type]_overdose") - LAZYREMOVE(reagents.addiction_list, R) - qdel(R) reagents.end_metabolization(keep_liverless = TRUE) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 29e0f9b1dd8..13233da3e3b 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -61,6 +61,10 @@ if(STAMINA_THRESHOLD_MESSAGE_OHGOD to INFINITY) to_chat(src, "You feel fatigued!") //SKYRAT EDIT END + if(mind) + for(var/key in mind.addiction_points) + var/datum/addiction/addiction = SSaddiction.all_addictions[key] + addiction.process_addiction(src) if(stat != DEAD) return 1 diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index 357b7ccb8ca..28df1dc0389 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -479,11 +479,11 @@ for(var/listed_type in slowdown_type) if(ispath(listed_type)) listed_type = "[listed_type]" //Path2String - LAZYADDASSOC(movespeed_mod_immunities, listed_type, source) + LAZYADDASSOCLIST(movespeed_mod_immunities, listed_type, source) else if(ispath(slowdown_type)) slowdown_type = "[slowdown_type]" //Path2String - LAZYADDASSOC(movespeed_mod_immunities, slowdown_type, source) + LAZYADDASSOCLIST(movespeed_mod_immunities, slowdown_type, source) if(update) update_movespeed() diff --git a/code/modules/movespeed/modifiers/drugs.dm b/code/modules/movespeed/modifiers/drugs.dm new file mode 100644 index 00000000000..a8f017bea9f --- /dev/null +++ b/code/modules/movespeed/modifiers/drugs.dm @@ -0,0 +1,4 @@ +/datum/movespeed_modifier/stimulants + movetypes = GROUND + multiplicative_slowdown = 1 + id = MOVESPEED_ID_STIMULANTS diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 0de8e402b0f..e8e6345f68d 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -60,10 +60,6 @@ var/ph = CHEMICAL_NORMAL_PH /// unused var/last_tick = 1 - /// see [/datum/reagents/proc/metabolize] for usage - var/addiction_tick = 1 - /// currently addicted reagents - var/list/datum/reagent/addiction_list /// various flags, see code\__DEFINES\reagents.dm var/flags ///list of reactions currently on going, this is a lazylist for optimisation @@ -81,7 +77,6 @@ /datum/reagents/Destroy() //We're about to delete all reagents, so lets cleanup - addiction_list = null for(var/reagent in reagent_list) var/datum/reagent/R = reagent qdel(R) @@ -311,8 +306,6 @@ R.on_mob_end_metabolize(my_atom) R.on_mob_delete(my_atom) - //Clear from relevant lists - LAZYREMOVE(addiction_list, R) reagent_list -= R LAZYREMOVE(previous_reagent_list, R.type) qdel(R) @@ -664,45 +657,13 @@ R.overdosed = TRUE need_mob_update += R.overdose_start(C) log_game("[key_name(C)] has started overdosing on [R.name] at [R.volume] units.") - var/is_addicted_to = addiction_list && is_type_in_list(R, addiction_list) - if(R.addiction_threshold) - if(R.volume >= R.addiction_threshold && !is_addicted_to) - var/datum/reagent/new_reagent = new R.addiction_type() - LAZYADD(addiction_list, new_reagent) - is_addicted_to = TRUE - log_game("[key_name(C)] has become addicted to [R.name] at [R.volume] units.") + for(var/addiction in R.addiction_types) + C.mind?.add_addiction_points(addiction, R.addiction_types[addiction] * REAGENTS_METABOLISM) + if(R.overdosed) need_mob_update += R.overdose_process(C) - var/datum/reagent/addiction_type = new R.addiction_type() - if(is_addicted_to) - for(var/addiction in addiction_list) - var/datum/reagent/A = addiction - if(istype(addiction_type, A)) - A.addiction_stage = -15 // you're satisfied for a good while. - need_mob_update += R.on_mob_life(C) - if(can_overdose) - if(addiction_tick == 6) - addiction_tick = 1 - for(var/addiction in addiction_list) - var/datum/reagent/R = addiction - if(!C) - break - R.addiction_stage++ - switch(R.addiction_stage) - if(1 to 10) - need_mob_update += R.addiction_act_stage1(C) - if(10 to 20) - need_mob_update += R.addiction_act_stage2(C) - if(20 to 30) - need_mob_update += R.addiction_act_stage3(C) - if(30 to 40) - need_mob_update += R.addiction_act_stage4(C) - if(40 to INFINITY) - remove_addiction(R) - else - SEND_SIGNAL(C, COMSIG_CLEAR_MOOD_EVENT, "[R.type]_overdose") - addiction_tick++ + need_mob_update += R.on_mob_life(C) if(C && need_mob_update) //some of the metabolized reagents had effects on the mob that requires some updates. C.updatehealth() C.update_stamina() @@ -723,14 +684,6 @@ R.metabolizing = FALSE R.on_mob_end_metabolize(C) -/// Removes addiction to a specific reagent on [/datum/reagents/var/my_atom] -/datum/reagents/proc/remove_addiction(datum/reagent/R) - to_chat(my_atom, "You feel like you've gotten over your need for [R.name].") - SEND_SIGNAL(my_atom, COMSIG_CLEAR_MOOD_EVENT, "[R.type]_overdose") - LAZYREMOVE(addiction_list, R) - qdel(R) - - /** * Calls [/datum/reagent/proc/on_move] on every reagent in this holder * diff --git a/code/modules/reagents/chemistry/items.dm b/code/modules/reagents/chemistry/items.dm index d4f7bf6fdfd..03a16ced1d7 100644 --- a/code/modules/reagents/chemistry/items.dm +++ b/code/modules/reagents/chemistry/items.dm @@ -157,7 +157,7 @@ if(cont.reagents.is_reacting) out_message += "A reaction appears to be occuring currently.\n" for(var/datum/reagent/R in cont.reagents.reagent_list) - out_message += "[round(R.volume, 0.01)]u of [R.name], Purity: [round(R.purity, 0.01)], [(scanmode?"[(R.overdose_threshold?"Overdose: [R.overdose_threshold]u, ":"")][(R.addiction_threshold?"Addiction: [R.addiction_threshold]u, ":"")]Base pH: [initial(R.ph)], Current pH: [R.ph].":"Current pH: [R.ph].")]\n" + out_message += "[round(R.volume, 0.01)]u of [R.name], Purity: [round(R.purity, 0.01)], [(scanmode?"[(R.overdose_threshold?"Overdose: [R.overdose_threshold]u, ":"")]Base pH: [initial(R.ph)], Current pH: [R.ph].":"Current pH: [R.ph].")]\n" if(scanmode) out_message += "Analysis: [R.description]\n" to_chat(user, "[out_message.Join()]") diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index d4997982db3..42a3b19487b 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -426,7 +426,7 @@ state = "Gas" var/const/P = 3 //The number of seconds between life ticks var/T = initial(R.metabolization_rate) * (60 / P) - analyze_vars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "pH" = initial(R.ph)) + analyze_vars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "pH" = initial(R.ph)) screen = "analyze" return TRUE @@ -585,7 +585,7 @@ for(var/e in holder.reaction_list) var/datum/equilibrium/E = e if(E.reaction.reaction_flags & REACTION_COMPETITIVE) - continue + continue for(var/result in E.reaction.required_reagents) var/datum/reagent/R = result if(R == reagent.type) diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 888b4f261f9..be68ab98d2f 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -58,12 +58,6 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) var/overrides_metab = 0 /// above this overdoses happen var/overdose_threshold = 0 - ///Overrides what addiction this chemicals feeds into, allowing you to have multiple chems that treat a single addiction. - var/addiction_type - /// above this amount addictions start - var/addiction_threshold = 0 - /// increases as addiction gets worse - var/addiction_stage = 0 /// You fucked up and this is now triggering its overdose effects, purge that shit quick. var/overdosed = FALSE ///if false stops metab in liverless mobs @@ -91,14 +85,13 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) var/inverse_chem = /datum/reagent/impurity/toxic ///what chem is made at the end of a reaction IF the purity is below the recipies purity_min at the END of a reaction only var/failed_chem = /datum/reagent/consumable/failed_reaction + ///Assoc list with key type of addiction this reagent feeds, and value amount of addiction points added per unit of reagent metabolzied (which means * REAGENTS_METABOLISM every life()) + var/list/addiction_types = null /datum/reagent/New() SHOULD_CALL_PARENT(TRUE) . = ..() - if(!addiction_type) - addiction_type = type - if(material) material = GET_MATERIAL_REF(material) @@ -160,6 +153,7 @@ Primarily used in reagents/reaction_agents /// Called when this reagent is removed while inside a mob /datum/reagent/proc/on_mob_delete(mob/living/L) + SEND_SIGNAL(L, COMSIG_CLEAR_MOOD_EVENT, "[type]_overdose") return /// Called when this reagent first starts being metabolized by a liver @@ -209,34 +203,6 @@ Primarily used in reagents/reaction_agents SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[type]_overdose", /datum/mood_event/overdose, name) return -/// Called when addiction hits stage1, see [/datum/reagents/proc/metabolize] -/datum/reagent/proc/addiction_act_stage1(mob/living/M) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[type]_overdose", /datum/mood_event/withdrawal_light, name) - if(prob(30)) - to_chat(M, "You feel like having some [name] right about now.") - return - -/// Called when addiction hits stage2, see [/datum/reagents/proc/metabolize] -/datum/reagent/proc/addiction_act_stage2(mob/living/M) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[type]_overdose", /datum/mood_event/withdrawal_medium, name) - if(prob(30)) - to_chat(M, "You feel like you need [name]. You just can't get enough.") - return - -/// Called when addiction hits stage3, see [/datum/reagents/proc/metabolize] -/datum/reagent/proc/addiction_act_stage3(mob/living/M) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[type]_overdose", /datum/mood_event/withdrawal_severe, name) - if(prob(30)) - to_chat(M, "You have an intense craving for [name].") - return - -/// Called when addiction hits stage4, see [/datum/reagents/proc/metabolize] -/datum/reagent/proc/addiction_act_stage4(mob/living/M) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[type]_overdose", /datum/mood_event/withdrawal_critical, name) - if(prob(30)) - to_chat(M, "You're not feeling good at all! You really need some [name].") - return - /** * New, standardized method for chemicals to affect hydroponics trays. * Defined on a per-chem level as opposed to by the tray. diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 80399fe1ad6..820482f6e36 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -36,6 +36,10 @@ All effects don't start immediately, but rather get worse over time; the rate is 91-100: Dangerously toxic - swift death */ +/datum/reagent/consumable/ethanol/New() + addiction_types = list(/datum/addiction/alcohol = 0.05 * boozepwr) + return ..() + /datum/reagent/consumable/ethanol/on_mob_life(mob/living/carbon/C) if(C.drunkenness < volume * boozepwr * ALCOHOL_THRESHOLD_MODIFIER || boozepwr < 0) var/booze_power = boozepwr @@ -179,38 +183,11 @@ All effects don't start immediately, but rather get worse over time; the rate is name = "Kong" description = "Makes You Go Ape!®" color = "#332100" // rgb: 51, 33, 0 - addiction_threshold = 15 taste_description = "the grip of a giant ape" glass_name = "glass of Kong" glass_desc = "Makes You Go Ape!®" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED -/datum/reagent/consumable/ethanol/whiskey/kong/addiction_act_stage1(mob/living/M) - if(prob(5)) - to_chat(M, "You've made so many mistakes.") - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "depression_minimal", /datum/mood_event/depression_minimal) - ..() - -/datum/reagent/consumable/ethanol/whiskey/kong/addiction_act_stage2(mob/living/M) - if(prob(5)) - to_chat(M, "No matter what you do, people will always get hurt.") - SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "depression_minimal", /datum/mood_event/depression_minimal) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "depression_mild", /datum/mood_event/depression_mild) - ..() - -/datum/reagent/consumable/ethanol/whiskey/kong/addiction_act_stage3(mob/living/M) - if(prob(5)) - to_chat(M, "You've lost so many people.") - SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "depression_mild", /datum/mood_event/depression_mild) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "depression_moderate", /datum/mood_event/depression_moderate) - ..() - -/datum/reagent/consumable/ethanol/whiskey/kong/addiction_act_stage4(mob/living/M) - if(prob(5)) - to_chat(M, "Just lie down and die.") - SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "depression_moderate", /datum/mood_event/depression_moderate) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "depression_severe", /datum/mood_event/depression_severe) - ..() /datum/reagent/consumable/ethanol/whiskey/candycorn name = "candy corn liquor" @@ -235,7 +212,6 @@ All effects don't start immediately, but rather get worse over time; the rate is boozepwr = 80 quality = DRINK_GOOD overdose_threshold = 60 - addiction_threshold = 30 taste_description = "jitters and death" glass_icon_state = "thirteen_loko_glass" glass_name = "glass of Thirteen Loko" @@ -492,6 +468,7 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_icon_state = "glass_brown2" glass_name = "Hooch" glass_desc = "You've really hit rock bottom now... your liver packed its bags and left last night." + addiction_types = list(/datum/addiction/alcohol = 5, /datum/addiction/maintenance_drugs = 2) chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/ethanol/hooch/on_mob_life(mob/living/carbon/M) diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index 813d2b8b22d..7a52fd392ea 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -1007,6 +1007,7 @@ glass_icon_state = "lean" glass_name = "Lean" glass_desc = "A drink that makes your life less miserable." + addiction_types = list(/datum/addiction/opiods = 6) chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/lean/on_mob_life(mob/living/carbon/M) diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index 27a59038f80..33e3951db05 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -15,6 +15,7 @@ overdose_threshold = 30 ph = 9 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/hallucinogens = 10) //4 per 2 seconds /datum/reagent/drug/space_drugs/on_mob_life(mob/living/carbon/M) M.set_drugginess(15) @@ -40,7 +41,6 @@ description = "Slightly reduces stun times. If overdosed it will deal toxin and oxygen damage." reagent_state = LIQUID color = "#60A584" // rgb: 96, 165, 132 - addiction_threshold = 10 taste_description = "smoke" trippy = FALSE overdose_threshold=15 @@ -76,13 +76,13 @@ /datum/reagent/drug/crank name = "Crank" - description = "Reduces stun times by about 200%. If overdosed or addicted it will deal significant Toxin, Brute and Brain damage." + description = "Reduces stun times by about 200%. If overdosed it will deal significant Toxin, Brute and Brain damage." reagent_state = LIQUID color = "#FA00C8" overdose_threshold = 20 - addiction_threshold = 10 ph = 10 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/stimulants = 14) //5.6 per 2 seconds /datum/reagent/drug/crank/on_mob_life(mob/living/carbon/M) if(prob(5)) @@ -96,44 +96,15 @@ M.AdjustParalyzed(-20) ..() . = 1 - -/datum/reagent/drug/crank/overdose_process(mob/living/M) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2*REM) - M.adjustToxLoss(2*REM, 0) - M.adjustBruteLoss(2*REM, FALSE, FALSE, BODYPART_ORGANIC) - ..() - . = 1 - -/datum/reagent/drug/crank/addiction_act_stage1(mob/living/M) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5*REM) - ..() - -/datum/reagent/drug/crank/addiction_act_stage2(mob/living/M) - M.adjustToxLoss(5*REM, 0) - ..() - . = 1 - -/datum/reagent/drug/crank/addiction_act_stage3(mob/living/M) - M.adjustBruteLoss(5*REM, 0) - ..() - . = 1 - -/datum/reagent/drug/crank/addiction_act_stage4(mob/living/M) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3*REM) - M.adjustToxLoss(5*REM, 0) - M.adjustBruteLoss(5*REM, 0) - ..() - . = 1 - /datum/reagent/drug/krokodil name = "Krokodil" - description = "Cools and calms you down. If overdosed it will deal significant Brain and Toxin damage. If addicted it will begin to deal fatal amounts of Brute damage as the subject's skin falls off." + description = "Cools and calms you down. If overdosed it will deal significant Brain and Toxin damage." reagent_state = LIQUID color = "#0064B4" overdose_threshold = 20 - addiction_threshold = 15 ph = 9 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/opiods = 18) //7.2 per 2 seconds /datum/reagent/drug/krokodil/on_mob_life(mob/living/carbon/M) @@ -141,6 +112,11 @@ if(prob(5)) to_chat(M, "[high_message]") SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "smacked out", /datum/mood_event/narcotic_heavy, name) + if(current_cycle == 35 && creation_purity <= 0.6) + if(!istype(M.dna.species, /datum/species/krokodil_addict)) + to_chat(M, "Your skin falls off easily!") + M.adjustBruteLoss(50*REM, 0) // holy shit your skin just FELL THE FUCK OFF + M.set_species(/datum/species/krokodil_addict) ..() /datum/reagent/drug/krokodil/overdose_process(mob/living/M) @@ -149,34 +125,7 @@ ..() . = 1 -/datum/reagent/drug/krokodil/addiction_act_stage1(mob/living/M) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2*REM) - M.adjustToxLoss(2*REM, 0) - ..() - . = 1 -/datum/reagent/drug/krokodil/addiction_act_stage2(mob/living/M) - if(prob(25)) - to_chat(M, "Your skin feels loose...") - ..() - -/datum/reagent/drug/krokodil/addiction_act_stage3(mob/living/M) - if(prob(25)) - to_chat(M, "Your skin starts to peel away...") - M.adjustBruteLoss(3*REM, 0) - ..() - . = 1 - -/datum/reagent/drug/krokodil/addiction_act_stage4(mob/living/carbon/human/M) - CHECK_DNA_AND_SPECIES(M) - if(!istype(M.dna.species, /datum/species/krokodil_addict)) - to_chat(M, "Your skin falls off easily!") - M.adjustBruteLoss(50*REM, 0) // holy shit your skin just FELL THE FUCK OFF - M.set_species(/datum/species/krokodil_addict) - else - M.adjustBruteLoss(5*REM, 0) - ..() - . = 1 /datum/reagent/drug/methamphetamine name = "Methamphetamine" @@ -184,10 +133,10 @@ reagent_state = LIQUID color = "#FAFAFA" overdose_threshold = 20 - addiction_threshold = 10 metabolization_rate = 0.75 * REAGENTS_METABOLISM ph = 5 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/stimulants = 12) //4.8 per 2 seconds /datum/reagent/drug/methamphetamine/on_mob_metabolize(mob/living/L) ..() @@ -228,50 +177,14 @@ M.adjustToxLoss(1, 0) M.adjustOrganLoss(ORGAN_SLOT_BRAIN, pick(0.5, 0.6, 0.7, 0.8, 0.9, 1)) . = 1 - -/datum/reagent/drug/methamphetamine/addiction_act_stage1(mob/living/M) - M.Jitter(5) - if(prob(20)) - M.emote(pick("twitch","drool","moan")) - ..() - -/datum/reagent/drug/methamphetamine/addiction_act_stage2(mob/living/M) - M.Jitter(10) - M.Dizzy(10) - if(prob(30)) - M.emote(pick("twitch","drool","moan")) - ..() - -/datum/reagent/drug/methamphetamine/addiction_act_stage3(mob/living/M) - if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED) && !ismovable(M.loc)) - for(var/i = 0, i < 4, i++) - step(M, pick(GLOB.cardinals)) - M.Jitter(15) - M.Dizzy(15) - if(prob(40)) - M.emote(pick("twitch","drool","moan")) - ..() - -/datum/reagent/drug/methamphetamine/addiction_act_stage4(mob/living/carbon/human/M) - if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED) && !ismovable(M.loc)) - for(var/i = 0, i < 8, i++) - step(M, pick(GLOB.cardinals)) - M.Jitter(20) - M.Dizzy(20) - M.adjustToxLoss(5, 0) - if(prob(50)) - M.emote(pick("twitch","drool","moan")) - ..() - . = 1 - /datum/reagent/drug/bath_salts name = "Bath Salts" description = "Makes you impervious to stuns and grants a stamina regeneration buff, but you will be a nearly uncontrollable tramp-bearded raving lunatic." reagent_state = LIQUID color = "#FAFAFA" overdose_threshold = 20 - addiction_threshold = 10 taste_description = "salt" // because they're bathsalts? + addiction_types = list(/datum/addiction/stimulants = 25) //8 per 2 seconds var/datum/brain_trauma/special/psychotic_brawling/bath_salts/rage ph = 8.2 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -317,61 +230,13 @@ M.drop_all_held_items() ..() -/datum/reagent/drug/bath_salts/addiction_act_stage1(mob/living/M) - M.hallucination += 10 - if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED) && !ismovable(M.loc)) - for(var/i = 0, i < 8, i++) - step(M, pick(GLOB.cardinals)) - M.Jitter(5) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10) - if(prob(20)) - M.emote(pick("twitch","drool","moan")) - ..() - -/datum/reagent/drug/bath_salts/addiction_act_stage2(mob/living/M) - M.hallucination += 20 - if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED) && !ismovable(M.loc)) - for(var/i = 0, i < 8, i++) - step(M, pick(GLOB.cardinals)) - M.Jitter(10) - M.Dizzy(10) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10) - if(prob(30)) - M.emote(pick("twitch","drool","moan")) - ..() - -/datum/reagent/drug/bath_salts/addiction_act_stage3(mob/living/M) - M.hallucination += 30 - if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED) && !ismovable(M.loc)) - for(var/i = 0, i < 12, i++) - step(M, pick(GLOB.cardinals)) - M.Jitter(15) - M.Dizzy(15) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10) - if(prob(40)) - M.emote(pick("twitch","drool","moan")) - ..() - -/datum/reagent/drug/bath_salts/addiction_act_stage4(mob/living/carbon/human/M) - M.hallucination += 30 - if(!HAS_TRAIT(M, TRAIT_IMMOBILIZED) && !ismovable(M.loc)) - for(var/i = 0, i < 16, i++) - step(M, pick(GLOB.cardinals)) - M.Jitter(50) - M.Dizzy(50) - M.adjustToxLoss(5, 0) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10) - if(prob(50)) - M.emote(pick("twitch","drool","moan")) - ..() - . = 1 - /datum/reagent/drug/aranesp name = "Aranesp" description = "Amps you up, gets you going, and rapidly restores stamina damage. Side effects include breathlessness and toxicity." reagent_state = LIQUID color = "#78FFF0" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/stimulants = 8) /datum/reagent/drug/aranesp/on_mob_life(mob/living/carbon/M) var/high_message = pick("You feel amped up.", "You feel ready.", "You feel like you can push it to the limit.") @@ -390,10 +255,10 @@ description = "Fills you with ecstasic numbness and causes minor brain damage. Highly addictive. If overdosed causes sudden mood swings." reagent_state = LIQUID color = "#EE35FF" - addiction_threshold = 10 overdose_threshold = 20 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED taste_description = "paint thinner" + addiction_types = list(/datum/addiction/hallucinogens = 18) /datum/reagent/drug/happiness/on_mob_metabolize(mob/living/L) ..() @@ -430,39 +295,6 @@ ..() . = 1 -/datum/reagent/drug/happiness/addiction_act_stage1(mob/living/M)// all work and no play makes jack a dull boy - var/datum/component/mood/mood = M.GetComponent(/datum/component/mood) - mood?.setSanity(min(mood.sanity, SANITY_DISTURBED)) - M.Jitter(5) - if(prob(20)) - M.emote(pick("twitch","laugh","frown")) - ..() - -/datum/reagent/drug/happiness/addiction_act_stage2(mob/living/M) - var/datum/component/mood/mood = M.GetComponent(/datum/component/mood) - mood?.setSanity(min(mood.sanity, SANITY_UNSTABLE)) - M.Jitter(10) - if(prob(30)) - M.emote(pick("twitch","laugh","frown")) - ..() - -/datum/reagent/drug/happiness/addiction_act_stage3(mob/living/M) - var/datum/component/mood/mood = M.GetComponent(/datum/component/mood) - mood?.setSanity(min(mood.sanity, SANITY_CRAZY)) - M.Jitter(15) - if(prob(40)) - M.emote(pick("twitch","laugh","frown")) - ..() - -/datum/reagent/drug/happiness/addiction_act_stage4(mob/living/carbon/human/M) - var/datum/component/mood/mood = M.GetComponent(/datum/component/mood) - mood?.setSanity(SANITY_INSANE) - M.Jitter(20) - if(prob(50)) - M.emote(pick("twitch","laugh","frown")) - ..() - . = 1 - /datum/reagent/drug/pumpup name = "Pump-Up" description = "Take on the world! A fast acting, hard hitting drug that pushes the limit on what you can handle." @@ -471,6 +303,7 @@ metabolization_rate = 2 * REAGENTS_METABOLISM overdose_threshold = 30 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/stimulants = 6) //2.6 per 2 seconds /datum/reagent/drug/pumpup/on_mob_metabolize(mob/living/L) ..() @@ -509,35 +342,7 @@ /datum/reagent/drug/maint name = "Maintenance Drugs" - addiction_type = /datum/reagent/drug/maint - -/datum/reagent/drug/maint/addiction_act_stage1(mob/living/M) - . = ..() - M.Jitter(1) - -/datum/reagent/drug/maint/addiction_act_stage2(mob/living/M) - . = ..() - M.Jitter(2) - if(prob(15)) - M.emote(pick("twitch","drool")) - -/datum/reagent/drug/maint/addiction_act_stage3(mob/living/M) - . = ..() - M.Jitter(1) - M.adjustToxLoss(2) - if(prob(5)) - M.drop_all_held_items() - if(prob(15)) - M.emote(pick("twitch","drool")) - -/datum/reagent/drug/maint/addiction_act_stage4(mob/living/M) - . = ..() - M.Jitter(2) - M.adjustToxLoss(3) - if(prob(10)) - M.drop_all_held_items() - if(prob(30)) - M.emote(pick("twitch","drool")) + chemical_flags = NONE /datum/reagent/drug/maint/powder name = "Maintenance Powder" @@ -546,8 +351,9 @@ color = "#ffffff" metabolization_rate = 0.5 * REAGENTS_METABOLISM overdose_threshold = 15 - addiction_threshold = 6 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/maintenance_drugs = 14) /datum/reagent/drug/maint/powder/on_mob_life(mob/living/carbon/M) . = ..() @@ -573,8 +379,8 @@ color = "#203d2c" metabolization_rate = 2 * REAGENTS_METABOLISM overdose_threshold = 25 - addiction_threshold = 10 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/maintenance_drugs = 8) /datum/reagent/drug/maint/sludge/on_mob_metabolize(mob/living/L) @@ -606,8 +412,8 @@ reagent_state = LIQUID color = "#000000" overdose_threshold = 30 - addiction_threshold = 10 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/maintenance_drugs = 5) /datum/reagent/drug/maint/tar/on_mob_life(mob/living/carbon/M) . = ..() diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index f0a4766c4a4..288ad6ce7a8 100755 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -419,6 +419,7 @@ taste_description = "mushroom" ph = 11 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/hallucinogens = 12) /datum/reagent/drug/mushroomhallucinogen/on_mob_life(mob/living/carbon/M) if(!M.slurring) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 035ff600cf9..4bf1938fd0e 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -510,9 +510,9 @@ color = "#D2FFFA" metabolization_rate = 0.5 * REAGENTS_METABOLISM overdose_threshold = 30 - addiction_threshold = 25 ph = 12 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/stimulants = 4) //1.6 per 2 seconds /datum/reagent/medicine/ephedrine/on_mob_metabolize(mob/living/L) ..() @@ -552,53 +552,7 @@ . = 1 return TRUE -/datum/reagent/medicine/ephedrine/addiction_act_stage1(mob/living/M) - if(prob(3) && iscarbon(M)) - M.visible_message("[M] starts having a seizure!", "You have a seizure!") - M.Unconscious(100) - M.Jitter(350) - if(prob(33)) - M.adjustToxLoss(2*REM, 0) - M.losebreath += 2 - . = 1 - ..() - -/datum/reagent/medicine/ephedrine/addiction_act_stage2(mob/living/M) - if(prob(6) && iscarbon(M)) - M.visible_message("[M] starts having a seizure!", "You have a seizure!") - M.Unconscious(100) - M.Jitter(350) - - if(prob(33)) - M.adjustToxLoss(3*REM, 0) - M.losebreath += 3 - . = 1 - ..() - -/datum/reagent/medicine/ephedrine/addiction_act_stage3(mob/living/M) - if(prob(12) && iscarbon(M)) - M.visible_message("[M] starts having a seizure!", "You have a seizure!") - M.Unconscious(100) - M.Jitter(350) - - if(prob(33)) - M.adjustToxLoss(4*REM, 0) - M.losebreath += 4 - . = 1 - ..() - -/datum/reagent/medicine/ephedrine/addiction_act_stage4(mob/living/M) - if(prob(24) && iscarbon(M)) - M.visible_message("[M] starts having a seizure!", "You have a seizure!") - M.Unconscious(100) - M.Jitter(350) - - if(prob(33)) - M.adjustToxLoss(5*REM, 0) - M.losebreath += 5 - . = 1 - ..() /datum/reagent/medicine/diphenhydramine name = "Diphenhydramine" @@ -623,9 +577,9 @@ color = "#A9FBFB" metabolization_rate = 0.5 * REAGENTS_METABOLISM overdose_threshold = 30 - addiction_threshold = 25 ph = 8.96 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/opiods = 10) /datum/reagent/medicine/morphine/on_mob_metabolize(mob/living/L) ..() @@ -655,38 +609,6 @@ M.Jitter(2) ..() -/datum/reagent/medicine/morphine/addiction_act_stage1(mob/living/M) - if(prob(33)) - M.drop_all_held_items() - M.Jitter(2) - ..() - -/datum/reagent/medicine/morphine/addiction_act_stage2(mob/living/M) - if(prob(33)) - M.drop_all_held_items() - M.adjustToxLoss(1*REM, 0) - . = 1 - M.Dizzy(3) - M.Jitter(3) - ..() - -/datum/reagent/medicine/morphine/addiction_act_stage3(mob/living/M) - if(prob(33)) - M.drop_all_held_items() - M.adjustToxLoss(2*REM, 0) - . = 1 - M.Dizzy(4) - M.Jitter(4) - ..() - -/datum/reagent/medicine/morphine/addiction_act_stage4(mob/living/M) - if(prob(33)) - M.drop_all_held_items() - M.adjustToxLoss(3*REM, 0) - . = 1 - M.Dizzy(5) - M.Jitter(5) - ..() /datum/reagent/medicine/oculine name = "Oculine" @@ -881,6 +803,15 @@ color = "#C0C0C0" //ditto chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + +/datum/reagent/medicine/neurine/on_mob_add(mob/living/L, amount) + . = ..() + ADD_TRAIT(L, TRAIT_ANTICONVULSANT, name) + +/datum/reagent/medicine/neurine/on_mob_delete(mob/living/L) + . = ..() + REMOVE_TRAIT(L, TRAIT_ANTICONVULSANT, name) + /datum/reagent/medicine/neurine/on_mob_life(mob/living/carbon/C) if(holder.has_reagent(/datum/reagent/consumable/ethanol/neurotoxin)) holder.remove_reagent(/datum/reagent/consumable/ethanol/neurotoxin, 5) @@ -932,6 +863,8 @@ overdose_threshold = 60 ph = 8.7 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/stimulants = 4) //0.8 per 2 seconds + /datum/reagent/medicine/stimulants/on_mob_metabolize(mob/living/L) ..() @@ -1052,6 +985,7 @@ overdose_threshold = 25 ph = 11 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/hallucinogens = 14) /datum/reagent/medicine/earthsblood/on_mob_life(mob/living/carbon/M) if(current_cycle <= 25) //10u has to be processed before u get into THE FUN ZONE diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 87138b043dc..871a0c48eff 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1106,6 +1106,7 @@ penetrates_skin = NONE ph = 4 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/alcohol = 4) /datum/reagent/fuel/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume)//Splashing people with welding fuel to make them easy to ignite! . = ..() @@ -1194,6 +1195,7 @@ taste_description = "numbness" ph = 9.1 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/opiods = 10) /datum/reagent/impedrezene/on_mob_life(mob/living/carbon/M) M.jitteriness = max(M.jitteriness-5,0) @@ -1372,6 +1374,7 @@ taste_description = "sourness" ph = 1.8 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/stimulants = 14) /datum/reagent/stimulum/on_mob_metabolize(mob/living/L) ..() @@ -1711,6 +1714,7 @@ color = "#2D2D2D" taste_description = "oil" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = null /datum/reagent/stable_plasma name = "Stable Plasma" diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index cb38a8806ae..1c2fb8445e7 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -289,6 +289,7 @@ taste_description = "sourness" ph = 11 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/hallucinogens = 18) //7.2 per 2 seconds /datum/reagent/toxin/mindbreaker/on_mob_life(mob/living/carbon/M) M.hallucination += 5 @@ -597,6 +598,7 @@ metabolization_rate = 0.5 * REAGENTS_METABOLISM toxpwr = 0 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED + addiction_types = list(/datum/addiction/opiods = 25) /datum/reagent/toxin/fentanyl/on_mob_life(mob/living/carbon/M) M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3*REM, 150) @@ -728,6 +730,14 @@ toxpwr = 0 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED +/datum/reagent/medicine/sodium_thiopental/on_mob_add(mob/living/L, amount) + . = ..() + ADD_TRAIT(L, TRAIT_ANTICONVULSANT, name) + +/datum/reagent/medicine/sodium_thiopental/on_mob_delete(mob/living/L) + . = ..() + REMOVE_TRAIT(L, TRAIT_ANTICONVULSANT, name) + /datum/reagent/toxin/sodium_thiopental/on_mob_life(mob/living/carbon/M) if(current_cycle >= 10) M.Sleeping(40) diff --git a/code/modules/reagents/withdrawal/_addiction.dm b/code/modules/reagents/withdrawal/_addiction.dm new file mode 100644 index 00000000000..416fe27ead0 --- /dev/null +++ b/code/modules/reagents/withdrawal/_addiction.dm @@ -0,0 +1,123 @@ +///base class for addiction, handles when you become addicted and what the effects of that are. By default you become addicted when you hit a certain threshold, and stop being addicted once you go below another one. +/datum/addiction + ///Name of this addiction + var/name = "cringe code" + ///Higher threshold, when you start being addicted + var/addiction_gain_threshold = 600 + ///Lower threshold, when you stop being addicted + var/addiction_loss_threshold = 400 + ///Messages for each stage of addictions. + var/list/withdrawal_stage_messages = list() + ///Rates at which you lose addiction (in units/second) if you are not on the drug at that time per stage + var/addiction_loss_per_stage = list(0.5, 0.5, 1, 1.5) + ///Rate at which high sanity helps addiction loss + var/high_sanity_addiction_loss = 2 + +///Called when you gain addiction points somehow. Takes a mind as argument and sees if you gained the addiction +/datum/addiction/proc/on_gain_addiction_points(datum/mind/victim_mind) + var/current_addiction_point_amount = victim_mind.addiction_points[type] + if(current_addiction_point_amount < addiction_gain_threshold) //Not enough to become addicted + return + if(LAZYACCESS(victim_mind.active_addictions, type)) //Already addicted + return + become_addicted(victim_mind) + + +///Called when you become addicted +/datum/addiction/proc/become_addicted(datum/mind/victim_mind) + LAZYSET(victim_mind.active_addictions, type, 1) //Start at first cycle. + log_game("[key_name(victim_mind.current)] has become addicted to [name].") + + +///Called when you lose addiction poitns somehow. Takes a mind as argument and sees if you lost the addiction +/datum/addiction/proc/on_lose_addiction_points(datum/mind/victim_mind) + var/current_addiction_point_amount = victim_mind.addiction_points[type] + if(!LAZYACCESS(victim_mind.active_addictions, type)) //Not addicted + return FALSE + if(current_addiction_point_amount > addiction_loss_threshold) //Not enough to stop being addicted + return FALSE + lose_addiction(victim_mind) + return TRUE + +/datum/addiction/proc/lose_addiction(datum/mind/victim_mind) + SEND_SIGNAL(victim_mind.current, COMSIG_CLEAR_MOOD_EVENT, "[type]_addiction") + to_chat(victim_mind.current, "You feel like you've gotten over your need for drugs.") + LAZYREMOVE(victim_mind.active_addictions, type) + +/datum/addiction/proc/process_addiction(mob/living/carbon/affected_carbon, delta_time = 2) + var/current_addiction_cycle = LAZYACCESS(affected_carbon.mind.active_addictions, type) //If this is null, we're not addicted + var/on_drug_of_this_addiction = FALSE + for(var/datum/reagent/possible_drug as anything in affected_carbon.reagents.reagent_list) //Go through the drugs in our system + for(var/addiction in possible_drug.addiction_types) //And check all of their addiction types + if(addiction == type && possible_drug.volume >= MIN_ADDICTION_REAGENT_AMOUNT) //If one of them matches, and we have enough of it in our system, we're not losing addiction + if(current_addiction_cycle) + LAZYSET(affected_carbon.mind.active_addictions, type, 1) //Keeps withdrawal at first cycle. + on_drug_of_this_addiction = TRUE + return + + var/withdrawal_stage + + switch(current_addiction_cycle) + if(WITHDRAWAL_STAGE1_START_CYCLE to WITHDRAWAL_STAGE1_END_CYCLE) + withdrawal_stage = 1 + if(WITHDRAWAL_STAGE2_START_CYCLE to WITHDRAWAL_STAGE2_END_CYCLE) + withdrawal_stage = 2 + if(WITHDRAWAL_STAGE3_START_CYCLE to INFINITY) + withdrawal_stage = 3 + else + withdrawal_stage = 0 + + if(!on_drug_of_this_addiction) + if(affected_carbon.mind.remove_addiction_points(type, addiction_loss_per_stage[withdrawal_stage + 1] * delta_time)) //If true was returned, we lost the addiction! + return + + if(!current_addiction_cycle) //Dont do the effects if were not on drugs + return FALSE + + switch(current_addiction_cycle) + if(WITHDRAWAL_STAGE1_START_CYCLE) + withdrawal_enters_stage_1(affected_carbon) + if(WITHDRAWAL_STAGE2_START_CYCLE) + withdrawal_enters_stage_2(affected_carbon) + if(WITHDRAWAL_STAGE3_START_CYCLE) + withdrawal_enters_stage_3(affected_carbon) + + ///One cycle is 2 seconds + switch(withdrawal_stage) + if(1) + withdrawal_stage_1_process(affected_carbon, delta_time) + if(2) + withdrawal_stage_2_process(affected_carbon, delta_time) + if(3) + withdrawal_stage_3_process(affected_carbon, delta_time) + + LAZYADDASSOC(affected_carbon.mind.active_addictions, type, 1 * delta_time) //Next cycle! + +/// Called when addiction enters stage 1 +/datum/addiction/proc/withdrawal_enters_stage_1(mob/living/carbon/affected_carbon) + SEND_SIGNAL(affected_carbon, COMSIG_ADD_MOOD_EVENT, "[type]_addiction", /datum/mood_event/withdrawal_light, name) + +/// Called when addiction enters stage 2 +/datum/addiction/proc/withdrawal_enters_stage_2(mob/living/carbon/affected_carbon) + SEND_SIGNAL(affected_carbon, COMSIG_ADD_MOOD_EVENT, "[type]_addiction", /datum/mood_event/withdrawal_medium, name) + +/// Called when addiction enters stage 3 +/datum/addiction/proc/withdrawal_enters_stage_3(mob/living/carbon/affected_carbon) + SEND_SIGNAL(affected_carbon, COMSIG_ADD_MOOD_EVENT, "[type]_addiction", /datum/mood_event/withdrawal_severe, name) + + +/// Called when addiction is in stage 1 every process +/datum/addiction/proc/withdrawal_stage_1_process(mob/living/carbon/affected_carbon, delta_time) + if(DT_PROB(5, delta_time)) + to_chat(affected_carbon, "[withdrawal_stage_messages[1]]") + +/// Called when addiction is in stage 2 every process +/datum/addiction/proc/withdrawal_stage_2_process(mob/living/carbon/affected_carbon, delta_time) + if(DT_PROB(10, delta_time)) + to_chat(affected_carbon, "[withdrawal_stage_messages[2]]") + + +/// Called when addiction is in stage 3 every process +/datum/addiction/proc/withdrawal_stage_3_process(mob/living/carbon/affected_carbon, delta_time) + if(DT_PROB(15, delta_time)) + to_chat(affected_carbon, "[withdrawal_stage_messages[3]]") diff --git a/code/modules/reagents/withdrawal/generic_addictions.dm b/code/modules/reagents/withdrawal/generic_addictions.dm new file mode 100644 index 00000000000..b163514e0d8 --- /dev/null +++ b/code/modules/reagents/withdrawal/generic_addictions.dm @@ -0,0 +1,156 @@ +///Opiods +/datum/addiction/opiods + name = "opiod" + withdrawal_stage_messages = list("I feel aches in my bodies..", "I need some pain relief...", "It aches all over...I need some opiods!") + +/datum/addiction/opiods/withdrawal_stage_1_process(mob/living/carbon/affected_carbon, delta_time) + . = ..() + if(DT_PROB(10, delta_time)) + affected_carbon.emote("yawn") + +/datum/addiction/opiods/withdrawal_enters_stage_2(mob/living/carbon/affected_carbon) + . = ..() + affected_carbon.apply_status_effect(STATUS_EFFECT_HIGHBLOODPRESSURE) + +/datum/addiction/opiods/withdrawal_stage_3_process(mob/living/carbon/affected_carbon, delta_time) + . = ..() + if(affected_carbon.disgust < DISGUST_LEVEL_DISGUSTED && DT_PROB(7.5, delta_time)) + affected_carbon.adjust_disgust(12.5 * delta_time) + + +/datum/addiction/opiods/lose_addiction(datum/mind/victim_mind) + . = ..() + victim_mind.current.remove_status_effect(STATUS_EFFECT_HIGHBLOODPRESSURE) + +///Stimulants + +/datum/addiction/stimulants + name = "stimulant" + withdrawal_stage_messages = list("You feel a bit tired...You could really use a pick me up.", "You are getting a bit woozy...", "So...Tired...") + +/datum/addiction/stimulants/withdrawal_enters_stage_1(mob/living/carbon/affected_carbon) + . = ..() + affected_carbon.add_actionspeed_modifier(/datum/actionspeed_modifier/stimulants) + +/datum/addiction/stimulants/withdrawal_enters_stage_2(mob/living/carbon/affected_carbon) + . = ..() + affected_carbon.apply_status_effect(STATUS_EFFECT_WOOZY) + +/datum/addiction/stimulants/withdrawal_enters_stage_3(mob/living/carbon/affected_carbon) + . = ..() + affected_carbon.add_movespeed_modifier(/datum/movespeed_modifier/stimulants) + +/datum/addiction/stimulants/lose_addiction(datum/mind/victim_mind) + . = ..() + victim_mind.current.remove_actionspeed_modifier(ACTIONSPEED_ID_STIMULANTS) + victim_mind.current.remove_status_effect(STATUS_EFFECT_WOOZY) + victim_mind.current.remove_movespeed_modifier(MOVESPEED_ID_STIMULANTS) + +///Alcohol +/datum/addiction/alcohol + name = "alcohol" + withdrawal_stage_messages = list("I could use a drink...", "Maybe the bar is still open?..", "God I need a drink!") + +/datum/addiction/alcohol/withdrawal_stage_1_process(mob/living/carbon/affected_carbon, delta_time) + . = ..() + affected_carbon.Jitter(5 * delta_time) + +/datum/addiction/alcohol/withdrawal_stage_2_process(mob/living/carbon/affected_carbon, delta_time) + . = ..() + affected_carbon.Jitter(10 * delta_time) + affected_carbon.hallucination = max(5 SECONDS, affected_carbon.hallucination) + +/datum/addiction/alcohol/withdrawal_stage_3_process(mob/living/carbon/affected_carbon, delta_time) + . = ..() + affected_carbon.Jitter(15 * delta_time) + affected_carbon.hallucination = max(5 SECONDS, affected_carbon.hallucination) + if(DT_PROB(4, delta_time)) + if(!HAS_TRAIT(affected_carbon, TRAIT_ANTICONVULSANT)) + affected_carbon.apply_status_effect(STATUS_EFFECT_SEIZURE) + +/datum/addiction/hallucinogens + name = "hallucinogen" + withdrawal_stage_messages = list("I feel so empty...", "I wonder what the machine elves are up to?..", "I need to see the beautiful colors again!!") + +/datum/addiction/hallucinogens/withdrawal_enters_stage_2(mob/living/carbon/affected_carbon) + . = ..() + var/atom/movable/plane_master_controller/game_plane_master_controller = affected_carbon.hud_used.plane_master_controllers[PLANE_MASTERS_GAME] + game_plane_master_controller.add_filter("hallucinogen_wave", 10, wave_filter(300, 300, 3, 0, WAVE_SIDEWAYS)) + game_plane_master_controller.add_filter("hallucinogen_blur", 10, angular_blur_filter(0, 0, 3)) + + +/datum/addiction/hallucinogens/withdrawal_enters_stage_3(mob/living/carbon/affected_carbon) + . = ..() + affected_carbon.apply_status_effect(/datum/status_effect/trance, 40 SECONDS, TRUE) + +/datum/addiction/hallucinogens/lose_addiction(datum/mind/victim_mind) + . = ..() + var/atom/movable/plane_master_controller/game_plane_master_controller = victim_mind.current.hud_used.plane_master_controllers[PLANE_MASTERS_GAME] + game_plane_master_controller.remove_filter("hallucinogen_blur") + game_plane_master_controller.remove_filter("hallucinogen_wave") + victim_mind.current.remove_status_effect(/datum/status_effect/trance, 40 SECONDS, TRUE) + +/datum/addiction/maintenance_drugs + name = "maintenance drug" + +/datum/addiction/maintenance_drugs/withdrawal_enters_stage_1(mob/living/carbon/affected_carbon) + . = ..() + affected_carbon.hal_screwyhud = SCREWYHUD_HEALTHY + +/datum/addiction/maintenance_drugs/withdrawal_stage_1_process(mob/living/carbon/affected_carbon, delta_time) + . = ..() + if(DT_PROB(7.5, delta_time)) + affected_carbon.emote("growls") + +/datum/addiction/maintenance_drugs/withdrawal_enters_stage_2(mob/living/carbon/affected_carbon) + . = ..() + if(!ishuman(affected_carbon)) + return + var/mob/living/carbon/human/affected_human = affected_carbon + if(affected_human.gender == MALE) + to_chat(affected_human, "Your chin itches.") + affected_human.facial_hairstyle = "Beard (Full)" + affected_human.update_hair() + //Only like gross food + affected_human.dna?.species.liked_food = GROSS + affected_human.dna?.species.disliked_food = NONE + affected_human.dna?.species.toxic_food = ~GROSS + +/datum/addiction/maintenance_drugs/withdrawal_enters_stage_3(mob/living/carbon/affected_carbon) + . = ..() + if(!ishuman(affected_carbon)) + return + + var/mob/living/carbon/human/affected_human + var/obj/item/organ/eyes/eyes = affected_human.getorgan(/obj/item/organ/eyes) + + ADD_TRAIT(affected_human, TRAIT_NIGHT_VISION, type) + eyes.refresh() + +/datum/addiction/maintenance_drugs/withdrawal_stage_3_process(mob/living/carbon/affected_carbon, delta_time) + if(!ishuman(affected_carbon)) + return + var/mob/living/carbon/human/affected_human = affected_carbon + var/turf/T = get_turf(affected_human) + var/lums = T.get_lumcount() + if(lums >= 0.4) + SEND_SIGNAL(affected_human, COMSIG_ADD_MOOD_EVENT, "too_bright", /datum/mood_event/bright_light) + affected_human.dizziness = min(40, affected_human.dizziness + 3) + affected_human.set_confusion(min(affected_human.get_confusion() + (0.5 * delta_time), 20)) + else + SEND_SIGNAL(affected_carbon, COMSIG_CLEAR_MOOD_EVENT, "too_bright") + +/datum/addiction/maintenance_drugs/lose_addiction(datum/mind/victim_mind) + . = ..() + if(iscarbon(victim_mind.current)) + var/mob/living/carbon/affected_carbon = victim_mind.current + affected_carbon.hal_screwyhud = SCREWYHUD_NONE + if(!ishuman(victim_mind.current)) + return + var/mob/living/carbon/human/affected_human = victim_mind.current + affected_human.dna?.species.liked_food = initial(affected_human.dna?.species.liked_food) + affected_human.dna?.species.disliked_food = initial(affected_human.dna?.species.disliked_food) + affected_human.dna?.species.toxic_food = initial(affected_human.dna?.species.toxic_food) + REMOVE_TRAIT(affected_human, TRAIT_NIGHT_VISION, type) + var/obj/item/organ/eyes/eyes = affected_human.getorgan(/obj/item/organ/eyes) + eyes.refresh() diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index 046b333f467..ef4eeb7ee56 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -48,6 +48,24 @@ if(M.has_dna() && ishuman(M)) M.dna.species.handle_body(M) //updates eye icon +/obj/item/organ/eyes/proc/refresh() + if(ishuman(owner)) + var/mob/living/carbon/human/affected_human = owner + old_eye_color = affected_human.eye_color + if(eye_color) + affected_human.eye_color = eye_color + affected_human.regenerate_icons() + else + eye_color = affected_human.eye_color + if(HAS_TRAIT(affected_human, TRAIT_NIGHT_VISION) && !lighting_alpha) + lighting_alpha = LIGHTING_PLANE_ALPHA_NV_TRAIT + owner.update_tint() + owner.update_sight() + if(owner.has_dna() && ishuman(owner)) + var/mob/living/carbon/human/affected_human = owner + affected_human.dna.species.handle_body(affected_human) //updates eye icon + + /obj/item/organ/eyes/Remove(mob/living/carbon/M, special = 0) ..() if(ishuman(M) && eye_color) diff --git a/code/modules/unit_tests/metabolizing.dm b/code/modules/unit_tests/metabolizing.dm index 36c12693426..67c9c4e2586 100644 --- a/code/modules/unit_tests/metabolizing.dm +++ b/code/modules/unit_tests/metabolizing.dm @@ -48,6 +48,18 @@ var/mob/living/carbon/human/syringe_user = allocate(/mob/living/carbon/human) var/mob/living/carbon/human/pill_syringe_user = allocate(/mob/living/carbon/human) + var/datum/mind/pill_mind = new /datum/mind("Mothcocks") + pill_mind.active = TRUE + pill_mind.transfer_to(pill_user) + + var/datum/mind/syringe_mind = new /datum/mind("Mothcocks") + syringe_mind.active = TRUE + syringe_mind.transfer_to(syringe_user) + + var/datum/mind/pill_syringe_mind = new /datum/mind("Mothcocks") + pill_syringe_mind.active = TRUE + pill_syringe_mind.transfer_to(pill_syringe_user) + var/obj/item/reagent_containers/pill/pill = allocate(/obj/item/reagent_containers/pill) var/obj/item/reagent_containers/pill/pill_two = allocate(/obj/item/reagent_containers/pill) @@ -55,9 +67,13 @@ var/datum/reagent/drug/methamphetamine/meth = allocate(/datum/reagent/drug/methamphetamine) + var/addiction_type_to_check + + for(var/key in meth.addiction_types) + addiction_type_to_check = key //idk how to do this otherwise // Let's start with stomach metabolism - pill.reagents.add_reagent(meth.type, meth.addiction_threshold) + pill.reagents.add_reagent(meth.type, 5) pill.attack(pill_user, pill_user) // Set the metabolism efficiency to 1.0 so it transfers all reagents to the body in one go. @@ -66,26 +82,26 @@ pill_user.Life() - TEST_ASSERT(pill_user.reagents.addiction_list && is_type_in_list(meth, pill_user.reagents.addiction_list), "User is not addicted to meth after ingesting the addiction threshold") + TEST_ASSERT(pill_user.mind.addiction_points[addiction_type_to_check], "User did not gain addiction points after metabolizing meth") // Then injected metabolism - syringe.volume = meth.addiction_threshold - syringe.amount_per_transfer_from_this = meth.addiction_threshold - syringe.reagents.add_reagent(meth.type, meth.addiction_threshold) + syringe.volume = 5 + syringe.amount_per_transfer_from_this = 5 + syringe.reagents.add_reagent(meth.type, 5) syringe.melee_attack_chain(syringe_user, syringe_user) syringe_user.Life() - TEST_ASSERT(syringe_user.reagents.addiction_list && is_type_in_list(meth, syringe_user.reagents.addiction_list), "User is not addicted to meth after injecting the addiction threshold") + TEST_ASSERT(syringe_user.mind.addiction_points[addiction_type_to_check], "User did not gain addiction points after metabolizing meth") // One half syringe syringe.reagents.remove_all() - syringe.volume = meth.addiction_threshold - syringe.amount_per_transfer_from_this = meth.addiction_threshold - syringe.reagents.add_reagent(meth.type, (meth.addiction_threshold * 0.5) + 1) + syringe.volume = 5 + syringe.amount_per_transfer_from_this = 5 + syringe.reagents.add_reagent(meth.type, (5 * 0.5) + 1) // One half pill - pill_two.reagents.add_reagent(meth.type, (meth.addiction_threshold * 0.5) + 1) + pill_two.reagents.add_reagent(meth.type, (5 * 0.5) + 1) pill_two.attack(pill_syringe_user, pill_syringe_user) syringe.melee_attack_chain(pill_syringe_user, pill_syringe_user) @@ -95,7 +111,7 @@ pill_syringe_user.Life() - TEST_ASSERT(pill_syringe_user.reagents.addiction_list && is_type_in_list(meth, pill_syringe_user.reagents.addiction_list), "User is not addicted to meth after injecting and ingesting half the addiction threshold each") + TEST_ASSERT(pill_syringe_user.mind.addiction_points[addiction_type_to_check], "User did not gain addiction points after metabolizing meth") /datum/unit_test/addictions/Destroy() SSmobs.ignite() diff --git a/icons/hud/screen_alert.dmi b/icons/hud/screen_alert.dmi index ca92a6c390c..a92dc82d2f9 100755 Binary files a/icons/hud/screen_alert.dmi and b/icons/hud/screen_alert.dmi differ diff --git a/modular_skyrat/modules/aphros/chemistry/reagents/aphrodisiac_reagent.dm b/modular_skyrat/modules/aphros/chemistry/reagents/aphrodisiac_reagent.dm index 864a6003a92..669cff98c2e 100644 --- a/modular_skyrat/modules/aphros/chemistry/reagents/aphrodisiac_reagent.dm +++ b/modular_skyrat/modules/aphros/chemistry/reagents/aphrodisiac_reagent.dm @@ -5,7 +5,6 @@ description = "Naturally found in the crocus and gardenia flowers, this drug acts as a natural and safe aphrodisiac." taste_description = "strawberries" color = "#FFADFF"//PINK, rgb(255, 173, 255) - //can_synth = FALSE /datum/reagent/drug/aphrodisiac/on_mob_life(mob/living/M) if(M.client && (M.client.prefs.skyrat_toggles & APHRO_PREF)) @@ -28,9 +27,8 @@ Addiction withdrawals can cause brain damage and shortness of breath. Overdosage can lead to brain damage." taste_description = "liquid desire" color = "#FF2BFF"//dark pink - addiction_threshold = 20 + addiction_types = list(/datum/addiction/hallucinogens = 10) overdose_threshold = 20 - //can_synth = FALSE /datum/reagent/drug/aphrodisiacplus/on_mob_life(mob/living/M) if(M.client && (M.client.prefs.skyrat_toggles & APHRO_PREF)) @@ -55,20 +53,6 @@ M.update_body() ..() -/datum/reagent/drug/aphrodisiacplus/addiction_act_stage2(mob/living/M) - if(prob(30)) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2) - ..() -/datum/reagent/drug/aphrodisiacplus/addiction_act_stage3(mob/living/M) - if(prob(30)) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3) - - ..() -/datum/reagent/drug/aphrodisiacplus/addiction_act_stage4(mob/living/M) - if(prob(30)) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 4) - ..() - /datum/reagent/drug/aphrodisiacplus/overdose_process(mob/living/M) if(M.client && (M.client.prefs.skyrat_toggles & APHRO_PREF) && prob(33)) if(prob(5) && ishuman(M)/* && M.has_dna() && some shit about bimbofication*/) diff --git a/tgstation.dme b/tgstation.dme index d4714a7a21c..9cb05bf60b6 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -302,6 +302,7 @@ #include "code\controllers\configuration\entries\interview.dm" #include "code\controllers\configuration\entries\resources.dm" #include "code\controllers\subsystem\achievements.dm" +#include "code\controllers\subsystem\addiction.dm" #include "code\controllers\subsystem\adjacent_air.dm" #include "code\controllers\subsystem\air.dm" #include "code\controllers\subsystem\ambience.dm" @@ -757,6 +758,7 @@ #include "code\datums\station_traits\positive_traits.dm" #include "code\datums\status_effects\buffs.dm" #include "code\datums\status_effects\debuffs.dm" +#include "code\datums\status_effects\drug_effects.dm" #include "code\datums\status_effects\gas.dm" #include "code\datums\status_effects\neutral.dm" #include "code\datums\status_effects\status_effect.dm" @@ -1439,6 +1441,7 @@ #include "code\game\turfs\open\space\space.dm" #include "code\game\turfs\open\space\transit.dm" #include "code\modules\actionspeed\_actionspeed_modifier.dm" +#include "code\modules\actionspeed\modifiers\addiction.dm" #include "code\modules\actionspeed\modifiers\base.dm" #include "code\modules\actionspeed\modifiers\mood.dm" #include "code\modules\actionspeed\modifiers\status_effects.dm" @@ -2721,6 +2724,7 @@ #include "code\modules\modular_computers\NTNet\NTNRC\conversation.dm" #include "code\modules\movespeed\_movespeed_modifier.dm" #include "code\modules\movespeed\modifiers\components.dm" +#include "code\modules\movespeed\modifiers\drugs.dm" #include "code\modules\movespeed\modifiers\innate.dm" #include "code\modules\movespeed\modifiers\items.dm" #include "code\modules\movespeed\modifiers\misc.dm" @@ -2997,6 +3001,8 @@ #include "code\modules\reagents\reagent_containers\pill.dm" #include "code\modules\reagents\reagent_containers\spray.dm" #include "code\modules\reagents\reagent_containers\syringes.dm" +#include "code\modules\reagents\withdrawal\_addiction.dm" +#include "code\modules\reagents\withdrawal\generic_addictions.dm" #include "code\modules\recycling\conveyor2.dm" #include "code\modules\recycling\sortingmachinery.dm" #include "code\modules\recycling\disposal\bin.dm"