mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-30 08:37:43 +01:00
[MIRROR] Adds Roach Infusion to the DNA infuser [MDB IGNORE] (#22190)
* Adds Roach Infusion to the DNA infuser * Icons --------- Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Co-authored-by: Giz <vinylspiders@gmail.com>
This commit is contained in:
co-authored by
MrMelbert
Giz
parent
3e37d9e827
commit
fcacebfe38
@@ -267,6 +267,7 @@ GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list(
|
||||
GLOBAL_LIST_INIT(book_types, typecacheof(list(
|
||||
/obj/item/book,
|
||||
/obj/item/spellbook,
|
||||
/obj/item/infuser_book,
|
||||
)))
|
||||
|
||||
// Jobs
|
||||
|
||||
@@ -587,10 +587,14 @@
|
||||
|
||||
///Squash flags. For squashable element
|
||||
|
||||
///Whether or not the squashing requires the squashed mob to be lying down
|
||||
/// Squashing will not occur if the mob is not lying down (bodyposition is LYING_DOWN)
|
||||
#define SQUASHED_SHOULD_BE_DOWN (1<<0)
|
||||
///Whether or not to gib when the squashed mob is moved over
|
||||
#define SQUASHED_SHOULD_BE_GIBBED (1<<0)
|
||||
/// If present, outright gibs the squashed mob instead of just dealing damage
|
||||
#define SQUASHED_SHOULD_BE_GIBBED (1<<1)
|
||||
/// If squashing always passes if the mob is dead
|
||||
#define SQUASHED_ALWAYS_IF_DEAD (1<<2)
|
||||
/// Don't squash our mob if its not located in a turf
|
||||
#define SQUASHED_DONT_SQUASH_IN_CONTENTS (1<<3)
|
||||
|
||||
/*
|
||||
* Defines for "AI emotions", allowing the AI to expression emotions
|
||||
|
||||
@@ -216,9 +216,15 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_RESISTLOWPRESSURE "resist_low_pressure"
|
||||
/// This human is immune to the effects of being exploded. (ex_act)
|
||||
#define TRAIT_BOMBIMMUNE "bomb_immunity"
|
||||
/// Immune to being irradiated
|
||||
#define TRAIT_RADIMMUNE "rad_immunity"
|
||||
#define TRAIT_GENELESS "geneless"
|
||||
/// This mob won't get gibbed by nukes going off
|
||||
#define TRAIT_NUKEIMMUNE "nuke_immunity"
|
||||
/// Can't be given viruses
|
||||
#define TRAIT_VIRUSIMMUNE "virus_immunity"
|
||||
/// Reduces the chance viruses will spread to this mob, and if the mob has a virus, slows its advancement
|
||||
#define TRAIT_VIRUS_RESISTANCE "virus_resistance"
|
||||
#define TRAIT_GENELESS "geneless"
|
||||
#define TRAIT_PIERCEIMMUNE "pierce_immunity"
|
||||
#define TRAIT_NODISMEMBER "dismember_immunity"
|
||||
#define TRAIT_NOFIRE "nonflammable"
|
||||
|
||||
@@ -68,6 +68,20 @@
|
||||
//doesn't have an object argument because this is "Stacking" with the animate call above
|
||||
//3 billion% intentional
|
||||
|
||||
/// Similar to shake but more spasm-y and jerk-y
|
||||
/atom/proc/spasm_animation(loops = -1)
|
||||
var/list/transforms = list(
|
||||
matrix(transform).Translate(-1, 0),
|
||||
matrix(transform).Translate(0, 1),
|
||||
matrix(transform).Translate(1, 0),
|
||||
matrix(transform).Translate(0, -1),
|
||||
)
|
||||
|
||||
animate(src, transform = transforms[1], time = 0.2, loop = loops)
|
||||
animate(transform = transforms[2], time = 0.1)
|
||||
animate(transform = transforms[3], time = 0.2)
|
||||
animate(transform = transforms[4], time = 0.3)
|
||||
|
||||
/**
|
||||
* Shear the transform on either or both axes.
|
||||
* * x - X axis shearing
|
||||
|
||||
@@ -37,11 +37,13 @@
|
||||
return
|
||||
|
||||
var/mob/living/parent_as_living = parent
|
||||
|
||||
if(squash_flags & SQUASHED_SHOULD_BE_DOWN && parent_as_living.body_position != LYING_DOWN)
|
||||
if((squash_flags & SQUASHED_DONT_SQUASH_IN_CONTENTS) && !isturf(parent_as_living.loc))
|
||||
return
|
||||
|
||||
var/should_squash = prob(squash_chance)
|
||||
if((squash_flags & SQUASHED_SHOULD_BE_DOWN) && parent_as_living.body_position != LYING_DOWN)
|
||||
return
|
||||
|
||||
var/should_squash = ((squash_flags & SQUASHED_ALWAYS_IF_DEAD) && parent_as_living.stat == DEAD) || prob(squash_chance)
|
||||
|
||||
if(should_squash && on_squash_callback)
|
||||
if(on_squash_callback.Invoke(parent_as_living, crossing_movable))
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
if(ishuman(src))
|
||||
var/mob/living/carbon/human/infecting_human = src
|
||||
|
||||
if(infecting_human.reagents.has_reagent(/datum/reagent/medicine/spaceacillin) && prob(75))
|
||||
if(HAS_TRAIT(infecting_human, TRAIT_VIRUS_RESISTANCE) && prob(75))
|
||||
return
|
||||
|
||||
switch(target_zone)
|
||||
@@ -95,10 +95,8 @@
|
||||
disease.try_infect(src)
|
||||
|
||||
/mob/living/proc/AirborneContractDisease(datum/disease/disease, force_spread)
|
||||
if(ishuman(src))
|
||||
var/mob/living/carbon/human/infecting_human = src
|
||||
if(infecting_human.reagents.has_reagent(/datum/reagent/medicine/spaceacillin) && prob(75))
|
||||
return
|
||||
if(HAS_TRAIT(src, TRAIT_VIRUS_RESISTANCE) && prob(75))
|
||||
return
|
||||
|
||||
if(((disease.spread_flags & DISEASE_SPREAD_AIRBORNE) || force_spread) && prob((50*disease.spreading_modifier) - 1))
|
||||
ForceContractDisease(disease)
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
|
||||
///Proc to process the disease and decide on whether to advance, cure or make the sympthoms appear. Returns a boolean on whether to continue acting on the symptoms or not.
|
||||
/datum/disease/proc/stage_act(seconds_per_tick, times_fired)
|
||||
var/slowdown = affected_mob.reagents.has_reagent(/datum/reagent/medicine/spaceacillin) ? 0.5 : 1 // spaceacillin slows stage speed by 50%
|
||||
var/slowdown = HAS_TRAIT(affected_mob, TRAIT_VIRUS_RESISTANCE) ? 0.5 : 1 // spaceacillin slows stage speed by 50%
|
||||
|
||||
if(has_cure())
|
||||
if(disease_flags & CHRONIC && SPT_PROB(cure_chance, seconds_per_tick))
|
||||
@@ -104,7 +104,7 @@
|
||||
if(!(spread_flags & DISEASE_SPREAD_AIRBORNE) && !force_spread)
|
||||
return
|
||||
|
||||
if(affected_mob.reagents.has_reagent(/datum/reagent/medicine/spaceacillin) || (affected_mob.satiety > 0 && prob(affected_mob.satiety/10)))
|
||||
if(HAS_TRAIT(affected_mob, TRAIT_VIRUS_RESISTANCE) || (affected_mob.satiety > 0 && prob(affected_mob.satiety/10)))
|
||||
return
|
||||
|
||||
var/spread_range = 2
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/// Simple element to be applied to reagents
|
||||
/// When those reagents are exposed to mobs with the bug biotype, causes toxins damage
|
||||
/// If this delivers the killing blow on a non-humanoid mob, it applies a special status effect that does a funny animation
|
||||
/datum/element/bugkiller_reagent
|
||||
|
||||
/datum/element/bugkiller_reagent/Attach(datum/target)
|
||||
. = ..()
|
||||
if(!istype(target, /datum/reagent))
|
||||
return
|
||||
|
||||
RegisterSignal(target, COMSIG_REAGENT_EXPOSE_MOB, PROC_REF(on_expose))
|
||||
|
||||
/datum/element/bugkiller_reagent/Detach(datum/source, ...)
|
||||
. = ..()
|
||||
UnregisterSignal(source, COMSIG_REAGENT_EXPOSE_MOB)
|
||||
|
||||
/datum/element/bugkiller_reagent/proc/on_expose(
|
||||
datum/reagent/source,
|
||||
mob/living/exposed_mob,
|
||||
methods = TOUCH,
|
||||
reac_volume,
|
||||
show_message = TRUE,
|
||||
touch_protection = 0,
|
||||
)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(exposed_mob.stat == DEAD)
|
||||
return
|
||||
if(!(exposed_mob.mob_biotypes & MOB_BUG))
|
||||
return
|
||||
|
||||
// capping damage so splashing a beaker on a moth is not an instant crit
|
||||
var/damage = min(round(0.4 * reac_volume * (1 - touch_protection), 0.1), 12)
|
||||
if(damage < 1)
|
||||
return
|
||||
|
||||
if(!(exposed_mob.mob_biotypes & MOB_HUMANOID) && exposed_mob.health <= damage)
|
||||
// no-ops if they are already in the process of dying
|
||||
exposed_mob.apply_status_effect(/datum/status_effect/bugkiller_death)
|
||||
return
|
||||
|
||||
if(exposed_mob.apply_damage(damage, TOX) && damage >= 6)
|
||||
// yes i know it's not burn damage. the burning is on the inside.
|
||||
to_chat(exposed_mob, span_danger("You feel a burning sensation."))
|
||||
|
||||
/// If bugkiller delivers a lethal dosage, applies this effect which does a funny animation THEN kills 'em
|
||||
/// Also makes it so simplemobs / basicmobs no longer delete when they die (if they do)
|
||||
/datum/status_effect/bugkiller_death
|
||||
id = "bugkiller_death"
|
||||
alert_type = /atom/movable/screen/alert/status_effect/bugkiller_death
|
||||
/// How many times the spasm loops
|
||||
var/spasm_loops = 0
|
||||
|
||||
/datum/status_effect/bugkiller_death/on_creation(mob/living/new_other, duration = 4 SECONDS)
|
||||
src.duration = duration
|
||||
src.spasm_loops = ROUND_UP(duration / 0.8) // one spasm ~= 0.8 deciseconds (yes deciseconds)
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/bugkiller_death/on_apply()
|
||||
if(owner.stat == DEAD)
|
||||
return FALSE
|
||||
playsound(owner, 'sound/voice/human/malescream_1.ogg', 25, TRUE, extrarange = SILENCED_SOUND_EXTRARANGE, frequency = 5)
|
||||
to_chat(owner, span_userdanger("The world begins to go dark..."))
|
||||
owner.spasm_animation(spasm_loops)
|
||||
owner.adjust_eye_blur(duration)
|
||||
return TRUE
|
||||
|
||||
/datum/status_effect/bugkiller_death/on_remove()
|
||||
if(owner.stat == DEAD || QDELETED(owner))
|
||||
return
|
||||
|
||||
if(isbasicmob(owner))
|
||||
var/mob/living/basic/basic_owner = owner
|
||||
basic_owner.basic_mob_flags &= ~DEL_ON_DEATH
|
||||
basic_owner.basic_mob_flags |= FLIP_ON_DEATH
|
||||
|
||||
if(isanimal(owner))
|
||||
var/mob/living/simple_animal/simple_owner = owner
|
||||
simple_owner.del_on_death = FALSE
|
||||
simple_owner.flip_on_death = TRUE
|
||||
|
||||
owner.investigate_log("died to being sprayed with bugkiller.", INVESTIGATE_DEATHS)
|
||||
owner.death()
|
||||
|
||||
/atom/movable/screen/alert/status_effect/bugkiller_death
|
||||
name = "Overwhelming Toxicity"
|
||||
desc = "Don't go into the light!"
|
||||
icon_state = "paralysis"
|
||||
@@ -1,4 +1,18 @@
|
||||
{
|
||||
"appendix": [
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "appendix",
|
||||
"blend_mode": "overlay",
|
||||
"color_ids": [ 1 ]
|
||||
},
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "appendix_insides",
|
||||
"blend_mode": "overlay",
|
||||
"color_ids": [ 2 ]
|
||||
}
|
||||
],
|
||||
"brain": [
|
||||
{
|
||||
"type": "icon_state",
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
return
|
||||
|
||||
if(victim.reagents)
|
||||
if(victim.reagents.has_reagent(/datum/reagent/medicine/spaceacillin))
|
||||
if(HAS_TRAIT(victim, TRAIT_VIRUS_RESISTANCE))
|
||||
sanitization += 0.9
|
||||
if(victim.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine/))
|
||||
sanitization += 0.9
|
||||
|
||||
@@ -136,6 +136,7 @@
|
||||
new_organ = new new_organ()
|
||||
new_organ.replace_into(target)
|
||||
check_tier_progression(target)
|
||||
return TRUE
|
||||
|
||||
/// Picks a random mutated organ from the infuser entry which is also compatible with the target mob.
|
||||
/// Tries to return a typepath of a valid mutant organ if all of the following criteria are true:
|
||||
|
||||
@@ -8,12 +8,22 @@
|
||||
throw_speed = 2
|
||||
throw_range = 5
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
drop_sound = 'sound/items/handling/book_drop.ogg'
|
||||
pickup_sound = 'sound/items/handling/book_pickup.ogg'
|
||||
|
||||
/obj/item/infuser_book/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "InfuserBook")
|
||||
ui.open()
|
||||
playsound(src, SFX_PAGE_TURN, 30, TRUE)
|
||||
|
||||
/obj/item/infuser_book/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(action == "play_flip_sound")
|
||||
playsound(src, SFX_PAGE_TURN, 30, TRUE)
|
||||
|
||||
/obj/item/infuser_book/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
@@ -75,3 +75,33 @@
|
||||
infusion_desc = "skittish"
|
||||
tier = DNA_MUTANT_TIER_ONE
|
||||
status_effect_type = /datum/status_effect/organ_set_bonus/rat
|
||||
|
||||
/datum/infuser_entry/roach
|
||||
name = "Roach"
|
||||
infuse_mob_name = "cockroach"
|
||||
desc = "It seems as if you're a fan of ancient literature by your interest in this. Assuredly, merging cockroach DNA into your genome \
|
||||
will not cause you to become incapable of leaving your bed. These creatures are incredibly resilient against many things \
|
||||
humans are weak to, and we can use that! Who wouldn't like to survive a nuclear blast? \
|
||||
NOTE: Squished roaches will not work for the infuser, if that wasn't obvious. Try spraying them with some pestkiller from botany!"
|
||||
threshold_desc = "you will no longer be gibbed by explosions, and gain incredible resistance to viruses and radiation."
|
||||
qualities = list(
|
||||
"resilience to attacks from behind",
|
||||
"healthier organs",
|
||||
"get over disgust very quickly",
|
||||
"the ability to survive a nuclear apocalypse",
|
||||
"harder to pick yourself up from falling over",
|
||||
"avoid toxins at all costs",
|
||||
"always down to find a snack",
|
||||
)
|
||||
input_obj_or_mob = list(
|
||||
/mob/living/basic/cockroach,
|
||||
)
|
||||
output_organs = list(
|
||||
/obj/item/organ/internal/heart/roach,
|
||||
/obj/item/organ/internal/stomach/roach,
|
||||
/obj/item/organ/internal/liver/roach,
|
||||
/obj/item/organ/internal/appendix/roach,
|
||||
)
|
||||
infusion_desc = "kafkaesque" // Gregor Samsa !!
|
||||
tier = DNA_MUTANT_TIER_ONE
|
||||
status_effect_type = /datum/status_effect/organ_set_bonus/roach
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
#define ROACH_ORGAN_COLOR "#7c4200"
|
||||
// Yeah i'm lazy and we don't use any of the other color slots
|
||||
#define ROACH_COLORS ROACH_ORGAN_COLOR + ROACH_ORGAN_COLOR + ROACH_ORGAN_COLOR
|
||||
|
||||
/datum/armor/roach_internal_armor
|
||||
bomb = 100
|
||||
bio = 90
|
||||
|
||||
/datum/status_effect/organ_set_bonus/roach
|
||||
id = "organ_set_bonus_roach"
|
||||
organs_needed = 4
|
||||
bonus_activate_text = span_notice("Roach DNA is deeply infused with you! \
|
||||
You feel increasingly resistant to explosives, radiation, and viral agents.")
|
||||
bonus_deactivate_text = span_notice("You are no longer majority roach, \
|
||||
and you feel much more vulnerable to nuclear apocalypses.")
|
||||
// - Immunity to nuke gibs
|
||||
// - Nukes come with radiation (not actually but yknow)
|
||||
bonus_traits = list(TRAIT_NUKEIMMUNE, TRAIT_RADIMMUNE, TRAIT_VIRUS_RESISTANCE)
|
||||
/// Armor type attached to the owner's physiology
|
||||
var/datum/armor/given_armor = /datum/armor/roach_internal_armor
|
||||
/// Storing biotypes pre-organ bonus applied so we don't remove bug from mobs which should have it.
|
||||
var/old_biotypes = NONE
|
||||
|
||||
/datum/status_effect/organ_set_bonus/roach/enable_bonus()
|
||||
. = ..()
|
||||
if(!ishuman(owner))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/human_owner = owner
|
||||
human_owner.physiology.armor = human_owner.physiology.armor.add_other_armor(given_armor)
|
||||
|
||||
old_biotypes = human_owner.mob_biotypes
|
||||
human_owner.mob_biotypes |= MOB_BUG
|
||||
|
||||
/datum/status_effect/organ_set_bonus/roach/disable_bonus()
|
||||
. = ..()
|
||||
if(!ishuman(owner) || QDELETED(owner))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/human_owner = owner
|
||||
human_owner.physiology.armor = human_owner.physiology.armor.subtract_other_armor(given_armor)
|
||||
|
||||
if(!(old_biotypes & MOB_BUG)) // only remove bug if it wasn't there before
|
||||
human_owner.mob_biotypes &= ~MOB_BUG
|
||||
|
||||
/// Roach heart:
|
||||
/// Reduces damage taken from brute attacks from behind,
|
||||
/// but increases duration of knockdowns
|
||||
/obj/item/organ/internal/heart/roach
|
||||
name = "mutated roach-heart"
|
||||
desc = "Roach DNA infused into what was once a normal heart."
|
||||
maxHealth = 2 * STANDARD_ORGAN_THRESHOLD
|
||||
|
||||
icon = 'icons/obj/medical/organs/infuser_organs.dmi'
|
||||
icon_state = "heart"
|
||||
greyscale_config = /datum/greyscale_config/mutant_organ
|
||||
greyscale_colors = ROACH_COLORS
|
||||
|
||||
/// Timer ID for resetting the damage resistance applied from attacks from behind
|
||||
var/defense_timerid
|
||||
/// Bodypart overlay applied to the chest the heart is in
|
||||
var/datum/bodypart_overlay/simple/roach_shell/roach_shell
|
||||
|
||||
/obj/item/organ/internal/heart/roach/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/noticable_organ, "has hardened, somewhat translucent skin.")
|
||||
AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/roach)
|
||||
roach_shell = new()
|
||||
|
||||
/obj/item/organ/internal/heart/roach/Destroy()
|
||||
QDEL_NULL(roach_shell)
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/internal/heart/roach/on_insert(mob/living/carbon/organ_owner, special)
|
||||
. = ..()
|
||||
if(!ishuman(organ_owner))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/human_owner = organ_owner
|
||||
|
||||
RegisterSignal(human_owner, COMSIG_MOB_APPLY_DAMAGE, PROC_REF(modify_damage))
|
||||
human_owner.physiology.knockdown_mod *= 3
|
||||
|
||||
var/obj/item/bodypart/chest/chest = human_owner.get_bodypart(BODY_ZONE_CHEST)
|
||||
chest.add_bodypart_overlay(roach_shell)
|
||||
human_owner.update_body_parts()
|
||||
|
||||
/obj/item/organ/internal/heart/roach/on_remove(mob/living/carbon/organ_owner, special)
|
||||
. = ..()
|
||||
if(!ishuman(organ_owner) || QDELETED(organ_owner))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/human_owner = organ_owner
|
||||
|
||||
UnregisterSignal(human_owner, COMSIG_MOB_APPLY_DAMAGE)
|
||||
human_owner.physiology.knockdown_mod /= 3
|
||||
|
||||
if(defense_timerid)
|
||||
reset_damage(human_owner)
|
||||
|
||||
var/obj/item/bodypart/chest/chest = human_owner.get_bodypart(BODY_ZONE_CHEST)
|
||||
chest.remove_bodypart_overlay(roach_shell)
|
||||
human_owner.update_body_parts()
|
||||
|
||||
/**
|
||||
* Signal proc for [COMSIG_MOB_APPLY_DAMAGE]
|
||||
*
|
||||
* Being hit with brute damage in the back will impart a large damage resistance bonus for a very short period.
|
||||
*/
|
||||
/obj/item/organ/internal/heart/roach/proc/modify_damage(datum/source, damage, damagetype, def_zone, blocked, wound_bonus, bare_wound_bonus, sharpness, attack_direction, obj/item/attacking_item)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!ishuman(owner) || !attack_direction || damagetype != BRUTE || owner.stat >= UNCONSCIOUS)
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/human_owner = owner
|
||||
// No tactical spinning
|
||||
if(human_owner.flags_1 & IS_SPINNING_1)
|
||||
return
|
||||
|
||||
// If we're lying down, or were attacked from the back, we get armor.
|
||||
var/should_armor_up = (human_owner.body_position == LYING_DOWN) || (human_owner.dir & attack_direction)
|
||||
if(!should_armor_up)
|
||||
return
|
||||
|
||||
// Take 50% less damage from attack behind us
|
||||
if(!defense_timerid)
|
||||
human_owner.physiology.brute_mod /= 2
|
||||
human_owner.visible_message(span_warning("[human_owner]'s back hardens against the blow!"))
|
||||
playsound(human_owner, 'sound/effects/constructform.ogg', 25, vary = TRUE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
|
||||
defense_timerid = addtimer(CALLBACK(src, PROC_REF(reset_damage), owner), 5 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE)
|
||||
|
||||
/obj/item/organ/internal/heart/roach/proc/reset_damage(mob/living/carbon/human/human_owner)
|
||||
defense_timerid = null
|
||||
if(!QDELETED(human_owner))
|
||||
human_owner.physiology.brute_mod *= 2
|
||||
human_owner.visible_message(span_warning("[human_owner]'s back softens again."))
|
||||
|
||||
// Simple overlay so we can add a roach shell to guys with roach hearts
|
||||
/datum/bodypart_overlay/simple/roach_shell
|
||||
icon_state = "roach_shell"
|
||||
layers = EXTERNAL_FRONT|EXTERNAL_BEHIND
|
||||
|
||||
/datum/bodypart_overlay/simple/roach_shell/get_image(image_layer, obj/item/bodypart/limb)
|
||||
return image(
|
||||
icon = icon,
|
||||
icon_state = "[icon_state]_[mutant_bodyparts_layertext(image_layer)]",
|
||||
layer = image_layer,
|
||||
)
|
||||
|
||||
/// Roach stomach:
|
||||
/// Makes disgust a non-issue, very slightly worse at passing off reagents
|
||||
/// Also makes you more hungry
|
||||
/obj/item/organ/internal/stomach/roach
|
||||
name = "mutated roach-stomach"
|
||||
desc = "Roach DNA infused into what was once a normal stomach."
|
||||
maxHealth = 2 * STANDARD_ORGAN_THRESHOLD
|
||||
disgust_metabolism = 32 // Demolishes any disgust we have
|
||||
metabolism_efficiency = 0.033 // Slightly worse at transferring reagents
|
||||
hunger_modifier = 3
|
||||
|
||||
icon = 'icons/obj/medical/organs/infuser_organs.dmi'
|
||||
icon_state = "stomach"
|
||||
greyscale_config = /datum/greyscale_config/mutant_organ
|
||||
greyscale_colors = ROACH_COLORS
|
||||
|
||||
/obj/item/organ/internal/stomach/roach/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/roach)
|
||||
|
||||
/// Roach liver:
|
||||
/// Purges toxins at a higher threshold, but takes more damage from them if not purged
|
||||
/obj/item/organ/internal/liver/roach
|
||||
name = "mutated roach-liver"
|
||||
desc = "Roach DNA infused into what was once a normal liver."
|
||||
maxHealth = 2 * STANDARD_ORGAN_THRESHOLD
|
||||
toxTolerance = 5 // More tolerance for toxins
|
||||
liver_resistance = 0.25 // But if they manage to get in you're screwed
|
||||
|
||||
icon = 'icons/obj/medical/organs/infuser_organs.dmi'
|
||||
icon_state = "liver"
|
||||
greyscale_config = /datum/greyscale_config/mutant_organ
|
||||
greyscale_colors = ROACH_COLORS
|
||||
|
||||
/obj/item/organ/internal/liver/roach/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/roach)
|
||||
|
||||
/obj/item/organ/internal/liver/roach/on_insert(mob/living/carbon/organ_owner, special)
|
||||
. = ..()
|
||||
if(!ishuman(organ_owner))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/human_owner = owner
|
||||
human_owner.physiology.tox_mod *= 2
|
||||
|
||||
/obj/item/organ/internal/liver/roach/on_remove(mob/living/carbon/organ_owner, special)
|
||||
. = ..()
|
||||
if(!ishuman(organ_owner) || QDELETED(organ_owner))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/human_owner = organ_owner
|
||||
human_owner.physiology.tox_mod /= 2
|
||||
|
||||
/// Roach appendix:
|
||||
/// No appendicitus! weee!
|
||||
/obj/item/organ/internal/appendix/roach
|
||||
name = "mutated roach-appendix"
|
||||
desc = "Roach DNA infused into what was once a normal appendix. It could get <i>worse</i>?"
|
||||
maxHealth = 2 * STANDARD_ORGAN_THRESHOLD
|
||||
|
||||
icon = 'icons/obj/medical/organs/infuser_organs.dmi'
|
||||
icon_state = "appendix"
|
||||
greyscale_config = /datum/greyscale_config/mutant_organ
|
||||
greyscale_colors = ROACH_COLORS
|
||||
|
||||
/obj/item/organ/internal/appendix/roach/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/roach)
|
||||
|
||||
/obj/item/organ/internal/appendix/roach/become_inflamed()
|
||||
return
|
||||
|
||||
#undef ROACH_ORGAN_COLOR
|
||||
#undef ROACH_COLORS
|
||||
@@ -159,22 +159,8 @@
|
||||
|
||||
if(!awakened)
|
||||
return
|
||||
var/static/list/transforms
|
||||
if(!transforms)
|
||||
var/matrix/M1 = matrix()
|
||||
var/matrix/M2 = matrix()
|
||||
var/matrix/M3 = matrix()
|
||||
var/matrix/M4 = matrix()
|
||||
M1.Translate(-1, 0)
|
||||
M2.Translate(0, 1)
|
||||
M3.Translate(1, 0)
|
||||
M4.Translate(0, -1)
|
||||
transforms = list(M1, M2, M3, M4)
|
||||
|
||||
animate(src, transform=transforms[1], time=0.2, loop=-1)
|
||||
animate(transform=transforms[2], time=0.1)
|
||||
animate(transform=transforms[3], time=0.2)
|
||||
animate(transform=transforms[4], time=0.3)
|
||||
spasm_animation()
|
||||
|
||||
/obj/item/his_grace/proc/drowse() //Good night, Mr. Grace.
|
||||
if(!awakened || ascended)
|
||||
|
||||
@@ -628,6 +628,9 @@ GLOBAL_VAR(station_nuke_source)
|
||||
* Helper proc that handles gibbing someone who has been nuked.
|
||||
*/
|
||||
/proc/nuke_gib(mob/living/gibbed, atom/source)
|
||||
if(HAS_TRAIT(gibbed, TRAIT_NUKEIMMUNE))
|
||||
return FALSE
|
||||
|
||||
if(istype(gibbed.loc, /obj/structure/closet/secure_closet/freezer))
|
||||
var/obj/structure/closet/secure_closet/freezer/freezer = gibbed.loc
|
||||
if(!freezer.jones)
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
name = "cockroach"
|
||||
desc = "This station is just crawling with bugs."
|
||||
icon_state = "cockroach"
|
||||
icon_dead = "cockroach" //Make this work
|
||||
icon_dead = "cockroach_no_animation"
|
||||
density = FALSE
|
||||
mob_biotypes = MOB_ORGANIC|MOB_BUG
|
||||
mob_size = MOB_SIZE_TINY
|
||||
held_w_class = WEIGHT_CLASS_TINY
|
||||
health = 1
|
||||
maxHealth = 1
|
||||
speed = 1.25
|
||||
can_be_held = TRUE
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
|
||||
|
||||
@@ -38,17 +40,23 @@
|
||||
var/static/list/roach_drops = list(/obj/effect/decal/cleanable/insectguts)
|
||||
AddElement(/datum/element/death_drops, roach_drops)
|
||||
AddElement(/datum/element/swabable, cockroach_cell_line, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 7)
|
||||
AddComponent(/datum/component/squashable, squash_chance = 50, squash_damage = 1)
|
||||
AddElement(/datum/element/basic_body_temp_sensitive, 270, INFINITY)
|
||||
AddComponent( \
|
||||
/datum/component/squashable, \
|
||||
squash_chance = 50, \
|
||||
squash_damage = 1, \
|
||||
squash_flags = SQUASHED_SHOULD_BE_GIBBED|SQUASHED_ALWAYS_IF_DEAD|SQUASHED_DONT_SQUASH_IN_CONTENTS, \
|
||||
)
|
||||
ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
|
||||
|
||||
/mob/living/basic/cockroach/death(gibbed)
|
||||
if(GLOB.station_was_nuked) //If the nuke is going off, then cockroaches are invincible. Keeps the nuke from killing them, cause cockroaches are immune to nukes.
|
||||
return
|
||||
return ..()
|
||||
ADD_TRAIT(src, TRAIT_NUKEIMMUNE, INNATE_TRAIT)
|
||||
ADD_TRAIT(src, TRAIT_RADIMMUNE, INNATE_TRAIT)
|
||||
|
||||
/mob/living/basic/cockroach/ex_act() //Explosions are a terrible way to handle a cockroach.
|
||||
return FALSE
|
||||
|
||||
// Roach goop is the gibs to drop
|
||||
/mob/living/basic/cockroach/spawn_gibs()
|
||||
return
|
||||
|
||||
/datum/ai_controller/basic_controller/cockroach
|
||||
blackboard = list(
|
||||
@@ -125,7 +133,13 @@
|
||||
/mob/living/basic/cockroach/hauberoach/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/caltrop, min_damage = 10, max_damage = 15, flags = (CALTROP_BYPASS_SHOES | CALTROP_SILENT))
|
||||
AddComponent(/datum/component/squashable, squash_chance = 100, squash_damage = 1, squash_callback = TYPE_PROC_REF(/mob/living/basic/cockroach/hauberoach, on_squish))
|
||||
AddComponent( \
|
||||
/datum/component/squashable, \
|
||||
squash_chance = 100, \
|
||||
squash_damage = 1, \
|
||||
squash_flags = SQUASHED_SHOULD_BE_GIBBED|SQUASHED_ALWAYS_IF_DEAD|SQUASHED_DONT_SQUASH_IN_CONTENTS, \
|
||||
squash_callback = TYPE_PROC_REF(/mob/living/basic/cockroach/hauberoach, on_squish), \
|
||||
)
|
||||
|
||||
///Proc used to override the squashing behavior of the normal cockroach.
|
||||
/mob/living/basic/cockroach/hauberoach/proc/on_squish(mob/living/cockroach, mob/living/living_target)
|
||||
@@ -136,6 +150,7 @@
|
||||
return TRUE
|
||||
living_target.visible_message(span_notice("[living_target] squashes [cockroach], not even noticing its spike."), span_notice("You squashed [cockroach], not even noticing its spike."))
|
||||
return FALSE
|
||||
|
||||
/datum/ai_controller/basic_controller/cockroach/hauberoach
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/pet_planning,
|
||||
|
||||
@@ -65,9 +65,9 @@
|
||||
if(stage < 6)
|
||||
INVOKE_ASYNC(src, PROC_REF(RefreshInfectionImage))
|
||||
var/slowdown = 1
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/baby_momma = owner
|
||||
slowdown = baby_momma.reagents.has_reagent(/datum/reagent/medicine/spaceacillin) ? 2 : 1 // spaceacillin doubles the time it takes to grow
|
||||
if(!isnull(owner)) // it gestates out of bodies.
|
||||
if(HAS_TRAIT(owner, TRAIT_VIRUS_RESISTANCE))
|
||||
slowdown *= 2 // spaceacillin doubles the time it takes to grow
|
||||
if(owner.has_status_effect(/datum/status_effect/nest_sustenance))
|
||||
slowdown *= 0.80 //egg gestates 20% faster if you're trapped in a nest
|
||||
|
||||
|
||||
@@ -16,7 +16,11 @@
|
||||
|
||||
var/siemens_coeff = 1 // resistance to shocks
|
||||
|
||||
var/stun_mod = 1 // % stun modifier
|
||||
/// Multiplier applied to all incapacitating stuns (knockdown, stun, paralyze, immobilize)
|
||||
var/stun_mod = 1
|
||||
/// Multiplied aplpied to just knockdowns, stacks with above multiplicatively
|
||||
var/knockdown_mod = 1
|
||||
|
||||
var/bleed_mod = 1 // % bleeding modifier
|
||||
var/datum/armor/armor // internal armor datum
|
||||
|
||||
|
||||
@@ -31,13 +31,6 @@
|
||||
BODY_ZONE_CHEST = /obj/item/bodypart/chest/fly,
|
||||
)
|
||||
|
||||
/datum/species/fly/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired)
|
||||
. = ..()
|
||||
if(. & COMSIG_MOB_STOP_REAGENT_CHECK)
|
||||
return
|
||||
if(chem.type == /datum/reagent/toxin/pestkiller)
|
||||
affected.adjustToxLoss(3 * REM * seconds_per_tick)
|
||||
|
||||
/datum/species/fly/check_species_weakness(obj/item/weapon, mob/living/attacker)
|
||||
if(istype(weapon, /obj/item/melee/flyswatter))
|
||||
return 30 //Flyswatters deal 30x damage to flypeople.
|
||||
|
||||
@@ -46,19 +46,11 @@
|
||||
|
||||
return randname
|
||||
|
||||
/datum/species/moth/handle_chemical(datum/reagent/chem, mob/living/carbon/human/affected, seconds_per_tick, times_fired)
|
||||
. = ..()
|
||||
if(. & COMSIG_MOB_STOP_REAGENT_CHECK)
|
||||
return
|
||||
if(chem.type == /datum/reagent/toxin/pestkiller)
|
||||
affected.adjustToxLoss(3 * REM * seconds_per_tick)
|
||||
|
||||
/datum/species/moth/check_species_weakness(obj/item/weapon, mob/living/attacker)
|
||||
if(istype(weapon, /obj/item/melee/flyswatter))
|
||||
return 10 //flyswatters deal 10x damage to moths
|
||||
return 1
|
||||
|
||||
|
||||
/datum/species/moth/randomize_features(mob/living/carbon/human/human_mob)
|
||||
human_mob.dna.features["moth_markings"] = pick(GLOB.moth_wings_list)
|
||||
randomize_external_organs(human_mob)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
|
||||
/mob/living/carbon/human/Stun(amount, ignore_canstun = FALSE)
|
||||
amount = dna.species.spec_stun(src,amount)
|
||||
amount = dna.species.spec_stun(src, amount)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/Knockdown(amount, ignore_canstun = FALSE)
|
||||
amount = dna.species.spec_stun(src,amount)
|
||||
amount = dna.species.spec_stun(src, amount) * physiology.knockdown_mod
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/Paralyze(amount, ignore_canstun = FALSE)
|
||||
@@ -16,7 +16,7 @@
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/Unconscious(amount, ignore_canstun = FALSE)
|
||||
amount = dna.species.spec_stun(src,amount)
|
||||
amount = dna.species.spec_stun(src, amount)
|
||||
if(HAS_TRAIT(src, TRAIT_HEAVY_SLEEPER))
|
||||
amount *= (rand(125, 130) * 0.01)
|
||||
return ..()
|
||||
|
||||
@@ -2002,17 +2002,18 @@
|
||||
taste_description = "the pain of ten thousand slain mosquitos"
|
||||
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
|
||||
|
||||
/datum/reagent/consumable/ethanol/bug_spray/on_new(data)
|
||||
. = ..()
|
||||
AddElement(/datum/element/bugkiller_reagent)
|
||||
|
||||
/datum/reagent/consumable/ethanol/bug_spray/on_mob_life(mob/living/carbon/drinker, seconds_per_tick, times_fired)
|
||||
//Bugs should not drink Bug spray.
|
||||
if(ismoth(drinker) || isflyperson(drinker))
|
||||
drinker.adjustToxLoss(1 * REM * seconds_per_tick, FALSE, required_biotype = affected_biotype)
|
||||
return ..()
|
||||
|
||||
/datum/reagent/consumable/ethanol/bug_spray/on_mob_metabolize(mob/living/carbon/drinker)
|
||||
|
||||
if(ismoth(drinker) || isflyperson(drinker))
|
||||
// Does some damage to bug biotypes
|
||||
var/did_damage = drinker.adjustToxLoss(1 * REM * seconds_per_tick, updating_health = FALSE, required_biotype = MOB_BUG)
|
||||
// Random chance of causing a screm if we did some damage
|
||||
if(did_damage && SPT_PROB(2, seconds_per_tick))
|
||||
drinker.emote("scream")
|
||||
return ..()
|
||||
|
||||
return ..() || did_damage
|
||||
|
||||
/datum/reagent/consumable/ethanol/applejack
|
||||
name = "Applejack"
|
||||
|
||||
@@ -261,6 +261,14 @@
|
||||
ph = 8.1
|
||||
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
|
||||
|
||||
/datum/reagent/medicine/spaceacillin/on_mob_metabolize(mob/living/L)
|
||||
. = ..()
|
||||
ADD_TRAIT(L, TRAIT_VIRUS_RESISTANCE, type)
|
||||
|
||||
/datum/reagent/medicine/spaceacillin/on_mob_end_metabolize(mob/living/L)
|
||||
. = ..()
|
||||
REMOVE_TRAIT(L, TRAIT_VIRUS_RESISTANCE, type)
|
||||
|
||||
//Goon Chems. Ported mainly from Goonstation. Easily mixable (or not so easily) and provide a variety of effects.
|
||||
|
||||
/datum/reagent/medicine/oxandrolone
|
||||
|
||||
@@ -401,17 +401,19 @@
|
||||
ph = 3.2
|
||||
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
|
||||
|
||||
/datum/reagent/toxin/pestkiller/on_new(data)
|
||||
. = ..()
|
||||
AddElement(/datum/element/bugkiller_reagent)
|
||||
|
||||
/datum/reagent/toxin/pestkiller/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired)
|
||||
. = affected_mob.adjustToxLoss(2 * toxpwr * REM * seconds_per_tick, updating_health = FALSE, required_biotype = MOB_BUG)
|
||||
return ..() || .
|
||||
|
||||
//Pest Spray
|
||||
/datum/reagent/toxin/pestkiller/on_hydroponics_apply(obj/machinery/hydroponics/mytray, mob/user)
|
||||
mytray.adjust_toxic(round(volume))
|
||||
mytray.adjust_pestlevel(-rand(1,2))
|
||||
|
||||
/datum/reagent/toxin/pestkiller/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume)
|
||||
. = ..()
|
||||
if(exposed_mob.mob_biotypes & MOB_BUG)
|
||||
var/damage = min(round(0.4*reac_volume, 0.1),10)
|
||||
exposed_mob.adjustToxLoss(damage, required_biotype = affected_biotype)
|
||||
|
||||
/datum/reagent/toxin/pestkiller/organic
|
||||
name = "Natural Pest Killer"
|
||||
description = "An organic mixture used to kill pests, with less of the side effects. Do not ingest!"
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
return
|
||||
|
||||
// spaceacillin has a 75% chance to block infection
|
||||
if(istype(target) && target.reagents.has_reagent(/datum/reagent/medicine/spaceacillin) && prob(75))
|
||||
if(HAS_TRAIT(target, TRAIT_VIRUS_RESISTANCE) && prob(75))
|
||||
return
|
||||
|
||||
var/obj/item/organ/internal/zombie_infection/infection
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 277 KiB After Width: | Height: | Size: 282 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1263,6 +1263,7 @@
|
||||
#include "code\datums\elements\befriend_petting.dm"
|
||||
#include "code\datums\elements\blocks_explosives.dm"
|
||||
#include "code\datums\elements\bsa_blocker.dm"
|
||||
#include "code\datums\elements\bugkiller_reagent.dm"
|
||||
#include "code\datums\elements\bump_click.dm"
|
||||
#include "code\datums\elements\can_barricade.dm"
|
||||
#include "code\datums\elements\caseless.dm"
|
||||
@@ -1787,6 +1788,7 @@
|
||||
#include "code\game\machinery\dna_infuser\organ_sets\goliath_organs.dm"
|
||||
#include "code\game\machinery\dna_infuser\organ_sets\gondola_organs.dm"
|
||||
#include "code\game\machinery\dna_infuser\organ_sets\rat_organs.dm"
|
||||
#include "code\game\machinery\dna_infuser\organ_sets\roach_organs.dm"
|
||||
#include "code\game\machinery\doors\airlock.dm"
|
||||
#include "code\game\machinery\doors\airlock_electronics.dm"
|
||||
#include "code\game\machinery\doors\airlock_types.dm"
|
||||
|
||||
@@ -28,7 +28,7 @@ type TierData = {
|
||||
name: string;
|
||||
};
|
||||
|
||||
const PAGE_HEIGHT = '235px';
|
||||
const PAGE_HEIGHT = 30;
|
||||
|
||||
const TIER2TIERDATA: TierData[] = [
|
||||
{
|
||||
@@ -69,7 +69,7 @@ const TIER2TIERDATA: TierData[] = [
|
||||
];
|
||||
|
||||
export const InfuserBook = (props, context) => {
|
||||
const { data } = useBackend<DnaInfuserData>(context);
|
||||
const { data, act } = useBackend<DnaInfuserData>(context);
|
||||
const { entries } = data;
|
||||
|
||||
const [bookPosition, setBookPosition] = useLocalState<BookPosition>(
|
||||
@@ -87,7 +87,11 @@ export const InfuserBook = (props, context) => {
|
||||
let currentEntry = paginatedEntries[chapter][pageInChapter];
|
||||
|
||||
const switchChapter = (newChapter) => {
|
||||
if (chapter === newChapter) {
|
||||
return;
|
||||
}
|
||||
setBookPosition({ chapter: newChapter, pageInChapter: 0 });
|
||||
act('play_flip_sound'); // just so we can play a sound fx on page turn
|
||||
};
|
||||
|
||||
const setPage = (newPage) => {
|
||||
@@ -112,6 +116,7 @@ export const InfuserBook = (props, context) => {
|
||||
newBookPosition.pageInChapter = newPage;
|
||||
}
|
||||
setBookPosition(newBookPosition);
|
||||
act('play_flip_sound'); // just so we can play a sound fx on page turn
|
||||
};
|
||||
|
||||
const tabs = [
|
||||
@@ -127,7 +132,7 @@ export const InfuserBook = (props, context) => {
|
||||
const restrictedNext = chapter === 3 && pageInChapter === 0;
|
||||
|
||||
return (
|
||||
<Window title="DNA Infusion Manual" width={620} height={375}>
|
||||
<Window title="DNA Infusion Manual" width={620} height={500}>
|
||||
<Window.Content>
|
||||
<Stack vertical>
|
||||
<Stack.Item mb={-1}>
|
||||
@@ -215,7 +220,7 @@ export const InfuserInstructions = (props, context) => {
|
||||
<br />
|
||||
3. Have someone activate the machine externally.
|
||||
<br />
|
||||
<Box inline color="white">
|
||||
<Box mt="10px" inline color="white">
|
||||
And you're done! Note that the infusion source will be
|
||||
obliterated in the process.
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user