[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:
SkyratBot
2023-07-14 23:11:18 -04:00
committed by GitHub
co-authored by MrMelbert Giz
parent 3e37d9e827
commit fcacebfe38
31 changed files with 485 additions and 80 deletions
+1
View File
@@ -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
+7 -3
View File
@@ -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
+7 -1
View File
@@ -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"
+14
View File
@@ -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
+5 -3
View File
@@ -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))
+3 -5
View File
@@ -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)
+2 -2
View File
@@ -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
+88
View File
@@ -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",
+1 -1
View File
@@ -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
+1 -15
View File
@@ -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!"
+1 -1
View File
@@ -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

+2
View File
@@ -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&apos;re done! Note that the infusion source will be
obliterated in the process.
</Box>