From 8a94c8f4648949db1cdce1adc93d3964dbc86141 Mon Sep 17 00:00:00 2001 From: Krysonism <49783092+Krysonism@users.noreply.github.com> Date: Sun, 6 Apr 2025 21:12:38 +0200 Subject: [PATCH] Punishable by death in 7 sectors! Kronkaine buff package. (#90192) ## About The Pull Request ![kronkus_complete_ultimate](https://github.com/user-attachments/assets/c3288739-bf8d-47c7-8b61-65cf2c5bdded) ### Kronkus vine buffs: Kronkus seeds are now three times as common. The Kronkus vine has a greatly increased endurance stat(10->40) so it does not die on you while you run around gathering ingredients and matures quicker (8->6) ### Kronkaine buffs: * The instant stamina boost restores **double stamina**(12 per u) when injected or smoked. * Now also restores stamina over time based on volume: **0.08 stamina per unit each cycle**. * Heart damage from kronkaine is now also dose dependant, overdose damage has been adjusted to account for this. * Reaction requires less ammonia(5->3u) and welding fuel(10->5u). * Added an alternate reaction that uses lye instead of ammonia, also takes 3u. * Added some new drug messages for when using these optimized methods of administration. * Reworked how the anti-purging mechanic works, now it only punishes you with adrenal fatigue while you take >30 stamina damage while trying to purge. This makes life saving OD treatment less annoying, but still prevents abuse mid combat in a more elegant way. The amount of heart damage inflicted is much lower if used at low doses, the same as before at 20u and greater if more than 20u is administered. The heart damage formula is : **0.1 + 0.04 * volume (+0.5 if overdosed) damage per cycle**. It should work out to something like a 27.5u lethal dose with a pristine heart. ### Kronkus extract buffs: Lasts twice as long. More heart damage per cycle 0.1 -> 0.2. This value is still pretty modest. UPDATE: I had previously buffed the stamina regen of this reagent, but now kronkaine itself has stamina regen per cycle. #### Technical changes: proc/copy_to can now trigger on_transfer and pass exposure methoid if the new copy_method parameter is set. This enables sources that use copy_to like smoke clouds to trigger INHALE dependent effects like the new kronkaine enhancement. Infinite hyposprays now also have the inject method like normal hyposprays. These two were the only two cases where reagents where reagents were added to a mob using copy_to. #### Fixes: kronkus extracts heart damage now uses seconds_per_tick. ## Why It's Good For The Game After surveying the available discussion on the subject, the kronkaine drug itself seems to be generally well received. However the rarity of the seed and the arcane preparation method has limited player engagement with the mechanic. There is confusion regarding both the preparation and, especially regarding how the stamina restoring effect works. This PR seeks to make things a little smoother and more pleasant without making a rare thing into a trivial thing,. Players seems to mostly use the action speed part of kronkaine so I have massively buffed the stamina restoration part in a flavourful way to encourage more types of players to plant the seeds should they find them. Over time more and more stuff have been added to the maintenance loot spawn lists which have diluted the spawn chance of the seed packet which contributes to the problem. This PR increases the weight from 1 -> 3. ## Changelog :cl: balance: kronkaine now restores double stamina when smoked or injected. balance: kronkaine now restores stamina each cycle, the effect is dose dependant. balance: kronkaine now causes heart damage in a dose dependant manner, instead of a flat value. balance: kronkus seed packs are now three times as common. balance: the kronkaine anti-purging disease now only triggers if you take stamina damage while using purging chems. balance: the kronkaine reaction uses less ammonia and welding fuel. add: added an alternative kronkaine reaction that uses lye instead of ammonia. balance: kronkus extract now lasts twice as long but deals a bit more heart damage(0.1->0.2) balance: the kronkus vine plant is now a lot hardier(endurance: 10 -> 40) and matures a bit quicker. tweak: kronkaine now warns the user more if it is about to kill your heart. fix: kronkus extract now inflicts heart damage correctly. /:cl: --- code/_globalvars/lists/maintenance_loot.dm | 2 +- .../fluid_spread/effects_smoke.dm | 2 +- code/game/objects/items/drug_items.dm | 2 +- code/modules/hydroponics/grown/kronkus.dm | 7 +- .../reagents/chemistry/holder/holder.dm | 6 +- .../chemistry/reagents/drug_reagents.dm | 66 +++++++++++++++---- .../chemistry/reagents/other_reagents.dm | 5 +- .../reagents/chemistry/recipes/drugs.dm | 5 +- .../reagents/reagent_containers/hypospray.dm | 2 +- 9 files changed, 73 insertions(+), 24 deletions(-) diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm index ec0b251314d..453f293ce65 100644 --- a/code/_globalvars/lists/maintenance_loot.dm +++ b/code/_globalvars/lists/maintenance_loot.dm @@ -204,7 +204,7 @@ GLOBAL_LIST_INIT(uncommon_loot, list(//uncommon: useful items /obj/item/beacon = 1, /obj/item/paper/fluff/stations/soap = 1, //recipes count as crafting. /obj/item/plaque = 1, - /obj/item/seeds/kronkus = 1, + /obj/item/seeds/kronkus = 3, /obj/item/seeds/odious_puffball = 1, /obj/item/stack/sheet/mineral/wood/fifty = 1, /obj/item/stock_parts/power_store/cell/high = 1, diff --git a/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm b/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm index 7060be966c1..3df12c427d6 100644 --- a/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm +++ b/code/game/objects/effects/effect_system/fluid_spread/effects_smoke.dm @@ -392,7 +392,7 @@ return FALSE var/fraction = (seconds_per_tick SECONDS) / initial(lifetime) - reagents.copy_to(smoker, reagents.total_volume, fraction) + reagents.copy_to(smoker, reagents.total_volume, fraction, copy_methods = INHALE) reagents.expose(smoker, INHALE, fraction) return TRUE diff --git a/code/game/objects/items/drug_items.dm b/code/game/objects/items/drug_items.dm index 7f31b155a26..2329802f579 100644 --- a/code/game/objects/items/drug_items.dm +++ b/code/game/objects/items/drug_items.dm @@ -24,7 +24,7 @@ /obj/item/food/drug/moon_rock name = "moon rock" - desc = "A small hard lump of kronkaine freebase.\nIt is said the average kronkaine addict causes as much criminal damage as four cat burglars, two arsonists and one rabid pit bull terrier combined." + desc = "A small hard lump of kronkaine freebase.\nIt is said the average kronkaine addict causes as much criminal damage as four cat burglars, two arsonists and one rabid pit bull terrier combined.\n\nNotorious in the medical community for causing dangerous interactions with purging meds!" icon_state = "moon_rock1" food_reagents = list(/datum/reagent/drug/kronkaine = 10) diff --git a/code/modules/hydroponics/grown/kronkus.dm b/code/modules/hydroponics/grown/kronkus.dm index b4ba30a5edd..419ff71d10f 100644 --- a/code/modules/hydroponics/grown/kronkus.dm +++ b/code/modules/hydroponics/grown/kronkus.dm @@ -8,10 +8,9 @@ product = /obj/item/food/grown/kronkus //shitty stats, because botany is easy lifespan = 60 - endurance = 10 - maturation = 8 + endurance = 40 + maturation = 6 production = 4 - yield = 3 growthstages = 3 growing_icon = 'icons/obj/service/hydroponics/growing.dmi' reagents_add = list(/datum/reagent/consumable/nutriment = 0.05) @@ -23,7 +22,7 @@ /obj/item/food/grown/kronkus seed = /obj/item/seeds/kronkus name = "kronkus vine segment" - desc = "A piece of mature kronkus vine. It exudes a sharp and noxious odor." + desc = "A piece of mature kronkus vine. It exudes a sharp and noxious odor.\n\nIt can be fermented to create a crude extract used by space-barge hobos to keep awake when the engine fumes creeps into their shacks.\n\nFurther processing is said to yield kronkaine, but infoteks regarding this subject are tightly controlled." icon_state = "kronkus" filling_color = "#37946e" foodtypes = VEGETABLES | TOXIC diff --git a/code/modules/reagents/chemistry/holder/holder.dm b/code/modules/reagents/chemistry/holder/holder.dm index d0a09c113bc..11483810442 100644 --- a/code/modules/reagents/chemistry/holder/holder.dm +++ b/code/modules/reagents/chemistry/holder/holder.dm @@ -538,13 +538,15 @@ * * multiplier - multiplies each reagent amount by this number well byond their available volume before transfering. used to create reagents from thin air if you ever need to * * preserve_data - preserve user data of all reagents after transfering * * no_react - if TRUE will not handle reactions + * * copy_methods - forwards reagent exposure method flags like INGEST & INHALE to reagent.on_transfer to trigger transfer effects. */ /datum/reagents/proc/copy_to( atom/target, amount = 1, multiplier = 1, preserve_data = TRUE, - no_react = FALSE + no_react = FALSE, + copy_methods ) if(QDELETED(target) || !total_volume) return @@ -578,6 +580,8 @@ if(preserve_data) trans_data = copy_data(reagent) transfered_amount = target_holder.add_reagent(reagent.type, transfer_amount, trans_data, chem_temp, reagent.purity, reagent.ph, no_react = TRUE, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT) + if(copy_methods && !no_react) + reagent.on_transfer(target, copy_methods, transfer_amount) if(!transfered_amount) continue total_transfered_amount += transfered_amount diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index d4003b8034e..b4f538842c9 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -762,6 +762,15 @@ overdose_threshold = 50 addiction_types = list(/datum/addiction/maintenance_drugs = 35) +/*Kronkaine is a rare natural stimulant that can help you instantly clear stamina damage in combat, +but it also greatly aids civilians by letting them perform everyday actions like cleaning, building, pick pocketing and even performing surgery at double speed. + +The main part of the stamina regeneration happens instantly once the reagent is added to the player and is doubled if smoked or injected. +After the initial burst of stamina, it also imparts stamina restoration per cycle. + +The instant and gradual restoration effects as well as the heart damage are dose dependant, encouraging the player to push the limit of what is safe and reeasonable! + +If you have at over 25u in your body you restore more than 20 stamina per cycle, enough to revive you from stamina crit, beware that this is a potentially fatal overdose!*/ /datum/reagent/drug/kronkaine name = "Kronkaine" description = "A highly illegal stimulant from the edge of the galaxy.\nIt is said the average kronkaine addict causes as much criminal damage as five stick up men, two rascals and one proferssional cambringo hustler combined." @@ -789,43 +798,76 @@ . = ..() kronkaine_fiend.add_actionspeed_modifier(/datum/actionspeed_modifier/kronkaine) kronkaine_fiend.sound_environment_override = SOUND_ENVIRONMENT_HANGAR + SEND_SOUND(kronkaine_fiend, sound('sound/effects/health/fastbeat.ogg', repeat = TRUE, channel = CHANNEL_HEARTBEAT, volume = 30)) /datum/reagent/drug/kronkaine/on_mob_end_metabolize(mob/living/kronkaine_fiend) . = ..() kronkaine_fiend.remove_actionspeed_modifier(/datum/actionspeed_modifier/kronkaine) kronkaine_fiend.sound_environment_override = NONE + //Stop the rapid heartneats, we make sure we are not in crit as to not mess with the heartbeats from organ/heart. + if(!kronkaine_fiend.stat) + kronkaine_fiend.stop_sound_channel(CHANNEL_HEARTBEAT) /datum/reagent/drug/kronkaine/on_transfer(atom/kronkaine_receptacle, methods, trans_volume) . = ..() if(!iscarbon(kronkaine_receptacle)) return var/mob/living/carbon/druggo = kronkaine_receptacle - if(druggo.adjustStaminaLoss(-6 * trans_volume, updating_stamina = FALSE)) + //The drug is more effective if smoked or injected, restoring more stamina per unit. + var/stamina_heal_per_unit + if(methods & (INJECT|INHALE)) + stamina_heal_per_unit = 12 + if(trans_volume >= 3) + SEND_SOUND(druggo, sound('sound/items/weapons/flash_ring.ogg')) //The efffect is often refered to as the "kronkaine bells". + to_chat(druggo, span_danger("Your ears ring as your blood pressure suddenly spikes!")) + to_chat(druggo, span_nicegreen("You feel an amazing rush!")) + else if(prob(15)) + to_chat(druggo, span_nicegreen(pick("You feel the cowardice melt away...", "You feel unbothered by the judgements of others.", "My life feels lovely!", "You lower your snout... and suddenly feel more charitable!"))) + else + stamina_heal_per_unit = 6 + if(druggo.adjustStaminaLoss(-stamina_heal_per_unit * trans_volume)) return UPDATE_MOB_HEALTH - //I wish i could give it some kind of bonus when smoked, but we don't have an INHALE method. + /datum/reagent/drug/kronkaine/on_mob_life(mob/living/carbon/kronkaine_fiend, seconds_per_tick, times_fired) . = ..() + var/need_mob_update kronkaine_fiend.add_mood_event("tweaking", /datum/mood_event/stimulant_medium) - if(kronkaine_fiend.adjustOrganLoss(ORGAN_SLOT_HEART, 0.4 * REM * seconds_per_tick, required_organ_flag = affected_organ_flags)) - . = UPDATE_MOB_HEALTH + if(kronkaine_fiend.adjustOrganLoss(ORGAN_SLOT_HEART, (0.1 + 0.04 * volume) * REM * seconds_per_tick, required_organ_flag = affected_organ_flags)) + need_mob_update = UPDATE_MOB_HEALTH + if(kronkaine_fiend.get_organ_loss(ORGAN_SLOT_HEART) >= 75 && prob(15)) + to_chat(kronkaine_fiend, span_userdanger("You feel like your heart is about to explode!")) + playsound(kronkaine_fiend, 'sound/effects/singlebeat.ogg', 200, TRUE) kronkaine_fiend.set_jitter_if_lower(20 SECONDS * REM * seconds_per_tick) kronkaine_fiend.AdjustSleeping(-2 SECONDS * REM * seconds_per_tick) kronkaine_fiend.adjust_drowsiness(-10 SECONDS * REM * seconds_per_tick) - if(volume < 10) - return - for(var/possible_purger in kronkaine_fiend.reagents.reagent_list) - if(istype(possible_purger, /datum/reagent/medicine/c2/multiver) || istype(possible_purger, /datum/reagent/medicine/haloperidol)) - kronkaine_fiend.ForceContractDisease(new /datum/disease/adrenal_crisis(), FALSE, TRUE) //We punish players for purging, since unchecked purging would allow players to reap the stamina healing benefits without any drawbacks. This also has the benefit of making haloperidol a counter, like it is supposed to be. - break + /* Do not try to cheese the overdose threshhold with purging chems to become stamina immune, if you purge and take stamina damage you will be punished! + + The reason why I choose to add the adrenal crisis anti-cheese mechanic is because the main combat benefit is so front loaded, you could easily negate all the risk and downsides by mixing it with a small amount of a purger like haloperidol. + I think that level of safety goes against the design we would like achieve with drugs; great rewards but at the cost of great risk.*/ + if(kronkaine_fiend.getStaminaLoss() > 30) + for(var/possible_purger in kronkaine_fiend.reagents.reagent_list) + if(istype(possible_purger, /datum/reagent/medicine/c2/multiver) || istype(possible_purger, /datum/reagent/medicine/haloperidol)) + if(kronkaine_fiend.HasDisease(/datum/disease/adrenal_crisis)) + break + kronkaine_fiend.visible_message(span_bolddanger("[kronkaine_fiend.name] suddenly tenses up, it looks like the shock is causing their body to shut down!"), span_userdanger("The sudden shock in combination with the cocktail of drugs and purgatives in your body makes your adrenal system go haywire. Uh oh!")) + kronkaine_fiend.ForceContractDisease(new /datum/disease/adrenal_crisis(), FALSE, TRUE) //We punish players for purging, since unchecked purging would allow players to reap the stamina healing benefits without any drawbacks. This also has the benefit of making haloperidol a counter, like it is supposed to be. + break + need_mob_update = kronkaine_fiend.adjustStaminaLoss(-0.8 * volume * REM * seconds_per_tick, updating_stamina = FALSE, required_biotype = affected_biotype) + if(need_mob_update) + return UPDATE_MOB_HEALTH /datum/reagent/drug/kronkaine/overdose_process(mob/living/kronkaine_fiend, seconds_per_tick, times_fired) . = ..() - if(kronkaine_fiend.adjustOrganLoss(ORGAN_SLOT_HEART, 1 * REM * seconds_per_tick, required_organ_flag = affected_organ_flags)) + if(kronkaine_fiend.adjustOrganLoss(ORGAN_SLOT_HEART, 0.5 * REM * seconds_per_tick, required_organ_flag = affected_organ_flags)) . = UPDATE_MOB_HEALTH kronkaine_fiend.set_jitter_if_lower(20 SECONDS * REM * seconds_per_tick) if(SPT_PROB(10, seconds_per_tick)) - to_chat(kronkaine_fiend, span_danger(pick("You feel like your heart is going to explode!", "Your ears are ringing!", "You sweat like a pig!", "You clench your jaw and grind your teeth.", "You feel prickles of pain in your chest."))) + to_chat(kronkaine_fiend, span_danger(pick("Your heart is racing!", "Your ears are ringing!", "You sweat like a pig!", "You clench your jaw and grind your teeth.", "You feel prickles of pain in your chest."))) + +/datum/reagent/drug/kronkaine/overdose_start(mob/living/affected_mob) + . = ..() + SEND_SOUND(affected_mob, sound('sound/effects/health/fastbeat.ogg', repeat = TRUE, channel = CHANNEL_HEARTBEAT, volume = 90)) ///dirty kronkaine, aka gore. far worse overdose effects. /datum/reagent/drug/kronkaine/gore diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index a9442de2ee8..e4fa0904cf6 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -3169,13 +3169,14 @@ description = "A frothy extract made from fermented kronkus vine pulp.\nHighly bitter due to the presence of a variety of kronkamines." taste_description = "bitterness" color = "#228f63" + metabolization_rate = 0.5 * REAGENTS_METABOLISM chemical_flags = REAGENT_CAN_BE_SYNTHESIZED addiction_types = list(/datum/addiction/stimulants = 5) -/datum/reagent/kronkus_extract/on_mob_life(mob/living/carbon/kronkus_enjoyer) +/datum/reagent/kronkus_extract/on_mob_life(mob/living/carbon/kronkus_enjoyer, seconds_per_tick) . = ..() var/need_mob_update - need_mob_update = kronkus_enjoyer.adjustOrganLoss(ORGAN_SLOT_HEART, 0.1) + need_mob_update = kronkus_enjoyer.adjustOrganLoss(ORGAN_SLOT_HEART, 0.2 * REM * seconds_per_tick, required_organ_flag = affected_organ_flags) need_mob_update += kronkus_enjoyer.adjustStaminaLoss(-6, updating_stamina = FALSE) if(need_mob_update) return UPDATE_MOB_HEALTH diff --git a/code/modules/reagents/chemistry/recipes/drugs.dm b/code/modules/reagents/chemistry/recipes/drugs.dm index 164e66bba90..47917ac326b 100644 --- a/code/modules/reagents/chemistry/recipes/drugs.dm +++ b/code/modules/reagents/chemistry/recipes/drugs.dm @@ -123,7 +123,7 @@ //These drug item reactions should probably be converted to fermichem in the future. /datum/chemical_reaction/moon_rock //botany is real easy so it requires a lot of kronkus_extract, make it cheaper if it doesnt get made. - required_reagents = list(/datum/reagent/kronkus_extract = 15, /datum/reagent/fuel = 10, /datum/reagent/ammonia = 5) + required_reagents = list(/datum/reagent/kronkus_extract = 15, /datum/reagent/fuel = 5, /datum/reagent/ammonia = 3) mob_react = FALSE reaction_flags = REACTION_INSTANT reaction_tags = REACTION_TAG_EASY | REACTION_TAG_DRUG | REACTION_TAG_ORGAN | REACTION_TAG_DAMAGING @@ -135,6 +135,9 @@ new_rock.pixel_x = rand(-6, 6) new_rock.pixel_y = rand(-6, 6) +/datum/chemical_reaction/moon_rock/draintek + required_reagents = list(/datum/reagent/kronkus_extract = 15, /datum/reagent/fuel = 5, /datum/reagent/lye = 3) + /datum/chemical_reaction/blastoff_ampoule required_reagents = list(/datum/reagent/silver = 10, /datum/reagent/toxin/cyanide = 10, /datum/reagent/lye = 5) mob_react = FALSE diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index a6b6ab7cf2e..d7639735ebd 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -55,7 +55,7 @@ trans = reagents.trans_to(affected_mob, amount_per_transfer_from_this, transferred_by = user, methods = INJECT) else reagents.expose(affected_mob, INJECT, fraction) - trans = reagents.copy_to(affected_mob, amount_per_transfer_from_this) + trans = reagents.copy_to(affected_mob, amount_per_transfer_from_this, copy_methods = INJECT) to_chat(user, span_notice("[trans] unit\s injected. [reagents.total_volume] unit\s remaining in [src].")) log_combat(user, affected_mob, "injected", src, "([contained])") return TRUE