diff --git a/_maps/RandomRuins/SpaceRuins/derelict2.dmm b/_maps/RandomRuins/SpaceRuins/derelict2.dmm index c57ac798ac..a20be471f4 100644 --- a/_maps/RandomRuins/SpaceRuins/derelict2.dmm +++ b/_maps/RandomRuins/SpaceRuins/derelict2.dmm @@ -64,12 +64,17 @@ /obj/structure/chair{ dir = 4 }, +/obj/item/clothing/under/polychromic/shirt, +/obj/item/clothing/neck/tie/black, +/obj/item/clothing/shoes/laceup, +/obj/item/storage/wallet/random, +/obj/item/clothing/gloves/color/white, /obj/effect/decal/remains/human, /turf/open/floor/plasteel, /area/ruin/space/has_grav/powered/dinner_for_two) "n" = ( /obj/structure/table, -/obj/item/candle{ +/obj/item/candle/infinite{ pixel_y = 5 }, /obj/item/trash/plate{ @@ -84,6 +89,11 @@ /obj/structure/chair{ dir = 8 }, +/obj/item/clothing/under/polychromic/skirt, +/obj/item/clothing/shoes/laceup, +/obj/item/clothing/gloves/color/white, +/obj/item/clothing/glasses/regular, +/obj/item/lipstick/random, /obj/effect/decal/remains/human, /turf/open/floor/plasteel, /area/ruin/space/has_grav/powered/dinner_for_two) diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index c4da3f1e32..053136a434 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -11448,12 +11448,6 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/fitness) -"aAq" = ( -/obj/machinery/atmospherics/components/unary/tank/air{ - dir = 8 - }, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) "aAr" = ( /obj/structure/closet, /obj/effect/decal/cleanable/cobweb, @@ -11963,13 +11957,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plating, /area/maintenance/starboard/fore) -"aBD" = ( -/obj/machinery/meter, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 8 - }, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) "aBE" = ( /obj/item/clothing/under/rank/mailman, /obj/item/clothing/head/mailman, @@ -12352,10 +12339,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/crew_quarters/fitness) -"aCx" = ( -/obj/machinery/atmospherics/components/binary/valve, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) "aCy" = ( /obj/effect/decal/cleanable/oil, /turf/open/floor/plating, @@ -12961,10 +12944,8 @@ /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet) "aDV" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden, /obj/machinery/meter, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 5 - }, /turf/open/floor/plating, /area/maintenance/starboard/fore) "aDW" = ( @@ -56758,6 +56739,12 @@ }, /turf/open/floor/wood, /area/maintenance/bar) +"gOZ" = ( +/obj/machinery/door/airlock/maintenance{ + req_access_txt = "12" + }, +/turf/open/floor/plating, +/area/crew_quarters/fitness) "gWd" = ( /obj/structure/cable{ icon_state = "1-4" @@ -56878,6 +56865,12 @@ /obj/machinery/rnd/production/techfab/department/cargo, /turf/open/floor/plasteel, /area/quartermaster/office) +"jnR" = ( +/obj/machinery/atmospherics/components/binary/valve{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "jqv" = ( /obj/structure/chair/wood/normal{ dir = 1 @@ -57260,6 +57253,12 @@ /obj/item/reagent_containers/food/drinks/beer, /turf/open/floor/plating, /area/maintenance/starboard/aft) +"rsp" = ( +/obj/machinery/atmospherics/components/unary/tank/air{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "rBq" = ( /obj/item/clothing/head/kitty, /obj/item/clothing/under/maid, @@ -57561,6 +57560,13 @@ }, /turf/open/floor/wood, /area/maintenance/bar) +"vpY" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 10 + }, +/obj/machinery/meter, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "vxh" = ( /obj/structure/table, /obj/effect/spawner/lootdrop/maintenance{ @@ -96101,12 +96107,12 @@ arj auB auB arj -arj +gOZ arj anf anf -anf -awD +rsp +rsp alP aGB aIf @@ -96355,14 +96361,14 @@ aaa aaa aaf aaa -aaa -aaf -aaa -aaa +gXs +aoV alP -ayf -aBD -aCx +anf +anf +anf +anf +aDW aDV alP aGL @@ -96612,15 +96618,15 @@ aaa aaa aaf aaa -aaa -aaf -aaa -aaa +gXs +aoV alP -aAq -aAq +awD +anf +anf +anf aCy -aCG +jnR alP aGL avI @@ -96877,7 +96883,7 @@ alP alP alP alP -aDW +vpY aFn aGP avI diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index 14d16fe659..d005f1eb40 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -4696,7 +4696,7 @@ }, /area/abductor_ship) "lI" = ( -/turf/open/space/transit, +/turf/open/space/transit/centcom, /area/space) "lJ" = ( /obj/machinery/door/airlock/centcom{ @@ -20511,7 +20511,7 @@ fX fX fX fX -fY +fX fX fX fX @@ -21282,7 +21282,7 @@ fX fX fX fX -fX +fY fX fX fX diff --git a/_maps/shuttles/pirate_default.dmm b/_maps/shuttles/pirate_default.dmm index 91305d2990..445c29241c 100644 --- a/_maps/shuttles/pirate_default.dmm +++ b/_maps/shuttles/pirate_default.dmm @@ -91,6 +91,40 @@ "aj" = ( /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/shuttle/pirate) +"ak" = ( +/obj/machinery/airalarm/all_access{ + dir = 4; + pixel_x = -24 + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small{ + dir = 8 + }, +/obj/structure/closet/secure_closet/freezer{ + locked = 0; + name = "fridge" + }, +/obj/item/storage/box/donkpockets{ + pixel_x = 2; + pixel_y = 3 + }, +/obj/item/storage/box/donkpockets, +/obj/item/storage/fancy/donut_box, +/obj/item/reagent_containers/food/snacks/cookie, +/obj/item/reagent_containers/food/snacks/cookie{ + pixel_x = -6; + pixel_y = -6 + }, +/obj/item/reagent_containers/food/snacks/chocolatebar, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/item/reagent_containers/food/condiment/milk, +/obj/item/reagent_containers/food/condiment/milk, +/turf/open/floor/plasteel, +/area/shuttle/pirate) "al" = ( /obj/machinery/loot_locator, /obj/effect/decal/cleanable/dirt, @@ -622,38 +656,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel, /area/shuttle/pirate) -"bw" = ( -/obj/machinery/airalarm/all_access{ - dir = 4; - pixel_x = -24 - }, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/light/small{ - dir = 8 - }, -/obj/structure/closet/secure_closet/freezer{ - locked = 0; - name = "fridge" - }, -/obj/item/storage/box/donkpockets{ - pixel_x = 2; - pixel_y = 3 - }, -/obj/item/storage/box/donkpockets, -/obj/item/storage/fancy/donut_box, -/obj/item/reagent_containers/food/snacks/cookie, -/obj/item/reagent_containers/food/snacks/cookie{ - pixel_x = -6; - pixel_y = -6 - }, -/obj/item/reagent_containers/food/snacks/chocolatebar, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/shuttle/pirate) "bx" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -1207,7 +1209,7 @@ eA aa ap aw -bw +ak bF aj aj diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index af1043f22e..15e8048926 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -97,6 +97,20 @@ //the define for visible message range in combat #define COMBAT_MESSAGE_RANGE 3 +//Shove knockdown lengths (deciseconds) +#define SHOVE_KNOCKDOWN_SOLID 30 +#define SHOVE_KNOCKDOWN_HUMAN 30 +#define SHOVE_KNOCKDOWN_TABLE 30 +#define SHOVE_KNOCKDOWN_COLLATERAL 10 +//Shove slowdown +#define SHOVE_SLOWDOWN_ID "shove_slowdown" +#define SHOVE_SLOWDOWN_LENGTH 30 +#define SHOVE_SLOWDOWN_STRENGTH 0.85 //multiplier +//Shove disarming item list +GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( + /obj/item/gun))) + + //Combat object defines //Embedded objects diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm index 76f66521a7..e6d4fd126b 100644 --- a/code/__DEFINES/obj_flags.dm +++ b/code/__DEFINES/obj_flags.dm @@ -25,6 +25,7 @@ #define NOBLUDGEON (1<<7) // when an item has this it produces no "X has been hit by Y with Z" message in the default attackby() #define NODROP (1<<8) // This flag makes it so that an item literally cannot be removed at all, or at least that's how it should be. Only deleted. #define ABSTRACT (1<<9) // for all things that are technically items but used for various different stuff +#define IMMUTABLE_SLOW (1<<10) //When players should not be able to change the slowdown of the item (Speed potions, ect) // Flags for the clothing_flags var on /obj/item/clothing diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index e8f718e590..d23d0905e9 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -167,4 +167,7 @@ attack_message = "[user] has [message_verb] [src][message_hit_area] with [I]!" visible_message("[attack_message]",\ "[attack_message]", null, COMBAT_MESSAGE_RANGE) + if(hit_area == BODY_ZONE_HEAD) + if(prob(2)) + playsound(src, 'sound/weapons/dink.ogg', 30, 1) return 1 diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm index 4b347b2a39..c92db7cd01 100644 --- a/code/controllers/subsystem/timer.dm +++ b/code/controllers/subsystem/timer.dm @@ -269,7 +269,7 @@ SUBSYSTEM_DEF(timer) var/new_bucket_count var/i = 1 for (i in 1 to length(alltimers)) - var/datum/timedevent/timer = alltimers[1] + var/datum/timedevent/timer = alltimers[i] if (!timer) continue diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 7528f83c38..7e75dc8e8e 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -227,7 +227,7 @@ if((mob_occupant.stat == DEAD) || (mob_occupant.suiciding) || mob_occupant.hellbound) //Autoeject corpses and suiciding dudes. connected_message("Clone Rejected: Deceased.") if(internal_radio) - SPEAK("The cloning of [mob_occupant.real_name] has been \ + SPEAK("The cloning has been \ aborted due to unrecoverable tissue failure.") go_out() mob_occupant.apply_vore_prefs() @@ -261,7 +261,7 @@ else if((mob_occupant.cloneloss <= (100 - heal_level))) connected_message("Cloning Process Complete.") if(internal_radio) - SPEAK("The cloning cycle of [mob_occupant.real_name] is complete.") + SPEAK("The cloning cycle is complete.") // If the cloner is upgraded to debugging high levels, sometimes // organs and limbs can be missing. @@ -319,7 +319,7 @@ return else connected_message("Emergency Ejection") - SPEAK("An emergency ejection of [clonemind.name] has occurred. Survival not guaranteed.") + SPEAK("An emergency ejection of the current clone has occurred. Survival not guaranteed.") to_chat(user, "You force an emergency ejection. ") go_out() mob_occupant.apply_vore_prefs() @@ -412,7 +412,7 @@ var/mob/living/mob_occupant = occupant if(mob_occupant && prob(100/(severity*efficiency))) connected_message(Gibberish("EMP-caused Accidental Ejection", 0)) - SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of [mob_occupant.real_name] prematurely." ,0)) + SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of, ERROR: John Doe, prematurely." ,0)) mob_occupant.apply_vore_prefs() go_out() diff --git a/code/game/objects/effects/effect_system/effects_sparks.dm b/code/game/objects/effects/effect_system/effects_sparks.dm index 44aab00852..0656d9b3ca 100644 --- a/code/game/objects/effects/effect_system/effects_sparks.dm +++ b/code/game/objects/effects/effect_system/effects_sparks.dm @@ -30,20 +30,20 @@ playsound(src, "sparks", 100, TRUE) var/turf/T = loc if(isturf(T)) - T.hotspot_expose(300,5) + T.hotspot_expose(700,5) QDEL_IN(src, 20) /obj/effect/particle_effect/sparks/Destroy() var/turf/T = loc if(isturf(T)) - T.hotspot_expose(300,1) + T.hotspot_expose(700,1) return ..() /obj/effect/particle_effect/sparks/Move() ..() var/turf/T = loc if(isturf(T)) - T.hotspot_expose(300,1) + T.hotspot_expose(700,1) /datum/effect_system/spark_spread effect_type = /obj/effect/particle_effect/sparks diff --git a/code/game/objects/items/RPD.dm b/code/game/objects/items/RPD.dm index 1c6cc9cfcb..41ddc22106 100644 --- a/code/game/objects/items/RPD.dm +++ b/code/game/objects/items/RPD.dm @@ -187,6 +187,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF var/datum/effect_system/spark_spread/spark_system + var/effectcooldown var/working = 0 var/p_dir = NORTH var/p_flipped = FALSE @@ -207,7 +208,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( /obj/item/pipe_dispenser/New() . = ..() spark_system = new /datum/effect_system/spark_spread - spark_system.set_up(5, 0, src) + spark_system.set_up(1, 0, src) spark_system.attach(src) if(!first_atmos) first_atmos = GLOB.atmos_pipe_recipes[GLOB.atmos_pipe_recipes[1]][1] @@ -313,8 +314,9 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( else mode |= n - if(playeffect) + if(playeffect && world.time >= effectcooldown) spark_system.start() + effectcooldown = world.time + 100 playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) /obj/item/pipe_dispenser/pre_attack(atom/A, mob/user) diff --git a/code/game/objects/items/candle.dm b/code/game/objects/items/candle.dm index b7a3b0c76c..1165501d9a 100644 --- a/code/game/objects/items/candle.dm +++ b/code/game/objects/items/candle.dm @@ -8,72 +8,70 @@ item_state = "candle1" w_class = WEIGHT_CLASS_TINY light_color = LIGHT_COLOR_FIRE + heat = 1000 var/wax = 1000 var/lit = FALSE var/infinite = FALSE var/start_lit = FALSE - heat = 1000 /obj/item/candle/Initialize() . = ..() if(start_lit) - // No visible message - light(show_message = FALSE) + light() /obj/item/candle/update_icon() - var/i - if(wax>750) - i = 1 - else if(wax>400) - i = 2 - else i = 3 - icon_state = "candle[i][lit ? "_lit" : ""]" - + icon_state = "candle[(wax > 400) ? ((wax > 750) ? 1 : 2) : 3][lit ? "_lit" : ""]" /obj/item/candle/attackby(obj/item/W, mob/user, params) - ..() var/msg = W.ignition_effect(src, user) if(msg) light(msg) + else + return ..() /obj/item/candle/fire_act(exposed_temperature, exposed_volume) - if(!src.lit) + if(!lit) light() //honk - ..() + return ..() + +/obj/item/candle/is_hot() + return lit * heat /obj/item/candle/proc/light(show_message) - if(!src.lit) - src.lit = TRUE - //src.damtype = "fire" + if(!lit) + lit = TRUE if(show_message) usr.visible_message(show_message) - set_light(CANDLE_LUMINOSITY, 0.8) + set_light(CANDLE_LUMINOSITY) START_PROCESSING(SSobj, src) update_icon() +/obj/item/candle/proc/put_out_candle() + if(!lit) + return + lit = FALSE + update_icon() + set_light(0) + return TRUE + +/obj/item/candle/extinguish() + put_out_candle() + return ..() /obj/item/candle/process() if(!lit) - return + return PROCESS_KILL if(!infinite) wax-- if(!wax) - new/obj/item/trash/candle(src.loc) + new /obj/item/trash/candle(loc) qdel(src) update_icon() open_flame() /obj/item/candle/attack_self(mob/user) - if(lit) - user.visible_message( - "[user] snuffs [src].") - lit = FALSE - update_icon() - set_light(0) - -/obj/item/candle/is_hot() - return lit * heat - + if(put_out_candle()) + user.visible_message("[user] snuffs [src].") /obj/item/candle/infinite infinite = TRUE diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/extinguisher.dm index a57bf47a2e..e0d6b553fd 100644 --- a/code/game/objects/items/extinguisher.dm +++ b/code/game/objects/items/extinguisher.dm @@ -227,7 +227,7 @@ repetition++ addtimer(CALLBACK(src, /obj/item/extinguisher/proc/move_chair, B, movementdirection, repetition), timer_seconds) -/obj/item/extinguisher/AltClick(mob/user) +/obj/item/extinguisher/screwdriver_act(mob/user, obj/item/tool) if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user))) return EmptyExtinguisher(user) @@ -242,3 +242,4 @@ theturf.MakeSlippery(TURF_WET_WATER, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS) user.visible_message("[user] empties out \the [src] onto the floor using the release valve.", "You quietly empty out \the [src] using its release valve.") + diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index 40435c2000..d6f304653d 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -51,6 +51,20 @@ new /obj/item/stack/rods(get_turf(src), number_of_rods) qdel(src) +/obj/structure/lattice/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) + if(the_rcd.mode == RCD_FLOORWALL) + return list("mode" = RCD_FLOORWALL, "delay" = 0, "cost" = 2) + +/obj/structure/lattice/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) + if(passed_mode == RCD_FLOORWALL) + to_chat(user, "You build a floor.") + var/turf/T = src.loc + if(isspaceturf(T)) + T.PlaceOnTop(/turf/open/floor/plating) + qdel(src) + return TRUE + return FALSE + /obj/structure/lattice/singularity_pull(S, current_size) if(current_size >= STAGE_FOUR) deconstruct() diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index 659a58b2dc..63b5f4b160 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -245,6 +245,10 @@ return 0 if(C.m_intent == MOVE_INTENT_WALK && (lube&NO_SLIP_WHEN_WALKING)) return 0 + if(ishuman(C) && (lube&NO_SLIP_WHEN_WALKING)) + var/mob/living/carbon/human/H = C + if(!H.sprinting && H.getStaminaLoss() >= 20) + return 0 if(!(lube&SLIDE_ICE)) to_chat(C, "You slipped[ O ? " on the [O.name]" : ""]!") playsound(C.loc, 'sound/misc/slip.ogg', 50, 1, -3) diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index 9d2adbdfba..e783b8a9a0 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -126,6 +126,17 @@ else to_chat(user, "You hit [src], to no effect!") +/turf/open/floor/plating/foam/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) + if(the_rcd.mode == RCD_FLOORWALL) + return list("mode" = RCD_FLOORWALL, "delay" = 0, "cost" = 1) + +/turf/open/floor/plating/foam/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) + if(passed_mode == RCD_FLOORWALL) + to_chat(user, "You build a floor.") + ChangeTurf(/turf/open/floor/plating) + return TRUE + return FALSE + /turf/open/floor/plating/foam/ex_act() ..() ScrapeAway() diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm index 7dcf27ce4b..f0f0667c37 100644 --- a/code/game/turfs/space/transit.dm +++ b/code/game/turfs/space/transit.dm @@ -41,6 +41,14 @@ /turf/open/space/transit/border/east dir = EAST +/turf/open/space/transit/centcom + dir = SOUTH + +/turf/open/space/transit/centcom/Entered(atom/movable/AM, atom/OldLoc) + ..() + if(!locate(/obj/structure/lattice) in src) + throw_atom(AM) + /turf/open/space/transit/border/Entered(atom/movable/AM, atom/OldLoc) ..() if(!locate(/obj/structure/lattice) in src) diff --git a/code/modules/VR/vr_sleeper.dm b/code/modules/VR/vr_sleeper.dm index 7169378179..4e342f6ced 100644 --- a/code/modules/VR/vr_sleeper.dm +++ b/code/modules/VR/vr_sleeper.dm @@ -167,6 +167,7 @@ vr_human.undershirt = H.undershirt vr_human.underwear = H.underwear vr_human.updateappearance(TRUE, TRUE, TRUE) + vr_human.give_genitals(TRUE) //CITADEL ADD if(outfit) var/datum/outfit/O = new outfit() O.equip(vr_human) @@ -229,4 +230,4 @@ for (var/mob/living/carbon/human/virtual_reality/H in vr_area) if (H.stat == DEAD && !H.vr_sleeper && !H.real_mind) qdel(H) - addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES) \ No newline at end of file + addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES) diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm index 85866d5c51..f5075b57b7 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm @@ -714,7 +714,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null SDQL_print(x, text_list) if (!isnull(x) && !isnum(x) && L[x] != null) text_list += " -> " - SDQL_print(L[L[x]]) + SDQL_print(L[L[x]], text_list) text_list += "]
" else if(isnull(object)) diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm index a984e40fee..3056b459d8 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm @@ -184,6 +184,9 @@ /proc/_list_swap(list/L, Index1, Index2) L.Swap(Index1, Index2) +/proc/_list_get(list/L, index) + return L[index] + /proc/_walk(ref, dir, lag) walk(ref, dir, lag) diff --git a/code/modules/admin/verbs/panicbunker.dm b/code/modules/admin/verbs/panicbunker.dm index 175ab45aeb..ab3aeb4ba5 100644 --- a/code/modules/admin/verbs/panicbunker.dm +++ b/code/modules/admin/verbs/panicbunker.dm @@ -22,7 +22,7 @@ to_chat(usr, "The Database is not enabled!") return - GLOB.bunker_passthrough |= ckeytobypass + GLOB.bunker_passthrough |= ckey(ckeytobypass) log_admin("[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.") message_admins("[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.") @@ -34,7 +34,7 @@ to_chat(usr, "The Database is not enabled!") return - GLOB.bunker_passthrough -= ckeytobypass + GLOB.bunker_passthrough -= ckey(ckeytobypass) log_admin("[key_name(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.") message_admins("[key_name(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.") diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index 51c8803cee..f3975851ca 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -185,6 +185,9 @@ structure_check() searches for nearby cultist structures required for the invoca color = RUNE_COLOR_OFFER req_cultists = 1 rune_in_use = FALSE + var/mob/living/currentconversionman + var/conversiontimeout + var/conversionresult /obj/effect/rune/convert/do_invoke_glow() return @@ -241,6 +244,25 @@ structure_check() searches for nearby cultist structures required for the invoca to_chat(M, "Something is shielding [convertee]'s mind!") log_game("Offer rune failed - convertee had anti-magic") return 0 + to_chat(convertee, "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \ + and something evil takes root.") + to_chat(convertee, "Do you wish to embrace the Geometer of Blood? Click here to stop resisting the truth. Or you could choose to continue resisting...") + currentconversionman = convertee + conversiontimeout = world.time + (10 SECONDS) + convertee.Stun(100) + convertee.add_trait(TRAIT_MUTE, "conversionrune") + conversionresult = FALSE + while(world.time < conversiontimeout && convertee && !conversionresult) + stoplag(1) + currentconversionman = null + if(!convertee) + return FALSE + convertee.remove_trait(TRAIT_MUTE, "conversionrune") + if(get_turf(convertee) != get_turf(src)) + return FALSE + if(!conversionresult) + do_sacrifice(convertee, invokers, TRUE) + return FALSE var/brutedamage = convertee.getBruteLoss() var/burndamage = convertee.getFireLoss() if(brutedamage || burndamage) @@ -252,8 +274,6 @@ structure_check() searches for nearby cultist structures required for the invoca SSticker.mode.add_cultist(convertee.mind, 1) new /obj/item/melee/cultblade/dagger(get_turf(src)) convertee.mind.special_role = ROLE_CULTIST - to_chat(convertee, "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \ - and something evil takes root.") to_chat(convertee, "Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve the Geometer above all else. Bring it back.\ ") if(ishuman(convertee)) @@ -263,7 +283,7 @@ structure_check() searches for nearby cultist structures required for the invoca H.cultslurring = 0 return 1 -/obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers) +/obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers, force_a_sac) var/mob/living/first_invoker = invokers[1] if(!first_invoker) return FALSE @@ -273,7 +293,7 @@ structure_check() searches for nearby cultist structures required for the invoca var/big_sac = FALSE - if((((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || C.cult_team.is_sacrifice_target(sacrificial.mind)) && invokers.len < 3) + if(!force_a_sac && (((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || C.cult_team.is_sacrifice_target(sacrificial.mind)) && invokers.len < 3) for(var/M in invokers) to_chat(M, "[sacrificial] is too greatly linked to the world! You need three acolytes!") log_game("Offer rune failed - not enough acolytes and target is living or sac target") @@ -313,6 +333,12 @@ structure_check() searches for nearby cultist structures required for the invoca sacrificial.gib() return TRUE +/obj/effect/rune/convert/Topic(href, href_list) + if(href_list["signmeup"]) + if(currentconversionman == usr) + conversionresult = TRUE + else + to_chat(usr, "Your fate has already been set in stone.") /obj/effect/rune/empower @@ -442,9 +468,9 @@ structure_check() searches for nearby cultist structures required for the invoca //Ritual of Dimensional Rending: Calls forth the avatar of Nar'Sie upon the station. /obj/effect/rune/narsie cultist_name = "Nar'Sie" - cultist_desc = "tears apart dimensional barriers, calling forth the Geometer. Requires 9 invokers." + cultist_desc = "tears apart dimensional barriers, calling forth the Geometer. Requires 9 invokers, minus one for every 3 sacrifices." invocation = "TOK-LYR RQA-NAP G'OLT-ULOFT!!" - req_cultists = 9 + req_cultists = 1 icon = 'icons/effects/96x96.dmi' color = RUNE_COLOR_DARKRED icon_state = "rune_large" @@ -471,6 +497,10 @@ structure_check() searches for nearby cultist structures required for the invoca if(!is_station_level(z)) return var/mob/living/user = invokers[1] + if(invokers.len < 9 - (GLOB.sacrificed.len * 0.35)) + to_chat(user, "You need at least [(9 - (GLOB.sacrificed.len * 0.35)) - invokers.len] more adjacent cultists to use this rune in such a manner.") + fail_invoke() + return var/datum/antagonist/cult/user_antag = user.mind.has_antag_datum(/datum/antagonist/cult,TRUE) var/datum/objective/eldergod/summon_objective = locate() in user_antag.cult_team.objectives var/area/place = get_area(src) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm index 6bafba9abc..07ee17a1bd 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm @@ -61,6 +61,8 @@ //Actually transfer the gas var/datum/gas_mixture/removed = air2.remove(transfer_moles) + removed.react(src) + update_parents() return removed diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm index bc7193e5ca..a9972ca2d4 100644 --- a/code/modules/cargo/packs.dm +++ b/code/modules/cargo/packs.dm @@ -622,7 +622,7 @@ /datum/supply_pack/security/armory/wt550 - name = "WT-550 Auto Rifle Crate" + name = "WT-550 Semi-Auto Rifle Crate" desc = "Contains two high-powered, semiautomatic rifles chambered in 4.6x30mm. Requires Armory access to open." cost = 3500 contains = list(/obj/item/gun/ballistic/automatic/wt550, @@ -630,8 +630,8 @@ crate_name = "auto rifle crate" /datum/supply_pack/security/armory/wt550ammo - name = "WT-550 Auto Rifle Ammo Crate" - desc = "Contains four 20-round magazines for the WT-550 Auto Rifle. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open." + name = "WT-550 Semi-Auto SMG Ammo Crate" + desc = "Contains four 20-round magazines for the WT-550 Semi-Auto SMG. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open." cost = 2500 contains = list(/obj/item/ammo_box/magazine/wt550m9, /obj/item/ammo_box/magazine/wt550m9, @@ -639,9 +639,9 @@ /obj/item/ammo_box/magazine/wt550m9) crate_name = "auto rifle ammo crate" -/datum/supply_pack/security/armory/wt550ammo_nonlethal // Takes around 11 shots to stun crit someone - name = "WT-550 Auto Rifle Non-Lethal Ammo Crate" - desc = "Contains four 20-round magazines for the WT-550 Auto Rifle. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open." +/datum/supply_pack/security/armory/wt550ammo_nonlethal // Takes around 12 shots to stun crit someone + name = "WT-550 Semi-Auto SMG Non-Lethal Ammo Crate" + desc = "Contains four 20-round magazines for the WT-550 Semi-Auto SMG. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open." cost = 1500 contains = list(/obj/item/ammo_box/magazine/wt550m9/wtrubber, /obj/item/ammo_box/magazine/wt550m9/wtrubber, @@ -650,8 +650,8 @@ crate_name = "auto rifle ammo crate" /datum/supply_pack/security/armory/wt550ammo_special - name = "WT-550 Auto Rifle Special Ammo Crate" - desc = "Contains 2 20-round Armour Piercing and Incendiary magazines for the WT-550 Auto Rifle. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open." + name = "WT-550 Semi-Auto SMG Special Ammo Crate" + desc = "Contains 2 20-round Armour Piercing and Incendiary magazines for the WT-550 Semi-Auto SMG. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open." cost = 4500 contains = list(/obj/item/ammo_box/magazine/wt550m9/wtap, /obj/item/ammo_box/magazine/wt550m9/wtap, diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 18f50f03a3..06f23574e1 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -499,7 +499,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) qdel(query_client_in_db) return if(!query_client_in_db.NextRow()) - if (CONFIG_GET(flag/panic_bunker) && !holder && !GLOB.deadmins[ckey] && !ckey in GLOB.bunker_passthrough) + if (CONFIG_GET(flag/panic_bunker) && !holder && !GLOB.deadmins[ckey] && !(ckey in GLOB.bunker_passthrough)) log_access("Failed Login: [key] - New account attempting to connect during panic bunker") message_admins("Failed Login: [key] - New account attempting to connect during panic bunker") to_chat(src, "You must first join the Discord to verify your account before joining this server.
To do so, read the rules and post a request in the #station-access-requests channel under the \"Main server\" category in the Discord server linked here: https://discord.gg/E6SQuhz
") //CIT CHANGE - makes the panic bunker disconnect message point to the discord diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 1e65c6ca3f..746d5da60d 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -24,6 +24,8 @@ var/can_flashlight = 0 var/scan_reagents = 0 //Can the wearer see reagents while it's equipped? + var/blocks_shove_knockdown = FALSE //Whether wearing the clothing item blocks the ability for shove to knock down. + var/clothing_flags = NONE //Var modification - PLEASE be careful with this I know who you are and where you live diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 7265800c49..ab9ffb9b18 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -3,7 +3,7 @@ desc = "Standard Security gear. Protects the head from impacts." icon_state = "helmet" item_state = "helmet" - armor = list("melee" = 35, "bullet" = 30, "laser" = 30,"energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) + armor = list("melee" = 40, "bullet" = 30, "laser" = 30,"energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) flags_inv = HIDEEARS cold_protection = HEAD min_cold_protection_temperature = HELMET_MIN_TEMP_PROTECT diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index ad8fafb872..8b1b1dac25 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -139,7 +139,7 @@ name = "security beret" desc = "A robust beret with the security insignia emblazoned on it. Uses reinforced fabric to offer sufficient protection." icon_state = "beret_badge" - armor = list("melee" = 40, "bullet" = 30, "laser" = 30,"energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 50) + armor = list("melee" = 40, "bullet" = 30, "laser" = 30,"energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) strip_delay = 60 dog_fashion = null @@ -152,7 +152,7 @@ name = "warden's beret" desc = "A special beret with the Warden's insignia emblazoned on it. For wardens with class." icon_state = "wardenberet" - armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 50) + armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) strip_delay = 60 /obj/item/clothing/head/beret/sec/navyofficer diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 97c9da289b..b10bf39729 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -110,13 +110,14 @@ /obj/item/clothing/suit/armor/riot name = "riot suit" - desc = "A suit of semi-flexible polycarbonate body armor with heavy padding to protect against melee attacks." + desc = "A suit of semi-flexible polycarbonate body armor with heavy padding to protect against melee attacks. Helps the wearer resist shoving in close quarters." icon_state = "riot" item_state = "swat_suit" body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS armor = list("melee" = 50, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80) + blocks_shove_knockdown = TRUE strip_delay = 80 equip_delay_other = 60 diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index 2e695e6772..b8195e23d9 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -239,10 +239,10 @@ if(ishostile(target)) var/mob/living/simple_animal/hostile/H = target if(H.ranged) //briefly delay ranged attacks - if(H.ranged_cooldown_time >= world.time) - H.ranged_cooldown_time += bonus_value + if(H.ranged_cooldown >= world.time) + H.ranged_cooldown += bonus_value else - H.ranged_cooldown_time = bonus_value + world.time + H.ranged_cooldown = bonus_value + world.time //magmawing watcher /obj/item/crusher_trophy/blaster_tubes/magma_wing diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm index 1e77a907c6..7276039443 100644 --- a/code/modules/mining/machine_vending.dm +++ b/code/modules/mining/machine_vending.dm @@ -11,6 +11,7 @@ var/obj/item/card/id/inserted_id var/list/prize_list = list( //if you add something to this, please, for the love of god, sort it by price/type. use tabs and not spaces. new /datum/data/mining_equipment("1 Marker Beacon", /obj/item/stack/marker_beacon, 10), + new /datum/data/mining_equipment("50 Point Transfer Card", /obj/item/card/mining_point_card, 50), new /datum/data/mining_equipment("10 Marker Beacons", /obj/item/stack/marker_beacon/ten, 100), new /datum/data/mining_equipment("30 Marker Beacons", /obj/item/stack/marker_beacon/thirty, 300), new /datum/data/mining_equipment("Whiskey", /obj/item/reagent_containers/food/drinks/bottle/whiskey, 100), @@ -23,7 +24,7 @@ new /datum/data/mining_equipment("Shelter Capsule", /obj/item/survivalcapsule, 400), new /datum/data/mining_equipment("GAR Meson Scanners", /obj/item/clothing/glasses/meson/gar, 500), new /datum/data/mining_equipment("Explorer's Webbing", /obj/item/storage/belt/mining, 500), - new /datum/data/mining_equipment("Point Transfer Card", /obj/item/card/mining_point_card, 500), + new /datum/data/mining_equipment("500 Point Transfer Card", /obj/item/card/mining_point_card/mp500, 500), new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/storage/firstaid/brute, 600), new /datum/data/mining_equipment("Tracking Implant Kit", /obj/item/storage/box/minertracker, 600), new /datum/data/mining_equipment("Survival Medipen", /obj/item/reagent_containers/hypospray/medipen/survival, 750), @@ -41,6 +42,9 @@ new /datum/data/mining_equipment("Lazarus Injector", /obj/item/lazarus_injector, 1000), new /datum/data/mining_equipment("Silver Pickaxe", /obj/item/pickaxe/silver, 1000), new /datum/data/mining_equipment("Mining Conscription Kit", /obj/item/storage/backpack/duffelbag/mining_conscript, 1000), + new /datum/data/mining_equipment("1000 Point Transfer Card", /obj/item/card/mining_point_card/mp1000, 1000), + new /datum/data/mining_equipment("1500 Point Transfer Card", /obj/item/card/mining_point_card/mp1500, 1500), + new /datum/data/mining_equipment("2000 Point Transfer Card", /obj/item/card/mining_point_card/mp2000, 2000), new /datum/data/mining_equipment("Jetpack Upgrade", /obj/item/tank/jetpack/suit, 2000), new /datum/data/mining_equipment("Space Cash", /obj/item/stack/spacecash/c1000, 2000), new /datum/data/mining_equipment("Mining Hardsuit", /obj/item/clothing/suit/space/hardsuit/mining, 2000), @@ -245,12 +249,30 @@ w_class = WEIGHT_CLASS_TINY /**********************Mining Point Card**********************/ - +//mp = Miner Pointers +//c = Cash +//TODO add in cr = Credits for cargo /obj/item/card/mining_point_card name = "mining points card" - desc = "A small card preloaded with mining points. Swipe your ID card over it to transfer the points, then discard." + desc = "A small card preloaded with mining points. Swipe your ID card over it to transfer the points, then discard. This one only holds a small 50 points on it." icon_state = "data_1" - var/points = 500 + var/points = 50 + +/obj/item/card/mining_point_card/mp500 + desc = "A small card preloaded with 500 mining points. Swipe your ID card over it to transfer the points, then discard." + points = 500 + +/obj/item/card/mining_point_card/mp1000 + desc = "A small card preloaded with 1000 mining points. Swipe your ID card over it to transfer the points, then discard." + points = 1000 + +/obj/item/card/mining_point_card/mp1500 + desc = "A small card preloaded with 1500 mining points. Swipe your ID card over it to transfer the points, then discard." + points = 1500 + +/obj/item/card/mining_point_card/mp2000 + desc = "A small card preloaded with 2000 mining points. Swipe your ID card over it to transfer the points, then discard." + points = 2000 /obj/item/card/mining_point_card/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/card/id)) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 7909b5e71a..fa66daf143 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -495,11 +495,11 @@ /mob/living/carbon/human/proc/canUseHUD() return !(src.stat || IsKnockdown() || IsStun() || src.restrained()) -/mob/living/carbon/human/can_inject(mob/user, error_msg, target_zone, var/penetrate_thick = 0) +/mob/living/carbon/human/can_inject(mob/user, error_msg, target_zone, penetrate_thick = FALSE, bypass_immunity = FALSE) . = 1 // Default to returning true. if(user && !target_zone) target_zone = user.zone_selected - if(has_trait(TRAIT_PIERCEIMMUNE)) + if(has_trait(TRAIT_PIERCEIMMUNE) && !bypass_immunity) . = 0 // If targeting the head, see if the head item is thin enough. // If targeting anything else, see if the wear suit is thin enough. @@ -892,6 +892,21 @@ . = ..(M,force,check_loc) stop_pulling() +/mob/living/carbon/human/proc/is_shove_knockdown_blocked() //If you want to add more things that block shove knockdown, extend this + var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, back, gloves, shoes, belt, s_store, glasses, ears, wear_id) //Everything but pockets. Pockets are l_store and r_store. (if pockets were allowed, putting something armored, gloves or hats for example, would double up on the armor) + for(var/bp in body_parts) + if(istype(bp, /obj/item/clothing)) + var/obj/item/clothing/C = bp + if(C.blocks_shove_knockdown) + return TRUE + return FALSE + +/mob/living/carbon/human/proc/clear_shove_slowdown() + remove_movespeed_modifier(SHOVE_SLOWDOWN_ID) + var/active_item = get_active_held_item() + if(is_type_in_typecache(active_item, GLOB.shove_disarming_types)) + visible_message("[src.name] regains their grip on \the [active_item]!", "You regain your grip on \the [active_item]", null, COMBAT_MESSAGE_RANGE) + /mob/living/carbon/human/do_after_coefficent() . = ..() . *= physiology.do_after_speed diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 7c0eaacf26..0e67ce7510 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -170,6 +170,9 @@ var/mob/living/L = M if(L.has_trait(TRAIT_PUSHIMMUNE)) return 1 + //If they're a human, and they're not in help intent, block pushing + if(ishuman(M) && (M.a_intent != INTENT_HELP)) + return TRUE //anti-riot equipment is also anti-push for(var/obj/item/I in M.held_items) if(!istype(M, /obj/item/clothing)) diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index a36800c2f9..e43db529b8 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -192,7 +192,7 @@ /obj/item/stock_parts/cell/secborg name = "security borg rechargeable D battery" - maxcharge = 600 //600 max charge / 100 charge per shot = six shots + maxcharge = 1750 //35/17/8 disabler/laser/taser shots. materials = list(MAT_GLASS=40) /obj/item/stock_parts/cell/secborg/empty/Initialize() diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm index 8e121dc809..fcc2c6c144 100644 --- a/code/modules/power/generator.dm +++ b/code/modules/power/generator.dm @@ -65,7 +65,7 @@ if(delta_temperature > 0 && cold_air_heat_capacity > 0 && hot_air_heat_capacity > 0) - var/efficiency = 0.45 + var/efficiency = 0.00025 + (hot_air.reaction_results["fire"]*0.01) var/energy_transfer = delta_temperature*hot_air_heat_capacity*cold_air_heat_capacity/(hot_air_heat_capacity+cold_air_heat_capacity) diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 9d2ad4c12a..a04ed08611 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -66,7 +66,7 @@ sparks = new sparks.attach(src) - sparks.set_up(5, TRUE, src) + sparks.set_up(1, TRUE, src) /obj/machinery/power/emitter/ComponentInitialize() . = ..() diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index ae6e309507..a7474fd8cb 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -451,6 +451,8 @@ target.visible_message("[user] pulls the trigger!", "[user] pulls the trigger!") + playsound('sound/weapons/dink.ogg', 30, 1) + if(chambered && chambered.BB) chambered.BB.damage *= 5 diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index b9a509f33f..157cf1f03f 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -161,6 +161,7 @@ var/turf/T = get_turf(user) process_fire(user, user, FALSE, null, BODY_ZONE_HEAD) user.visible_message("[user] blows [user.p_their()] brain[user.p_s()] out with [src]!") + playsound(src, 'sound/weapons/dink.ogg', 30, 1) var/turf/target = get_ranged_target_turf(user, turn(user.dir, 180), BRAINS_BLOWN_THROW_RANGE) B.Remove(user) B.forceMove(T) diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm index d1dcdf22d8..8aa8d53726 100644 --- a/code/modules/projectiles/guns/ballistic/automatic.dm +++ b/code/modules/projectiles/guns/ballistic/automatic.dm @@ -113,8 +113,8 @@ icon_state = "c20r[magazine ? "-[CEILING(get_ammo(0)/4, 1)*4]" : ""][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]" /obj/item/gun/ballistic/automatic/wt550 - name = "security auto rifle" - desc = "An outdated personal defence weapon. Uses 4.6x30mm rounds and is designated the WT-550 Automatic Rifle." + name = "security semi-auto smg" + desc = "An outdated personal defence weapon. Uses 4.6x30mm rounds and is designated the WT-550 Semi-Automatic SMG." icon_state = "wt550" item_state = "arg" mag_type = /obj/item/ammo_box/magazine/wt550m9 diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 5e3432a149..6060ceba99 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -184,6 +184,7 @@ if(user.is_holding(src)) user.visible_message("[user] melts [user.p_their()] face off with [src]!") playsound(loc, fire_sound, 50, 1, -1) + playsound(src, 'sound/weapons/dink.ogg', 30, 1) var/obj/item/ammo_casing/energy/shot = ammo_type[select] cell.use(shot.e_cost) update_icon() diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index a549e309c8..066b652984 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -50,7 +50,8 @@ can_charge = FALSE desc = "An energy-based laser gun that draws power from the cyborg's internal energy cell directly. So this is what freedom looks like?" selfcharge = EGUN_SELFCHARGE_BORG - charge_delay = 6 + cell_type = /obj/item/stock_parts/cell/secborg + charge_delay = 3 /obj/item/gun/energy/laser/cyborg/emp_act() return diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm index 7368a9fa7b..3733dad9a3 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -29,7 +29,8 @@ can_flashlight = FALSE can_charge = FALSE selfcharge = EGUN_SELFCHARGE_BORG - charge_delay = 10 + cell_type = /obj/item/stock_parts/cell/secborg + charge_delay = 5 /obj/item/gun/energy/e_gun/advtaser/cyborg/mean desc = "An integrated hybrid taser that draws directly from a cyborg's power cell." @@ -49,7 +50,8 @@ desc = "An integrated disabler that draws from a cyborg's power cell. This one contains a limiter to prevent the cyborg's power cell from overheating." can_charge = FALSE selfcharge = EGUN_SELFCHARGE_BORG - charge_delay = 10 + cell_type = /obj/item/stock_parts/cell/secborg + charge_delay = 5 /obj/item/gun/energy/disabler/cyborg/mean desc = "An integrated disabler that draws from a cyborg's power cell." diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 267770eb22..1391e9ce42 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -185,6 +185,8 @@ playsound(loc, hitsound, volume, 1, -1) L.visible_message("[L] is hit by \a [src][organ_hit_text]!", \ "[L] is hit by \a [src][organ_hit_text]!", null, COMBAT_MESSAGE_RANGE) + if(def_zone == BODY_ZONE_HEAD) + playsound(src, 'sound/weapons/dink.ogg', 30, 1) L.on_hit(src) var/reagent_note diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index eb3daef393..d77756a649 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -167,10 +167,10 @@ /datum/reagent/drug/methamphetamine/on_mob_add(mob/living/L) ..() - L.add_trait(TRAIT_GOTTAGOREALLYFAST, id) + L.add_trait(TRAIT_IGNORESLOWDOWN, id) /datum/reagent/drug/methamphetamine/on_mob_delete(mob/living/L) - L.remove_trait(TRAIT_GOTTAGOREALLYFAST, id) + L.remove_trait(TRAIT_IGNORESLOWDOWN, id) ..() /datum/reagent/drug/methamphetamine/on_mob_life(mob/living/carbon/M) @@ -180,9 +180,12 @@ M.AdjustStun(-40, 0) M.AdjustKnockdown(-40, 0) M.AdjustUnconscious(-40, 0) - M.adjustStaminaLoss(-2, 0) + M.adjustStaminaLoss(-7.5 * REM, 0) M.Jitter(2) M.adjustBrainLoss(rand(1,4)) + if(prob(30)) + M.confused = max(1, M.confused) + M.heal_overall_damage(2, 2) if(prob(5)) M.emote(pick("twitch", "shiver")) ..() diff --git a/code/modules/reagents/reagent_containers/patch.dm b/code/modules/reagents/reagent_containers/patch.dm index d4111467ba..12439c6b2f 100644 --- a/code/modules/reagents/reagent_containers/patch.dm +++ b/code/modules/reagents/reagent_containers/patch.dm @@ -14,11 +14,11 @@ /obj/item/reagent_containers/pill/patch/attack(mob/living/L, mob/user) if(ishuman(L)) var/obj/item/bodypart/affecting = L.get_bodypart(check_zone(user.zone_selected)) - if(!L.can_inject(user, 1, affecting)) //like monkey code, thickmaterial stops patches - return if(!affecting) to_chat(user, "The limb is missing!") return + if(!L.can_inject(user, TRUE, user.zone_selected, FALSE, TRUE)) //stopped by clothing, not by species immunity. + return if(affecting.status != BODYPART_ORGANIC) to_chat(user, "Medicine won't work on a robotic limb!") return diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm index 2402967ff3..9b42709fe2 100644 --- a/code/modules/research/designs/weapon_designs.dm +++ b/code/modules/research/designs/weapon_designs.dm @@ -218,8 +218,8 @@ //WT550 Mags /datum/design/mag_oldsmg - name = "WT-550 Auto Gun Magazine (4.6x30mm)" - desc = "A 20 round magazine for the out of date security WT-550 Auto Rifle" + name = "WT-550 Semi-Auto SMG Magazine (4.6x30mm)" + desc = "A 20 round magazine for the out of date security WT-550 Semi-Auto SMG." id = "mag_oldsmg" build_type = PROTOLATHE materials = list(MAT_METAL = 4000) @@ -228,16 +228,16 @@ departmental_flags = DEPARTMENTAL_FLAG_SECURITY /datum/design/mag_oldsmg/ap_mag - name = "WT-550 Auto Gun Armour Piercing Magazine (4.6x30mm AP)" - desc = "A 20 round armour piercing magazine for the out of date security WT-550 Auto Rifle" + name = "WT-550 Semi-Auto SMG Armour Piercing Magazine (4.6x30mm AP)" + desc = "A 20 round armour piercing magazine for the out of date security WT-550 Semi-Auto SMG." id = "mag_oldsmg_ap" materials = list(MAT_METAL = 6000, MAT_SILVER = 600) build_path = /obj/item/ammo_box/magazine/wt550m9/wtap departmental_flags = DEPARTMENTAL_FLAG_SECURITY /datum/design/mag_oldsmg/ic_mag - name = "WT-550 Auto Gun Incendiary Magazine (4.6x30mm IC)" - desc = "A 20 round armour piercing magazine for the out of date security WT-550 Auto Rifle" + name = "WT-550 Semi-Auto SMG Incendiary Magazine (4.6x30mm IC)" + desc = "A 20 round armour piercing magazine for the out of date security WT-550 Semi-Auto SMG." id = "mag_oldsmg_ic" materials = list(MAT_METAL = 6000, MAT_SILVER = 600, MAT_GLASS = 1000) build_path = /obj/item/ammo_box/magazine/wt550m9/wtic diff --git a/code/modules/research/xenobiology/crossbreeding/_corecross.dm b/code/modules/research/xenobiology/crossbreeding/__corecross.dm similarity index 100% rename from code/modules/research/xenobiology/crossbreeding/_corecross.dm rename to code/modules/research/xenobiology/crossbreeding/__corecross.dm diff --git a/code/modules/research/xenobiology/crossbreeding/_clothing.dm b/code/modules/research/xenobiology/crossbreeding/_clothing.dm new file mode 100644 index 0000000000..016fd95899 --- /dev/null +++ b/code/modules/research/xenobiology/crossbreeding/_clothing.dm @@ -0,0 +1,144 @@ +/* +Slimecrossing Armor + Armor added by the slimecrossing system. + Collected here for clarity. +*/ + +//Rebreather mask - Chilling Blue +/obj/item/clothing/mask/nobreath + name = "rebreather mask" + desc = "A transparent mask, resembling a conventional breath mask, but made of bluish slime. Seems to lack any air supply tube, though." + icon_state = "slime" + item_state = "slime" + body_parts_covered = NONE + w_class = WEIGHT_CLASS_SMALL + gas_transfer_coefficient = 0 + permeability_coefficient = 0.5 + flags_cover = MASKCOVERSMOUTH + resistance_flags = NONE + +/obj/item/clothing/mask/nobreath/equipped(mob/living/carbon/human/user, slot) + . = ..() + if(slot == SLOT_WEAR_MASK) + user.add_trait(TRAIT_NOBREATH, "breathmask_[REF(src)]") + user.failed_last_breath = FALSE + user.clear_alert("not_enough_oxy") + user.apply_status_effect(/datum/status_effect/rebreathing) + +/obj/item/clothing/mask/nobreath/dropped(mob/living/carbon/human/user) + ..() + user.remove_trait(TRAIT_NOBREATH, "breathmask_[REF(src)]") + user.remove_status_effect(/datum/status_effect/rebreathing) + +/obj/item/clothing/glasses/prism_glasses + name = "prism glasses" + desc = "The lenses seem to glow slightly, and reflect light into dazzling colors." + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "prismglasses" + actions_types = list(/datum/action/item_action/change_prism_colour, /datum/action/item_action/place_light_prism) + var/glasses_color = "#FFFFFF" + +/obj/item/clothing/glasses/prism_glasses/item_action_slot_check(slot) + if(slot == SLOT_GLASSES) + return TRUE + +/obj/structure/light_prism + name = "light prism" + desc = "A shining crystal of semi-solid light. Looks fragile." + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "lightprism" + density = FALSE + anchored = TRUE + max_integrity = 10 + +/obj/structure/light_prism/Initialize(mapload, var/newcolor) + . = ..() + color = newcolor + light_color = newcolor + set_light(5) + +/obj/structure/light_prism/attack_hand(mob/user) + to_chat(user, "You dispel [src]") + qdel(src) + +/datum/action/item_action/change_prism_colour + name = "Adjust Prismatic Lens" + icon_icon = 'icons/obj/slimecrossing.dmi' + button_icon_state = "prismcolor" + +/datum/action/item_action/change_prism_colour/Trigger() + if(!IsAvailable()) + return + var/obj/item/clothing/glasses/prism_glasses/glasses = target + var/new_color = input(owner, "Choose the lens color:", "Color change",glasses.glasses_color) as color|null + if(!new_color) + return + glasses.glasses_color = new_color + +/datum/action/item_action/place_light_prism + name = "Fabricate Light Prism" + icon_icon = 'icons/obj/slimecrossing.dmi' + button_icon_state = "lightprism" + +/datum/action/item_action/place_light_prism/Trigger() + if(!IsAvailable()) + return + var/obj/item/clothing/glasses/prism_glasses/glasses = target + if(locate(/obj/structure/light_prism) in get_turf(owner)) + to_chat(owner, "There isn't enough ambient energy to fabricate another light prism here.") + return + if(istype(glasses)) + if(!glasses.glasses_color) + to_chat(owner, "The lens is oddly opaque...") + return + to_chat(owner, "You channel nearby light into a glowing, ethereal prism.") + new /obj/structure/light_prism(get_turf(owner), glasses.glasses_color) + +/obj/item/clothing/head/peaceflower + name = "heroine bud" + desc = "An extremely addictive flower, full of peace magic." + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "peaceflower" + item_state = "peaceflower" + slot_flags = ITEM_SLOT_HEAD + body_parts_covered = NONE + dynamic_hair_suffix = "" + force = 0 + throwforce = 0 + w_class = WEIGHT_CLASS_TINY + throw_speed = 1 + throw_range = 3 + +/obj/item/clothing/head/peaceflower/equipped(mob/living/carbon/human/user, slot) + . = ..() + if(slot == SLOT_HEAD) + user.add_trait(TRAIT_PACIFISM, "peaceflower_[REF(src)]") + +/obj/item/clothing/head/peaceflower/dropped(mob/living/carbon/human/user) + ..() + user.remove_trait(TRAIT_PACIFISM, "peaceflower_[REF(src)]") + +/obj/item/clothing/head/peaceflower/attack_hand(mob/user) + if(iscarbon(user)) + var/mob/living/carbon/C = user + if(src == C.head) + to_chat(user, "You feel at peace. Why would you want anything else?") + return + return ..() + +/obj/item/clothing/suit/armor/heavy/adamantine + name = "adamantine armor" + desc = "A full suit of adamantine plate armor. Impressively resistant to damage, but weighs about as much as you do." + icon_state = "adamsuit" + item_state = "adamsuit" + flags_inv = NONE + obj_flags = IMMUTABLE_SLOW + slowdown = 4 + var/hit_reflect_chance = 10 // Citadel Change: because 40% chance of bouncing lasers back into peoples faces isn't good. + armor = list("melee" = 70, "bullet" = 70, "laser" = 40, "energy" = 40, "bomb" = 80, "bio" = 80, "rad" = 80, "fire" = 70, "acid" = 90) //Citadel Change to avoid immortal Xenobiologists. + +/obj/item/clothing/suit/armor/heavy/adamantine/IsReflect(def_zone) + if(def_zone in list(BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) && prob(hit_reflect_chance)) + return TRUE + else + return FALSE diff --git a/code/modules/research/xenobiology/crossbreeding/_misc.dm b/code/modules/research/xenobiology/crossbreeding/_misc.dm new file mode 100644 index 0000000000..0784946a37 --- /dev/null +++ b/code/modules/research/xenobiology/crossbreeding/_misc.dm @@ -0,0 +1,135 @@ +//Barrier cube - Chilling Grey +/obj/item/barriercube + name = "barrier cube" + desc = "A compressed cube of slime. When squeezed, it grows to massive size!" + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "barriercube" + w_class = WEIGHT_CLASS_TINY + +/obj/item/barriercube/attack_self(mob/user) + if(locate(/obj/structure/barricade/slime) in get_turf(loc)) + to_chat(user, "You can't fit more than one barrier in the same space!") + return + to_chat(user, "You squeeze [src].") + var/obj/B = new /obj/structure/barricade/slime(get_turf(loc)) + B.visible_message("[src] suddenly grows into a large, gelatinous barrier!") + qdel(src) + +//Slime barricade - Chilling Grey +/obj/structure/barricade/slime + name = "gelatinous barrier" + desc = "A huge chunk of grey slime. Bullets might get stuck in it." + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "slimebarrier" + proj_pass_rate = 40 + max_integrity = 60 + +//Melting Gel Wall - Chilling Metal +/obj/effect/forcefield/slimewall + name = "solidified gel" + desc = "A mass of solidified slime gel - completely impenetrable, but it's melting away!" + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "slimebarrier_thick" + CanAtmosPass = ATMOS_PASS_NO + opacity = TRUE + timeleft = 100 + +//Rainbow barrier - Chilling Rainbow +/obj/effect/forcefield/slimewall/rainbow + name = "rainbow barrier" + desc = "Despite others' urgings, you probably shouldn't taste this." + icon_state = "rainbowbarrier" + +//Ration pack - Chilling Silver +/obj/item/reagent_containers/food/snacks/rationpack + name = "ration pack" + desc = "A square bar that sadly looks like chocolate, packaged in a nondescript grey wrapper. Has saved soldiers' lives before - usually by stopping bullets." + icon_state = "rationpack" + bitesize = 3 + junkiness = 15 + filling_color = "#964B00" + tastes = list("cardboard" = 3, "sadness" = 3) + foodtype = null //Don't ask what went into them. You're better off not knowing. + list_reagents = list("stabilizednutriment" = 10, "nutriment" = 2) //Won't make you fat. Will make you question your sanity. + +/obj/item/reagent_containers/food/snacks/rationpack/checkLiked(fraction, mob/M) //Nobody likes rationpacks. Nobody. + if(last_check_time + 50 < world.time) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.mind && !H.has_trait(TRAIT_AGEUSIA)) + to_chat(H,"That didn't taste very good...") //No disgust, though. It's just not good tasting. + GET_COMPONENT_FROM(mood, /datum/component/mood, H) + if(mood) + mood.add_event(null,"gross_food", /datum/mood_event/gross_food) + last_check_time = world.time + return + ..() + +//Ice stasis block - Chilling Dark Blue +/obj/structure/ice_stasis + name = "ice block" + desc = "A massive block of ice. You can see something vaguely humanoid inside." + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "frozen" + density = TRUE + max_integrity = 100 + armor = list("melee" = 30, "bullet" = 50, "laser" = -50, "energy" = -50, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = -80, "acid" = 30) + +/obj/structure/ice_stasis/Initialize() + . = ..() + playsound(src, 'sound/magic/ethereal_exit.ogg', 50, 1) + +/obj/structure/ice_stasis/Destroy() + for(var/atom/movable/M in contents) + M.forceMove(loc) + playsound(src, 'sound/effects/glassbr3.ogg', 50, 1) + return ..() + +//Gold capture device - Chilling Gold +/obj/item/capturedevice + name = "gold capture device" + desc = "Bluespace technology packed into a roughly egg-shaped device, used to store nonhuman creatures. Can't catch them all, though - it only fits one." + w_class = WEIGHT_CLASS_SMALL + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "capturedevice" + +/obj/item/capturedevice/attack(mob/living/M, mob/user) + if(length(contents)) + to_chat(user, "The device already has something inside.") + return + if(!isanimal(M)) + to_chat(user, "The capture device only works on simple creatures.") + return + if(M.mind) + to_chat(user, "You offer the device to [M].") + if(alert(M, "Would you like to enter [user]'s capture device?", "Gold Capture Device", "Yes", "No") == "Yes") + if(user.canUseTopic(src, BE_CLOSE) && user.canUseTopic(M, BE_CLOSE)) + to_chat(user, "You store [M] in the capture device.") + to_chat(M, "The world warps around you, and you're suddenly in an endless void, with a window to the outside floating in front of you.") + store(M, user) + else + to_chat(user, "You were too far away from [M].") + to_chat(M, "You were too far away from [user].") + else + to_chat(user, "[M] refused to enter the device.") + return + else + if(istype(M, /mob/living/simple_animal/hostile) && !("neutral" in M.faction)) + to_chat(user, "This creature is too aggressive to capture.") + return + to_chat(user, "You store [M] in the capture device.") + store(M) + +/obj/item/capturedevice/attack_self(mob/user) + if(contents.len) + to_chat(user, "You open the capture device!") + release() + else + to_chat(user, "The device is empty...") + +/obj/item/capturedevice/proc/store(var/mob/living/M) + M.forceMove(src) + +/obj/item/capturedevice/proc/release() + for(var/atom/movable/M in contents) + M.forceMove(get_turf(loc)) diff --git a/code/modules/research/xenobiology/crossbreeding/_mobs.dm b/code/modules/research/xenobiology/crossbreeding/_mobs.dm new file mode 100644 index 0000000000..57d0a31149 --- /dev/null +++ b/code/modules/research/xenobiology/crossbreeding/_mobs.dm @@ -0,0 +1,13 @@ +//Slime corgi - Chilling Pink +/mob/living/simple_animal/pet/dog/corgi/puppy/slime + name = "\improper slime corgi puppy" + real_name = "slime corgi puppy" + desc = "An unbearably cute pink slime corgi puppy." + icon_state = "slime_puppy" + icon_living = "slime_puppy" + icon_dead = "slime_puppy_dead" + nofur = TRUE + gold_core_spawnable = NO_SPAWN + speak_emote = list("blorbles", "bubbles", "borks") + emote_hear = list("bubbles!", "splorts.", "splops!") + emote_see = list("gets goop everywhere.", "flops.", "jiggles!") \ No newline at end of file diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm index f56aa11bae..aba54cfdf3 100644 --- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm +++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm @@ -57,6 +57,184 @@ owner.visible_message("[owner]'s gel coating liquefies and dissolves away.", "Your gel second-skin dissolves!") +/datum/status_effect/slimerecall + id = "slime_recall" + duration = -1 //Will be removed by the extract. + alert_type = null + var/interrupted = FALSE + var/mob/target + var/icon/bluespace + var/datum/weakref/redirect_component + +/datum/status_effect/slimerecall/on_apply() + redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/resistField)))) + to_chat(owner, "You feel a sudden tug from an unknown force, and feel a pull to bluespace!") + to_chat(owner, "Resist if you wish avoid the force!") + bluespace = icon('icons/effects/effects.dmi',"chronofield") + owner.add_overlay(bluespace) + return ..() + +/datum/status_effect/slimerecall/proc/resistField() + interrupted = TRUE + owner.remove_status_effect(src) +/datum/status_effect/slimerecall/on_remove() + qdel(redirect_component.resolve()) + redirect_component = null + owner.cut_overlay(bluespace) + if(interrupted || !ismob(target)) + to_chat(owner, "The bluespace tug fades away, and you feel that the force has passed you by.") + return + owner.visible_message("[owner] disappears in a flurry of sparks!", + "The unknown force snatches briefly you from reality, and deposits you next to [target]!") + do_sparks(3, TRUE, owner) + owner.forceMove(target.loc) + +/obj/screen/alert/status_effect/freon/stasis + desc = "You're frozen inside of a protective ice cube! While inside, you can't do anything, but are immune to harm! Resist to get out." + +/datum/status_effect/frozenstasis + id = "slime_frozen" + status_type = STATUS_EFFECT_UNIQUE + duration = -1 //Will remove self when block breaks. + alert_type = /obj/screen/alert/status_effect/freon/stasis + var/obj/structure/ice_stasis/cube + var/datum/weakref/redirect_component + +/datum/status_effect/frozenstasis/on_apply() + redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/breakCube)))) + cube = new /obj/structure/ice_stasis(get_turf(owner)) + owner.forceMove(cube) + owner.status_flags |= GODMODE + return ..() + +/datum/status_effect/frozenstasis/tick() + if(!cube || owner.loc != cube) + owner.remove_status_effect(src) + +/datum/status_effect/frozenstasis/proc/breakCube() + owner.remove_status_effect(src) + +/datum/status_effect/frozenstasis/on_remove() + if(cube) + qdel(cube) + owner.status_flags &= ~GODMODE + qdel(redirect_component.resolve()) + redirect_component = null + +/datum/status_effect/slime_clone + id = "slime_cloned" + status_type = STATUS_EFFECT_UNIQUE + duration = -1 + alert_type = null + var/mob/living/clone + var/datum/mind/originalmind //For when the clone gibs. + +/datum/status_effect/slime_clone/on_apply() + var/typepath = owner.type + clone = new typepath(owner.loc) + var/mob/living/carbon/O = owner + var/mob/living/carbon/C = clone + if(istype(C) && istype(O)) + C.real_name = O.real_name + O.dna.transfer_identity(C) + C.updateappearance(mutcolor_update=1) + if(owner.mind) + originalmind = owner.mind + owner.mind.transfer_to(clone) + clone.apply_status_effect(/datum/status_effect/slime_clone_decay) + return ..() + +/datum/status_effect/slime_clone/tick() + if(!istype(clone) || clone.stat != CONSCIOUS) + owner.remove_status_effect(src) + +/datum/status_effect/slime_clone/on_remove() + if(clone && clone.mind && owner) + clone.mind.transfer_to(owner) + else + if(owner && originalmind) + originalmind.transfer_to(owner) + if(originalmind.key) + owner.ckey = originalmind.key + if(clone) + clone.unequip_everything() + qdel(clone) + +/obj/screen/alert/status_effect/clone_decay + name = "Clone Decay" + desc = "You are simply a construct, and cannot maintain this form forever. You will be returned to your original body if you should fall." + icon_state = "slime_clonedecay" + +/datum/status_effect/slime_clone_decay + id = "slime_clonedecay" + status_type = STATUS_EFFECT_UNIQUE + duration = -1 + alert_type = /obj/screen/alert/status_effect/clone_decay + +/datum/status_effect/slime_clone_decay/tick() + owner.adjustToxLoss(1, 0) + owner.adjustOxyLoss(1, 0) + owner.adjustBruteLoss(1, 0) + owner.adjustFireLoss(1, 0) + owner.color = "#007BA7" + +/obj/screen/alert/status_effect/bloodchill + name = "Bloodchilled" + desc = "You feel a shiver down your spine after getting hit with a glob of cold blood. You'll move slower and get frostbite for a while!" + icon_state = "bloodchill" + +/datum/status_effect/bloodchill + id = "bloodchill" + duration = 100 + alert_type = /obj/screen/alert/status_effect/bloodchill + +/datum/status_effect/bloodchill/on_apply() + owner.add_movespeed_modifier("bloodchilled", TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = 3) + return ..() + +/datum/status_effect/bloodchill/tick() + if(prob(50)) + owner.adjustFireLoss(2) + +/datum/status_effect/bloodchill/on_remove() + owner.remove_movespeed_modifier("bloodchilled") + +/obj/screen/alert/status_effect/bloodchill + name = "Bloodchilled" + desc = "You feel a shiver down your spine after getting hit with a glob of cold blood. You'll move slower and get frostbite for a while!" + icon_state = "bloodchill" + +/datum/status_effect/bonechill + id = "bonechill" + duration = 80 + alert_type = /obj/screen/alert/status_effect/bonechill + +/datum/status_effect/bonechill/on_apply() + owner.add_movespeed_modifier("bonechilled", TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = 3) + return ..() + +/datum/status_effect/bonechill/tick() + if(prob(50)) + owner.adjustFireLoss(1) + owner.Jitter(3) + owner.adjust_bodytemperature(-10) + +/datum/status_effect/bonechill/on_remove() + owner.remove_movespeed_modifier("bonechilled") + +/obj/screen/alert/status_effect/bonechill + name = "Bonechilled" + desc = "You feel a shiver down your spine after hearing the haunting noise of bone rattling. You'll move slower and get frostbite for a while!" + icon_state = "bloodchill" + +/datum/status_effect/rebreathing + id = "rebreathing" + duration = -1 + alert_type = null + +datum/status_effect/rebreathing/tick() + owner.adjustOxyLoss(-6, 0) //Just a bit more than normal breathing. + /////////////////////////////////////////////////////// //////////////////CONSUMING EXTRACTS/////////////////// /////////////////////////////////////////////////////// diff --git a/code/modules/research/xenobiology/crossbreeding/_weapons.dm b/code/modules/research/xenobiology/crossbreeding/_weapons.dm new file mode 100644 index 0000000000..1138f65105 --- /dev/null +++ b/code/modules/research/xenobiology/crossbreeding/_weapons.dm @@ -0,0 +1,45 @@ +//Bloodchiller - Chilling Green +/obj/item/gun/magic/bloodchill + name = "blood chiller" + desc = "A horrifying weapon made of your own bone and blood vessels. It shoots slowing globules of your own blood. Ech." + icon = 'icons/obj/slimecrossing.dmi' + icon_state = "bloodgun" + item_state = "bloodgun" + lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' + item_flags = ABSTRACT | DROPDEL | NODROP + w_class = WEIGHT_CLASS_HUGE + force = 5 + max_charges = 1 //Recharging costs blood. + recharge_rate = 1 + ammo_type = /obj/item/ammo_casing/magic/bloodchill + fire_sound = 'sound/effects/attackblob.ogg' + +/obj/item/gun/magic/bloodchill/process() + charge_tick++ + if(charge_tick < recharge_rate || charges >= max_charges) + return 0 + charge_tick = 0 + var/mob/living/M = loc + if(istype(M) && M.blood_volume >= 20) + charges++ + M.blood_volume -= 20 + if(charges == 1) + recharge_newshot() + return 1 + +/obj/item/ammo_casing/magic/bloodchill + projectile_type = /obj/item/projectile/magic/bloodchill + +/obj/item/projectile/magic/bloodchill + name = "blood ball" + icon_state = "pulse0_bl" + damage = 0 + damage_type = OXY + nodamage = 1 + hitsound = 'sound/effects/splat.ogg' + +/obj/item/projectile/magic/bloodchill/on_hit(mob/living/target) + . = ..() + if(isliving(target)) + target.apply_status_effect(/datum/status_effect/bloodchill) \ No newline at end of file diff --git a/code/modules/research/xenobiology/crossbreeding/chilling.dm b/code/modules/research/xenobiology/crossbreeding/chilling.dm new file mode 100644 index 0000000000..25dbaa461f --- /dev/null +++ b/code/modules/research/xenobiology/crossbreeding/chilling.dm @@ -0,0 +1,312 @@ +/* +Chilling extracts: + Have a unique, primarily defensive effect when + filled with 10u plasma and activated in-hand. +*/ +/obj/item/slimecross/chilling + name = "chilling extract" + desc = "It's cold to the touch, as if frozen solid." + effect = "chilling" + container_type = INJECTABLE | DRAWABLE + icon_state = "chilling" + +/obj/item/slimecross/chilling/Initialize() + . = ..() + create_reagents(10) + +/obj/item/slimecross/chilling/attack_self(mob/user) + if(!reagents.has_reagent("plasma",10)) + to_chat(user, "This extract needs to be full of plasma to activate!") + return + reagents.remove_reagent("plasma",10) + to_chat(user, "You squeeze the extract, and it absorbs the plasma!") + playsound(src, 'sound/effects/bubbles.ogg', 50, 1) + playsound(src, 'sound/effects/glassbr1.ogg', 50, 1) + do_effect(user) + +/obj/item/slimecross/chilling/proc/do_effect(mob/user) //If, for whatever reason, you don't want to delete the extract, don't do ..() + qdel(src) + return + +/obj/item/slimecross/chilling/grey + colour = "grey" + +/obj/item/slimecross/chilling/grey/do_effect(mob/user) + user.visible_message("[src] produces a few small, grey cubes") + for(var/i in 1 to 3) + new /obj/item/barriercube(get_turf(user)) + ..() + +/obj/item/slimecross/chilling/orange + colour = "orange" + +/obj/item/slimecross/chilling/orange/do_effect(mob/user) + user.visible_message("[src] shatters, and lets out a jet of heat!") + for(var/turf/T in orange(get_turf(user),2)) + if(get_dist(get_turf(user), T) > 1) + new /obj/effect/hotspot(T) + ..() + +/obj/item/slimecross/chilling/purple + colour = "purple" + +/obj/item/slimecross/chilling/purple/do_effect(mob/user) + var/area/A = get_area(get_turf(user)) + if(A.outdoors) + to_chat(user, "[src] can't affect such a large area.") + return + user.visible_message("[src] shatters, and a healing aura fills the room briefly.") + for(var/mob/living/carbon/C in A) + C.reagents.add_reagent("regen_jelly",10) + ..() + +/obj/item/slimecross/chilling/blue + colour = "blue" + +/obj/item/slimecross/chilling/blue/do_effect(mob/user) + user.visible_message("[src] cracks, and spills out a liquid goo, which reforms into a mask!") + new /obj/item/clothing/mask/nobreath(get_turf(user)) + ..() + +/obj/item/slimecross/chilling/metal + colour = "metal" + +/obj/item/slimecross/chilling/metal/do_effect(mob/user) + user.visible_message("[src] melts like quicksilver, and surrounds [user] in a wall!") + for(var/turf/T in orange(get_turf(user),1)) + if(get_dist(get_turf(user), T) > 0) + new /obj/effect/forcefield/slimewall(T) + ..() + +/obj/item/slimecross/chilling/yellow + colour = "yellow" + +/obj/item/slimecross/chilling/yellow/do_effect(mob/user) + var/area/A = get_area(get_turf(user)) + user.visible_message("[src] shatters, and a the air suddenly feels charged for a moment.") + for(var/obj/machinery/power/apc/C in A) + if(C.cell) + C.cell.charge = min(C.cell.charge + C.cell.maxcharge/2, C.cell.maxcharge) + ..() + +/obj/item/slimecross/chilling/darkpurple + colour = "dark purple" + +/obj/item/slimecross/chilling/darkpurple/do_effect(mob/user) + var/area/A = get_area(get_turf(user)) + if(A.outdoors) + to_chat(user, "[src] can't affect such a large area.") + return + var/filtered = FALSE + for(var/turf/open/T in A) + var/datum/gas_mixture/G = T.air + if(istype(G)) + G.assert_gas(/datum/gas/plasma) + G.gases[/datum/gas/plasma][MOLES] = 0 + filtered = TRUE + G.garbage_collect() + T.air_update_turf() + if(filtered) + user.visible_message("Cracks spread throughout [src], and some air is sucked in!") + else + user.visible_message("[src] cracks, but nothing happens.") + ..() + +/obj/item/slimecross/chilling/darkblue + colour = "dark blue" + +/obj/item/slimecross/chilling/darkblue/do_effect(mob/user) + if(isliving(user)) + user.visible_message("[src] freezes over [user]'s entire body!") + var/mob/living/M = user + M.apply_status_effect(/datum/status_effect/frozenstasis) + ..() + +/obj/item/slimecross/chilling/silver + colour = "silver" + +/obj/item/slimecross/chilling/silver/do_effect(mob/user) + user.visible_message("[src] crumbles into icy powder, leaving behind several emergency food supplies!") + var/amount = rand(5, 10) + for(var/i in 1 to amount) + new /obj/item/reagent_containers/food/snacks/rationpack(get_turf(user)) + ..() + +/obj/item/slimecross/chilling/bluespace + colour = "bluespace" + var/list/allies = list() + var/active = FALSE + +/obj/item/slimecross/chilling/bluespace/afterattack(atom/target, mob/user, proximity) + if(!proximity || !isliving(target) || active) + return + if(target in allies) + allies -= target + to_chat(user, "You unlink [src] with [target].") + else + allies |= target + to_chat(user, "You link [src] with [target].") + return + +/obj/item/slimecross/chilling/bluespace/do_effect(mob/user) + if(allies.len <= 0) + to_chat(user, "[src] is not linked to anyone!") + return + to_chat(user, "You feel [src] pulse as it begins charging bluespace energies...") + active = TRUE + for(var/mob/living/M in allies) + var/datum/status_effect/slimerecall/S = M.apply_status_effect(/datum/status_effect/slimerecall) + S.target = user + if(do_after(user, 100, target=src)) + to_chat(user, "[src] shatters as it tears a hole in reality, snatching the linked individuals from the void!") + for(var/mob/living/M in allies) + var/datum/status_effect/slimerecall/S = M.has_status_effect(/datum/status_effect/slimerecall) + M.remove_status_effect(S) + else + to_chat(user, "[src] falls dark, dissolving into nothing as the energies fade away.") + for(var/mob/living/M in allies) + var/datum/status_effect/slimerecall/S = M.has_status_effect(/datum/status_effect/slimerecall) + if(istype(S)) + S.interrupted = TRUE + M.remove_status_effect(S) + ..() + +/obj/item/slimecross/chilling/sepia + colour = "sepia" + var/list/allies = list() + +/obj/item/slimecross/chilling/sepia/afterattack(atom/target, mob/user, proximity) + if(!proximity || !isliving(target)) + return + if(target in allies) + allies -= target + to_chat(user, "You unlink [src] with [target].") + else + allies |= target + to_chat(user, "You link [src] with [target].") + return + +/obj/item/slimecross/chilling/sepia/do_effect(mob/user) + user.visible_message("[src] shatters, freezing time itself!") + new /obj/effect/timestop(get_turf(user), 2, 300, allies) + ..() + +/obj/item/slimecross/chilling/cerulean + colour = "cerulean" + +/obj/item/slimecross/chilling/cerulean/do_effect(mob/user) + if(isliving(user)) + user.visible_message("[src] creaks and shifts into a clone of [user]!") + var/mob/living/M = user + M.apply_status_effect(/datum/status_effect/slime_clone) + ..() + +/obj/item/slimecross/chilling/pyrite + colour = "pyrite" + +/obj/item/slimecross/chilling/pyrite/do_effect(mob/user) + user.visible_message("[src] crystallizes into a pair of spectacles!") + new /obj/item/clothing/glasses/prism_glasses(get_turf(user)) + ..() + +/obj/item/slimecross/chilling/red + colour = "red" + +/obj/item/slimecross/chilling/red/do_effect(mob/user) + var/slimesfound = FALSE + for(var/mob/living/simple_animal/slime/S in view(get_turf(user), 7)) + slimesfound = TRUE + S.docile = TRUE + if(slimesfound) + user.visible_message("[src] lets out a peaceful ring as it shatters, and nearby slimes seem calm.") + else + user.visible_message("[src] lets out a peaceful ring as it shatters, but nothing happens...") + ..() + +/obj/item/slimecross/chilling/green + colour = "green" + +/obj/item/slimecross/chilling/green/do_effect(mob/user) + var/which_hand = "l_hand" + if(!(user.active_hand_index % 2)) + which_hand = "r_hand" + var/mob/living/L = user + if(!istype(user)) + return + var/obj/item/held = L.get_active_held_item() //This should be itself, but just in case... + L.dropItemToGround(held) + var/obj/item/gun/magic/bloodchill/gun = new(user) + if(!L.put_in_hands(gun)) + qdel(gun) + user.visible_message("[src] flash-freezes [user]'s arm, cracking the flesh horribly!") + else + user.visible_message("[src] chills and snaps off the front of the bone on [user]'s arm, leaving behind a strange, gun-like structure!") + user.emote("scream") + L.apply_damage(30,BURN,which_hand) + ..() + +/obj/item/slimecross/chilling/pink + colour = "pink" + +/obj/item/slimecross/chilling/pink/do_effect(mob/user) + user.visible_message("[src] cracks like an egg, and an adorable puppy comes tumbling out!") + new /mob/living/simple_animal/pet/dog/corgi/puppy/slime(get_turf(user)) + ..() + +/obj/item/slimecross/chilling/gold + colour = "gold" + +/obj/item/slimecross/chilling/gold/do_effect(mob/user) + user.visible_message("[src] lets off golden light as it melts and reforms into an egg-like device!") + new /obj/item/capturedevice(get_turf(user)) + ..() + +/obj/item/slimecross/chilling/oil + colour = "oil" + +/obj/item/slimecross/chilling/oil/do_effect(mob/user) + user.visible_message("[src] begins to shake with muted intensity!") + addtimer(CALLBACK(src, .proc/boom), 50) + +/obj/item/slimecross/chilling/oil/proc/boom() + explosion(get_turf(src), -1, -1, 3, 10) //Large radius, but mostly light damage. + qdel(src) + +/obj/item/slimecross/chilling/black + colour = "black" + +/obj/item/slimecross/chilling/black/do_effect(mob/user) + if(ishuman(user)) + user.visible_message("[src] crystallizes along [user]'s skin, turning into metallic scales!") + var/mob/living/carbon/human/H = user + H.set_species(/datum/species/golem/random) + ..() + +/obj/item/slimecross/chilling/lightpink + colour = "light pink" + +/obj/item/slimecross/chilling/lightpink/do_effect(mob/user) + user.visible_message("[src] blooms into a beautiful flower!") + new /obj/item/clothing/head/peaceflower(get_turf(user)) + ..() + +/obj/item/slimecross/chilling/adamantine + colour = "adamantine" + +/obj/item/slimecross/chilling/adamantine/do_effect(mob/user) + user.visible_message("[src] creaks and breaks as it shifts into a heavy set of armor!") + new /obj/item/clothing/suit/armor/heavy/adamantine(get_turf(user)) + ..() + +/obj/item/slimecross/chilling/rainbow + colour = "rainbow" + +/obj/item/slimecross/chilling/rainbow/do_effect(mob/user) + var/area/area = get_area(user) + if(area.outdoors) + to_chat(user, "[src] can't affect such a large area.") + return + user.visible_message("[src] reflects an array of dazzling colors and light, energy rushing to nearby doors!") + for(var/obj/machinery/door/airlock/door in area) + new /obj/effect/forcefield/slimewall/rainbow(door.loc) + return ..() diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 5da091152f..ca12accbed 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -840,7 +840,7 @@ return if(isitem(C)) var/obj/item/I = C - if(I.slowdown <= 0) + if(I.slowdown <= 0 || I.obj_flags & IMMUTABLE_SLOW) to_chat(user, "The [C] can't be made any faster!") return ..() I.slowdown = 0 diff --git a/code/modules/surgery/advanced/revival.dm b/code/modules/surgery/advanced/revival.dm index 085253e4c9..8a791c850b 100644 --- a/code/modules/surgery/advanced/revival.dm +++ b/code/modules/surgery/advanced/revival.dm @@ -27,7 +27,7 @@ /datum/surgery_step/revive name = "repair body" - implements = list(/obj/item/twohanded/shockpaddles = 100, /obj/item/melee/baton = 75, /obj/item/gun/energy = 60) + implements = list(/obj/item/twohanded/shockpaddles = 100, /obj/item/abductor/gizmo = 100, /obj/item/melee/baton = 75, /obj/item/organ/cyberimp/arm/baton = 75, /obj/item/organ/cyberimp/arm/gun/taser = 60, /obj/item/gun/energy/e_gun/advtaser = 60, /obj/item/gun/energy/taser = 60) time = 120 /datum/surgery_step/revive/tool_check(mob/user, obj/item/tool) diff --git a/html/changelogs/AutoChangeLog-pr-8056.yml b/html/changelogs/AutoChangeLog-pr-8056.yml new file mode 100644 index 0000000000..0953743ae4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8056.yml @@ -0,0 +1,4 @@ +author: "deathride58" +delete-after: True +changes: + - balance: "The TEG will now only produce a meaningful amount of power if the hot pipe contains gas that's actively combusting" diff --git a/html/changelogs/AutoChangeLog-pr-8058.yml b/html/changelogs/AutoChangeLog-pr-8058.yml new file mode 100644 index 0000000000..a484cc8ce1 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8058.yml @@ -0,0 +1,4 @@ +author: "deathride58" +delete-after: True +changes: + - rscadd: "Jogging is no longer treated exactly the same as sprinting for water slips. When you're jogging, you will only slip on water if you have more than 20% staminaloss." diff --git a/html/changelogs/AutoChangeLog-pr-8070.yml b/html/changelogs/AutoChangeLog-pr-8070.yml new file mode 100644 index 0000000000..a2ebab9068 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8070.yml @@ -0,0 +1,5 @@ +author: "deathride58" +delete-after: True +changes: + - rscadd: "Bloodcult conversions are now consensual. Convertees are given a ten second timer to accept or wait out. This should drastically improve the quality of those that get converted into bloodcult." + - rscadd: "All sacrifices now count as a third of a cultist for the end-game narsie summon." diff --git a/html/changelogs/AutoChangeLog-pr-8080.yml b/html/changelogs/AutoChangeLog-pr-8080.yml new file mode 100644 index 0000000000..9abd9e6f50 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8080.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - balance: "Halved borg energy guns self-recharge delay and increased their cell capacity by 3/4" diff --git a/html/changelogs/AutoChangeLog-pr-8084.yml b/html/changelogs/AutoChangeLog-pr-8084.yml new file mode 100644 index 0000000000..fbec9cfe1f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8084.yml @@ -0,0 +1,4 @@ +author: "Poojawa" +delete-after: True +changes: + - tweak: "Clone pods no longer announce the name of the clone" diff --git a/html/changelogs/AutoChangeLog-pr-8090.yml b/html/changelogs/AutoChangeLog-pr-8090.yml new file mode 100644 index 0000000000..b314fde12b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8090.yml @@ -0,0 +1,5 @@ +author: "deathride58 (Original PR by actioninja)" +delete-after: True +changes: + - rscadd: "Disarm pushing (combat mode right click in disarm intent) will now actually push mobs away. Knockdowns from disarm pushing are no longer rng based on the target's staminaloss. Knockdowns from disarm pushing now only happen when you push someone into another mob, a table, or a wall. Pushes will now also temporarily stop targets from using firearms, and will disarm the firearm if performed a second time. Pushes still deal staminaloss to standing targets, and won't deal a single ounce of staminaloss to resting targets." + - rscdel: "You can no longer displace mobs that are in harm intent by simply walking into them. Mobs that aren't in help intent have to be disarm pushed to actually be moved." diff --git a/html/changelogs/AutoChangeLog-pr-8091.yml b/html/changelogs/AutoChangeLog-pr-8091.yml new file mode 100644 index 0000000000..e98b7df89c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8091.yml @@ -0,0 +1,5 @@ +author: "deathride58" +delete-after: True +changes: + - bugfix: "Transit turfs on the centcom z-level now function properly again at keeping mobs within the areas defined by their boundaries." + - bugfix: "The title screen is also positioned correctly again." diff --git a/html/changelogs/AutoChangeLog-pr-8098.yml b/html/changelogs/AutoChangeLog-pr-8098.yml new file mode 100644 index 0000000000..956b83d223 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8098.yml @@ -0,0 +1,4 @@ +author: "Coolgat3" +delete-after: True +changes: + - bugfix: "Made the sec and warden berret offer as much protection like the helmet" diff --git a/html/changelogs/AutoChangeLog-pr-8104.yml b/html/changelogs/AutoChangeLog-pr-8104.yml new file mode 100644 index 0000000000..61bf66a0c2 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8104.yml @@ -0,0 +1,5 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixes chemical patches always checking the suit slot even if the targetted limb was the head." + - bugfix: "Skeleton, nightmare and golem races are once again available to get chemical patches applied onto." diff --git a/html/changelogs/AutoChangeLog-pr-8108.yml b/html/changelogs/AutoChangeLog-pr-8108.yml new file mode 100644 index 0000000000..fea83213be --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8108.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - rscadd: "Adds two cartons of space milk to the space skellie pirates cutter's fridge." diff --git a/html/changelogs/AutoChangeLog-pr-8114.yml b/html/changelogs/AutoChangeLog-pr-8114.yml new file mode 100644 index 0000000000..96e6914e6b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8114.yml @@ -0,0 +1,4 @@ +author: "izzyinbox" +delete-after: True +changes: + - tweak: "lowered the player age for command jobs to 1/3 of their previous setting" diff --git a/html/changelogs/AutoChangeLog-pr-8119.yml b/html/changelogs/AutoChangeLog-pr-8119.yml new file mode 100644 index 0000000000..6e282e2a8d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8119.yml @@ -0,0 +1,5 @@ +author: "deathride58" +delete-after: True +changes: + - bugfix: "Sparks and igniters will now actually heat areas rather than cooling them, as was intended." + - tweak: "To alleviate some potential complaints, RPDs now have a cooldown before they can create sparks, and both RPDs and emitters produce less sparks." diff --git a/html/changelogs/AutoChangeLog-pr-8121.yml b/html/changelogs/AutoChangeLog-pr-8121.yml new file mode 100644 index 0000000000..27ce1ee0a1 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8121.yml @@ -0,0 +1,5 @@ +author: "deathride58" +delete-after: True +changes: + - tweak: "Conversion runes will now mute the victim temporarily while they're deciding whether to convert or be sacrificed." + - bugfix: "Conversion runes no longer require a third cultist to sacrifice if the victim refuses conversion" diff --git a/icons/mob/eyes.dmi b/icons/mob/eyes.dmi index 4bbe27f09d..aad4718cbd 100644 Binary files a/icons/mob/eyes.dmi and b/icons/mob/eyes.dmi differ diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index 03d6190507..2f39dd5940 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/inhands/weapons/guns_lefthand.dmi b/icons/mob/inhands/weapons/guns_lefthand.dmi index dae3861233..f6ac6ca499 100644 Binary files a/icons/mob/inhands/weapons/guns_lefthand.dmi and b/icons/mob/inhands/weapons/guns_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/guns_righthand.dmi b/icons/mob/inhands/weapons/guns_righthand.dmi index f3d5c42570..504121feba 100644 Binary files a/icons/mob/inhands/weapons/guns_righthand.dmi and b/icons/mob/inhands/weapons/guns_righthand.dmi differ diff --git a/icons/mob/mask.dmi b/icons/mob/mask.dmi index 18b323c997..788bfc0447 100644 Binary files a/icons/mob/mask.dmi and b/icons/mob/mask.dmi differ diff --git a/icons/mob/pets.dmi b/icons/mob/pets.dmi index d0983a8fab..45b0ab1f04 100644 Binary files a/icons/mob/pets.dmi and b/icons/mob/pets.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index 904084adb5..b518157bb5 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi index a474b5f285..a0153b1596 100644 Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index 51a5a4e358..8e0359e6b3 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/food/food.dmi b/icons/obj/food/food.dmi index 7f4e368c6e..9861a2e618 100644 Binary files a/icons/obj/food/food.dmi and b/icons/obj/food/food.dmi differ diff --git a/icons/obj/slimecrossing.dmi b/icons/obj/slimecrossing.dmi index 56ccfc21f7..6d74116a18 100644 Binary files a/icons/obj/slimecrossing.dmi and b/icons/obj/slimecrossing.dmi differ diff --git a/modular_citadel/code/game/objects/items/storage/firstaid.dm b/modular_citadel/code/game/objects/items/storage/firstaid.dm index 82d7df4a00..6ddf3963dd 100755 --- a/modular_citadel/code/game/objects/items/storage/firstaid.dm +++ b/modular_citadel/code/game/objects/items/storage/firstaid.dm @@ -23,7 +23,14 @@ /obj/item/storage/firstaid/o2 icon_state = "oxy" - + +/obj/item/storage/firstaid/radbgone + icon_state = "rad" + +/obj/item/storage/firstaid/radbgone/Initialize(mapload) + . = ..() + icon_state = pick("[initial(icon_state)]","[initial(icon_state)]2","[initial(icon_state)]3","[initial(icon_state)]4") + /obj/item/storage/firstaid/tactical icon_state = "tactical" diff --git a/modular_citadel/code/modules/jobs/job_types/captain.dm b/modular_citadel/code/modules/jobs/job_types/captain.dm index 7d8d1ac5ca..674cd9d09e 100644 --- a/modular_citadel/code/modules/jobs/job_types/captain.dm +++ b/modular_citadel/code/modules/jobs/job_types/captain.dm @@ -1,9 +1,9 @@ /datum/job/captain - minimal_player_age = 60 + minimal_player_age = 20 exp_type = EXP_TYPE_COMMAND /datum/job/hop - minimal_player_age = 60 + minimal_player_age = 20 head_announce = list("Service") exp_type_department = EXP_TYPE_SERVICE diff --git a/modular_citadel/code/modules/jobs/job_types/engineering.dm b/modular_citadel/code/modules/jobs/job_types/engineering.dm index f199bbefea..4d6aa4119d 100644 --- a/modular_citadel/code/modules/jobs/job_types/engineering.dm +++ b/modular_citadel/code/modules/jobs/job_types/engineering.dm @@ -1,5 +1,5 @@ /datum/job/chief_engineer - minimal_player_age = 30 + minimal_player_age = 10 /datum/job/engineer access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS, diff --git a/modular_citadel/code/modules/jobs/job_types/medical.dm b/modular_citadel/code/modules/jobs/job_types/medical.dm index 31c8b7d3c4..15841ad9d5 100644 --- a/modular_citadel/code/modules/jobs/job_types/medical.dm +++ b/modular_citadel/code/modules/jobs/job_types/medical.dm @@ -1,5 +1,5 @@ /datum/job/cmo - minimal_player_age = 30 + minimal_player_age = 10 /datum/outfit/job/doctor backpack_contents = list(/obj/item/storage/hypospraykit/regular) diff --git a/modular_citadel/code/modules/jobs/job_types/science.dm b/modular_citadel/code/modules/jobs/job_types/science.dm index 4542e7d099..94272d24a6 100644 --- a/modular_citadel/code/modules/jobs/job_types/science.dm +++ b/modular_citadel/code/modules/jobs/job_types/science.dm @@ -1,2 +1,2 @@ /datum/job/rd - minimal_player_age = 30 \ No newline at end of file + minimal_player_age = 10 diff --git a/modular_citadel/code/modules/jobs/job_types/security.dm b/modular_citadel/code/modules/jobs/job_types/security.dm index 9e59d98d00..de00f2d948 100644 --- a/modular_citadel/code/modules/jobs/job_types/security.dm +++ b/modular_citadel/code/modules/jobs/job_types/security.dm @@ -1,5 +1,5 @@ /datum/job/hos - minimal_player_age = 30 + minimal_player_age = 10 /datum/outfit/job/warden - suit_store = /obj/item/gun/energy/pumpaction/defender \ No newline at end of file + suit_store = /obj/item/gun/energy/pumpaction/defender diff --git a/modular_citadel/code/modules/mob/cit_emotes.dm b/modular_citadel/code/modules/mob/cit_emotes.dm index 6d6bc77b0b..a314baa852 100644 --- a/modular_citadel/code/modules/mob/cit_emotes.dm +++ b/modular_citadel/code/modules/mob/cit_emotes.dm @@ -15,9 +15,12 @@ /datum/emote/living/insult/run_emote(mob/living/user, params) var/insult_message = "" + var/miming = user.mind ? user.mind.miming : 0 if(!user.is_muzzled()) insult_message += pick_list_replacements(INSULTS_FILE, "insult_gen") message = insult_message + else if(miming) + message = "creatively gesticulates." else message = "muffles something." . = ..() @@ -224,4 +227,4 @@ return user.nextsoundemote = world.time + 7 playsound(user, 'modular_citadel/sound/voice/merp.ogg', 50, 1, -1) - . = ..() \ No newline at end of file + . = ..() diff --git a/modular_citadel/code/modules/mob/living/carbon/human/species.dm b/modular_citadel/code/modules/mob/living/carbon/human/species.dm index 73a50dccf0..d468f34653 100644 --- a/modular_citadel/code/modules/mob/living/carbon/human/species.dm +++ b/modular_citadel/code/modules/mob/living/carbon/human/species.dm @@ -44,37 +44,105 @@ if(user.getStaminaLoss() >= STAMINA_SOFTCRIT) to_chat(user, "You're too exhausted.") return FALSE - else if(target.check_block()) - target.visible_message("[target] blocks [user]'s disarm attempt!") - return 0 + if(target.check_block()) + target.visible_message("[target] blocks [user]'s shoving attempt!") + return FALSE if(attacker_style && attacker_style.disarm_act(user,target)) - return 1 + return TRUE + if(user.resting) + return FALSE else + if(user == target) + return user.do_attack_animation(target, ATTACK_EFFECT_DISARM) - - user.adjustStaminaLossBuffered(4) //CITADEL CHANGE - makes disarmspam cause staminaloss + user.adjustStaminaLossBuffered(4) + playsound(target, 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1) if(target.w_uniform) target.w_uniform.add_fingerprint(user) - var/randomized_zone = ran_zone(user.zone_selected) SEND_SIGNAL(target, COMSIG_HUMAN_DISARM_HIT, user, user.zone_selected) - var/obj/item/bodypart/affecting = target.get_bodypart(randomized_zone) - if((!target.combatmode && user.combatmode || prob(target.getStaminaLoss()*(user.resting ? 0.25 : 1)*(user.combatmode ? 1 : 0.05))) && !target.resting) //probability depends on staminaloss. it's plausible, but unlikely that you'll be able to push someone over while resting, and pretty rare to successfully push someone outside of combat mode. The few people that even know how to right-click outside of combat mode are a rarity but let's take that into account regardless. - playsound(target, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - target.visible_message("[user] [user.combatmode ? "has" : "gently"] pushed [target]!", - "[user] has pushed [target]!", null, COMBAT_MESSAGE_RANGE) - target.apply_effect(40, EFFECT_KNOCKDOWN, target.run_armor_check(affecting, "melee", "Your armor prevents your fall!", "Your armor softens your fall!")) - target.forcesay(GLOB.hit_appends) - log_combat(user, target, "disarmed", " pushing them to the ground") - return + if(!target.resting) + target.adjustStaminaLoss(5) + + + var/turf/target_oldturf = target.loc + var/shove_dir = get_dir(user.loc, target_oldturf) + var/turf/target_shove_turf = get_step(target.loc, shove_dir) + var/mob/living/carbon/human/target_collateral_human + var/obj/structure/table/target_table + var/shove_blocked = FALSE //Used to check if a shove is blocked so that if it is knockdown logic can be applied + + //Thank you based whoneedsspace + target_collateral_human = locate(/mob/living/carbon/human) in target_shove_turf.contents + if(target_collateral_human) + shove_blocked = TRUE + else + target.Move(target_shove_turf, shove_dir) + if(get_turf(target) == target_oldturf) + target_table = locate(/obj/structure/table) in target_shove_turf.contents + shove_blocked = TRUE + + if(shove_blocked && !target.is_shove_knockdown_blocked()) + var/directional_blocked = FALSE + if(shove_dir in GLOB.cardinals) //Directional checks to make sure that we're not shoving through a windoor or something like that + var/target_turf = get_turf(target) + for(var/obj/O in target_turf) + if(O.flags_1 & ON_BORDER_1 && O.dir == shove_dir && O.density) + directional_blocked = TRUE + break + if(target_turf != target_shove_turf) //Make sure that we don't run the exact same check twice on the same tile + for(var/obj/O in target_shove_turf) + if(O.flags_1 & ON_BORDER_1 && O.dir == turn(shove_dir, 180) && O.density) + directional_blocked = TRUE + break + var/targetatrest = target.resting + if(((!target_table && !target_collateral_human) || directional_blocked) && !targetatrest) + target.Knockdown(SHOVE_KNOCKDOWN_SOLID) + user.visible_message("[user.name] shoves [target.name], knocking them down!", + "You shove [target.name], knocking them down!", null, COMBAT_MESSAGE_RANGE) + log_combat(user, target, "shoved", "knocking them down") + else if(target_table) + if(!targetatrest) + target.Knockdown(SHOVE_KNOCKDOWN_TABLE) + user.visible_message("[user.name] shoves [target.name] onto \the [target_table]!", + "You shove [target.name] onto \the [target_table]!", null, COMBAT_MESSAGE_RANGE) + target.forceMove(target_shove_turf) + log_combat(user, target, "shoved", "onto [target_table]") + else if(target_collateral_human && !targetatrest) + target.Knockdown(SHOVE_KNOCKDOWN_HUMAN) + if(!target_collateral_human.resting) + target_collateral_human.Knockdown(SHOVE_KNOCKDOWN_COLLATERAL) + user.visible_message("[user.name] shoves [target.name] into [target_collateral_human.name]!", + "You shove [target.name] into [target_collateral_human.name]!", null, COMBAT_MESSAGE_RANGE) + log_combat(user, target, "shoved", "into [target_collateral_human.name]") + + else + user.visible_message("[user.name] shoves [target.name]!", + "You shove [target.name]!", null, COMBAT_MESSAGE_RANGE) + var/target_held_item = target.get_active_held_item() + var/knocked_item = FALSE + if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types)) + target_held_item = null + if(!target.has_movespeed_modifier(SHOVE_SLOWDOWN_ID)) + target.add_movespeed_modifier(SHOVE_SLOWDOWN_ID, multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH) + if(target_held_item) + target.visible_message("[target.name]'s grip on \the [target_held_item] loosens!", + "Your grip on \the [target_held_item] loosens!", null, COMBAT_MESSAGE_RANGE) + addtimer(CALLBACK(target, /mob/living/carbon/human/proc/clear_shove_slowdown), SHOVE_SLOWDOWN_LENGTH) + else if(target_held_item) + target.dropItemToGround(target_held_item) + knocked_item = TRUE + target.visible_message("[target.name] drops \the [target_held_item]!!", + "You drop \the [target_held_item]!!", null, COMBAT_MESSAGE_RANGE) + var/append_message = "" + if(target_held_item) + if(knocked_item) + append_message = "causing them to drop [target_held_item]" + else + append_message = "loosening their grip on [target_held_item]" + log_combat(user, target, "shoved", append_message) - playsound(target, 'sound/weapons/thudswoosh.ogg', 25, 1, -1) - target.visible_message("[user] [user.combatmode ? "attempted to push" : "tries to gently push"] [target] over!", \ - "[user] [user.combatmode ? "attempted to push" : "tries to gently push"] [target] over!", null, COMBAT_MESSAGE_RANGE) - if(!target.resting && !user.resting && user.combatmode) - target.adjustStaminaLoss(rand(1,5)) //This is the absolute most inefficient way to get someone into soft stamcrit, but if you've got a crowd trying to shove you over, you've no option but to get knocked down and accept fate - log_combat(user, target, "attempted to disarm push") //////////////////// /////BODYPARTS///// diff --git a/modular_citadel/code/modules/research/designs/weapon_designs.dm b/modular_citadel/code/modules/research/designs/weapon_designs.dm index bdb77170ed..b27cedbcc2 100644 --- a/modular_citadel/code/modules/research/designs/weapon_designs.dm +++ b/modular_citadel/code/modules/research/designs/weapon_designs.dm @@ -1,7 +1,7 @@ /datum/design/mag_oldsmg/rubber_mag - name = "WT-550 Auto Gun rubberbullets Magazine (4.6x30mm rubber)" - desc = "A 20 round rubber shots magazine for the out of date security WT-550 Auto Rifle" + name = "WT-550 Semi-Auto SMG rubberbullets Magazine (4.6x30mm rubber)" + desc = "A 20 round rubber shots magazine for the out of date security WT-550 Semi-Auto SMG" id = "mag_oldsmg_rubber" materials = list(MAT_METAL = 6000) build_path = /obj/item/ammo_box/magazine/wt550m9/wtrubber - departmental_flags = DEPARTMENTAL_FLAG_SECURITY \ No newline at end of file + departmental_flags = DEPARTMENTAL_FLAG_SECURITY diff --git a/modular_citadel/code/modules/research/designs/weapon_designs/weapon_designs.dm b/modular_citadel/code/modules/research/designs/weapon_designs/weapon_designs.dm index 0db3bb9b1d..6246b9e24e 100644 --- a/modular_citadel/code/modules/research/designs/weapon_designs/weapon_designs.dm +++ b/modular_citadel/code/modules/research/designs/weapon_designs/weapon_designs.dm @@ -1,7 +1,7 @@ /datum/design/mag_oldsmg/tx_mag - name = "WT-550 Auto Gun Uranium Magazine (4.6x30mm TX)" - desc = "A 20 round uranium tipped magazine for the out of date security WT-550 Auto Rifle" + name = "WT-550 Semi-Auto SMG Uranium Magazine (4.6x30mm TX)" + desc = "A 20 round uranium tipped magazine for the out of date security WT-550 Semi-Auto SMG." id = "mag_oldsmg_tx" materials = list(MAT_METAL = 6000, MAT_SILVER = 600, MAT_URANIUM = 2000) build_path = /obj/item/ammo_box/magazine/wt550m9/wttx - departmental_flags = DEPARTMENTAL_FLAG_SECURITY \ No newline at end of file + departmental_flags = DEPARTMENTAL_FLAG_SECURITY diff --git a/sound/weapons/dink.ogg b/sound/weapons/dink.ogg new file mode 100644 index 0000000000..54f3678f79 Binary files /dev/null and b/sound/weapons/dink.ogg differ diff --git a/tgstation.dme b/tgstation.dme index 268d4f1ff9..c43b1a7019 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -2528,10 +2528,15 @@ #include "code\modules\research\techweb\all_nodes.dm" #include "code\modules\research\xenobiology\xenobio_camera.dm" #include "code\modules\research\xenobiology\xenobiology.dm" -#include "code\modules\research\xenobiology\crossbreeding\_corecross.dm" +#include "code\modules\research\xenobiology\crossbreeding\__corecross.dm" +#include "code\modules\research\xenobiology\crossbreeding\_clothing.dm" +#include "code\modules\research\xenobiology\crossbreeding\_misc.dm" +#include "code\modules\research\xenobiology\crossbreeding\_mobs.dm" #include "code\modules\research\xenobiology\crossbreeding\_status_effects.dm" +#include "code\modules\research\xenobiology\crossbreeding\_weapons.dm" #include "code\modules\research\xenobiology\crossbreeding\burning.dm" #include "code\modules\research\xenobiology\crossbreeding\charged.dm" +#include "code\modules\research\xenobiology\crossbreeding\chilling.dm" #include "code\modules\research\xenobiology\crossbreeding\consuming.dm" #include "code\modules\research\xenobiology\crossbreeding\industrial.dm" #include "code\modules\research\xenobiology\crossbreeding\prismatic.dm"