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/RandomRuins/SpaceRuins/mrow_thats_right.dmm b/_maps/RandomRuins/SpaceRuins/mrow_thats_right.dmm index 00ba365abf..0baac3252a 100644 --- a/_maps/RandomRuins/SpaceRuins/mrow_thats_right.dmm +++ b/_maps/RandomRuins/SpaceRuins/mrow_thats_right.dmm @@ -350,6 +350,7 @@ dir = 4 }, /obj/structure/closet/cabinet, +/obj/item/pda/neko, /obj/item/gps{ gpstag = "kitty" }, 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/__HELPERS/_cit_helpers.dm b/code/__HELPERS/_cit_helpers.dm index b6c968b163..eb2a564d1b 100644 --- a/code/__HELPERS/_cit_helpers.dm +++ b/code/__HELPERS/_cit_helpers.dm @@ -90,10 +90,6 @@ GLOBAL_LIST_INIT(dildo_colors, list(//mostly neon colors "Purple" = "#e300ff"//purple )) -//Looc stuff -GLOBAL_VAR_INIT(looc_allowed, 1) -GLOBAL_VAR_INIT(dlooc_allowed, 1) - //Crew objective and miscreants stuff GLOBAL_VAR_INIT(miscreants_allowed, FALSE) @@ -124,36 +120,6 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE) src << "You will [(prefs.chat_toggles & CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel." SSblackbox.record_feedback("tally", "admin_verb", 1, "TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/datum/admins/proc/togglelooc() - set category = "Server" - set desc="Fukken metagamers" - set name="Toggle LOOC" - toggle_looc() - log_admin("[key_name(usr)] toggled LOOC.") - message_admins("[key_name_admin(usr)] toggled LOOC.") - SSblackbox.record_feedback("tally", "admin_verb", 1, "TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/proc/toggle_looc(toggle = null) - if(toggle != null) //if we're specifically en/disabling ooc - if(toggle != GLOB.looc_allowed) - GLOB.looc_allowed = toggle - else - return - else //otherwise just toggle it - GLOB.looc_allowed = !GLOB.looc_allowed - world << "The LOOC channel has been globally [GLOB.looc_allowed ? "enabled" : "disabled"]." - -/datum/admins/proc/toggleloocdead() - set category = "Server" - set desc="Toggle dis bitch" - set name="Toggle Dead LOOC" - GLOB.dlooc_allowed = !( GLOB.dlooc_allowed ) - - log_admin("[key_name(usr)] toggled Dead LOOC.") - message_admins("[key_name_admin(usr)] toggled Dead LOOC.") - SSblackbox.record_feedback("tally", "admin_verb", 1, "TDLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - /mob/living/carbon/proc/has_penis() if(getorganslot("penis"))//slot shared with ovipositor if(istype(getorganslot("penis"), /obj/item/organ/genital/penis)) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 7d578337bc..ad29125d95 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -413,7 +413,8 @@ var/list/candidates = list() for(var/mob/dead/observer/G in GLOB.player_list) - candidates += G + if(G.can_reenter_round) + candidates += G return pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category, flashwindow, candidates) diff --git a/code/_globalvars/configuration.dm b/code/_globalvars/configuration.dm index fe83828e05..2334ce6bca 100644 --- a/code/_globalvars/configuration.dm +++ b/code/_globalvars/configuration.dm @@ -9,6 +9,7 @@ GLOBAL_VAR_INIT(changelog_hash, "") GLOBAL_VAR_INIT(hub_visibility, FALSE) GLOBAL_VAR_INIT(ooc_allowed, TRUE) // used with admin verbs to disable ooc - not a config option apparently +GLOBAL_VAR_INIT(looc_allowed, TRUE) GLOBAL_VAR_INIT(dooc_allowed, TRUE) GLOBAL_VAR_INIT(aooc_allowed, FALSE) GLOBAL_VAR_INIT(enter_allowed, TRUE) diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm index cc13e262a8..e5c0ffc1ab 100644 --- a/code/_onclick/drag_drop.dm +++ b/code/_onclick/drag_drop.dm @@ -111,7 +111,7 @@ if(mob && LAZYLEN(mob.mousemove_intercept_objects)) for(var/datum/D in mob.mousemove_intercept_objects) D.onMouseMove(object, location, control, params) - if(mob) //CIT CHANGE - passes onmousemove() to mobs + if(!show_popup_menus && mob) //CIT CHANGE - passes onmousemove() to mobs mob.onMouseMove(object, location, control, params) //CIT CHANGE - ditto ..() 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/ticker.dm b/code/controllers/subsystem/ticker.dm index d54f6fc3ef..35a92d7c19 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -655,7 +655,8 @@ SUBSYSTEM_DEF(ticker) 'sound/roundend/its_only_game.ogg', 'sound/roundend/yeehaw.ogg', 'sound/roundend/disappointed.ogg', - 'sound/roundend/gondolabridge.ogg'\ + 'sound/roundend/gondolabridge.ogg', + 'sound/roundend/haveabeautifultime.ogg'\ ) SEND_SOUND(world, sound(round_end_sound)) diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm index 06a365a82c..d6513b5d40 100644 --- a/code/game/gamemodes/clock_cult/clock_cult.dm +++ b/code/game/gamemodes/clock_cult/clock_cult.dm @@ -131,9 +131,9 @@ Credit where due: config_tag = "clockwork_cult" antag_flag = ROLE_SERVANT_OF_RATVAR false_report_weight = 10 - required_players = 20 - required_enemies = 2 - recommended_enemies = 4 + required_players = 30 + required_enemies = 3 + recommended_enemies = 5 enemy_minimum_age = 7 protected_jobs = list("AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain") //Silicons can eventually be converted restricted_jobs = list("Chaplain", "Captain") diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 782ad54e4c..7b492e3a95 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -37,9 +37,9 @@ false_report_weight = 10 restricted_jobs = list("Chaplain","AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel") protected_jobs = list() - required_players = 20 - required_enemies = 2 - recommended_enemies = 4 + required_players = 30 + required_enemies = 3 + recommended_enemies = 5 enemy_minimum_age = 7 announce_span = "cult" 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/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index 3542b4e8bd..5c8cd4ffb8 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -71,7 +71,7 @@ return if(timing) - if(world.time - activation_time >= timer_duration) + if(world.realtime - activation_time >= timer_duration) timer_end() // open doors, reset timer, clear status screen update_icon() @@ -87,7 +87,7 @@ if(stat & (NOPOWER|BROKEN)) return 0 - activation_time = world.time + activation_time = world.realtime timing = TRUE for(var/obj/machinery/door/window/brigdoor/door in targets) @@ -136,7 +136,7 @@ /obj/machinery/door_timer/proc/time_left(seconds = FALSE) - . = max(0,timer_duration - (activation_time ? world.time - activation_time : 0)) + . = max(0,timer_duration - (activation_time ? world.realtime - activation_time : 0)) if(seconds) . /= 10 @@ -240,7 +240,7 @@ preset_time = PRESET_LONG . = set_timer(preset_time) if(timing) - activation_time = world.time + activation_time = world.realtime else . = FALSE 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/devices/PDA/PDA_types.dm b/code/game/objects/items/devices/PDA/PDA_types.dm index 089286efda..80d8cb5963 100644 --- a/code/game/objects/items/devices/PDA/PDA_types.dm +++ b/code/game/objects/items/devices/PDA/PDA_types.dm @@ -114,7 +114,7 @@ /obj/item/pda/heads/rd name = "research director PDA" default_cartridge = /obj/item/cartridge/rd - inserted_item = /obj/item/pen/fountain + inserted_item = /obj/item/pen/fourcolor icon_state = "pda-rd" /obj/item/pda/captain @@ -185,6 +185,12 @@ desc = "A portable microcomputer by Thinktronic Systems, LTD. This model is a special edition with a transparent case." note = "Congratulations, you have chosen the Thinktronic 5230 Personal Data Assistant Deluxe Special Max Turbo Limited Edition!" +/obj/item/pda/neko + name = "neko PDA" + icon_state = "pda-neko" + desc = "A portable microcomputer by Thinktronic Systems, LTD. This model is a special edition a feline fine case." + note = "Congratulations, you have chosen the Thinktronic 5230 Personal Data Assistant Deluxe Special Mew Turbo Limited Edition NYA~!" + /obj/item/pda/cook name = "cook PDA" icon_state = "pda-cook" diff --git a/code/game/objects/items/devices/forcefieldprojector.dm b/code/game/objects/items/devices/forcefieldprojector.dm index 86e98aef93..de62869e7e 100644 --- a/code/game/objects/items/devices/forcefieldprojector.dm +++ b/code/game/objects/items/devices/forcefieldprojector.dm @@ -34,6 +34,10 @@ if(LAZYLEN(current_fields) >= max_fields) to_chat(user, "[src] cannot sustain any more forcefields!") return + var/obj/structure/projected_forcefield/same = locate() in T + if(same) + to_chat(user, "There is already a forcefield on [T]!") + return playsound(src,'sound/weapons/resonator_fire.ogg',50,1) user.visible_message("[user] projects a forcefield!","You project a forcefield.") @@ -59,6 +63,8 @@ /obj/item/forcefield_projector/Destroy() STOP_PROCESSING(SSobj, src) + for(var/i in current_fields) + qdel(i) return ..() /obj/item/forcefield_projector/process() 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/admin.dm b/code/modules/admin/admin.dm index 1a398f56fc..b400f44b98 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -538,13 +538,22 @@ message_admins("[key_name_admin(usr)] toggled OOC.") SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle OOC", "[GLOB.ooc_allowed ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/datum/admins/proc/toggleooclocal() + set category = "Server" + set desc="Toggle dat bitch" + set name="Toggle Local OOC" + toggle_looc() + log_admin("[key_name(usr)] toggled LOOC.") + message_admins("[key_name_admin(usr)] toggled LOOC.") + SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Local OOC", "[GLOB.ooc_allowed ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + /datum/admins/proc/toggleoocdead() set category = "Server" set desc="Toggle dis bitch" set name="Toggle Dead OOC" toggle_dooc() - log_admin("[key_name(usr)] toggled OOC.") + log_admin("[key_name(usr)] toggled Dead OOC.") message_admins("[key_name_admin(usr)] toggled Dead OOC.") SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Dead OOC", "[GLOB.dooc_allowed ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index e21c2b8873..ac1ae51f69 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -24,6 +24,7 @@ GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin()) /client/proc/game_panel, /*game panel, allows to change game-mode etc*/ /client/proc/check_ai_laws, /*shows AI and borg laws*/ /datum/admins/proc/toggleooc, /*toggles ooc on/off for everyone*/ + /datum/admins/proc/toggleooclocal, /*toggles looc on/off for everyone*/ /datum/admins/proc/toggleoocdead, /*toggles ooc on/off for everyone who is dead*/ /datum/admins/proc/toggleaooc, /*toggles antag ooc on/off*/ /datum/admins/proc/toggleenter, /*toggles whether people can join the current game*/ 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..2897427d6f 100644 --- a/code/modules/admin/verbs/panicbunker.dm +++ b/code/modules/admin/verbs/panicbunker.dm @@ -13,6 +13,7 @@ if (new_pb && !SSdbcore.Connect()) message_admins("The Database is not connected! Panic bunker will not work until the connection is reestablished.") SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Panic Bunker", "[new_pb ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + send2irc("Panic Bunker", "[key_name(usr)] has toggled the Panic Bunker, it is now [new_pb ? "enabled" : "disabled"].") /client/proc/addbunkerbypass(ckeytobypass as text) set category = "Special Verbs" @@ -22,9 +23,10 @@ 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.") + message_admins("[key_name_admin(usr)] has added [ckeytobypass] to the current round's bunker bypass list.") + send2irc("Panic Bunker", "[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.") /client/proc/revokebunkerbypass(ckeytobypass as text) set category = "Special Verbs" @@ -34,7 +36,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.") - + message_admins("[key_name_admin(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.") + send2irc("Panic Bunker", "[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/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index 276c488bce..7274f73965 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -41,6 +41,11 @@ return if(QDELETED(src) || QDELETED(user)) return + if(isobserver(user)) + var/mob/dead/observer/O = user + if(!O.can_reenter_round) + to_chat(user, "You are unable to reenter the round.") + return var/ghost_role = alert(latejoinercalling ? "Latejoin as [mob_name]? (This is a ghost role, and as such, it's very likely to be off-station.)" : "Become [mob_name]? (Warning, You can no longer be cloned!)",,"Yes","No") if(ghost_role == "No" || !loc) return 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/client/verbs/looc.dm b/code/modules/client/verbs/looc.dm index ccfcdae405..4049034203 100644 --- a/code/modules/client/verbs/looc.dm +++ b/code/modules/client/verbs/looc.dm @@ -24,11 +24,8 @@ return if(!holder) - if(!GLOB.ooc_allowed) - to_chat(src, " OOC is globally muted") - return - if(!GLOB.dooc_allowed && (mob.stat == DEAD)) - to_chat(usr, " OOC for dead mobs has been turned off.") + if(!GLOB.looc_allowed) + to_chat(src, " LOOC is globally muted") return if(prefs.muted & MUTE_OOC) to_chat(src, " You cannot use OOC (muted).") diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm index 1d54b9f4a0..5df13a1ffe 100644 --- a/code/modules/client/verbs/ooc.dm +++ b/code/modules/client/verbs/ooc.dm @@ -80,6 +80,16 @@ GLOB.ooc_allowed = !GLOB.ooc_allowed to_chat(world, "The OOC channel has been globally [GLOB.ooc_allowed ? "enabled" : "disabled"].") +/proc/toggle_looc(toggle = null) + if(toggle != null) + if(toggle != GLOB.looc_allowed) + GLOB.looc_allowed = toggle + else + return + else + GLOB.looc_allowed = !GLOB.looc_allowed + + /proc/toggle_dooc(toggle = null) if(toggle != null) if(toggle != GLOB.dooc_allowed) diff --git a/code/modules/client/verbs/suicide.dm b/code/modules/client/verbs/suicide.dm index 64d58cd40b..2e643cc05d 100644 --- a/code/modules/client/verbs/suicide.dm +++ b/code/modules/client/verbs/suicide.dm @@ -198,11 +198,13 @@ death(0) -/mob/living/proc/suicide_log() - log_game("[key_name(src)] committed suicide at [AREACOORD(src)] as [src.type].") +/mob/living/proc/suicide_log(ghosting) + log_game("[key_name(src)] [ghosting ? "ghosted" : "committed suicide"] at [AREACOORD(src)] as [src.type].") + message_admins("[key_name(src)] [ghosting ? "ghosted" : "committed suicide"] at [AREACOORD(src)].") -/mob/living/carbon/human/suicide_log() - log_game("[key_name(src)] (job: [src.job ? "[src.job]" : "None"]) committed suicide at [AREACOORD(src)].") +/mob/living/carbon/human/suicide_log(ghosting) + log_game("[key_name(src)] (job: [src.job ? "[src.job]" : "None"]) [is_special_character(src) ? "(ANTAG!) " : ""][ghosting ? "ghosted" : "committed suicide"] at [AREACOORD(src)].") + message_admins("[key_name(src)] (job: [src.job ? "[src.job]" : "None"]) [is_special_character(src) ? "(ANTAG!) " : ""][ghosting ? "ghosted" : "committed suicide"] at [AREACOORD(src)].") /mob/living/proc/canSuicide() switch(stat) 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/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index 974936ba30..c061d756b7 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -712,7 +712,10 @@ /obj/item/clothing/suit/space/hardsuit/shielded/worn_overlays(isinhands) . = list() if(!isinhands) - . += mutable_appearance('icons/effects/effects.dmi', shield_state, MOB_LAYER + 0.01) + if(taurmode >= SNEK_TAURIC) + . += mutable_appearance('modular_citadel/icons/mob/64x32_effects.dmi', shield_state, MOB_LAYER + 0.01) + else + . += mutable_appearance('icons/effects/effects.dmi', shield_state, MOB_LAYER + 0.01) /obj/item/clothing/head/helmet/space/hardsuit/shielded resistance_flags = FIRE_PROOF | ACID_PROOF diff --git a/code/modules/clothing/suits/_suits.dm b/code/modules/clothing/suits/_suits.dm index ad0311f160..054154639c 100644 --- a/code/modules/clothing/suits/_suits.dm +++ b/code/modules/clothing/suits/_suits.dm @@ -36,7 +36,7 @@ if(tauric == TRUE) center = TRUE dimension_x = 64 - else if(H.dna.features["taur"] in list("Fox", "Wolf", "Otie", "Drake", "Lab", "Shepherd", "Husky", "Eevee", "Panther", "Tajaran", "Horse", "Cow")) + else if(H.dna.features["taur"] in list("Fox","Wolf","Otie","Drake","Lab","Shepherd","Husky","Eevee","Panther","Horse","Cow","Tiger")) taurmode = PAW_TAURIC if(tauric == TRUE) center = TRUE @@ -61,7 +61,10 @@ if(damaged_clothes) . += mutable_appearance('icons/effects/item_damage.dmi', "damaged[blood_overlay_type]") IF_HAS_BLOOD_DNA(src) - . += mutable_appearance('icons/effects/blood.dmi', "[blood_overlay_type]blood") + if(taurmode >= SNEK_TAURIC) + . += mutable_appearance('modular_citadel/icons/mob/64x32_effects.dmi', "[blood_overlay_type]blood") + else + . += mutable_appearance('icons/effects/blood.dmi', "[blood_overlay_type]blood") var/mob/living/carbon/human/M = loc if(ishuman(M) && M.w_uniform) var/obj/item/clothing/under/U = M.w_uniform 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/food_and_drinks/food/snacks_meat.dm b/code/modules/food_and_drinks/food/snacks_meat.dm index c77242e69d..d3466caa5e 100644 --- a/code/modules/food_and_drinks/food/snacks_meat.dm +++ b/code/modules/food_and_drinks/food/snacks_meat.dm @@ -184,6 +184,15 @@ tastes = list("the jungle" = 1, "bananas" = 1) foodtype = MEAT | SUGAR +/obj/item/reagent_containers/food/snacks/monkeycube/On_Consume(mob/living/carbon/M) + if(iscarbon(M)) + M.visible_message("[src] bursts out of [M]!") + M.emote("scream") + M.Knockdown(40) + M.adjustBruteLoss(60) + Expand() + return ..() + /obj/item/reagent_containers/food/snacks/monkeycube/proc/Expand() var/mob/spammer = get_mob_by_key(fingerprintslast) var/mob/living/carbon/monkey/bananas = new(drop_location(), TRUE, spammer) diff --git a/code/modules/food_and_drinks/food/snacks_pizza.dm b/code/modules/food_and_drinks/food/snacks_pizza.dm index 5bf5abacb0..403636db08 100644 --- a/code/modules/food_and_drinks/food/snacks_pizza.dm +++ b/code/modules/food_and_drinks/food/snacks_pizza.dm @@ -160,6 +160,15 @@ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "pineapple" = 6, "ham" = 2) foodtype = PINEAPPLE //Over powering tast of gods fruit +/obj/item/reagent_containers/food/snacks/pizza/pineapple/anomaly + desc = "A anomaly made pizza with pineapple..." + bonus_reagents = list("nutriment" = 16, "vitamin" = 16) + tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "pineapple" = 6, "ham" = 2, "good" = 10) + +/obj/item/reagent_containers/food/snacks/pizzaslice/pineapple/anomaly + desc = "A slice of good tasting pizza. But has pineapple on it, what a anomaly!" + tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "pineapple" = 6, "ham" = 2, "good" = 10) + /obj/item/reagent_containers/food/snacks/pizza/arnold name = "\improper Arnold pizza" desc = "Hello, you've reached Arnold's pizza shop. I'm not here now, I'm out killing pepperoni." diff --git a/code/modules/food_and_drinks/recipes/drinks_recipes.dm b/code/modules/food_and_drinks/recipes/drinks_recipes.dm index 02106e808c..f41f6cce80 100644 --- a/code/modules/food_and_drinks/recipes/drinks_recipes.dm +++ b/code/modules/food_and_drinks/recipes/drinks_recipes.dm @@ -692,3 +692,15 @@ id = "pwr_game" results = list("pwr_game" = 5) required_reagents = list("sodawater" = 1, "blackcrayonpowder" = 1, "sodiumchloride" = 1) + +/datum/chemical_reaction/pinkmilk + name = "Strawberry Milk" + id = "pinkmilk" + results = list("pinkmilk" = 5) + required_reagents = list("aphro+" = 1, "milk" = 1) + +/datum/chemical_reaction/pinktea + name = "Strawberry Tea" + id = "pinktea" + results = list("pinktea" = 5) + required_reagents = list("aphro" = 1, "arnold_palmer" = 1, "sugar" = 1) diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pizza.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pizza.dm index 70f4b50727..64447dd180 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pizza.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pizza.dm @@ -101,3 +101,22 @@ ) result = /obj/item/reagent_containers/food/snacks/pizza/pineapple subcategory = CAT_PIZZA + +/datum/crafting_recipe/food/pineapplepizza/anomaly + name = "Anomaly Hawaiian pizza" + reqs = list( + /obj/item/assembly/signaler/anomaly = 1, + /obj/item/reagent_containers/food/snacks/pizza/pineapple = 1 + ) + result = /obj/item/reagent_containers/food/snacks/pizza/pineapple/anomaly + subcategory = CAT_PIZZA + +/datum/crafting_recipe/food/anomalypizzaboy + name = "Anomaly pizza box" + reqs = list( + /obj/item/pizzabox = 5, + /obj/item/assembly/signaler/anomaly = 1 + ) + tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + result = /obj/item/pizzabox/infinite + subcategory = CAT_PIZZA 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/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 12fe984d6f..55b8891534 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -18,6 +18,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) invisibility = INVISIBILITY_OBSERVER hud_type = /datum/hud/ghost var/can_reenter_corpse + var/can_reenter_round = TRUE var/datum/hud/living/carbon/hud = null // hud var/bootime = 0 var/started_as_observer //This variable is set to 1 when you enter the game as an observer. @@ -266,6 +267,7 @@ Works together with spawning an observer, noted above. var/mob/dead/observer/ghost = new(src) // Transfer safety to observer spawning proc. SStgui.on_transfer(src, ghost) // Transfer NanoUIs. ghost.can_reenter_corpse = can_reenter_corpse + ghost.can_reenter_round = (can_reenter_corpse && !suiciding) ghost.key = key return ghost @@ -280,7 +282,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp // CITADEL EDIT if(istype(loc, /obj/machinery/cryopod)) - var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you may not play again this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body") + var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you won't be able to re-enter this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body") if(response != "Ghost")//darn copypaste return var/obj/machinery/cryopod/C = loc @@ -293,17 +295,18 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(stat == DEAD) ghostize(1) else - var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you may not play again this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body") + var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you won't be able to re-enter this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body") if(response != "Ghost") return //didn't want to ghost after-all ghostize(0) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3 + suicide_log(TRUE) /mob/camera/verb/ghost() set category = "OOC" set name = "Ghost" set desc = "Relinquish your life and enter the land of the dead." - var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you may not play again this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body") + var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you won't be able to re-enter this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body") if(response != "Ghost") return ghostize(0) @@ -617,6 +620,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp to_chat(src, "This isn't really a creature, now is it!") return 0 + if(!can_reenter_round) + to_chat(src, "You are unable to re-enter the round.") + return FALSE + if(can_reenter_corpse && mind && mind.current) if(alert(src, "Your soul is still tied to your former life as [mind.current.name], if you go forward there is no going back to that life. Are you sure you wish to continue?", "Move On", "Yes", "No") == "No") return 0 diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 77cf6fc4bb..c6ba900b13 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -341,8 +341,13 @@ else if(isobserver(user) && traitstring) msg += "Traits: [traitstring]
" - if(print_flavor_text() && get_visible_name() != "Unknown")//Are we sure we know who this is? Don't show flavor text unless we can recognize them. Prevents certain metagaming with impersonation. - msg += "[print_flavor_text()]\n" + if(print_flavor_text()) + if(get_visible_name() == "Unknown") //Are we sure we know who this is? Don't show flavor text unless we can recognize them. Prevents certain metagaming with impersonation. + msg += "...?
" + else if(skipface) //Sometimes we're not unknown, but impersonating someone in a hardsuit, let's not reveal our flavor text then either. + msg += "...?
" + else + msg += "[print_flavor_text()]\n" msg += "*---------*" to_chat(user, msg) 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/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index ce906565d2..b66ebdb001 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -4,7 +4,9 @@ if(def_zone) if(isbodypart(def_zone)) - return checkarmor(def_zone, type) + var/obj/item/bodypart/bp = def_zone + if(bp.body_part) + return checkarmor(def_zone, type) var/obj/item/bodypart/affecting = get_bodypart(ran_zone(def_zone)) return checkarmor(affecting, type) //If a specific bodypart is targetted, check how that bodypart is protected and return the value. diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 0e5eef2ffb..e1935a9b5d 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1653,13 +1653,19 @@ GLOBAL_LIST_EMPTY(roundstart_races) var/obj/item/bodypart/BP = null if(isbodypart(def_zone)) - BP = def_zone + if(damagetype == STAMINA && istype(def_zone, /obj/item/bodypart/head)) + BP = H.get_bodypart(check_zone(BODY_ZONE_CHEST)) + else + BP = def_zone else if(!def_zone) def_zone = ran_zone(def_zone) + if(damagetype == STAMINA && def_zone == BODY_ZONE_HEAD) + def_zone = BODY_ZONE_CHEST BP = H.get_bodypart(check_zone(def_zone)) - if(!BP) - BP = H.bodyparts[1] + + if(!BP) + BP = H.bodyparts[1] switch(damagetype) if(BRUTE) 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/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index b73462115f..38ad3b8e5a 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -487,28 +487,6 @@ if(O) O.reagents.add_reagent("enzyme", 2 * coeff) -/obj/item/robot_module/butler/be_transformed_to(obj/item/robot_module/old_module) - var/mob/living/silicon/robot/R = loc - var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Waitress", "Butler", "Tophat", "Kent", "Bro") - if(!borg_icon) - return FALSE - switch(borg_icon) - if("Waitress") - cyborg_base_icon = "service_f" - if("Butler") - cyborg_base_icon = "service_m" - if("Bro") - cyborg_base_icon = "brobot" - if("Kent") - cyborg_base_icon = "kent" - special_light_key = "medical" - hat_offset = 3 - if("Tophat") - cyborg_base_icon = "tophat" - special_light_key = null - hat_offset = INFINITY //He is already wearing a hat - return ..() - /obj/item/robot_module/miner name = "Miner" basic_modules = list( diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index fa908db729..d041836f20 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -29,27 +29,10 @@ /proc/ran_zone(zone, probability = 80) - - zone = check_zone(zone) - if(prob(probability)) - return zone - - var/t = rand(1, 18) // randomly pick a different zone, or maybe the same one - switch(t) - if(1) - return BODY_ZONE_HEAD - if(2) - return BODY_ZONE_CHEST - if(3 to 6) - return BODY_ZONE_L_ARM - if(7 to 10) - return BODY_ZONE_R_ARM - if(11 to 14) - return BODY_ZONE_L_LEG - if(15 to 18) - return BODY_ZONE_R_LEG - + zone = check_zone(zone) + else + zone = pickweight(list(BODY_ZONE_HEAD = 6, BODY_ZONE_CHEST = 6, BODY_ZONE_L_ARM = 22, BODY_ZONE_R_ARM = 22, BODY_ZONE_L_LEG = 22, BODY_ZONE_R_LEG = 22)) return zone /proc/above_neck(zone) 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/projectile.dm b/code/modules/projectiles/projectile.dm index 267770eb22..efae090707 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -18,6 +18,7 @@ var/def_zone = "" //Aiming at var/atom/movable/firer = null//Who shot it var/suppressed = FALSE //Attack message + var/candink = FALSE //Can this projectile play the dink sound when hitting the head? var/yo = null var/xo = null var/atom/original = null // the original target clicked @@ -185,6 +186,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(candink && 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/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 725ef9baa6..7daeca91ea 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -4,6 +4,7 @@ damage = 60 damage_type = BRUTE nodamage = FALSE + candink = TRUE flag = "bullet" hitsound_wall = "ricochet" impact_effect_type = /obj/effect/temp_visual/impact_effect diff --git a/code/modules/projectiles/projectile/bullets/special.dm b/code/modules/projectiles/projectile/bullets/special.dm index 091dff454c..38a570c75f 100644 --- a/code/modules/projectiles/projectile/bullets/special.dm +++ b/code/modules/projectiles/projectile/bullets/special.dm @@ -5,6 +5,7 @@ knockdown = 60 forcedodge = TRUE nodamage = TRUE + candink = FALSE hitsound = 'sound/items/bikehorn.ogg' icon = 'icons/obj/hydroponics/harvest.dmi' icon_state = "banana" diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index 0cbd1f2d85..6ec37f3ec4 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -745,3 +745,37 @@ taste_description = "sweet pomegranates" glass_name = "glass of grenadine" glass_desc = "Delicious flavored syrup." + +/datum/reagent/consumable/pinkmilk + name = "Strawberry Milk" + id = "pinkmilk" + description = "A drink of a bygone era of milk and artificial sweetener back on a rock." + color = "#f76aeb"//rgb(247, 106, 235) + glass_icon_state = "pinkmilk" + quality = DRINK_FANTASTIC //Love drink + taste_description = "sweet strawberry and milk cream" + glass_name = "tall glass of strawberry milk" + glass_desc = "Delicious flavored strawberry syrup mixed with milk." + +/datum/reagent/consumable/tea/pinkmilk/on_mob_life(mob/living/carbon/M) + if(prob(15)) + to_chat(M, "[pick("You cant help to smile.","You feel nostalgia all of sudden.","You remember to relax.")]") + ..() + . = 1 + +/datum/reagent/consumable/pinktea //Tiny Tim song + name = "Strawberry Tea" + id = "pinktea" + description = "A timeless classic!" + color = "#f76aeb"//rgb(247, 106, 235) + glass_icon_state = "pinktea" + quality = DRINK_FANTASTIC //Love drink + taste_description = "sweet tea with a hint of strawberry" + glass_name = "mug of strawberry tea" + glass_desc = "Delicious traditional tea flavored with strawberries." + +/datum/reagent/consumable/tea/pinktea/on_mob_life(mob/living/carbon/M) + if(prob(10)) + to_chat(M, "[pick("Diamond skies where white deer fly.","Sipping strawberry tea.","Silver raindrops drift through timeless, Neverending June.","Crystal ... pearls free, with love!","Beaming love into me.")]") + ..() + . = 1 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-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-8118.yml b/html/changelogs/AutoChangeLog-pr-8118.yml new file mode 100644 index 0000000000..be5c0871ab --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8118.yml @@ -0,0 +1,6 @@ +author: "deathride58" +delete-after: True +changes: + - tweak: "Ghost role eligibility for both event and spawner ghost roles is now affected by DNR status. If you suicide, ghost, or cryo out, you will be unable to qualify for any ghost roles" + - tweak: "Cryo now applies DNR status no matter how long the round has been going on" + - tweak: "Suicide is now properly admin logged as it is supposed to be. Ghosting while alive is now also logged." 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/html/changelogs/AutoChangeLog-pr-8122.yml b/html/changelogs/AutoChangeLog-pr-8122.yml new file mode 100644 index 0000000000..2b9d091601 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8122.yml @@ -0,0 +1,4 @@ +author: "deathride58" +delete-after: True +changes: + - bugfix: "Staminaloss targeted at the head now properly redirects to the chest." diff --git a/html/changelogs/AutoChangeLog-pr-8130.yml b/html/changelogs/AutoChangeLog-pr-8130.yml new file mode 100644 index 0000000000..ac1dd56028 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8130.yml @@ -0,0 +1,4 @@ +author: "Poojawa" +delete-after: True +changes: + - bugfix: "fixed flavor text appearing when your face is hidden but you're not an Unknown" diff --git a/html/changelogs/AutoChangeLog-pr-8132.yml b/html/changelogs/AutoChangeLog-pr-8132.yml new file mode 100644 index 0000000000..05e27044be --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8132.yml @@ -0,0 +1,4 @@ +author: "Poojawa" +delete-after: True +changes: + - bugfix: "Tauric suits now apply an (placeholder) blood overlay, as well as their shield overlay." diff --git a/html/changelogs/AutoChangeLog-pr-8140.yml b/html/changelogs/AutoChangeLog-pr-8140.yml new file mode 100644 index 0000000000..ae21917771 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8140.yml @@ -0,0 +1,4 @@ +author: "deathride58" +delete-after: True +changes: + - code_imp: "In an attempt to improve performance during highpop, mouse movements will now only call onmousemove() while a user is in combat mode" diff --git a/html/changelogs/AutoChangeLog-pr-8141.yml b/html/changelogs/AutoChangeLog-pr-8141.yml new file mode 100644 index 0000000000..2a465b21e5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8141.yml @@ -0,0 +1,4 @@ +author: "deathride58" +delete-after: True +changes: + - tweak: "Ballistic projectiles are now the only projectiles capable of emitting dinks." diff --git a/html/changelogs/AutoChangeLog-pr-8145.yml b/html/changelogs/AutoChangeLog-pr-8145.yml new file mode 100644 index 0000000000..55cd6c378b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8145.yml @@ -0,0 +1,4 @@ +author: "deathride58" +delete-after: True +changes: + - admin: "Panic bunker toggling and bypassing is now logged in admin IRC" diff --git a/html/changelogs/AutoChangeLog-pr-8146.yml b/html/changelogs/AutoChangeLog-pr-8146.yml new file mode 100644 index 0000000000..566532fdd3 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8146.yml @@ -0,0 +1,5 @@ +author: "deathride58" +delete-after: True +changes: + - tweak: "OOC and LOOC now use separate toggles. You can now use LOOC while OOC is globally toggled off, and admins now have the option to toggle LOOC off separately from OOC" + - code_imp: "also revamped and reorganized relevant looc adminverb code" diff --git a/html/changelogs/AutoChangeLog-pr-8160.yml b/html/changelogs/AutoChangeLog-pr-8160.yml new file mode 100644 index 0000000000..33d2445f48 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8160.yml @@ -0,0 +1,5 @@ +author: "Poojawa" +delete-after: True +changes: + - bugfix: "Digitigrade legs returned to normal, since digi leg markings overlay them anyway." + - bugfix: "commented out lizard mam_snout entries, because too many abominations" diff --git a/html/changelogs/AutoChangeLog-pr-8169.yml b/html/changelogs/AutoChangeLog-pr-8169.yml new file mode 100644 index 0000000000..5c50eac652 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8169.yml @@ -0,0 +1,4 @@ +author: "Poojawa" +delete-after: True +changes: + - bugfix: "Normal blood splattering isn't offset due to tauric mode" 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/human_parts_greyscale.dmi b/icons/mob/human_parts_greyscale.dmi index 47ef8e816f..a8d2a2aef3 100644 Binary files a/icons/mob/human_parts_greyscale.dmi and b/icons/mob/human_parts_greyscale.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/machinery/cryopod.dm b/modular_citadel/code/game/machinery/cryopod.dm index 9369fa7677..1ff628bfbd 100644 --- a/modular_citadel/code/game/machinery/cryopod.dm +++ b/modular_citadel/code/game/machinery/cryopod.dm @@ -365,10 +365,8 @@ // Ghost and delete the mob. if(!mob_occupant.get_ghost(1)) - if(world.time < 30 * 600)//before the 30 minute mark - mob_occupant.ghostize(0) // Players despawned too early may not re-enter the game - else - mob_occupant.ghostize(1) + mob_occupant.ghostize(0) // Players who cryo out may not re-enter the round + QDEL_NULL(occupant) open_machine() name = initial(name) 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/client/loadout/__donator.dm b/modular_citadel/code/modules/client/loadout/__donator.dm index 66245fbb8a..c0a4df2243 100644 --- a/modular_citadel/code/modules/client/loadout/__donator.dm +++ b/modular_citadel/code/modules/client/loadout/__donator.dm @@ -367,4 +367,10 @@ datum/gear/darksabresheath name = "Soul Necklace" category = SLOT_NECK path = /obj/item/clothing/neck/undertale - ckeywhitelist = list("twilightic") \ No newline at end of file + ckeywhitelist = list("twilightic") + +/datum/gear/frenchberet + name = "French Beret" + category = SLOT_HEAD + path = /obj/item/clothing/head/frenchberet + ckeywhitelist = list("notazoltan") \ No newline at end of file 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/dead/new_player/sprite_accessories.dm b/modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm index bd301a2e85..ecb4a57407 100644 --- a/modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm +++ b/modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm @@ -36,7 +36,8 @@ color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_tails.dmi' -/************* Lizard compatable snoots ************/ +//christ this was a mistake, but it's here just in case someone wants to selectively fix +/************* Lizard compatable snoots *********** /datum/sprite_accessory/snouts/bird name = "Beak" icon_state = "bird" @@ -155,6 +156,7 @@ icon_state = "toucan" icon = 'modular_citadel/icons/mob/mam_snouts.dmi' color_src = MATRIXED +*/ /****************************************** ************ Human Ears/Tails ************* 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/mob/living/silicon/robot/robot_modules.dm b/modular_citadel/code/modules/mob/living/silicon/robot/robot_modules.dm index 68ea248963..a0dbe3a02a 100644 --- a/modular_citadel/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/modular_citadel/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -222,7 +222,7 @@ /obj/item/robot_module/medical/be_transformed_to(obj/item/robot_module/old_module) var/mob/living/silicon/robot/R = loc - var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Default", "Droid", "Eyebot") + var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Default", "Heavy", "Sleek", "Marina", "Droid", "Eyebot") if(!borg_icon) return FALSE switch(borg_icon) @@ -232,15 +232,59 @@ cyborg_base_icon = "medical" cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' hat_offset = 4 + if("Sleek") + cyborg_base_icon = "sleekmed" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Marina") + cyborg_base_icon = "marinamed" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' if("Eyebot") cyborg_base_icon = "eyebotmed" cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' - special_light_key = "eyebotmed" + if("Heavy") + cyborg_base_icon = "heavymed" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + return ..() + +/obj/item/robot_module/janitor/be_transformed_to(obj/item/robot_module/old_module) + var/mob/living/silicon/robot/R = loc + var/list/janimodels = list("Default", "Sleek", "Marina", "Can", "Heavy") + var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in janimodels + if(!borg_icon) + return FALSE + switch(borg_icon) + if("Default") + cyborg_base_icon = "janitor" + if("Marina") + cyborg_base_icon = "marinajan" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Sleek") + cyborg_base_icon = "sleekjan" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Can") + cyborg_base_icon = "canjan" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Heavy") + cyborg_base_icon = "heavyres" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + return ..() + +/obj/item/robot_module/peacekeeper/be_transformed_to(obj/item/robot_module/old_module) + var/mob/living/silicon/robot/R = loc + var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Default", "Spider") + if(!borg_icon) + return FALSE + switch(borg_icon) + if("Default") + cyborg_base_icon = "peace" + if("Spider") + cyborg_base_icon = "whitespider" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' return ..() /obj/item/robot_module/security/be_transformed_to(obj/item/robot_module/old_module) var/mob/living/silicon/robot/R = loc - var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Default", "Default - Treads", "Droid", "Spider") + var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Default", "Default - Treads", "Heavy", "Sleek", "Can", "Marina", "Spider") if(!borg_icon) return FALSE switch(borg_icon) @@ -250,19 +294,56 @@ cyborg_base_icon = "sec-tread" special_light_key = "sec" cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' - if("Droid") - cyborg_base_icon = "Security" - special_light_key = "service" - hat_offset = 0 + if("Sleek") + cyborg_base_icon = "sleeksec" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Marina") + cyborg_base_icon = "marinasec" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Can") + cyborg_base_icon = "cansec" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' if("Spider") cyborg_base_icon = "spidersec" - special_light_key = "spidersec" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Heavy") + cyborg_base_icon = "heavysec" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + return ..() + +/obj/item/robot_module/butler/be_transformed_to(obj/item/robot_module/old_module) + var/mob/living/silicon/robot/R = loc + var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Waitress", "Heavy", "Sleek", "Butler", "Tophat", "Kent", "Bro") + if(!borg_icon) + return FALSE + switch(borg_icon) + if("Waitress") + cyborg_base_icon = "service_f" + if("Butler") + cyborg_base_icon = "service_m" + if("Bro") + cyborg_base_icon = "brobot" + if("Kent") + cyborg_base_icon = "kent" + special_light_key = "medical" + hat_offset = 3 + if("Tophat") + cyborg_base_icon = "tophat" + special_light_key = null + hat_offset = INFINITY //He is already wearing a hat + if("Sleek") + cyborg_base_icon = "sleekserv" + special_light_key = "sleekserv" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Heavy") + cyborg_base_icon = "heavyserv" + special_light_key = "heavyserv" cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' return ..() /obj/item/robot_module/engineering/be_transformed_to(obj/item/robot_module/old_module) var/mob/living/silicon/robot/R = loc - var/list/engymodels = list("Default", "Default - Treads","Loader","Handy", "Pup Dozer") + var/list/engymodels = list("Default", "Default - Treads", "Heavy", "Sleek", "Marina", "Can", "Spider", "Loader","Handy", "Pup Dozer") if(R.client && R.client.ckey in list("nezuli")) engymodels += "Alina" var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in engymodels @@ -281,11 +362,24 @@ has_snowflake_deadsprite = TRUE if("Handy") cyborg_base_icon = "handyeng" - special_light_key = "handyeng" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Sleek") + cyborg_base_icon = "sleekeng" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Can") + cyborg_base_icon = "caneng" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Marina") + cyborg_base_icon = "marinaeng" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Spider") + cyborg_base_icon = "spidereng" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Heavy") + cyborg_base_icon = "heavyeng" cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' if("Pup Dozer") cyborg_base_icon = "pupdozer" - special_light_key = "pupdozer" can_be_pushed = FALSE hat_offset = INFINITY cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi' @@ -305,7 +399,7 @@ /obj/item/robot_module/miner/be_transformed_to(obj/item/robot_module/old_module) var/mob/living/silicon/robot/R = loc - var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Lavaland", "Asteroid", "Droid") + var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Lavaland", "Heavy", "Sleek", "Marina", "Can", "Spider", "Asteroid", "Droid") if(!borg_icon) return FALSE switch(borg_icon) @@ -318,4 +412,19 @@ cyborg_base_icon = "miner" cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' hat_offset = 4 + if("Sleek") + cyborg_base_icon = "sleekmin" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Can") + cyborg_base_icon = "canmin" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Marina") + cyborg_base_icon = "marinamin" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Spider") + cyborg_base_icon = "spidermin" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' + if("Heavy") + cyborg_base_icon = "heavymin" + cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' return ..() 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/modular_citadel/icons/mob/64x32_effects.dmi b/modular_citadel/icons/mob/64x32_effects.dmi new file mode 100644 index 0000000000..7db65a8fc3 Binary files /dev/null and b/modular_citadel/icons/mob/64x32_effects.dmi differ diff --git a/modular_citadel/icons/mob/robots.dmi b/modular_citadel/icons/mob/robots.dmi index 230a01f4d4..b47ee12896 100644 Binary files a/modular_citadel/icons/mob/robots.dmi and b/modular_citadel/icons/mob/robots.dmi differ diff --git a/modular_citadel/icons/mob/widerobot.dmi b/modular_citadel/icons/mob/widerobot.dmi index f9fa2bab48..c730467e1d 100644 Binary files a/modular_citadel/icons/mob/widerobot.dmi and b/modular_citadel/icons/mob/widerobot.dmi differ diff --git a/modular_citadel/icons/obj/food/drink.dmi b/modular_citadel/icons/obj/food/drink.dmi new file mode 100644 index 0000000000..0972025b4f Binary files /dev/null and b/modular_citadel/icons/obj/food/drink.dmi differ diff --git a/sound/roundend/haveabeautifultime.ogg b/sound/roundend/haveabeautifultime.ogg new file mode 100644 index 0000000000..0d5a5ed336 Binary files /dev/null and b/sound/roundend/haveabeautifultime.ogg differ 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"