diff --git a/code/game/objects/micro_structures.dm b/code/game/objects/micro_structures.dm index 6fa2e7829f..707501786a 100644 --- a/code/game/objects/micro_structures.dm +++ b/code/game/objects/micro_structures.dm @@ -9,6 +9,7 @@ GLOBAL_LIST_EMPTY(micro_tunnels) anchored = TRUE density = FALSE + var/random = FALSE //For random tummels- spits the micro out at a random location. var/magic = FALSE //For events and stuff, if true, this tunnel will show up in the list regardless of whether it's in valid range, of if you're in a tunnel with this var, all tunnels of the same faction will show up redardless of range micro_target = TRUE @@ -278,6 +279,9 @@ GLOBAL_LIST_EMPTY(micro_tunnels) /obj/structure/micro_tunnel/magic magic = TRUE +/obj/structure/micro_tunnel/random + random = TRUE + /obj/Initialize(mapload) . = ..() if(micro_target) diff --git a/code/game/objects/random/mapping.dm b/code/game/objects/random/mapping.dm index aa2a1bb880..55f2d815c7 100644 --- a/code/game/objects/random/mapping.dm +++ b/code/game/objects/random/mapping.dm @@ -26,8 +26,8 @@ /obj/effect/decal/cleanable/blood/oil/streak, /obj/effect/decal/cleanable/bug_remains, /obj/effect/decal/remains/mouse, - /obj/effect/decal/cleanable/vomit, - /obj/effect/decal/cleanable/blood/splatter, + /obj/effect/decal/cleanable/vomit/old, + /obj/effect/decal/cleanable/blood/old, /obj/effect/decal/cleanable/ash, /obj/effect/decal/cleanable/generic, /obj/effect/decal/cleanable/flour, diff --git a/code/game/objects/structures/dummystairs.dm b/code/game/objects/structures/dummystairs.dm new file mode 100644 index 0000000000..fed5c07af8 --- /dev/null +++ b/code/game/objects/structures/dummystairs.dm @@ -0,0 +1,17 @@ +/obj/structure/dummystairs + name = "stairs" + desc = "A short set of stairs" + icon = 'icons/obj/dummystairs.dmi' + icon_state = "stair" + anchored = TRUE + density = FALSE + layer = 2.5 + +/obj/structure/dummystairs/bronzeledge + icon_state = "stair_bronze" + +/obj/structure/dummystairs/greyledge + icon_state = "stair_grey" + +/obj/structure/dummystairs/hazardledge + icon_state = "stair_hazard" diff --git a/code/game/objects/structures/railing.dm b/code/game/objects/structures/railing.dm index 42ea30d2e5..1b3e0d417b 100644 --- a/code/game/objects/structures/railing.dm +++ b/code/game/objects/structures/railing.dm @@ -243,3 +243,14 @@ qdel(src) return return + +/obj/structure/railing/overhang/hazard + name = "hazardous ledge" + desc = "An overhang made of a steel. It's painted with vibrant hazard markings." + icon = 'icons/obj/railing.dmi' + icon_modifier = "hazard_" + icon_state = "hazard_railing0" + +/obj/structure/railing/overhang/hazard/nanite + icon_modifier = "inactive_" + icon_state = "inactive_railing0" diff --git a/code/game/turfs/flooring/flooring_decals.dm b/code/game/turfs/flooring/flooring_decals.dm index 070b03295a..5de08728d9 100644 --- a/code/game/turfs/flooring/flooring_decals.dm +++ b/code/game/turfs/flooring/flooring_decals.dm @@ -1293,3 +1293,65 @@ var/list/floor_decals = list() /obj/effect/floor_decal/arrows name = "floor arrows" icon_state = "arrows" + +//cetus plaques + +/obj/effect/floor_decal/cetus/cetus1 + name = "cetus1" + icon_state = "cetus1" + +/obj/effect/floor_decal/cetus/cetus2 + name = "cetus2" + icon_state = "cetus2" + +/obj/effect/floor_decal/cetus/cetus3 + name = "cetus3" + icon_state = "cetus3" + +/obj/effect/floor_decal/cetus/cetus4 + name = "cetus4" + icon_state = "cetus4" + +/obj/effect/floor_decal/cetus/cetus5 + name = "cetus5" + icon_state = "cetus5" + +/obj/effect/floor_decal/cetus/cetus6 + name = "cetus6" + icon_state = "cetus6" + +/obj/effect/floor_decal/cetus/cetus7 + name = "cetus7" + icon_state = "cetus7" + +/obj/effect/floor_decal/cetus/cetus8 + name = "cetus8" + icon_state = "cetus8" + +/obj/effect/floor_decal/cetus/cetus9 + name = "cetus9" + icon_state = "cetus9" + +/obj/effect/floor_decal/cetus/andromeda1 + name = "andromeda1" + icon_state = "andromeda1" + +/obj/effect/floor_decal/cetus/andromeda2 + name = "andromeda2" + icon_state = "andromeda2" + +/obj/effect/floor_decal/cetus/andromeda3 + name = "andromeda3" + icon_state = "andromeda3" + +/obj/effect/floor_decal/cetus/andromeda4 + name = "andromeda4" + icon_state = "andromeda4" + +/obj/effect/floor_decal/cetus/andromeda5 + name = "andromeda5" + icon_state = "andromeda5" + +/obj/effect/floor_decal/cetus/andromeda6 + name = "andromeda6" + icon_state = "andromeda6" diff --git a/code/game/turfs/initialization/maintenance.dm b/code/game/turfs/initialization/maintenance.dm index 1cbe3dccb9..07f941021b 100644 --- a/code/game/turfs/initialization/maintenance.dm +++ b/code/game/turfs/initialization/maintenance.dm @@ -1,6 +1,8 @@ /datum/turf_initializer/maintenance/InitializeTurf(var/turf/simulated/T) if(T.density) return + if(!T.can_dirty) + return // Quick and dirty check to avoid placing things inside windows if(locate(/obj/structure/grille, T)) return @@ -58,3 +60,21 @@ if(dir == EAST) new /obj/effect/decal/cleanable/cobweb2(T) return + +/datum/turf_initializer/maintenance/shallow/InitializeTurf(var/turf/simulated/dirty) + if(dirty.density) + return + if(!dirty.can_dirty) + return + // Quick and dirty check to avoid placing things inside windows + if(locate(/obj/structure/grille, dirty)) + return + + var/cardinal_turfs = dirty.CardinalTurfs() + + dirty.dirt = rand(10, 50) + rand(10, 50) + // If a neighbor is dirty, then we get dirtier. + var/how_dirty = dirty_neighbors(cardinal_turfs) + for(var/i = 0; i < how_dirty; i++) + dirty.dirt += rand(0,10) + dirty.update_dirt() diff --git a/code/game/turfs/simulated/nanogoop.dm b/code/game/turfs/simulated/nanogoop.dm new file mode 100644 index 0000000000..9cb17f753c --- /dev/null +++ b/code/game/turfs/simulated/nanogoop.dm @@ -0,0 +1,345 @@ +GLOBAL_LIST_BOILERPLATE(nanite_turfs, /turf/simulated/floor/water/digestive_enzymes/nanites) + +//half of this code is ripped from digestive enzymes themselves, with runtimes and such trimmed +/turf/simulated/floor/water/digestive_enzymes/nanites //i just wanted to map, why has it come to making such terrible crimes against humanity + name = "nanite-infested tiles." + desc = "This section of reinforced plating appears to host a colony of nanites between the tiles" + icon = 'icons/turf/nanitegoo.dmi' + icon_state = "composite" + water_icon = 'icons/turf/nanitegoo.dmi' + water_state = "goo_inactive" + under_state = "reinforced" + depth = 0 + movement_cost = 0 + mobstuff = FALSE + footstep = FOOTSTEP_PLATING + barefootstep = FOOTSTEP_HARD_BAREFOOT + clawfootstep = FOOTSTEP_HARD_CLAW + watercolor = "black" + reagent_type = REAGENT_ID_LIQUIDPROTEAN + oxygen = MOLES_O2STANDARD + nitrogen = MOLES_N2STANDARD + temperature = T20C + var/digesting = FALSE + var/digest_synth = FALSE + var/digest_robot = FALSE + var/active = FALSE + var/usesmes = TRUE + var/datum/weakref/moblink + var/datum/weakref/linkedsmes //when the nanites digest something, it becomes power in an SMES + var/id = null + + +/turf/simulated/floor/water/digestive_enzymes/nanites/Initialize(mapload) + . = ..() + for(var/obj/machinery/power/smes/tolink in GLOB.smeses) + if(!tolink) + continue + if(!get_area(tolink)) + continue + if(get_area(tolink) == get_area(src)) + linkedsmes = WEAKREF(tolink) + +/turf/simulated/floor/water/digestive_enzymes/nanites/attack_hand(mob/user) + var/mob/living/nutrienttarget = moblink?.resolve() + var/obj/machinery/power/smes/smes = linkedsmes?.resolve() + if(check_target() && (user != nutrienttarget))//prioritize this here, so mobs can turn the turf off + return ..() + if(ishuman(user)) + if(smes || isAI(nutrienttarget)) + return ..() + var/mob/living/carbon/human/checker = user + if(checker.nif)//Proteans have NIFS + var/choice1 = tgui_input_list(user, "Do you wish interface with \the [src]", "Desired state", list("On", "Off")) + switch(choice1) + if("On") + var/choice2 = tgui_input_list(user, "Which entities do you wish for \the [src] to recycle?", "Desired targets", list("None", "All", "Organics and Cyborgs", "Organics and Synthetics", "Only Organics")) + if(checker.isSynthetic()) + to_chat(checker, span_warning("With you in control, \the [src] will not attempt to recycle your body, no matter the setting you pick")) + else + to_chat(checker, span_warning("You realize there is no way for the simplistic [src] to ignore your form, if you set it to recycle.")) + user.visible_message(span_warning("\The [user] inspects \the [src]"), span_warning("You begin to interface with \the [src].")) + if(do_after(user, 30, src)) + moblink = WEAKREF(user) + switch(choice2) + if("None") + moblink = WEAKREF(user) + toggle_all(TRUE) + if("All") + moblink = WEAKREF(user) + toggle_all(TRUE, TRUE, TRUE, TRUE) + if("Organics and Cyborgs") + moblink = WEAKREF(user) + toggle_all(TRUE, TRUE, TRUE) + if("Organics and Synthetics") + moblink = WEAKREF(user) + toggle_all(TRUE, TRUE, FALSE, TRUE) + if("Only Organics") + moblink = WEAKREF(user) + toggle_all(TRUE, TRUE) + + if("Off") + if(active) + user.visible_message(span_warning("\The [user] inspects \the [src]"), span_warning("You begin to interface with \the [src].")) + if(do_after(user, 30, src)) + toggle_all(FALSE) + return ..() + +/turf/simulated/floor/water/digestive_enzymes/nanites/attack_ai(mob/user) + var/mob/living/nutrienttarget = moblink?.resolve() + var/obj/machinery/power/smes/smes = linkedsmes?.resolve() + if(isrobot(user) && !isshell(user)) + if(smes || isAI(nutrienttarget)) + return ..() + if(check_target() && user != nutrienttarget) + return ..() + if(isAI(user) || isshell(user))// AI have priority + if(check_target()) + if(isAI(nutrienttarget) && user != nutrienttarget)//first come first serve, for AI + if(isshell(user)) + return ..() + if(!locate(user) in range(1, src))// AI can always control adjacent nanite tiles + return ..() + var/choice1 = tgui_input_list(user, "Do you wish interface with \the [src]", "Desired state", list("On", "Off")) + switch(choice1) + if("On") + var/choice2 = tgui_input_list(user, "Which entities do you wish for [src] to recycle?", "Desired targets", list("None", "All", "Organics and Cyborgs", "Organics and Synthetics", "Only Organics")) + to_chat(user, span_warning("With you in control, \the [src] will not attempt to recycle your body, no matter the setting you pick")) + switch(choice2) + if("None") + moblink = WEAKREF(user) + toggle_all(TRUE) + if("All") + moblink = WEAKREF(user) + toggle_all(TRUE, TRUE, TRUE, TRUE) + if("Organics and Cyborgs") + moblink = WEAKREF(user) + toggle_all(TRUE, TRUE, TRUE) + if("Organics and Synthetics") + moblink = WEAKREF(user) + toggle_all(TRUE, TRUE, FALSE, TRUE) + if("Only Organics") + moblink = WEAKREF(user) + toggle_all(TRUE, TRUE) + + if("Off") + if(active) + toggle_all(FALSE) + +/turf/simulated/floor/water/digestive_enzymes/nanites/can_digest(atom/movable/AM) //copypasting the entire proc because we use an SMES instead of a linked mob + . = FALSE + var/mob/living/nutrienttarget = moblink?.resolve() + if(!active) + return FALSE + if(!check_target()) + return FALSE + if(!digesting) + return FALSE + if(AM.loc != src) + return FALSE + if(isitem(AM)) + var/obj/item/targetitem = AM + if(targetitem.unacidable || targetitem.throwing || targetitem.is_incorporeal() || !targetitem) + return FALSE + var/food = FALSE + if(istype(targetitem,/obj/item/reagent_containers/food)) + food = TRUE + if(prob(95)) //Give people a chance to pick them up + return TRUE + targetitem.visible_message(span_warning("\The [targetitem] sizzles...")) + var/yum = targetitem.digest_act() //Glorp + if(istype(targetitem , /obj/item/card)) + yum = 0 //No, IDs do not have infinite nutrition, thank you + if(yum) + if(food) + yum += 50 + give_nutrients(yum) + return TRUE + if(isliving(AM)) + var/mob/living/targetmob = AM + if(targetmob.unacidable || !targetmob.digestable || targetmob.buckled || targetmob.hovering || targetmob.throwing || targetmob.is_incorporeal()) + return FALSE + if(isrobot(targetmob)) + if(!digest_robot) + return FALSE + if(targetmob == nutrienttarget) + return FALSE + if(ishuman(targetmob)) + var/mob/living/carbon/human/targethuman = targetmob + if(targethuman.isSynthetic()) + if(!digest_synth) + return FALSE + if(targetmob == nutrienttarget) + return FALSE + if(!targethuman.pl_suit_protected()) + return TRUE + if(targethuman.resting && !targethuman.pl_head_protected()) + return TRUE + return TRUE + +/turf/simulated/floor/water/digestive_enzymes/nanites/proc/check_target()//check if the target is in the area, or if this is a + var/mob/living/nutrienttarget = moblink?.resolve() + var/obj/machinery/power/smes/smes = linkedsmes?.resolve() + if(nutrienttarget) + if(nutrienttarget.client && !nutrienttarget.stat) + if(smes && isAI(nutrienttarget)) + return nutrienttarget + if(get_area(nutrienttarget)) + if(get_area(nutrienttarget) == get_area(src)) + return nutrienttarget + toggle_all(FALSE) + return FALSE + +/turf/simulated/floor/water/digestive_enzymes/nanites/digest_stuff(atom/movable/AM) //copypasting the entire proc because we use an SMES instead of a linked mob + . = FALSE + + var/damage = 2 + var/list/stuff = list() + var/nutrients = 0 + for(var/thing in src) + if(can_digest(thing)) + stuff |= thing + if(!stuff.len) + return FALSE + var/thing = pick(stuff) //We only think about one thing at a time, otherwise things get wacky + . = TRUE + if(iscarbon(thing)) + var/mob/living/carbon/targetcarbon = thing + if(!targetcarbon) + return + if(targetcarbon.stat == DEAD) + targetcarbon.unacidable = TRUE //Don't touch this one again, we're gonna delete it in a second + targetcarbon.release_vore_contents() + for(var/obj/item/targetitem in targetcarbon) + if(istype(targetitem, /obj/item/organ/internal/mmi_holder/posibrain)) + var/obj/item/organ/internal/mmi_holder/MMI = targetitem + MMI.removed() + if(istype(targetitem, /obj/item/organ)) + targetitem.unacidable = TRUE + continue + if(istype(targetitem, /obj/item/implant/backup) || istype(targetitem, /obj/item/nif)) + continue + targetcarbon.drop_from_inventory(targetitem) + var/how_much = targetcarbon.mob_size + targetcarbon.nutrition + if(!targetcarbon.ckey) + how_much = how_much / 10 //Braindead mobs are worth less + nutrients += how_much + targetcarbon.mind?.vore_death = TRUE + GLOB.prey_digested_roundstat++ + qdel(targetcarbon) //glorp + return + targetcarbon.adjustFireLoss(damage) + var/how_much = (damage * targetcarbon.size_multiplier) * targetcarbon.get_digestion_nutrition_modifier() + if(!targetcarbon.ckey) + how_much = how_much / 10 //Braindead mobs are worth less + nutrients += how_much + if(targetcarbon.bloodstr.get_reagent_amount(REAGENT_ID_NUMBENZYME) < 2) //best play it safe with digestion pain + targetcarbon.bloodstr.add_reagent(REAGENT_ID_NUMBENZYME,4) + nutrients += how_much + else if (isliving(thing)) + var/mob/living/targetmob = thing + if(!targetmob) + return + if(targetmob.stat == DEAD) + targetmob.unacidable = TRUE //Don't touch this one again, we're gonna delete it in a second + targetmob.release_vore_contents() + var/how_much = targetmob.mob_size + targetmob.nutrition + if(!targetmob.ckey) + how_much = how_much / 10 //Braindead mobs are worth less + nutrients += how_much + qdel(targetmob) //gloop + return + targetmob.adjustFireLoss(damage) + var/how_much = (damage * targetmob.size_multiplier) * targetmob.get_digestion_nutrition_modifier() + if(!targetmob.ckey) + how_much = how_much / 10 //Braindead mobs are worth less + nutrients += how_much + give_nutrients(nutrients) + +/turf/simulated/floor/water/digestive_enzymes/nanites/proc/give_nutrients(var/amt) + var/mob/living/nutrienttarget = moblink?.resolve() + var/obj/machinery/power/smes/smes = linkedsmes?.resolve() + if(smes) + smes.charge += (amt * 20) + return + if(nutrienttarget) + if(ishuman(nutrienttarget)) + var/mob/living/carbon/human/targetcarbon = nutrienttarget + if(targetcarbon.isSynthetic()) + targetcarbon.nutrition = targetcarbon.nutrition+(10 * amt * (1-min(targetcarbon.species.synthetic_food_coeff, 0.9))) + return + if(isrobot(nutrienttarget)) + var/mob/living/silicon/robot/targetrobot = nutrienttarget + if(targetrobot.cell) + targetrobot.cell.give(amt * 20) + return + + +/turf/simulated/floor/water/digestive_enzymes/nanites/return_air_for_internal_lifeform(var/mob/living/targetmob) + if(!can_digest(targetmob)) + return return_air() //Nanites should always be nonlethal until the AI turns on digestion + return ..() + +/turf/simulated/floor/water/digestive_enzymes/nanites/proc/toggle_all(var/on = TRUE, var/digest = FALSE, var/robot = FALSE, var/synth = FALSE) + var/mob/living/nutrienttarget = moblink?.resolve() + for(var/turf/simulated/floor/water/digestive_enzymes/nanites/nanites in GLOB.nanite_turfs) + if(nanites.id == id) + nanites.moblink = null + if(on) + nanites.moblink = WEAKREF(nutrienttarget) + nanites.select_state(on, digest, robot, synth) + +/turf/simulated/floor/water/digestive_enzymes/nanites/proc/select_state(var/on = TRUE, var/digest = FALSE, var/robot = FALSE, var/synth = FALSE) + if(!on) + name = "nanite-infested tiles." + desc = "This section of reinforced plating appears to host a colony of nanites between the tiles" + depth = 0 + movement_cost = 0 + footstep = FOOTSTEP_PLATING + barefootstep = FOOTSTEP_HARD_BAREFOOT + clawfootstep = FOOTSTEP_HARD_CLAW + water_state = "goo_inactive" + digesting = FALSE + digest_synth = FALSE + digest_robot = FALSE + active = FALSE + for(var/obj/structure/railing/overhang/hazard/nanite/R in src) + R.icon_modifier = "inactive_" + R.icon_state = "inactive_railing0" + for(var/obj/structure/railing/overhang/hazard/nanite/R in range(src, 1)) + R.update_icon() + for(var/obj/structure/dummystairs/hazardledge/stairs in src) + stairs.icon_state = "stair_hazard" + stairs.update_icon() + update_icon() + return + name = "nanite goop." + desc = "A deep pool of pulsating, possibly deadly nanite goop." + depth = 2 + movement_cost = 16 //twice as difficult as deep water to navigate + footstep = FOOTSTEP_WATER + barefootstep = FOOTSTEP_WATER + clawfootstep = FOOTSTEP_WATER + water_state = "goo_active" + digesting = digest + digest_synth = synth + digest_robot = robot + active = TRUE + for(var/obj/structure/railing/overhang/hazard/nanite/R in src) + R.icon_modifier = "active_" + R.icon_state = "active_railing0" + for(var/obj/structure/railing/overhang/hazard/nanite/R in range(src, 1)) + R.update_icon() + for(var/obj/structure/dummystairs/hazardledge/stairs in src) + depth = 1 + movement_cost = 8 + stairs.icon_state = "stair_hazard_nanite" + stairs.update_icon() + for(var/atom/AM in src) + Entered(AM) + update_icon() + +/turf/simulated/floor/water/digestive_enzymes/nanites/Destroy() + moblink = null + linkedsmes = null + return ..() diff --git a/code/game/turfs/simulated/water.dm b/code/game/turfs/simulated/water.dm index 70e046c76f..35eabc9567 100644 --- a/code/game/turfs/simulated/water.dm +++ b/code/game/turfs/simulated/water.dm @@ -22,6 +22,8 @@ var/reagent_type = REAGENT_ID_WATER // var/datum/looping_sound/water/soundloop CHOMPEdit: Removing soundloop for now. + var/watercolor = null + /turf/simulated/floor/water/Initialize(mapload) . = ..() update_icon() diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 96aecb3394..1702141f69 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -212,6 +212,8 @@ if(T.movement_cost && !flying) //If you are flying you are probably not affected by the terrain on the ground. var/turf_move_cost = T.movement_cost + if(locate(/obj/structure/catwalk) in T) //catwalks prevent turfs from slowing your + return 0 if(istype(T, /turf/simulated/floor/water)) if(species.water_movement) turf_move_cost = CLAMP(turf_move_cost + species.water_movement, HUMAN_LOWEST_SLOWDOWN, 15) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index e44782a69b..64895b2a97 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -705,13 +705,31 @@ H.adjustToxLoss(amount) /datum/species/proc/handle_falling(mob/living/carbon/human/H, atom/hit_atom, damage_min, damage_max, silent, planetary) - if(soft_landing) - if(planetary || !istype(H)) - return FALSE + var/turf/landing = get_turf(hit_atom) + if(!istype(landing)) + return FALSE + if(planetary || !istype(H)) + return FALSE + //commented out, as this turf doesn't exist upstream + /*if(istype(landing, /turf/simulated/floor/boxing)) + if(!silent) + to_chat(H, span_notice("\The [landing] cushions your fall.")) + landing.visible_message(span_infoplain(span_bold("\The [H]") + " 's fall is cushioned by \The [landing].")) + playsound(H, "rustle", 25, 1) + if(!soft_landing) + H.Weaken(10) + return TRUE*/ + //end edit + if(istype(landing, /turf/simulated/floor/water)) + var/turf/simulated/floor/water/W = landing + if(W.depth) + if(!silent) + to_chat(H, span_notice("You splash down into \the [landing].")) + landing.visible_message(span_infoplain(span_bold("\The [H]") + " splashes down into \The [landing].")) + playsound(H, "'sound/effects/slosh.ogg'", 25, 5) + return TRUE - var/turf/landing = get_turf(hit_atom) - if(!istype(landing)) - return FALSE + if(soft_landing) if(!silent) to_chat(H, span_notice("You manage to lower impact of the fall and land safely.")) diff --git a/code/modules/mob/living/carbon/human/species/station/traits/positive.dm b/code/modules/mob/living/carbon/human/species/station/traits/positive.dm index 7259132f24..3c5808d29a 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits/positive.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits/positive.dm @@ -281,12 +281,23 @@ var_changes = list("water_breather" = 1, "water_movement" = -4) //Negate shallow water. Half the speed in deep water. allowed_species = list(SPECIES_HANNER, SPECIES_CUSTOM) //So it only shows up for custom species and hanner custom_only = FALSE + excludes = list(/datum/trait/positive/good_swimmer, /datum/trait/negative/bad_swimmer, /datum/trait/positive/aquatic/plus) /datum/trait/positive/aquatic/apply(var/datum/species/S,var/mob/living/carbon/human/H) ..() add_verb(H, /mob/living/carbon/human/proc/water_stealth) add_verb(H, /mob/living/carbon/human/proc/underwater_devour) +/datum/trait/positive/aquatic/plus + name = "Aquatic 2" + desc = "You can breathe under water and can traverse water more efficiently than most aquatic humanoids. Additionally, you can eat others in the water." + cost = 2 + custom_only = FALSE + var_changes = list("water_breather" = 1, "water_movement" = -4, "swim_mult" = 0.5) //Negate shallow water. Half the speed in deep water. + allowed_species = list(SPECIES_HANNER, SPECIES_CUSTOM) //So it only shows up for custom species and hanner + custom_only = FALSE + excludes = list(/datum/trait/positive/good_swimmer, /datum/trait/negative/bad_swimmer, /datum/trait/positive/aquatic) + /datum/trait/positive/cocoon_tf name = "Cocoon Spinner" desc = "Allows you to build a cocoon around yourself, using it to transform your body if you desire." diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 92092bff68..46011745a7 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -1199,6 +1199,10 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) //see UpdateDamageIcon() var/atom/A = loc // We'd better be swimming and on a turf var/image/I = image(icon = 'icons/mob/submerged.dmi', icon_state = "human_swimming_[depth]", layer = BODY_LAYER+MOB_WATER_LAYER) //TODO: Improve I.color = A.color + if(istype(A, /turf/simulated/floor/water)) + var/turf/simulated/floor/water/underwater = A + if(underwater.watercolor) + I.color = underwater.watercolor overlays_standing[MOB_WATER_LAYER] = I apply_layer(MOB_WATER_LAYER) diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm index e517c4d55e..348a5e3227 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm @@ -1432,6 +1432,7 @@ water_icon = 'icons/turf/stomach_vr.dmi' water_state = "enzyme_shallow" under_state = "flesh_floor" + watercolor = "green" reagent_type = REAGENT_ID_SACID //why not outdoors = FALSE diff --git a/code/modules/nifsoft/nif.dm b/code/modules/nifsoft/nif.dm index 628c546cd7..86b018fba8 100644 --- a/code/modules/nifsoft/nif.dm +++ b/code/modules/nifsoft/nif.dm @@ -671,6 +671,13 @@ You can also set the stat of a NIF to NIF_TEMPFAIL without any issues to disable /datum/nifsoft/malware ) + +/obj/item/nif/glitch/bad + name = "odd NIF" + desc = "A NIF of a very dubious origin." + durability = 100 + bioadap = FALSE + //////////////////////////////// // Special Promethean """surgery""" /obj/item/nif/attack(mob/living/M, mob/living/user, var/target_zone) diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 9503f3362e..d4b1523f8c 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -304,6 +304,7 @@ GLOBAL_LIST_EMPTY(light_type_cache) /obj/machinery/light/small/emergency light_type = /obj/item/light/bulb/red + nightshift_allowed = FALSE /obj/machinery/light/small/emergency/flicker auto_flicker = TRUE diff --git a/code/modules/shuttles/landmarks.dm b/code/modules/shuttles/landmarks.dm index 5ee542bbd3..5c56d0fc2f 100644 --- a/code/modules/shuttles/landmarks.dm +++ b/code/modules/shuttles/landmarks.dm @@ -23,6 +23,8 @@ var/turf/base_turf //Name of the shuttle, null for generic waypoint var/shuttle_restricted + //does it use docking codes? + var/use_docking_codes = TRUE /obj/effect/shuttle_landmark/Initialize(mapload) . = ..() @@ -54,7 +56,7 @@ log_mapping("Could not find docking controller for shuttle waypoint '[name]', docking tag was '[docking_tag]'.") if(using_map.use_overmap) var/obj/effect/overmap/visitable/location = get_overmap_sector(z) - if(location && location.docking_codes) + if(location && location.docking_codes && use_docking_codes) docking_controller.docking_codes = location.docking_codes /obj/effect/shuttle_landmark/forceMove() diff --git a/icons/obj/dummystairs.dmi b/icons/obj/dummystairs.dmi new file mode 100644 index 0000000000..ded270c06e Binary files /dev/null and b/icons/obj/dummystairs.dmi differ diff --git a/icons/obj/railing.dmi b/icons/obj/railing.dmi index 3a1f07cdbf..6c62cf14da 100644 Binary files a/icons/obj/railing.dmi and b/icons/obj/railing.dmi differ diff --git a/icons/turf/flooring/decals_vr.dmi b/icons/turf/flooring/decals_vr.dmi index ec5a10b009..346f9a4bdf 100644 Binary files a/icons/turf/flooring/decals_vr.dmi and b/icons/turf/flooring/decals_vr.dmi differ diff --git a/icons/turf/nanitegoo.dmi b/icons/turf/nanitegoo.dmi new file mode 100644 index 0000000000..f8f798a888 Binary files /dev/null and b/icons/turf/nanitegoo.dmi differ diff --git a/icons/turf/outdoors.dmi b/icons/turf/outdoors.dmi index 5895a29740..33878db011 100644 Binary files a/icons/turf/outdoors.dmi and b/icons/turf/outdoors.dmi differ diff --git a/icons/turf/outdoors_edge.dmi b/icons/turf/outdoors_edge.dmi index b3919c2675..47a39712c8 100644 Binary files a/icons/turf/outdoors_edge.dmi and b/icons/turf/outdoors_edge.dmi differ diff --git a/vorestation.dme b/vorestation.dme index e316a8d69e..4e57a3f33e 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -1893,6 +1893,7 @@ #include "code\game\objects\structures\dogbed.dm" #include "code\game\objects\structures\door_assembly.dm" #include "code\game\objects\structures\droppod.dm" +#include "code\game\objects\structures\dummystairs.dm" #include "code\game\objects\structures\electricchair.dm" #include "code\game\objects\structures\extinguisher.dm" #include "code\game\objects\structures\fence.dm" @@ -2063,6 +2064,7 @@ #include "code\game\turfs\simulated\floor_types_eris.dm" #include "code\game\turfs\simulated\floor_types_vr.dm" #include "code\game\turfs\simulated\lava.dm" +#include "code\game\turfs\simulated\nanogoop.dm" #include "code\game\turfs\simulated\underwater.dm" #include "code\game\turfs\simulated\wall_attacks.dm" #include "code\game\turfs\simulated\wall_icon.dm"