diff --git a/code/datums/components/traits/radiation_effects.dm b/code/datums/components/traits/radiation_effects.dm index 366dadeaf6..095cd2834d 100644 --- a/code/datums/components/traits/radiation_effects.dm +++ b/code/datums/components/traits/radiation_effects.dm @@ -3,27 +3,40 @@ * Allows for glowing, healing, contamination, and immunity. */ /datum/component/radiation_effects + + ///If we show the user the radiation panel. + var/show_panel = TRUE + ///Below this value, no glow occurs. var/radiation_glow_threshold = 50 ///If we spread radiation or not. var/contamination = FALSE + ///Strength of our contamination, if we contaminate. Each 1 strength is 100% of the rads we're dissipating. var/contamination_strength = 0.1 + ///What level our radiation has to be above to begin to contaminate our surroundings. var/contamination_threshold = 600 + ///If we can control if we glow or not + var/glow_toggle = TRUE + ///If we glow or not. var/glows = TRUE ///What color we glow. var/radiation_color = "#c3f314" + ///Intensity modifier of our glow var/intensity_mod = 1 + ///Range modifier of our glow var/range_mod = 1 + ///How much we divide our radiation by to determine how far our glow is. var/range_coefficient = 100 + ///How much we divide our radiation by to determine how intense our glow is. var/intensity_coefficient = 150 @@ -36,15 +49,38 @@ ///If we dissipate radiation or keep it. var/radiation_dissipation = TRUE + //Radiation Nutrition vars + ///If we gain nutrition from radiation. + var/radiation_nutrition = FALSE + + ///If we can toggle gaining nutrition from radiation. + var/nutrition_toggle = FALSE + + ///What is the max nutrition we can gain from radiation. + var/radiation_nutrition_cap = 1000 + + //Radiation Damage vars + ///If we do custom damage handling from radiation. + var/custom_damage = FALSE + + ///What type of damage we take from radiation. + var/damage_type = TOX + + ///How much the damage we take from rads is multiplied by. + var/damage_multiplier = 1.0 + + dupe_mode = COMPONENT_DUPE_UNIQUE dupe_type = /datum/component/radiation_effects -/datum/component/radiation_effects/Initialize(glows, radiation_glow_minor_threshold, contamination, contamination_strength, radiation_color, intensity_mod, range_mod, radiation_immunity, radiation_healing, radiation_dissipation) +/datum/component/radiation_effects/Initialize(glows, radiation_glow_minor_threshold, contamination, contamination_strength, radiation_color, intensity_mod, range_mod, radiation_immunity, radiation_healing, radiation_dissipation, radiation_nutrition, radiation_nutrition_cap, glow_toggle, nutrition_toggle) if(!isliving(parent)) return COMPONENT_INCOMPATIBLE if(glows) src.glows = glows + if(glow_toggle) + src.glow_toggle = glow_toggle if(radiation_glow_threshold) src.radiation_glow_threshold = radiation_glow_threshold if(contamination) @@ -59,12 +95,31 @@ src.range_mod = range_mod if(radiation_immunity) src.radiation_immunity = radiation_immunity + if(radiation_nutrition) + src.radiation_nutrition = radiation_nutrition + if(nutrition_toggle) + src.nutrition_toggle = nutrition_toggle + if(radiation_nutrition_cap) + src.radiation_nutrition_cap = radiation_nutrition_cap if(radiation_healing) src.radiation_healing = radiation_healing if(radiation_dissipation) src.radiation_dissipation = radiation_dissipation + if(custom_damage) + src.custom_damage = custom_damage + if(damage_type) + src.damage_type = damage_type + if(damage_multiplier) + src.damage_multiplier = damage_multiplier - add_verb(parent, /mob/living/proc/radiation_control_panel) + if(show_panel) + add_verb(parent, /mob/living/proc/radiation_control_panel) + +/datum/component/radiation_effects/Destroy(force) + if(show_panel) + remove_verb(parent, /mob/living/proc/radiation_control_panel) + + return ..() /datum/component/radiation_effects/RegisterWithParent() RegisterSignal(parent, COMSIG_HANDLE_RADIATION, PROC_REF(process_component)) @@ -122,16 +177,24 @@ if(contamination && living_guy.radiation > contamination_threshold) SSradiation.radiate(living_guy, rads * contamination_strength * rad_removal_mod) + ///Used for radiation nutrition and healing. + var/rads_to_utilize + + if(radiation_nutrition) + if(living_guy.nutrition < radiation_nutrition_cap) + rads_to_utilize = rads * rad_removal_mod + living_guy.adjust_nutrition(rads_to_utilize) + if(radiation_immunity || radiation_healing) //We have to remove radiation here since we're blocking radiation altogether. - var/rads_to_utilize = rads * rad_removal_mod + if(!rads_to_utilize) //In case we did it above. Save some CPU. + rads_to_utilize = rads * rad_removal_mod //If we heal from radiation, we will dissipate (use up) the amount we heal. if(radiation_healing) living_guy.radiation -= rads_to_utilize living_guy.accumulated_rads -= rads_to_utilize rads_to_utilize = CLAMP(rads_to_utilize, 1, 10) //Only heal up to 10 rads. - living_guy.adjust_nutrition(rads_to_utilize) living_guy.adjustBruteLoss(-rads_to_utilize) living_guy.adjustFireLoss(-rads_to_utilize) living_guy.adjustOxyLoss(-rads_to_utilize) @@ -144,6 +207,18 @@ return COMPONENT_BLOCK_LIVING_RADIATION + if(custom_damage) + if(!rads_to_utilize) //In case we did it above. Save some CPU. + rads_to_utilize = rads * rad_removal_mod + + //Special handling for halloss to prevent unfun permastuns. Only lets your halloss damage go to 90% of your maxhealth, crippling but not KOing you. + if(damage_type == HALLOSS && ((living_guy.halloss >= living_guy.maxHealth * 0.90) || (living_guy.halloss + (rads_to_utilize * damage_multiplier)) >= living_guy.maxHealth * 0.90)) + return COMPONENT_BLOCK_LIVING_RADIATION + + living_guy.apply_damage(rads_to_utilize * damage_multiplier, damage_type) + + return COMPONENT_BLOCK_LIVING_RADIATION + /datum/component/radiation_effects/proc/handle_irradiate_effect(var/mob/living/living_guy, var/effect, var/effecttype, var/blocked, var/check_protection, var/rad_protection) SIGNAL_HANDLER ///If we're not contaminating, don't worry about this. Proceed like normal. @@ -166,20 +241,8 @@ //However, we'll lose our rads faster than we accumulate. living_guy.radiation += max((radiation_to_apply * rad_protection), 0) return COMPONENT_BLOCK_IRRADIATION -/datum/component/radiation_effects/promethean - radiation_immunity = TRUE - -/datum/component/radiation_effects/shadekin - radiation_immunity = TRUE - glows = FALSE - -///Heals from radiation. Does not glow. -/datum/component/radiation_effects/diona - glows = FALSE - radiation_healing = TRUE ///TGUI below here -//TGUI Weaver Panel /datum/component/radiation_effects/tgui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) @@ -200,9 +263,15 @@ rad.tgui_interact(src) /datum/component/radiation_effects/tgui_data(mob/user) + var/mob/living/living_guy = parent var/data = list( "glowing" = glows, "radiation_color" = radiation_color, + "glowtoggle" = glow_toggle, + "radiation_nutrition" = radiation_nutrition, + "nutrition_toggle" = nutrition_toggle, + "radiation_nutrition_cap" = radiation_nutrition_cap, + "current_nutrition" = living_guy.nutrition ) return data @@ -222,8 +291,46 @@ glows = !glows to_chat(parent, span_info("You are [glows ? "now" : "no longer"] glowing.")) return FALSE + if("toggle_nutrition") + radiation_nutrition = !radiation_nutrition + to_chat(parent, span_info("You are [radiation_nutrition ? "now" : "no longer"] gaining nutrition from radiation.")) + return FALSE /mob/living/proc/get_radiation_component() var/datum/component/radiation_effects/rad = GetComponent(/datum/component/radiation_effects) if(rad) return rad + +//Subtypes + +// Promethean +/datum/component/radiation_effects/promethean + radiation_immunity = TRUE + radiation_nutrition = TRUE + +// Shadekin +/datum/component/radiation_effects/shadekin + glows = FALSE + glow_toggle = FALSE + + nutrition_toggle = TRUE + radiation_immunity = TRUE + radiation_nutrition = TRUE + +// Black Eyed Shadekin +/datum/component/radiation_effects/besk + show_panel = FALSE + glows = FALSE + glow_toggle = FALSE + custom_damage = TRUE + damage_type = HALLOSS + damage_multiplier = 0.25 + +// Diona +/datum/component/radiation_effects/diona + glows = FALSE + glow_toggle = FALSE + + nutrition_toggle = TRUE + radiation_healing = TRUE + radiation_nutrition = TRUE diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index fde983e3ff..ab54ccd1f5 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -1392,6 +1392,8 @@ BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right/crewkin) ) + species_component = list(/datum/component/radiation_effects/besk) + /datum/species/crew_shadekin/get_bodytype() return SPECIES_SHADEKIN diff --git a/code/modules/mob/living/carbon/human/species/station/traits/positive.dm b/code/modules/mob/living/carbon/human/species/station/traits/positive.dm index 31d308908b..243e60033e 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits/positive.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits/positive.dm @@ -922,6 +922,7 @@ G.radiation_color = trait_prefs["glow_color"] G.glows = trait_prefs["glow_enabled"] G.radiation_healing = TRUE + G.radiation_nutrition = TRUE /datum/trait/positive/radioactive_heal/unapply(var/datum/species/S,var/mob/living/carbon/human/H, var/list/trait_prefs) ..() //Does all the removal stuff @@ -930,3 +931,4 @@ var/datum/component/radiation_effects/G = H.GetComponent(added_component_path) if(G) G.radiation_healing = initial(G.radiation_healing) + G.radiation_nutrition = initial(G.radiation_nutrition) diff --git a/tgui/packages/tgui/interfaces/RadiationConfig.tsx b/tgui/packages/tgui/interfaces/RadiationConfig.tsx index e21d2a8cb5..e911ed2e18 100644 --- a/tgui/packages/tgui/interfaces/RadiationConfig.tsx +++ b/tgui/packages/tgui/interfaces/RadiationConfig.tsx @@ -4,50 +4,90 @@ import { Button, ColorBox, LabeledList, + NoticeBox, Section, Stack, } from 'tgui-core/components'; +import type { BooleanLike } from 'tgui-core/react'; type Data = { radiation_color: string | null; glowing: number; + glowtoggle: BooleanLike; + radiation_nutrition: BooleanLike; + radiation_nutrition_cap: number; + nutrition_toggle: BooleanLike; + current_nutrition: number; }; export const RadiationConfig = (props) => { const { act, data } = useBackend(); - const { radiation_color, glowing } = data; + const { + radiation_color, + glowing, + glowtoggle, + radiation_nutrition, + radiation_nutrition_cap, + nutrition_toggle, + current_nutrition, + } = data; + + const windowHeight = + 45 + (glowtoggle ? 100 : 0) + (nutrition_toggle ? 100 : 0); + return ( - + -
- - - - - - - - - - - - - act('toggle_glow')} - /> - - -
+ {!!glowtoggle && ( +
+ + + + + + + + + + + + + act('toggle_glow')} + /> + + +
+ )} +
+ + {!!nutrition_toggle && ( +
+ radiation_nutrition_cap}> + {`Nutrition: ${current_nutrition.toFixed()} / + ${radiation_nutrition_cap}`} + + + + act('toggle_nutrition')} + tooltip={`Gain nutrition when toggled on, up to ${radiation_nutrition_cap}.`} + /> + + +
+ )}