diff --git a/code/__DEFINES/dcs/signals/atom/mob/living/signals_xeno.dm b/code/__DEFINES/dcs/signals/atom/mob/living/signals_xeno.dm index e6e1e64e9c7e..ab233e9cf82c 100644 --- a/code/__DEFINES/dcs/signals/atom/mob/living/signals_xeno.dm +++ b/code/__DEFINES/dcs/signals/atom/mob/living/signals_xeno.dm @@ -78,3 +78,6 @@ /// From /mob/living/carbon/xenomorph/proc/hivemind_talk(): (message) #define COMSIG_XENO_TRY_HIVEMIND_TALK "xeno_try_hivemind_talk" #define COMPONENT_OVERRIDE_HIVEMIND_TALK (1<<0) + +/// used in /datum/component/status_effect/cleanse() +#define COMSIG_XENO_DEBUFF_CLEANSE "xeno_debuff_cleanse" diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 988f82f3b73e..7b669124a2d0 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -179,6 +179,8 @@ // HIVE TRAITS /// If the Hive is a Xenonid Hive #define TRAIT_XENONID "t_xenonid" +/// if the xeno's connection to the hivemind is cut +#define TRAIT_HIVEMIND_INTERFERENCE "t_interference" /// If the hive or xeno can use objects. #define TRAIT_OPPOSABLE_THUMBS "t_thumbs" /// If the Hive delays round end (this is overridden for some hives). Does not occur naturally. Must be applied in events. @@ -355,6 +357,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_ABILITY_NO_PLASMA_TRANSFER" = TRAIT_ABILITY_NO_PLASMA_TRANSFER, "TRAIT_ABILITY_OVIPOSITOR" = TRAIT_ABILITY_OVIPOSITOR, "TRAIT_OPPOSABLE_THUMBS" = TRAIT_OPPOSABLE_THUMBS, + "TRAIT_INTERFERENCE" = TRAIT_HIVEMIND_INTERFERENCE, ), /datum/hive_status = list( "TRAIT_XENONID" = TRAIT_XENONID, @@ -434,6 +437,8 @@ GLOBAL_LIST(trait_name_map) #define TRAIT_SOURCE_TEMPORARY_MUTE "t_s_temporary_mute" ///Status trait forced by the xeno action charge #define TRAIT_SOURCE_XENO_ACTION_CHARGE "t_s_xeno_action_charge" +///Status trait coming from hivemind interference +#define TRAIT_SOURCE_HIVEMIND_INTERFERENCE "t_s_hivemind_interference" ///Status trait coming from a xeno nest #define XENO_NEST_TRAIT "xeno_nest" ///Status trait from a generic throw by xeno abilities diff --git a/code/datums/ammo/bullet/pistol.dm b/code/datums/ammo/bullet/pistol.dm index 1c014e00601f..ced951241754 100644 --- a/code/datums/ammo/bullet/pistol.dm +++ b/code/datums/ammo/bullet/pistol.dm @@ -62,7 +62,7 @@ /datum/ammo/bullet/pistol/ap/toxin/on_hit_mob(mob/M, obj/projectile/P) . = ..() - M.AddComponent(/datum/component/toxic_buildup, acid_per_hit) + M.AddComponent(/datum/component/status_effect/toxic_buildup, acid_per_hit) /datum/ammo/bullet/pistol/ap/toxin/on_hit_turf(turf/T, obj/projectile/P) . = ..() @@ -194,7 +194,7 @@ /datum/ammo/bullet/pistol/squash/toxin/on_hit_mob(mob/M, obj/projectile/P) . = ..() - M.AddComponent(/datum/component/toxic_buildup, acid_per_hit) + M.AddComponent(/datum/component/status_effect/toxic_buildup, acid_per_hit) /datum/ammo/bullet/pistol/squash/toxin/on_hit_turf(turf/T, obj/projectile/P) . = ..() diff --git a/code/datums/ammo/bullet/revolver.dm b/code/datums/ammo/bullet/revolver.dm index def0a8e31952..f9ab0b12d34e 100644 --- a/code/datums/ammo/bullet/revolver.dm +++ b/code/datums/ammo/bullet/revolver.dm @@ -47,7 +47,7 @@ /datum/ammo/bullet/revolver/marksman/toxin/on_hit_mob(mob/M, obj/projectile/P) . = ..() - M.AddComponent(/datum/component/toxic_buildup, acid_per_hit) + M.AddComponent(/datum/component/status_effect/toxic_buildup, acid_per_hit) /datum/ammo/bullet/revolver/marksman/toxin/on_hit_turf(turf/T, obj/projectile/P) . = ..() diff --git a/code/datums/ammo/bullet/rifle.dm b/code/datums/ammo/bullet/rifle.dm index 7711e082a596..e127a2ba2663 100644 --- a/code/datums/ammo/bullet/rifle.dm +++ b/code/datums/ammo/bullet/rifle.dm @@ -70,7 +70,7 @@ /datum/ammo/bullet/rifle/ap/toxin/on_hit_mob(mob/M, obj/projectile/P) . = ..() - M.AddComponent(/datum/component/toxic_buildup, acid_per_hit) + M.AddComponent(/datum/component/status_effect/toxic_buildup, acid_per_hit) /datum/ammo/bullet/rifle/ap/toxin/on_hit_turf(turf/T, obj/projectile/P) . = ..() diff --git a/code/datums/ammo/bullet/smg.dm b/code/datums/ammo/bullet/smg.dm index 3fa087972fbe..0e8983a33a87 100644 --- a/code/datums/ammo/bullet/smg.dm +++ b/code/datums/ammo/bullet/smg.dm @@ -47,7 +47,7 @@ /datum/ammo/bullet/smg/ap/toxin/on_hit_mob(mob/M, obj/projectile/P) . = ..() - M.AddComponent(/datum/component/toxic_buildup, acid_per_hit) + M.AddComponent(/datum/component/status_effect/toxic_buildup, acid_per_hit) /datum/ammo/bullet/smg/ap/toxin/on_hit_turf(turf/T, obj/projectile/P) . = ..() diff --git a/code/datums/ammo/energy.dm b/code/datums/ammo/energy.dm index 1f48806d2d52..3ddd11eedf55 100644 --- a/code/datums/ammo/energy.dm +++ b/code/datums/ammo/energy.dm @@ -229,7 +229,7 @@ if(isxeno(hit_mob)) var/mob/living/carbon/xenomorph/xeno = hit_mob xeno.apply_damage(damage * 0.75, BURN) - xeno.interference = 30 + xeno.AddComponent(/datum/component/status_effect/interference, 30, 30) /datum/ammo/energy/yautja/rifle/bolt/set_bullet_traits() . = ..() diff --git a/code/datums/components/healing_reduction.dm b/code/datums/components/healing_reduction.dm index 54ea02dc6b73..e61cbb9052a7 100644 --- a/code/datums/components/healing_reduction.dm +++ b/code/datums/components/healing_reduction.dm @@ -7,13 +7,13 @@ Healing above this strength will be reduced by the strength of the buildup. Humans will take continuous damage instead. */ -/datum/component/healing_reduction +/datum/component/status_effect/healing_reduction dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS var/healing_reduction = 0 var/healing_reduction_dissipation = AMOUNT_PER_TIME(1, 5 SECONDS) var/max_buildup = 50 //up to 50 damage off of healing max by default -/datum/component/healing_reduction/Initialize(healing_reduction, healing_reduction_dissipation = AMOUNT_PER_TIME(1, 2.5 SECONDS), max_buildup = 50) +/datum/component/status_effect/healing_reduction/Initialize(healing_reduction, healing_reduction_dissipation = AMOUNT_PER_TIME(1, 2.5 SECONDS), max_buildup = 50) if(!isxeno_human(parent)) return COMPONENT_INCOMPATIBLE . = ..() @@ -21,7 +21,7 @@ Humans will take continuous damage instead. src.healing_reduction_dissipation = healing_reduction_dissipation src.max_buildup = max_buildup -/datum/component/healing_reduction/InheritComponent(datum/component/healing_reduction/inherit_component, i_am_original, healing_reduction) +/datum/component/status_effect/healing_reduction/InheritComponent(datum/component/status_effect/healing_reduction/inherit_component, i_am_original, healing_reduction) . = ..() if(!inherit_component) src.healing_reduction += healing_reduction @@ -30,7 +30,12 @@ Humans will take continuous damage instead. src.healing_reduction = min(src.healing_reduction, max_buildup) -/datum/component/healing_reduction/process(delta_time) +/datum/component/status_effect/healing_reduction/process(delta_time) + var/atom/parent_atom = parent + if(has_immunity) + parent_atom.remove_filter("healing_reduction") + return ..() + if(!parent) qdel(src) return @@ -49,10 +54,9 @@ Humans will take continuous damage instead. var/intensity = healing_reduction/max_buildup color += num2text(MAX_ALPHA*intensity, 2, 16) - var/atom/parent_atom = parent parent_atom.add_filter("healing_reduction", 2, list("type" = "outline", "color" = color, "size" = 1)) -/datum/component/healing_reduction/RegisterWithParent() +/datum/component/status_effect/healing_reduction/RegisterWithParent() START_PROCESSING(SSdcs, src) RegisterSignal(parent, list( COMSIG_XENO_ON_HEAL, @@ -60,7 +64,7 @@ Humans will take continuous damage instead. ), PROC_REF(apply_healing_reduction)) RegisterSignal(parent, COMSIG_XENO_APPEND_TO_STAT, PROC_REF(stat_append)) -/datum/component/healing_reduction/UnregisterFromParent() +/datum/component/status_effect/healing_reduction/UnregisterFromParent() STOP_PROCESSING(SSdcs, src) UnregisterSignal(parent, list( COMSIG_XENO_ON_HEAL, @@ -70,12 +74,17 @@ Humans will take continuous damage instead. var/atom/parent_atom = parent parent_atom.remove_filter("healing_reduction") -/datum/component/healing_reduction/proc/stat_append(mob/target_mob, list/stat_list) +/datum/component/status_effect/healing_reduction/proc/stat_append(mob/target_mob, list/stat_list) SIGNAL_HANDLER + if(has_immunity) + stat_list += "Healing Reduction Immunity: [grace_period]/[initial(grace_period)]" + return stat_list += "Healing Reduction: [healing_reduction]/[max_buildup]" -/datum/component/healing_reduction/proc/apply_healing_reduction(mob/living/carbon/xenomorph/xeno, list/healing) +/datum/component/status_effect/healing_reduction/proc/apply_healing_reduction(mob/living/carbon/xenomorph/xeno, list/healing) SIGNAL_HANDLER + if(has_immunity) + return healing["healing"] -= healing_reduction #undef MAX_ALPHA diff --git a/code/datums/components/speed_modifier.dm b/code/datums/components/speed_modifier.dm index 3e96fbc56777..c19d85ffd38b 100644 --- a/code/datums/components/speed_modifier.dm +++ b/code/datums/components/speed_modifier.dm @@ -3,14 +3,14 @@ //Adjusts the speed of a xenomorph the component is on. Humans will take or heal stamina damage. -/datum/component/speed_modifier +/datum/component/status_effect/speed_modifier dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS var/speed_modifier = 0 var/speed_modifier_dissipation = AMOUNT_PER_TIME(1, 2.5 SECONDS) var/max_buildup = 10 var/increase_speed = FALSE -/datum/component/speed_modifier/Initialize(speed_modifier, increase_speed = FALSE, speed_modifier_dissipation = AMOUNT_PER_TIME(1, 2.5 SECONDS), max_buildup = 10) +/datum/component/status_effect/speed_modifier/Initialize(speed_modifier, increase_speed = FALSE, speed_modifier_dissipation = AMOUNT_PER_TIME(1, 2.5 SECONDS), max_buildup = 10) if(!isxeno_human(parent)) return COMPONENT_INCOMPATIBLE . = ..() @@ -19,7 +19,7 @@ src.max_buildup = max_buildup src.increase_speed = increase_speed -/datum/component/speed_modifier/InheritComponent(datum/component/speed_modifier/C, i_am_original, speed_modifier) +/datum/component/status_effect/speed_modifier/InheritComponent(datum/component/status_effect/speed_modifier/C, i_am_original, speed_modifier) . = ..() if(!C) src.speed_modifier += speed_modifier @@ -28,7 +28,12 @@ src.speed_modifier = min(src.speed_modifier, max_buildup) -/datum/component/speed_modifier/process(delta_time) +/datum/component/status_effect/speed_modifier/process(delta_time) + var/atom/parent_atom = parent + if(has_immunity) + parent_atom.remove_filter("speed_modifier") + return ..() + if(!parent) qdel(src) speed_modifier = max(speed_modifier - speed_modifier_dissipation * delta_time, 0) @@ -47,15 +52,14 @@ var/intensity = speed_modifier/max_buildup color += num2text(MAX_ALPHA*intensity, 2, 16) - var/atom/A = parent - A.add_filter("speed_modifier", 2, list("type" = "outline", "color" = color, "size" = 1)) + parent_atom.add_filter("speed_modifier", 2, list("type" = "outline", "color" = color, "size" = 1)) -/datum/component/speed_modifier/RegisterWithParent() +/datum/component/status_effect/speed_modifier/RegisterWithParent() START_PROCESSING(SSdcs, src) RegisterSignal(parent, COMSIG_XENO_MOVEMENT_DELAY, PROC_REF(apply_speed_modifier)) RegisterSignal(parent, COMSIG_XENO_APPEND_TO_STAT, PROC_REF(stat_append)) -/datum/component/speed_modifier/UnregisterFromParent() +/datum/component/status_effect/speed_modifier/UnregisterFromParent() STOP_PROCESSING(SSdcs, src) UnregisterSignal(parent, list( COMSIG_XENO_MOVEMENT_DELAY, @@ -64,15 +68,20 @@ var/atom/A = parent A.remove_filter("speed_modifier") -/datum/component/speed_modifier/proc/stat_append(mob/M, list/L) +/datum/component/status_effect/speed_modifier/proc/stat_append(mob/M, list/L) SIGNAL_HANDLER + if(has_immunity) + L += "Slow immunity: [grace_period]/[initial(grace_period)]" + return if(!increase_speed) L += "Slow: [speed_modifier]/[max_buildup]" else L += "Speed Boost: [speed_modifier]/[max_buildup]" -/datum/component/speed_modifier/proc/apply_speed_modifier(mob/living/carbon/xenomorph/X, list/speeds) +/datum/component/status_effect/speed_modifier/proc/apply_speed_modifier(mob/living/carbon/xenomorph/X, list/speeds) SIGNAL_HANDLER + if(has_immunity) + return if(!increase_speed) speeds["speed"] += speed_modifier * 0.075 else //increasing speed is more effective than decreasing speed diff --git a/code/datums/components/status_effect_component.dm b/code/datums/components/status_effect_component.dm new file mode 100644 index 000000000000..34c077f61935 --- /dev/null +++ b/code/datums/components/status_effect_component.dm @@ -0,0 +1,23 @@ +//exists only to handle immunities for now + +/datum/component/status_effect + var/has_immunity = FALSE + var/grace_period = 30 + +/datum/component/status_effect/InheritComponent(datum/component/C, i_am_original) + if(has_immunity) + grace_period = min(grace_period + 1, initial(grace_period)) + +/datum/component/status_effect/Initialize() + . = ..() + RegisterSignal(parent, list(COMSIG_XENO_DEBUFF_CLEANSE, COMSIG_LIVING_REJUVENATED), PROC_REF(cleanse)) + +/datum/component/status_effect/proc/cleanse() + SIGNAL_HANDLER + has_immunity = TRUE + +/datum/component/status_effect/process(delta_time) + if(has_immunity) + grace_period -= 1 * delta_time + if(grace_period <= 0) + qdel(src) diff --git a/code/datums/components/toxin_buildup.dm b/code/datums/components/toxin_buildup.dm index a30f7397e9f6..d761a4b0297e 100644 --- a/code/datums/components/toxin_buildup.dm +++ b/code/datums/components/toxin_buildup.dm @@ -1,4 +1,4 @@ -/datum/component/toxic_buildup +/datum/component/status_effect/toxic_buildup dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS var/toxic_buildup = 0 var/toxic_buildup_dissipation = AMOUNT_PER_TIME(5, 10 SECONDS) @@ -7,13 +7,14 @@ var/max_alpha = 35 var/glow_color = "#00ff00" -/datum/component/toxic_buildup/Initialize(toxic_buildup, toxic_buildup_dissipation = AMOUNT_PER_TIME(1, 3 SECONDS), max_buildup = 75) +/datum/component/status_effect/toxic_buildup/Initialize(toxic_buildup, toxic_buildup_dissipation = AMOUNT_PER_TIME(1, 3 SECONDS), max_buildup = 75) . = ..() src.toxic_buildup = toxic_buildup src.toxic_buildup_dissipation = toxic_buildup_dissipation src.max_buildup = max_buildup + to_chat(parent, SPAN_XENOHIGHDANGER("The toxic substance damages our armor!")) -/datum/component/toxic_buildup/InheritComponent(datum/component/toxic_buildup/C, i_am_original, toxic_buildup) +/datum/component/status_effect/toxic_buildup/InheritComponent(datum/component/status_effect/toxic_buildup/C, i_am_original, toxic_buildup) . = ..() if(!C) src.toxic_buildup += toxic_buildup @@ -22,7 +23,12 @@ src.toxic_buildup = min(src.toxic_buildup, max_buildup) -/datum/component/toxic_buildup/process(delta_time) +/datum/component/status_effect/toxic_buildup/process(delta_time) + var/atom/parent_atom = parent + if(has_immunity) + parent_atom.remove_filter("toxic_buildup") + return ..() + toxic_buildup = max(toxic_buildup - toxic_buildup_dissipation * delta_time, 0) if(ishuman(parent)) @@ -37,10 +43,9 @@ color += num2text(max_alpha*intensity, 2, 16) if(parent) - var/atom/A = parent - A.add_filter("toxic_buildup", 2, list("type" = "outline", "color" = color, "size" = 1)) + parent_atom.add_filter("toxic_buildup", 2, list("type" = "outline", "color" = color, "size" = 1)) -/datum/component/toxic_buildup/RegisterWithParent() +/datum/component/status_effect/toxic_buildup/RegisterWithParent() START_PROCESSING(SSdcs, src) RegisterSignal(parent, list( COMSIG_XENO_PRE_CALCULATE_ARMOURED_DAMAGE_PROJECTILE, @@ -48,7 +53,7 @@ ), PROC_REF(apply_toxic_buildup)) RegisterSignal(parent, COMSIG_XENO_APPEND_TO_STAT, PROC_REF(stat_append)) -/datum/component/toxic_buildup/UnregisterFromParent() +/datum/component/status_effect/toxic_buildup/UnregisterFromParent() STOP_PROCESSING(SSdcs, src) UnregisterSignal(parent, list( COMSIG_XENO_PRE_CALCULATE_ARMOURED_DAMAGE_PROJECTILE, @@ -58,10 +63,15 @@ var/atom/A = parent A.remove_filter("toxic_buildup") -/datum/component/toxic_buildup/proc/stat_append(mob/M, list/L) +/datum/component/status_effect/toxic_buildup/proc/stat_append(mob/M, list/L) SIGNAL_HANDLER + if(has_immunity) + L += "Toxin Buildup immunity [grace_period]/[initial(grace_period)]" + return L += "Toxin Buildup: [toxic_buildup]/[max_buildup]" -/datum/component/toxic_buildup/proc/apply_toxic_buildup(mob/living/carbon/xenomorph/X, list/damagedata) +/datum/component/status_effect/toxic_buildup/proc/apply_toxic_buildup(mob/living/carbon/xenomorph/X, list/damagedata) SIGNAL_HANDLER + if(has_immunity) + return damagedata["armor"] = max(damagedata["armor"] - toxic_buildup, 0) diff --git a/code/datums/components/xeno/hivemind_interference.dm b/code/datums/components/xeno/hivemind_interference.dm new file mode 100644 index 000000000000..9a8a0db25567 --- /dev/null +++ b/code/datums/components/xeno/hivemind_interference.dm @@ -0,0 +1,56 @@ +/datum/component/status_effect/interference + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + var/interference = 0 + var/max_buildup = 100 + var/dissipation = AMOUNT_PER_TIME(2, 2 SECONDS) + +/datum/component/status_effect/interference/Initialize(interference, max_buildup = 100, dissipation = AMOUNT_PER_TIME(2, 2 SECONDS)) + . = ..() + if(!isxeno(parent)) + return COMPONENT_INCOMPATIBLE + ADD_TRAIT(parent, TRAIT_HIVEMIND_INTERFERENCE, TRAIT_SOURCE_HIVEMIND_INTERFERENCE) + src.interference = interference + src.max_buildup = max_buildup + src.dissipation = dissipation + to_chat(parent, SPAN_XENOHIGHDANGER("Our awareness dims to a small area!")) + +/datum/component/status_effect/interference/InheritComponent(datum/component/status_effect/interference/inter, i_am_original, amount, max_buildup) + . = ..() + + src.max_buildup = max(max_buildup, src.max_buildup) //if the new component's cap is higher, use that + + if(!inter) + interference += amount + else + interference += inter.interference + + interference = min(interference, max_buildup) + +/datum/component/status_effect/interference/process(delta_time) + if(has_immunity) + return ..() + + interference = clamp(interference - dissipation * delta_time, 0, max_buildup) + + if(interference <= 0) + REMOVE_TRAIT(parent, TRAIT_HIVEMIND_INTERFERENCE, TRAIT_SOURCE_HIVEMIND_INTERFERENCE) + qdel(src) + +/datum/component/status_effect/interference/RegisterWithParent() + START_PROCESSING(SSdcs, src) + RegisterSignal(parent, COMSIG_XENO_APPEND_TO_STAT, PROC_REF(stat_append)) + +/datum/component/status_effect/interference/UnregisterFromParent() + STOP_PROCESSING(SSdcs, src) + UnregisterSignal(parent, COMSIG_XENO_APPEND_TO_STAT) + +/datum/component/status_effect/interference/proc/stat_append(mob/M, list/L) + SIGNAL_HANDLER + if(has_immunity) + L += "Hivemind Interference immunity [grace_period]/[initial(grace_period)]" + return + L += "Hivemind Interference: [interference]/[max_buildup]" + +/datum/component/status_effect/interference/cleanse() + REMOVE_TRAIT(parent, TRAIT_HIVEMIND_INTERFERENCE, TRAIT_SOURCE_HIVEMIND_INTERFERENCE) + return ..() diff --git a/code/datums/components/xeno/xeno_daze.dm b/code/datums/components/xeno/xeno_daze.dm new file mode 100644 index 000000000000..1295950ad62d --- /dev/null +++ b/code/datums/components/xeno/xeno_daze.dm @@ -0,0 +1,58 @@ +//snowflake used only for warcrime's effects + +/datum/component/status_effect/daze + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + var/daze = 0 + var/max_buildup = 20 + var/dissipation = AMOUNT_PER_TIME(2, 2 SECONDS) + +/datum/component/status_effect/daze/Initialize(daze, max_buildup = 30, dissipation = AMOUNT_PER_TIME(2, 2 SECONDS)) + . = ..() + if(!isxeno(parent)) + return COMPONENT_INCOMPATIBLE + ADD_TRAIT(parent, TRAIT_DAZED, TRAIT_STATUS_EFFECT("daze_warcrimes")) + src.daze = daze + src.max_buildup = max_buildup + src.dissipation = dissipation + to_chat(parent, SPAN_XENOHIGHDANGER("We feel weak and dazed!")) + +/datum/component/status_effect/daze/InheritComponent(datum/component/status_effect/daze/daze_new, i_am_original, amount, max_buildup) + . = ..() + + src.max_buildup = max(max_buildup, src.max_buildup) //if the new component's cap is higher, use that + + if(!daze_new) + daze += amount + else + daze += daze_new.daze + + daze = min(daze, max_buildup) + +/datum/component/status_effect/daze/process(delta_time) + if(has_immunity) + return ..() + + daze = clamp(daze - dissipation * delta_time, 0, max_buildup) + + if(daze <= 0) + REMOVE_TRAIT(parent, TRAIT_DAZED, TRAIT_STATUS_EFFECT("daze_warcrimes")) + qdel(src) + +/datum/component/status_effect/daze/RegisterWithParent() + START_PROCESSING(SSdcs, src) + RegisterSignal(parent, COMSIG_XENO_APPEND_TO_STAT, PROC_REF(stat_append)) + +/datum/component/status_effect/daze/UnregisterFromParent() + STOP_PROCESSING(SSdcs, src) + UnregisterSignal(parent, COMSIG_XENO_APPEND_TO_STAT) + +/datum/component/status_effect/daze/proc/stat_append(mob/M, list/L) + SIGNAL_HANDLER + if(has_immunity) + L += "Daze immunity [grace_period]/[initial(grace_period)]" + return + L += "Daze: [daze]/[max_buildup]" + +/datum/component/status_effect/daze/cleanse() + REMOVE_TRAIT(parent, TRAIT_DAZED, TRAIT_STATUS_EFFECT("daze_warcrimes")) + return ..() diff --git a/code/game/objects/effects/effect_system/chemsmoke.dm b/code/game/objects/effects/effect_system/chemsmoke.dm index ad86e66d5f0f..702760333ccc 100644 --- a/code/game/objects/effects/effect_system/chemsmoke.dm +++ b/code/game/objects/effects/effect_system/chemsmoke.dm @@ -8,6 +8,7 @@ time_to_live = 300 anchored = TRUE smokeranking = SMOKE_RANK_HIGH + alpha = 100 /obj/effect/particle_effect/smoke/chem/Initialize() . = ..() @@ -138,10 +139,10 @@ var/dist = cheap_pythag(T.x - location.x, T.y - location.y) if(!dist) dist = 1 - R.reaction_mob(A, volume = R.volume / dist, permeable = FALSE) + R.reaction_mob(A, volume = R.volume * POTENCY_MULTIPLIER_VLOW / dist, permeable = FALSE) else if(istype(A, /obj)) R.reaction_obj(A, R.volume) - sleep(30) + sleep(3 SECONDS) //build smoke icon @@ -199,10 +200,7 @@ smoke.pixel_x = -32 + rand(-8,8) smoke.pixel_y = -32 + rand(-8,8) walk_to(smoke, T) - smoke.set_opacity(1) //switching opacity on after the smoke has spawned, and then - sleep(150+rand(0,20)) // turning it off before it is deleted results in cleaner - if(smoke.opacity) - smoke.set_opacity(0) + sleep(150+rand(0,20)) fadeOut(smoke) qdel(smoke) @@ -259,3 +257,8 @@ targetTurfs = complete return + +/obj/effect/particle_effect/smoke/chem/affect(mob/living/carbon/M) + if(reagents.reagent_list.len) + for(var/datum/reagent/reagent in reagents.reagent_list) + reagent.reaction_mob(M, volume = reagent.volume * POTENCY_MULTIPLIER_LOW, permeable = FALSE) diff --git a/code/game/objects/effects/effect_system/smoke.dm b/code/game/objects/effects/effect_system/smoke.dm index ac0d36ead1e3..5deeff9617ca 100644 --- a/code/game/objects/effects/effect_system/smoke.dm +++ b/code/game/objects/effects/effect_system/smoke.dm @@ -295,9 +295,7 @@ var/effect_amt = floor(6 + amount*6) if(xeno_creature) - if(xeno_creature.interference < 4) - to_chat(xeno_creature, SPAN_XENOHIGHDANGER("Your awareness dims to a small area!")) - xeno_creature.interference = 10 + xeno_creature.AddComponent(/datum/component/status_effect/interference, 10, 10) xeno_creature.blinded = TRUE else creature.apply_damage(12, OXY) diff --git a/code/modules/cm_aliens/structures/fruit.dm b/code/modules/cm_aliens/structures/fruit.dm index 02fdb2da415b..f555cac64b8c 100644 --- a/code/modules/cm_aliens/structures/fruit.dm +++ b/code/modules/cm_aliens/structures/fruit.dm @@ -131,6 +131,7 @@ playsound(loc, 'sound/voice/alien_drool1.ogg', 50, 1) mature = FALSE picked = TRUE + recipient.clear_debuffs() // all froots clear debuffs icon_state = consumed_icon_state update_icon() if(!QDELETED(bound_xeno)) diff --git a/code/modules/cm_preds/yaut_items.dm b/code/modules/cm_preds/yaut_items.dm index 22e1318a7358..db0153c4d504 100644 --- a/code/modules/cm_preds/yaut_items.dm +++ b/code/modules/cm_preds/yaut_items.dm @@ -761,10 +761,10 @@ if(ishuman(C)) C.emote("pain") if(isxeno(C)) - var/mob/living/carbon/xenomorph/X = C + var/mob/living/carbon/xenomorph/xeno = C C.emote("needhelp") - X.interference = 100 // Some base interference to give pred time to get some damage in, if it cannot land a single hit during this time pred is cheeks - RegisterSignal(X, COMSIG_XENO_PRE_HEAL, PROC_REF(block_heal)) + xeno.AddComponent(/datum/component/status_effect/interference, 100) // Some base interference to give pred time to get some damage in, if it cannot land a single hit during this time pred is cheeks + RegisterSignal(xeno, COMSIG_XENO_PRE_HEAL, PROC_REF(block_heal)) message_all_yautja("A hunting trap has caught something in [get_area_name(loc)]!") /obj/item/hunting_trap/proc/block_heal(mob/living/carbon/xenomorph/xeno) diff --git a/code/modules/cm_preds/yaut_weapons.dm b/code/modules/cm_preds/yaut_weapons.dm index 2eaf9a5920e0..2db3c2ca4b68 100644 --- a/code/modules/cm_preds/yaut_weapons.dm +++ b/code/modules/cm_preds/yaut_weapons.dm @@ -166,7 +166,7 @@ . = ..() if((human_adapted || isyautja(user)) && isxeno(target)) var/mob/living/carbon/xenomorph/xenomorph = target - xenomorph.interference = 30 + xenomorph.AddComponent(/datum/component/status_effect/interference, 30, 30) /obj/item/weapon/yautja/sword name = "clan sword" @@ -190,7 +190,7 @@ . = ..() if((human_adapted || isyautja(user)) && isxeno(target)) var/mob/living/carbon/xenomorph/xenomorph = target - xenomorph.interference = 30 + xenomorph.AddComponent(/datum/component/status_effect/interference, 30, 30) /obj/item/weapon/yautja/scythe name = "dual war scythe" @@ -214,7 +214,7 @@ ..() if((human_adapted || isyautja(user)) && isxeno(target)) var/mob/living/carbon/xenomorph/xenomorph = target - xenomorph.interference = 15 + xenomorph.AddComponent(/datum/component/status_effect/interference, 15, 15) if(prob(15)) user.visible_message(SPAN_DANGER("An opening in combat presents itself!"),SPAN_DANGER("You manage to strike at your foe once more!")) @@ -438,7 +438,7 @@ return if((human_adapted || isspeciesyautja(user)) && isxeno(target)) var/mob/living/carbon/xenomorph/xenomorph = target - xenomorph.interference = 30 + xenomorph.AddComponent(/datum/component/status_effect/interference, 30, 30) if(target == user || target.stat == DEAD) to_chat(user, SPAN_DANGER("You think you're smart?")) //very funny @@ -769,7 +769,7 @@ return if((human_adapted || isyautja(user)) && isxeno(target)) var/mob/living/carbon/xenomorph/xenomorph = target - xenomorph.interference = 30 + xenomorph.AddComponent(/datum/component/status_effect/interference, 30, 30) /obj/item/weapon/twohanded/yautja/glaive/alt icon_state = "glaive_alt" diff --git a/code/modules/mob/living/carbon/xenomorph/XenoOverwatch.dm b/code/modules/mob/living/carbon/xenomorph/XenoOverwatch.dm index 0da2b61142e8..1fb48f699efa 100644 --- a/code/modules/mob/living/carbon/xenomorph/XenoOverwatch.dm +++ b/code/modules/mob/living/carbon/xenomorph/XenoOverwatch.dm @@ -89,7 +89,11 @@ to_chat(src, SPAN_XENOWARNING("We can't watch ourselves!")) return - if(targetXeno.interference) + if(HAS_TRAIT(src, TRAIT_HIVEMIND_INTERFERENCE)) + to_chat(src, SPAN_XENOWARNING("Our psychic connection is cut off!")) + return + + if(HAS_TRAIT(targetXeno, TRAIT_HIVEMIND_INTERFERENCE)) to_chat(src, SPAN_XENOWARNING("Our sister's psychic connection is cut off!")) return @@ -132,8 +136,19 @@ // Called from xeno Life() // Makes sure that Xeno overwatch is reset when the overwatched Xeno dies. /mob/living/carbon/xenomorph/proc/handle_overwatch() - if (observed_xeno && (observed_xeno.stat == DEAD || QDELETED(observed_xeno))) + if(observed_xeno) + if(observed_xeno.stat == DEAD || QDELETED(observed_xeno)) + overwatch(null, TRUE) + return + + if(HAS_TRAIT(observed_xeno, TRAIT_HIVEMIND_INTERFERENCE)) + to_chat(src, SPAN_XENOWARNING("Our sister's psychic connection is cut off!")) + overwatch(null, TRUE) + return + + if(HAS_TRAIT(src, TRAIT_HIVEMIND_INTERFERENCE)) overwatch(null, TRUE) + return /mob/living/carbon/xenomorph/proc/overwatch_handle_mob_move_or_look(mob/living/carbon/xenomorph/mover, actually_moving, direction, specific_direction) SIGNAL_HANDLER diff --git a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm index 31f49887b5b3..45edbfe7d9e3 100644 --- a/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm +++ b/code/modules/mob/living/carbon/xenomorph/XenoProcs.dm @@ -747,3 +747,16 @@ /// Handler callback to reset immobilization status after a successful [/mob/living/carbon/xenomorph/proc/throw_carbon] /mob/living/carbon/xenomorph/proc/throw_carbon_end(mob/living/carbon/target) REMOVE_TRAIT(target, TRAIT_IMMOBILIZED, XENO_THROW_TRAIT) + +/// snowflake proc to clear effects from research warcrimes +/mob/living/carbon/xenomorph/proc/clear_debuffs() + SEND_SIGNAL(src, COMSIG_XENO_DEBUFF_CLEANSE) + SetKnockOut(0) + SetStun(0) + SetKnockDown(0) + SetDaze(0) + SetSlow(0) + SetSuperslow(0) + SetRoot(0) + SetEyeBlur(0) + updatehealth() diff --git a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm index adfb65169c88..d33adcbce714 100644 --- a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm +++ b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm @@ -222,7 +222,6 @@ var/list/xeno_shields = list() // List of /datum/xeno_shield that holds all active shields on the Xeno. var/acid_splash_cooldown = 5 SECONDS //Time it takes between acid splash retaliate procs var/acid_splash_last //Last recorded time that an acid splash procced - var/interference = 0 // Stagger for predator weapons. Prevents hivemind usage, queen overwatching, etc. var/mob/living/carbon/xenomorph/observed_xeno // Overwatched xeno for xeno hivemind vision var/need_weeds = TRUE // Do we need weeds to regen HP? var/datum/behavior_delegate/behavior_delegate = null // Holds behavior delegate. Governs all 'unique' hooked behavior of the Xeno. Set by caste datums and strains. diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_powers.dm index 010f98c9c4e9..d9e342c1f7e6 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/praetorian/praetorian_powers.dm @@ -879,12 +879,7 @@ targetXeno.visible_message(SPAN_BOLDNOTICE("[X] points at [targetXeno], and it spasms as it recuperates unnaturally quickly!")) //marines probably should know if a xeno gets rejuvenated targetXeno.xeno_jitter(1 SECONDS) //it might confuse them as to why the queen got up half a second after being AT rocketed, and give them feedback on the Praetorian rejuvenating targetXeno.flick_heal_overlay(3 SECONDS, "#F5007A") //therefore making the Praetorian a priority target - targetXeno.set_effect(0, PARALYZE) - targetXeno.set_effect(0, STUN) - targetXeno.set_effect(0, WEAKEN) - targetXeno.set_effect(0, DAZE) - targetXeno.set_effect(0, SLOW) - targetXeno.set_effect(0, SUPERSLOW) + targetXeno.clear_debuffs() use_plasma = TRUE if (use_plasma) use_plasma_owner() diff --git a/code/modules/mob/living/carbon/xenomorph/life.dm b/code/modules/mob/living/carbon/xenomorph/life.dm index 1aa83065bf16..a6fd0d15877d 100644 --- a/code/modules/mob/living/carbon/xenomorph/life.dm +++ b/code/modules/mob/living/carbon/xenomorph/life.dm @@ -201,7 +201,7 @@ blinded = TRUE set_stat(UNCONSCIOUS) else - if(!interference)//If their connection to hivemind is affected, their vision should be too. + if(!HAS_TRAIT(src, TRAIT_HIVEMIND_INTERFERENCE))//If their connection to hivemind is affected, their vision should be too. blinded = FALSE set_stat(CONSCIOUS) if(regular_update && halloss > 0) @@ -215,7 +215,6 @@ src.ReduceEyeBlur(1) handle_statuses()//natural decrease of stunned, knocked_down, etc... - handle_interference() return TRUE @@ -547,15 +546,6 @@ Make sure their actual health updates immediately.*/ amount *= 2 / 3 return ..() -/mob/living/carbon/xenomorph/proc/handle_interference() - if(interference) - interference = max(interference-2, 0) - - if(observed_xeno && observed_xeno.interference) - overwatch(observed_xeno,TRUE) - - return interference - /mob/living/carbon/xenomorph/handle_slowed() if(slowed) adjust_effect(life_slow_reduction, SLOW, EFFECT_FLAG_LIFE) diff --git a/code/modules/mob/living/carbon/xenomorph/say.dm b/code/modules/mob/living/carbon/xenomorph/say.dm index c40a50ce7523..2c9404b745ef 100644 --- a/code/modules/mob/living/carbon/xenomorph/say.dm +++ b/code/modules/mob/living/carbon/xenomorph/say.dm @@ -16,10 +16,6 @@ if(stat == UNCONSCIOUS) return //Unconscious? Nope. - if(HAS_TRAIT(src, TRAIT_DAZED)) - to_chat(src, SPAN_WARNING("You are too dazed to talk.")) - return - if(copytext(message, 1, 2) == "*") if(!findtext(message, "*", 2)) //Second asterisk means it is markup for *bold*, not an *emote. return emote(lowertext(copytext(message, 2)), intentional = TRUE) @@ -94,8 +90,8 @@ //General proc for hivemind. Lame, but effective. /mob/living/carbon/xenomorph/proc/hivemind_talk(message) - if(interference) - to_chat(src, SPAN_WARNING("A headhunter temporarily cut off your psychic connection!")) + if(HAS_TRAIT(src, TRAIT_HIVEMIND_INTERFERENCE)) + to_chat(src, SPAN_WARNING("Our psychic connection has been temporarily disabled!")) return if(SEND_SIGNAL(src, COMSIG_XENO_TRY_HIVEMIND_TALK, message) & COMPONENT_OVERRIDE_HIVEMIND_TALK) diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_verbs.dm b/code/modules/mob/living/carbon/xenomorph/xeno_verbs.dm index 271b06973a6b..8a1981fe512b 100644 --- a/code/modules/mob/living/carbon/xenomorph/xeno_verbs.dm +++ b/code/modules/mob/living/carbon/xenomorph/xeno_verbs.dm @@ -11,8 +11,8 @@ to_chat(src, SPAN_WARNING("There is no Queen. We are alone.")) return - if(interference) - to_chat(src, SPAN_WARNING("A headhunter temporarily cut off our psychic connection!")) + if(HAS_TRAIT(src, TRAIT_HIVEMIND_INTERFERENCE)) + to_chat(src, SPAN_WARNING("Our psychic connection has been temporarily disabled!")) return hive.hive_ui.open_hive_status(src) @@ -36,8 +36,8 @@ to_chat(src, SPAN_WARNING("There is no Queen. You are alone.")) return - if(interference) - to_chat(src, SPAN_WARNING("A headhunter temporarily cut off your psychic connection!")) + if(HAS_TRAIT(src, TRAIT_HIVEMIND_INTERFERENCE)) + to_chat(src, SPAN_WARNING("Our psychic connection has been temporarily disabled!")) return hive.faction_ui.tgui_interact(src) diff --git a/code/modules/mob/living/living_health_procs.dm b/code/modules/mob/living/living_health_procs.dm index 15cd243d6818..ffe1a56b59f8 100644 --- a/code/modules/mob/living/living_health_procs.dm +++ b/code/modules/mob/living/living_health_procs.dm @@ -526,7 +526,7 @@ jitteriness = 0 dizziness = 0 stamina.apply_damage(-stamina.max_stamina) - + // restore all of a human's blood if(ishuman(src)) var/mob/living/carbon/human/H = src diff --git a/code/modules/projectiles/guns/flamer/flamer.dm b/code/modules/projectiles/guns/flamer/flamer.dm index b15856af1637..28bcc76c42df 100644 --- a/code/modules/projectiles/guns/flamer/flamer.dm +++ b/code/modules/projectiles/guns/flamer/flamer.dm @@ -277,7 +277,7 @@ var/datum/effect_system/smoke_spread/chem/smoke = new() smoke.set_up(to_disperse, 1, loca = turf) smoke.start() - sleep(2) + sleep(4) distance++ diff --git a/code/modules/projectiles/magazines/flamer.dm b/code/modules/projectiles/magazines/flamer.dm index bf5663cad069..feaaf7bc0a79 100644 --- a/code/modules/projectiles/magazines/flamer.dm +++ b/code/modules/projectiles/magazines/flamer.dm @@ -13,6 +13,7 @@ w_class = SIZE_MEDIUM //making sure you can't sneak this onto your belt. gun_type = /obj/item/weapon/gun/flamer caliber = "UT-Napthal Fuel" //Ultra Thick Napthal Fuel, from the lore book. + var/custom = FALSE //accepts custom fuels if true var/flamer_chem = "utnapthal" flags_magazine = AMMUNITION_HIDE_AMMO @@ -90,6 +91,10 @@ to_chat(user, SPAN_WARNING("You can't mix fuel mixtures!")) return + if(istype(to_add, /datum/reagent/generated) && !custom) + to_chat(user, SPAN_WARNING("[src] cannot accept custom fuels!")) + return + if(!to_add.intensityfire && to_add.id != "stablefoam" && !istype(src, /obj/item/ammo_magazine/flamer_tank/smoke)) to_chat(user, SPAN_WARNING("This chemical is not potent enough to be used in a flamethrower!")) return @@ -161,6 +166,7 @@ max_rounds = 100 max_range = 5 fuel_pressure = 1 + custom = TRUE /obj/item/ammo_magazine/flamer_tank/custom/verb/set_fuel_pressure() set name = "Change Fuel Pressure" @@ -242,3 +248,4 @@ desc = "A tank holding powdered smoke that expands when exposed to an open flame and carries any chemicals along with it." matter = list("metal" = 3750) flamer_chem = null + custom = TRUE diff --git a/code/modules/reagents/Chemistry-Generator.dm b/code/modules/reagents/Chemistry-Generator.dm index 0b03b621e388..f4cc32be3670 100644 --- a/code/modules/reagents/Chemistry-Generator.dm +++ b/code/modules/reagents/Chemistry-Generator.dm @@ -333,7 +333,7 @@ PROPERTY_HYPOMETABOLIC = PROPERTY_HYPERMETABOLIC, PROPERTY_HYPERTHROTTLING = PROPERTY_NEUROINHIBITING, PROPERTY_FOCUSING = PROPERTY_NERVESTIMULATING, PROPERTY_THERMOSTABILIZING = PROPERTY_HYPERTHERMIC, PROPERTY_THERMOSTABILIZING = PROPERTY_HYPOTHERMIC, PROPERTY_AIDING = PROPERTY_NEUROINHIBITING, PROPERTY_OXYGENATING = PROPERTY_HYPOXEMIC, PROPERTY_ANTICARCINOGENIC = PROPERTY_CARCINOGENIC, \ - PROPERTY_CIPHERING = PROPERTY_CIPHERING_PREDATOR, PROPERTY_TRANSFORMATIVE = PROPERTY_ANTITOXIC) + PROPERTY_CIPHERING = PROPERTY_CIPHERING_PREDATOR, PROPERTY_TRANSFORMATIVE = PROPERTY_ANTITOXIC, PROPERTY_MUSCLESTIMULATING = PROPERTY_NERVESTIMULATING) //The list below defines which properties should be combined into a combo property var/list/combining_properties = list( PROPERTY_DEFIBRILLATING = list(PROPERTY_MUSCLESTIMULATING, PROPERTY_CARDIOPEUTIC),\ PROPERTY_THANATOMETABOL = list(PROPERTY_HYPOXEMIC, PROPERTY_CRYOMETABOLIZING, PROPERTY_NEUROCRYOGENIC),\ @@ -342,7 +342,9 @@ PROPERTY_NEUROSHIELDING = list(PROPERTY_ALCOHOLIC, PROPERTY_BALDING),\ PROPERTY_ANTIADDICTIVE = list(PROPERTY_PSYCHOSTIMULATING, PROPERTY_ANTIHALLUCINOGENIC),\ PROPERTY_ADDICTIVE = list(PROPERTY_PSYCHOSTIMULATING, PROPERTY_NEUROTOXIC),\ - PROPERTY_CIPHERING_PREDATOR = list(PROPERTY_CIPHERING, PROPERTY_CROSSMETABOLIZING)) + PROPERTY_CIPHERING_PREDATOR = list(PROPERTY_CIPHERING, PROPERTY_CROSSMETABOLIZING),\ + PROPERTY_FIRE_PENETRATING = list(PROPERTY_OXYGENATING, PROPERTY_VISCOUS),\ + PROPERTY_BONEMENDING = list(PROPERTY_HYPERDENSIFICATING, PROPERTY_NUTRITIOUS)) var/datum/chem_property/match var/datum/chem_property/initial_property for(var/datum/chem_property/P in properties) diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm index 9825c12501c0..3e4fb8f300a3 100644 --- a/code/modules/reagents/Chemistry-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents.dm @@ -182,14 +182,17 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) if(potency <= 0) continue P.process(M, potency, delta_time) - if(flags & REAGENT_CANNOT_OVERDOSE) - continue if(overdose && volume > overdose) - P.process_overdose(M, potency, delta_time) - if(overdose_critical && volume > overdose_critical) - P.process_critical(M, potency, delta_time) - var/overdose_message = "[istype(src, /datum/reagent/generated) ? "custom chemical" : initial(name)] overdose" - M.last_damage_data = create_cause_data(overdose_message, last_source_mob?.resolve()) + if(flags & REAGENT_CANNOT_OVERDOSE) + var/ammount_overdosed = volume - overdose + holder.remove_reagent(id, ammount_overdosed) + holder.add_reagent("sugar", ammount_overdosed) + else + P.process_overdose(M, potency, delta_time) + if(overdose_critical && volume > overdose_critical) + P.process_critical(M, potency, delta_time) + var/overdose_message = "[istype(src, /datum/reagent/generated) ? "custom chemical" : initial(name)] overdose" + M.last_damage_data = create_cause_data(overdose_message, last_source_mob?.resolve()) if(mods[REAGENT_PURGE]) holder.remove_all_type(/datum/reagent,mods[REAGENT_PURGE] * delta_time) diff --git a/code/modules/reagents/chemistry_machinery/chem_simulator.dm b/code/modules/reagents/chemistry_machinery/chem_simulator.dm index 42576bdeccd4..3c096568e0c8 100644 --- a/code/modules/reagents/chemistry_machinery/chem_simulator.dm +++ b/code/modules/reagents/chemistry_machinery/chem_simulator.dm @@ -441,7 +441,7 @@ min_creation_cost += slots_used - 2 for(var/datum/chem_property/P in creation_template) creation_cost += max(abs(P.value), 1) * P.level - if(P.level > 5) // a penalty is added at each level above 5 (+1 at 6, +2 at 7, +4 at 8, +5 at 9, +7 at 10) + if(P.level > 5 && P.cost_penalty) // a penalty is added at each level above 5 (+1 at 6, +2 at 7, +4 at 8, +5 at 9, +7 at 10) creation_cost += P.level - 6 + ceil((P.level - 5) / 2) creation_cost += ((new_od_level - 10) / 5) * 3 //3 cost for every 5 units above 10 for(var/rarity in creation_complexity) diff --git a/code/modules/reagents/chemistry_properties/chem_property.dm b/code/modules/reagents/chemistry_properties/chem_property.dm index bf03b4a1c049..d8bf392cf2bc 100644 --- a/code/modules/reagents/chemistry_properties/chem_property.dm +++ b/code/modules/reagents/chemistry_properties/chem_property.dm @@ -12,6 +12,8 @@ var/updates_stats = FALSE //should the property change other variables in the reagent when added or removed? /// Should reagent with this property explode/start fire when mixed more than overdose threshold at once? var/volatile = FALSE + /// a cost penalty is added at each level above 5 (+1 at 6, +2 at 7, +4 at 8, +5 at 9, +7 at 10) + var/cost_penalty = TRUE /datum/chem_property/Destroy() holder = null diff --git a/code/modules/reagents/chemistry_properties/prop_negative.dm b/code/modules/reagents/chemistry_properties/prop_negative.dm index 5b196bbfc9d6..783584102182 100644 --- a/code/modules/reagents/chemistry_properties/prop_negative.dm +++ b/code/modules/reagents/chemistry_properties/prop_negative.dm @@ -84,6 +84,7 @@ rarity = PROPERTY_COMMON starter = TRUE value = 1 //has a combat use + cost_penalty = FALSE /datum/chem_property/negative/corrosive/process(mob/living/M, potency = 1, delta_time) ..() @@ -148,10 +149,9 @@ if(!M.unacidable) M.take_limb_damage(min(6, volume)) if(isxeno(M)) - var/mob/living/carbon/xenomorph/X = M + var/mob/living/carbon/xenomorph/xeno = M if(potency > POTENCY_MAX_TIER_1) //Needs level 7+ to have any effect - X.AddComponent(/datum/component/toxic_buildup, potency * volume * 0.25) - to_chat(X, SPAN_XENODANGER("The corrosive substance damages your carapace!")) + xeno.AddComponent(/datum/component/status_effect/toxic_buildup, potency * volume * 0.25) /datum/chem_property/negative/corrosive/reaction_obj(obj/O, volume, potency) if((istype(O,/obj/item) || istype(O,/obj/effect/glowshroom)) && prob(potency * 10)) @@ -243,6 +243,7 @@ description = "Ruptures endothelial cells making up bloodvessels, causing blood to escape from the circulatory system." rarity = PROPERTY_UNCOMMON value = 2 + cost_penalty = FALSE /datum/chem_property/negative/hemorrhaging/process(mob/living/M, potency = 1, delta_time) if(!ishuman(M)) @@ -278,7 +279,7 @@ L.wounds += I /datum/chem_property/negative/hemorrhaging/reaction_mob(mob/M, method = TOUCH, volume, potency) - M.AddComponent(/datum/component/healing_reduction, potency * volume * POTENCY_MULTIPLIER_VLOW) //deals brute DOT to humans, prevents healing for xenos + M.AddComponent(/datum/component/status_effect/healing_reduction, potency * volume * POTENCY_MULTIPLIER_VLOW) //deals brute DOT to humans, prevents healing for xenos /datum/chem_property/negative/carcinogenic name = PROPERTY_CARCINOGENIC @@ -411,6 +412,7 @@ description = "Breaks down neurons causing widespread damage to the central nervous system and brain functions. Exposure may cause disorientation or unconsciousness to affected persons." rarity = PROPERTY_COMMON category = PROPERTY_TYPE_TOXICANT|PROPERTY_TYPE_STIMULANT + cost_penalty = FALSE /datum/chem_property/negative/neurotoxic/process(mob/living/M, potency = 1) M.apply_damage(POTENCY_MULTIPLIER_MEDIUM * potency, BRAIN) @@ -429,10 +431,12 @@ /datum/chem_property/negative/neurotoxic/reaction_mob(mob/M, method = TOUCH, volume, potency) if(ishuman(M)) - var/mob/living/carbon/human/H = M - H.apply_damage(potency, BRAIN) - to_chat(M, SPAN_WARNING("You start to go numb.")) - M.apply_effect(potency * volume * POTENCY_MULTIPLIER_LOW, DAZE) + var/mob/living/carbon/human/human = M + human.Daze(potency * volume * POTENCY_MULTIPLIER_VLOW) + to_chat(human, SPAN_WARNING("You start to go numb.")) + if(isxeno(M)) + var/mob/living/carbon/xenomorph/xeno = M + xeno.AddComponent(/datum/component/status_effect/daze, volume * potency * POTENCY_MULTIPLIER_LOW, 30) /datum/chem_property/negative/hypermetabolic name = PROPERTY_HYPERMETABOLIC diff --git a/code/modules/reagents/chemistry_properties/prop_neutral.dm b/code/modules/reagents/chemistry_properties/prop_neutral.dm index 67120f4e2627..da0cc0c6054f 100644 --- a/code/modules/reagents/chemistry_properties/prop_neutral.dm +++ b/code/modules/reagents/chemistry_properties/prop_neutral.dm @@ -592,6 +592,7 @@ rarity = PROPERTY_RARE starter = FALSE value = 3 + cost_penalty = FALSE var/heal_amount = 0.75 /datum/chem_property/neutral/transformative/process(mob/living/M, potency = 1, delta_time) diff --git a/code/modules/reagents/chemistry_properties/prop_positive.dm b/code/modules/reagents/chemistry_properties/prop_positive.dm index a8a11fc299ad..d469daff494c 100644 --- a/code/modules/reagents/chemistry_properties/prop_positive.dm +++ b/code/modules/reagents/chemistry_properties/prop_positive.dm @@ -28,6 +28,7 @@ rarity = PROPERTY_COMMON starter = TRUE value = 1 + cost_penalty = FALSE /datum/chem_property/positive/anticorrosive/process(mob/living/M, potency = 1) M.heal_limb_damage(0, potency) @@ -47,6 +48,7 @@ rarity = PROPERTY_COMMON starter = TRUE value = 1 + cost_penalty = FALSE /datum/chem_property/positive/neogenetic/process(mob/living/M, potency = 1) M.heal_limb_damage(potency, 0) @@ -216,7 +218,7 @@ /datum/chem_property/positive/musclestimulating/reaction_mob(mob/M, method = TOUCH, volume, potency = 1) if(!isxeno_human(M)) return - M.AddComponent(/datum/component/speed_modifier, volume, TRUE, AMOUNT_PER_TIME(1, potency SECONDS), potency*volume) //Long-lasting speed for beans, stamina for humans + M.AddComponent(/datum/component/status_effect/speed_modifier, volume, TRUE, AMOUNT_PER_TIME(1, potency SECONDS), potency*volume) //Long-lasting speed for beans, stamina for humans /datum/chem_property/positive/painkilling name = PROPERTY_PAINKILLING @@ -399,7 +401,7 @@ L.time_to_knit = 600 // 6 mins if(L.time_to_knit && (L.status & LIMB_BROKEN) && L.knitting_time == -1) if(!(L.status & LIMB_SPLINTED)) - potency -= 2.5 // It'll work, but we're effectively 5 level lower. + potency -= 1 // It'll work, but we're effectively 2 levels lower. if(potency > 0) var/total_knitting_time = world.time + L.time_to_knit - min(150*potency, L.time_to_knit - 50) L.knitting_time = total_knitting_time @@ -450,6 +452,7 @@ description = "Causes a temporal freeze of all neurological processes and cellular respirations in the brain. This allows the brain to be preserved for long periods of time." rarity = PROPERTY_UNCOMMON category = PROPERTY_TYPE_REACTANT + cost_penalty = FALSE /datum/chem_property/positive/neurocryogenic/process(mob/living/M, potency = 1, delta_time) if(prob(10 * delta_time)) @@ -473,7 +476,7 @@ /datum/chem_property/positive/neurocryogenic/reaction_mob(mob/M, method = TOUCH, volume, potency = 1) if(!isxeno_human(M)) return - M.AddComponent(/datum/component/speed_modifier, potency * volume * 0.5) //Brainfreeze + M.AddComponent(/datum/component/status_effect/speed_modifier, potency * volume * 0.5) //Brainfreeze /datum/chem_property/positive/antiparasitic name = PROPERTY_ANTIPARASITIC @@ -548,6 +551,7 @@ rarity = PROPERTY_RARE category = PROPERTY_TYPE_REACTANT value = 3 + cost_penalty = FALSE COOLDOWN_DECLARE(ghost_notif) /datum/chem_property/positive/defibrillating/on_delete(mob/living/M) @@ -684,6 +688,7 @@ rarity = PROPERTY_DISABLED category = PROPERTY_TYPE_REACTANT|PROPERTY_TYPE_COMBUSTIBLE value = 2 + cost_penalty = FALSE var/intensitymod_per_level = 0 var/radiusmod_per_level = 0 @@ -777,8 +782,6 @@ rarity = PROPERTY_COMMON value = 1 range_per_level = 1 - duration_per_level = -1 - intensity_per_level = -1 intensitymod_per_level = -0.05 radiusmod_per_level = 0.05 @@ -835,6 +838,7 @@ description = "Disrupts certain neurological processes related to communication in animals." rarity = PROPERTY_UNCOMMON category = PROPERTY_TYPE_TOXICANT + cost_penalty = FALSE /datum/chem_property/positive/disrupting/process(mob/living/M, potency = 1) to_chat(M, SPAN_NOTICE("Your mind feels oddly... quiet.")) @@ -848,8 +852,8 @@ /datum/chem_property/positive/disrupting/reaction_mob(mob/M, method=TOUCH, volume, potency) if(!isxeno(M)) return - var/mob/living/carbon/xenomorph/X = M - X.interference += (volume * potency) + var/mob/living/carbon/xenomorph/xeno = M + xeno.AddComponent(/datum/component/status_effect/interference, volume * potency, 90) /datum/chem_property/positive/neutralizing name = PROPERTY_NEUTRALIZING @@ -857,6 +861,7 @@ description = "Neutralizes certain reactive chemicals and plasmas on contact. Unsafe to administer intravenously." rarity = PROPERTY_UNCOMMON category = PROPERTY_TYPE_IRRITANT + cost_penalty = FALSE /datum/chem_property/positive/neutralizing/process(mob/living/M, potency = 1) M.apply_damages(0, potency, potency * POTENCY_MULTIPLIER_LOW) @@ -873,8 +878,9 @@ var/mob/living/L = M L.ExtinguishMob() //Extinguishes mobs on contact if(isxeno(L)) - var/mob/living/carbon/xenomorph/X = M - X.plasma_stored = max(X.plasma_stored - POTENCY_MULTIPLIER_VHIGH * POTENCY_MULTIPLIER_VHIGH * potency, 0) + var/mob/living/carbon/xenomorph/xeno = M + xeno.plasma_stored = max(xeno.plasma_stored - POTENCY_MULTIPLIER_HIGH * volume * potency, 0) + to_chat(xeno, SPAN_WARNING("You feel your plasma reserves being drained!")) /datum/chem_property/positive/neutralizing/reaction_turf(turf/T, volume, potency) if(!istype(T)) @@ -992,3 +998,37 @@ /datum/chem_property/positive/anticarcinogenic/process_critical(mob/living/M, potency = 1) M.take_limb_damage(POTENCY_MULTIPLIER_MEDIUM * potency)//Hyperactive apoptosis + +/datum/chem_property/positive/regulating + name = PROPERTY_REGULATING + code = "REG" + description = "The chemical regulates its own metabolization, any amount overdosed is turned into sugar." + rarity = PROPERTY_COMMON + category = PROPERTY_TYPE_METABOLITE + max_level = 1 + value = 1 + +/datum/chem_property/positive/regulating/reset_reagent() + holder.flags = initial(holder.flags) + ..() + +/datum/chem_property/positive/regulating/update_reagent() + holder.flags |= REAGENT_CANNOT_OVERDOSE + ..() + +/datum/chem_property/positive/firepenetrating + name = PROPERTY_FIRE_PENETRATING + code = "PTR" + description = "Gives the chemical a unique, anomalous combustion chemistry, causing the flame to react with flame-resistant material and obliterate through it." + rarity = PROPERTY_RARE + category = PROPERTY_TYPE_REACTANT + value = 8 + max_level = 1 + +/datum/chem_property/positive/firepenetrating/reset_reagent() + holder.fire_penetrating = initial(holder.fire_penetrating) + ..() + +/datum/chem_property/positive/firepenetrating/update_reagent() + holder.fire_penetrating = TRUE + ..() diff --git a/code/modules/reagents/chemistry_properties/prop_special.dm b/code/modules/reagents/chemistry_properties/prop_special.dm index cee75ca58c06..d3e5e6efcf00 100644 --- a/code/modules/reagents/chemistry_properties/prop_special.dm +++ b/code/modules/reagents/chemistry_properties/prop_special.dm @@ -6,28 +6,12 @@ /datum/chem_property/special/boosting name = PROPERTY_BOOSTING code = "BST" - description = "Boosts the potency of all other properties in this chemical when inside the body." + description = "Boosts the potency of all other properties in this chemical when inside the body by 0.5 levels for every level that this property has." rarity = PROPERTY_LEGENDARY category = PROPERTY_TYPE_METABOLITE /datum/chem_property/special/boosting/pre_process(mob/living/M) - return list(REAGENT_BOOST = level) - -/datum/chem_property/special/regulating - name = PROPERTY_REGULATING - code = "REG" - description = "The chemical regulates its own metabolization and can thus never cause overdosis." - rarity = PROPERTY_LEGENDARY - category = PROPERTY_TYPE_METABOLITE - max_level = 1 - -/datum/chem_property/special/regulating/reset_reagent() - holder.flags = initial(holder.flags) - ..() - -/datum/chem_property/special/regulating/update_reagent() - holder.flags |= REAGENT_CANNOT_OVERDOSE - ..() + return list(REAGENT_BOOST = level * 0.5) /datum/chem_property/special/hypergenetic name = PROPERTY_HYPERGENETIC @@ -53,7 +37,7 @@ /datum/chem_property/special/hypergenetic/reaction_mob(mob/M, method=TOUCH, volume, potency) if(!isxeno_human(M)) return - M.AddComponent(/datum/component/healing_reduction, -potency * volume * POTENCY_MULTIPLIER_LOW) //reduces heal reduction if present + M.AddComponent(/datum/component/status_effect/healing_reduction, -potency * volume * POTENCY_MULTIPLIER_LOW) //reduces heal reduction if present if(ishuman(M)) //heals on contact with humans/xenos var/mob/living/carbon/human/H = M H.heal_limb_damage(potency * volume * POTENCY_MULTIPLIER_LOW) @@ -352,20 +336,3 @@ holder.durationfire += 1 * level holder.durationmod += 0.1 * level ..() - -/datum/chem_property/special/firepenetrating - name = PROPERTY_FIRE_PENETRATING - code = "PTR" - description = "Gives the chemical a unique, anomalous combustion chemistry, causing the flame to react with flame-resistant material and obliterate through it." - rarity = PROPERTY_LEGENDARY - category = PROPERTY_TYPE_REACTANT - value = 8 - max_level = 1 - -/datum/chem_property/special/firepenetrating/reset_reagent() - holder.fire_penetrating = initial(holder.fire_penetrating) - ..() - -/datum/chem_property/special/firepenetrating/update_reagent() - holder.fire_penetrating = TRUE - ..() diff --git a/code/modules/reagents/chemistry_reagents/other.dm b/code/modules/reagents/chemistry_reagents/other.dm index dc70d65452fe..86002a65d98f 100644 --- a/code/modules/reagents/chemistry_reagents/other.dm +++ b/code/modules/reagents/chemistry_reagents/other.dm @@ -254,7 +254,7 @@ color = "#484848" // rgb: 72, 72, 72 overdose = REAGENTS_OVERDOSE chemclass = CHEM_CLASS_BASIC - properties = list(PROPERTY_NEUROTOXIC = 4) + properties = list(PROPERTY_NEUROTOXIC = 4, PROPERTY_NEUROCRYOGENIC = 1, PROPERTY_DISRUPTING = 1) /datum/reagent/sulfur name = "Sulfur" @@ -310,7 +310,7 @@ overdose = REAGENTS_OVERDOSE overdose_critical = REAGENTS_OVERDOSE_CRITICAL chemclass = CHEM_CLASS_BASIC - properties = list(PROPERTY_TOXIC = 1) + properties = list(PROPERTY_TOXIC = 1, PROPERTY_NEUTRALIZING = 1) /datum/reagent/sodium name = "Sodium" @@ -380,7 +380,7 @@ reagent_state = SOLID color = "#C7C7C7" // rgb: 199,199,199 chemclass = CHEM_CLASS_BASIC - properties = list(PROPERTY_CARCINOGENIC = 2) + properties = list(PROPERTY_CARCINOGENIC = 2, PROPERTY_HEMORRAGING = 1) /datum/reagent/thermite name = "Thermite" diff --git a/colonialmarines.dme b/colonialmarines.dme index 82a9692c251a..e7f280cd99df 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -414,6 +414,7 @@ #include "code\datums\components\overlay_lighting.dm" #include "code\datums\components\rename.dm" #include "code\datums\components\speed_modifier.dm" +#include "code\datums\components\status_effect_component.dm" #include "code\datums\components\temporary_mute.dm" #include "code\datums\components\toxin_buildup.dm" #include "code\datums\components\tutorial_status.dm" @@ -421,7 +422,9 @@ #include "code\datums\components\weed_food.dm" #include "code\datums\components\autofire\_automated_fire.dm" #include "code\datums\components\autofire\autofire.dm" +#include "code\datums\components\xeno\hivemind_interference.dm" #include "code\datums\components\xeno\shield_slash.dm" +#include "code\datums\components\xeno\xeno_daze.dm" #include "code\datums\construction\construction_template.dm" #include "code\datums\construction\xenomorph\construction_template_xenomorph.dm" #include "code\datums\decorators\decorator.dm"