diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index 53b12ca0bb..55ed3e72ff 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -35129,9 +35129,6 @@ /turf/open/floor/plasteel/white, /area/medical/sleeper) "bDD" = ( -/obj/structure/sign/warning/nosmoking{ - pixel_x = -28 - }, /obj/structure/bed, /obj/item/bedsheet/medical, /obj/effect/turf_decal/tile/blue{ @@ -36070,6 +36067,9 @@ "bFJ" = ( /obj/structure/bed, /obj/item/bedsheet/medical, +/obj/structure/sign/warning/nosmoking{ + pixel_x = -28 + }, /turf/open/floor/plasteel/white, /area/medical/sleeper) "bFK" = ( @@ -57530,6 +57530,10 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/aft) +"nWU" = ( +/obj/machinery/smartfridge/organ/preloaded, +/turf/closed/wall, +/area/medical/sleeper) "oce" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 1 @@ -93288,7 +93292,7 @@ bvj bvj bvd bFu -bvj +nWU bvj bvd bKH diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index d9d46066bf..ac7d291b2f 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -103794,10 +103794,10 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "dsI" = ( -/obj/structure/sign/warning/nosmoking, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, +/obj/machinery/smartfridge/organ/preloaded, /turf/closed/wall, /area/medical/surgery) "dsJ" = ( @@ -127428,6 +127428,10 @@ /obj/item/assembly/signaler, /turf/open/floor/plating, /area/crew_quarters/abandoned_gambling_den) +"mMC" = ( +/obj/structure/sign/warning/nosmoking, +/turf/closed/wall, +/area/medical/surgery) "mQE" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -174919,7 +174923,7 @@ dkv dma dma dma -dma +mMC dsI dro dvz diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index f72a787214..0e6feb67c6 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -62776,6 +62776,9 @@ "cro" = ( /obj/structure/bed/roller, /obj/machinery/iv_drip, +/obj/structure/sign/warning/nosmoking{ + pixel_x = -28 + }, /turf/open/floor/plasteel/white, /area/medical/surgery) "crq" = ( @@ -63296,9 +63299,6 @@ dir = 1; pixel_y = -22 }, -/obj/structure/sign/warning/nosmoking{ - pixel_x = -28 - }, /obj/machinery/iv_drip, /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ @@ -83997,6 +83997,10 @@ }, /turf/open/floor/plating, /area/maintenance/port) +"qnB" = ( +/obj/machinery/smartfridge/organ/preloaded, +/turf/closed/wall, +/area/medical/surgery) "qqg" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 6 @@ -104229,7 +104233,7 @@ cia cia cpX cia -cia +qnB cia ceu dyg diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm index a7ab212bd6..bd3d72dc85 100644 --- a/_maps/map_files/OmegaStation/OmegaStation.dmm +++ b/_maps/map_files/OmegaStation/OmegaStation.dmm @@ -42880,6 +42880,12 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall/r_wall, /area/maintenance/disposal/incinerator) +"uvp" = ( +/obj/machinery/smartfridge/organ/preloaded{ + pixel_y = 2 + }, +/turf/closed/wall, +/area/medical/medbay/zone3) "uxJ" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/public/glass{ @@ -81595,7 +81601,7 @@ aSh bcf bcW blt -aSh +uvp aOL bfA bfX diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index d70bc0187b..9f1c1824cd 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -37749,6 +37749,9 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, +/obj/machinery/light_switch{ + pixel_x = -22 + }, /turf/open/floor/plasteel/white, /area/medical/surgery) "bIp" = ( @@ -38828,10 +38831,6 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 1 }, -/obj/machinery/firealarm{ - dir = 8; - pixel_x = -26 - }, /obj/effect/turf_decal/tile/blue{ dir = 1 }, @@ -39305,15 +39304,16 @@ /obj/item/clothing/gloves/color/latex, /obj/item/clothing/mask/surgical, /obj/item/clothing/suit/apron/surgical, -/obj/machinery/light_switch{ - pixel_x = -22 - }, /obj/effect/turf_decal/tile/blue{ dir = 1 }, /obj/effect/turf_decal/tile/blue{ dir = 8 }, +/obj/machinery/firealarm{ + dir = 8; + pixel_x = -26 + }, /turf/open/floor/plasteel/white, /area/medical/surgery) "bLN" = ( @@ -55674,6 +55674,10 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) +"jdA" = ( +/obj/machinery/smartfridge/organ/preloaded, +/turf/closed/wall, +/area/medical/surgery) "jeq" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -92221,7 +92225,7 @@ bFU bFU bIn bJt -bFU +jdA bFU bFU bFU diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index b79f1c2e59..9dad2926f8 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -5,6 +5,11 @@ #define COMPONENT_INCOMPATIBLE 1 #define COMPONENT_NOTRANSFER 2 +#define ELEMENT_INCOMPATIBLE 1 // Return value to cancel attaching + +// /datum/element flags +#define ELEMENT_DETACH (1 << 0) + // How multiple components of the exact same type are handled in the same datum #define COMPONENT_DUPE_HIGHLANDER 0 //old component is deleted (default) @@ -28,7 +33,7 @@ #define COMSIG_COMPONENT_ADDED "component_added" //when a component is added to a datum: (/datum/component) #define COMSIG_COMPONENT_REMOVING "component_removing" //before a component is removed from a datum because of RemoveComponent: (/datum/component) #define COMSIG_PARENT_PREQDELETED "parent_preqdeleted" //before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation -#define COMSIG_PARENT_QDELETED "parent_qdeleted" //after a datum's Destroy() is called: (force, qdel_hint), at this point none of the other components chose to interrupt qdel and Destroy has been called +#define COMSIG_PARENT_QDELETING "parent_qdeleting" //just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called // /atom signals #define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params) diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm index d3e724aefb..94c2c372f0 100644 --- a/code/__DEFINES/obj_flags.dm +++ b/code/__DEFINES/obj_flags.dm @@ -25,23 +25,22 @@ #define NO_MAT_REDEMPTION (1<<5) //Stops you from putting things like an RCD or other items into an ORM or protolathe for materials. #define DROPDEL (1<<6) //When dropped, it calls qdel on itself #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 ABSTRACT (1<<8) //for all things that are technically items but used for various different stuff +#define ABSTRACT (1<<8) //for all things that are technically items but used for various different stuff #define IMMUTABLE_SLOW (1<<9) //When players should not be able to change the slowdown of the item (Speed potions, ect) #define SURGICAL_TOOL (1<<10) //Tool commonly used for surgery: won't attack targets in an active surgical operation on help intent (in case of mistakes) -#define NO_UNIFORM_REQUIRED (1<<11) //Can be worn on certain slots (currently belt and id) that would otherwise require an uniform. +#define NO_UNIFORM_REQUIRED (1<<11) //Can be worn on certain slots (currently belt and id) that would otherwise require an uniform. // Flags for the clothing_flags var on /obj/item/clothing #define LAVAPROTECT (1<<0) #define STOPSPRESSUREDAMAGE (1<<1) //SUIT and HEAD items which stop pressure damage. To stop you taking all pressure damage you must have both a suit and head item with this flag. #define BLOCK_GAS_SMOKE_EFFECT (1<<2) //blocks the effect that chemical clouds would have on a mob --glasses, mask and helmets ONLY! -#define ALLOWINTERNALS (1<<3) //mask allows internals +#define ALLOWINTERNALS (1<<3) //mask allows internals #define NOSLIP (1<<4) //prevents from slipping on wet floors, in space etc #define THICKMATERIAL (1<<5) //prevents syringes, parapens and hypos if the external suit or helmet (if targeting head) has this flag. Example: space suits, biosuit, bombsuits, thick suits that cover your body. #define VOICEBOX_TOGGLABLE (1<<6) //The voicebox in this clothing can be toggled. #define VOICEBOX_DISABLED (1<<7) //The voicebox is currently turned off. -#define SNUG_FIT (1<<8) //Prevents knock-off from things like hat-throwing. -#define ANTI_TINFOIL_MANEUVER (1<<9) //Hats with negative effects when worn (i.e the tinfoil hat). +#define IGNORE_HAT_TOSS (1<<8) //Hats with negative effects when worn (i.e the tinfoil hat). // Flags for the organ_flags var on /obj/item/organ @@ -50,4 +49,4 @@ #define ORGAN_FAILING (1<<2) //Failing organs perform damaging effects until replaced or fixed #define ORGAN_EXTERNAL (1<<3) //Was this organ implanted/inserted/etc, if true will not be removed during species change. #define ORGAN_VITAL (1<<4) //Currently only the brain -#define ORGAN_NO_SPOIL (1<<5) //Do not spoil under any circumstances \ No newline at end of file +#define ORGAN_NO_SPOIL (1<<5) //Do not spoil under any circumstances diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 60212385f8..d3e9131226 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -162,6 +162,7 @@ #define TRAIT_FRIENDLY "friendly" #define TRAIT_ASSBLASTUSA "assblastusa" #define TRAIT_CULT_EYES "cult_eyes" +#define TRAIT_FREESPRINT "free_sprinting" // common trait sources @@ -216,4 +217,4 @@ #define NINJA_SUIT_TRAIT "ninja-suit" #define ANTI_DROP_IMPLANT_TRAIT "anti-drop-implant" #define ABDUCTOR_ANTAGONIST "abductor-antagonist" -#define MADE_UNCLONEABLE "made-uncloneable" \ No newline at end of file +#define MADE_UNCLONEABLE "made-uncloneable" diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 2c92816264..b899d7f6ab 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -313,14 +313,13 @@ parts += "[FOURSPACES]Threat level: [mode.threat_level]" parts += "[FOURSPACES]Threat left: [mode.threat]" parts += "[FOURSPACES]Executed rules:" + for(var/datum/dynamic_ruleset/rule in mode.executed_rules) + parts += "[FOURSPACES][FOURSPACES][rule.ruletype] - [rule.name]: -[rule.cost + rule.scaled_times * rule.scaling_cost] threat" + parts += "[FOURSPACES]Other threat changes:" for(var/str in mode.threat_log) parts += "[FOURSPACES][FOURSPACES][str]" for(var/entry in mode.threat_tallies) parts += "[FOURSPACES][FOURSPACES][entry] added [mode.threat_tallies[entry]]" - /* - for(var/datum/dynamic_ruleset/rule in mode.executed_rules) - parts += "[FOURSPACES][FOURSPACES][rule.ruletype] - [rule.name]: -[rule.cost + rule.scaled_times * rule.scaling_cost] threat" - */ return parts.Join("
") /client/proc/roundend_report_file() diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 91f5105553..e0cf8ebdd5 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -142,8 +142,7 @@ GLOBAL_LIST_INIT(bitfields, list( "THICKMATERIAL" = THICKMATERIAL, "VOICEBOX_TOGGLABLE" = VOICEBOX_TOGGLABLE, "VOICEBOX_DISABLED" = VOICEBOX_DISABLED, - "SNUG_FIT" = SNUG_FIT, - "ANTI_TINFOIL_MANEUVER" = ANTI_TINFOIL_MANEUVER, + "IGNORE_HAT_TOSS" = IGNORE_HAT_TOSS, ), "tesla_flags" = list( "TESLA_MOB_DAMAGE" = TESLA_MOB_DAMAGE, diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index 0ac8a61183..e2705ad49f 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -46,10 +46,15 @@ GLOBAL_LIST_INIT(ai_core_display_screens, list( ":thinking:", "Alien", "Angel", + "Angryface", + "AtlantisCZE", "Banned", "Bliss", "Blue", - "Clown", + "Boy", + "Boy-Malf", + "Girl", + "Girl-Malf", "Database", "Dorf", "Firewall", @@ -61,26 +66,44 @@ GLOBAL_LIST_INIT(ai_core_display_screens, list( "Hades", "Heartline", "Helios", + "Hotdog", + "Hourglass", "House", "Inverted", + "Jack", "Matrix", "Monochrome", + "Mothman", "Murica", "Nanotrasen", "Not Malf", + "Patriot", + "Pirate", "President", - "Random", "Rainbow", - "Red", + "Clown", + "Random", + "Ravensdale", "Red October", + "Red", + "Royal", + "Searif", + "Serithi", + "SilveryFerret", + "Smiley", "Static", "Syndicat Meow", "TechDemon", + "Terminal", "Text", "Too Deep", "Triumvirate", "Triumvirate-M", - "Weird")) + "Wasp", + "Weird", + "Xerxes", + "Yes-Man" + )) /proc/resolve_ai_icon(input) if(!input || !(input in GLOB.ai_core_display_screens)) diff --git a/code/_globalvars/lists/typecache.dm b/code/_globalvars/lists/typecache.dm index 96807214f2..1ec3de0bc5 100644 --- a/code/_globalvars/lists/typecache.dm +++ b/code/_globalvars/lists/typecache.dm @@ -10,3 +10,5 @@ GLOBAL_LIST_INIT(typecache_living, typecacheof(/mob/living)) GLOBAL_LIST_INIT(typecache_stack, typecacheof(/obj/item/stack)) GLOBAL_LIST_INIT(typecache_machine_or_structure, typecacheof(list(/obj/machinery, /obj/structure))) + +GLOBAL_LIST_INIT(freezing_objects, typecacheof(list(/obj/structure/closet/crate/freezer, /obj/structure/closet/secure_closet/freezer, /obj/structure/bodycontainer, /obj/item/autosurgeon, /obj/machinery/smartfridge/organ))) //list of all cold objects, that freeze organs when inside diff --git a/code/controllers/subsystem/dcs.dm b/code/controllers/subsystem/dcs.dm index c1e101a0e7..e94f233f04 100644 --- a/code/controllers/subsystem/dcs.dm +++ b/code/controllers/subsystem/dcs.dm @@ -1,6 +1,15 @@ -SUBSYSTEM_DEF(dcs) +PROCESSING_SUBSYSTEM_DEF(dcs) name = "Datum Component System" - flags = SS_NO_INIT | SS_NO_FIRE + flags = SS_NO_INIT + var/list/elements_by_type = list() -/datum/controller/subsystem/dcs/Recover() +/datum/controller/subsystem/processing/dcs/Recover() comp_lookup = SSdcs.comp_lookup + +/datum/controller/subsystem/processing/dcs/proc/GetElement(eletype) + . = elements_by_type[eletype] + if(.) + return + if(!ispath(eletype, /datum/element)) + CRASH("Attempted to instantiate [eletype] as a /datum/element") + . = elements_by_type[eletype] = new eletype \ No newline at end of file diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index eec9f63a12..f8ca1e7eae 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -98,7 +98,7 @@ SUBSYSTEM_DEF(garbage) state = SS_RUNNING break - + /datum/controller/subsystem/garbage/proc/HandleQueue(level = GC_QUEUE_CHECK) @@ -266,8 +266,8 @@ SUBSYSTEM_DEF(garbage) D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED var/start_time = world.time var/start_tick = world.tick_usage + SEND_SIGNAL(D, COMSIG_PARENT_QDELETING, force) // Let the (remaining) components know about the result of Destroy var/hint = D.Destroy(arglist(args.Copy(2))) // Let our friend know they're about to get fucked up. - SEND_SIGNAL(D, COMSIG_PARENT_QDELETED, force, hint) // Let the (remaining) components know about the result of Destroy if(world.time != start_time) I.slept_destroy++ else diff --git a/code/controllers/subsystem/traumas.dm b/code/controllers/subsystem/traumas.dm index fb9e163f91..1ad4a15ee7 100644 --- a/code/controllers/subsystem/traumas.dm +++ b/code/controllers/subsystem/traumas.dm @@ -87,7 +87,7 @@ SUBSYSTEM_DEF(traumas) "skeletons" = typecacheof(list(/obj/item/organ/tongue/bone, /obj/item/clothing/suit/armor/bone, /obj/item/stack/sheet/bone, /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton, /obj/effect/decal/remains/human)), - "conspiracies" = typecacheof(list(/obj/item/clothing/under/rank/captain, /obj/item/clothing/under/rank/head_of_security, + "conspiracies" = typecacheof(list(/obj/item/clothing/under/rank/captain, /obj/item/clothing/under/rank/head_of_security, /obj/item/clothing/under/rank/chief_engineer, /obj/item/clothing/under/rank/chief_medical_officer, /obj/item/clothing/under/rank/head_of_personnel, /obj/item/clothing/under/rank/research_director, /obj/item/clothing/under/rank/head_of_security/grey, /obj/item/clothing/under/rank/head_of_security/alt, diff --git a/code/datums/components/earhealing.dm b/code/datums/components/earhealing.dm deleted file mode 100644 index bd3d57480d..0000000000 --- a/code/datums/components/earhealing.dm +++ /dev/null @@ -1,30 +0,0 @@ -// An item worn in the ear slot with this component will heal your ears each -// Life() tick, even if normally your ears would be too damaged to heal. - -/datum/component/earhealing - var/mob/living/carbon/wearer - -/datum/component/earhealing/Initialize() - if(!isitem(parent)) - return COMPONENT_INCOMPATIBLE - RegisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED), .proc/equippedChanged) - -/datum/component/earhealing/proc/equippedChanged(datum/source, mob/living/carbon/user, slot) - if (slot == SLOT_EARS && istype(user)) - if (!wearer) - START_PROCESSING(SSobj, src) - wearer = user - else - if (wearer) - STOP_PROCESSING(SSobj, src) - wearer = null - -/datum/component/earhealing/process() - if (!wearer) - STOP_PROCESSING(SSobj, src) - return - if(!HAS_TRAIT(wearer, TRAIT_DEAF)) - var/obj/item/organ/ears/ears = wearer.getorganslot(ORGAN_SLOT_EARS) - if (ears) - ears.deaf = max(ears.deaf - 1, (ears.damage < ears.maxHealth ? 0 : 1)) // Do not clear deafness if our ears are too damaged - ears.damage = max(ears.damage - 0.1, 0) diff --git a/code/datums/components/mood.dm b/code/datums/components/mood.dm index b46919a6c6..a0e6f97de0 100644 --- a/code/datums/components/mood.dm +++ b/code/datums/components/mood.dm @@ -248,7 +248,7 @@ var/datum/hud/hud = owner.hud_used screen_obj = new hud.infodisplay += screen_obj - RegisterSignal(hud, COMSIG_PARENT_QDELETED, .proc/unmodify_hud) + RegisterSignal(hud, COMSIG_PARENT_QDELETING, .proc/unmodify_hud) RegisterSignal(screen_obj, COMSIG_CLICK, .proc/hud_click) /datum/component/mood/proc/unmodify_hud(datum/source) diff --git a/code/datums/components/virtual_reality.dm b/code/datums/components/virtual_reality.dm index f8f0679e9b..7bad836e47 100644 --- a/code/datums/components/virtual_reality.dm +++ b/code/datums/components/virtual_reality.dm @@ -12,7 +12,7 @@ return COMPONENT_INCOMPATIBLE var/mob/vr_M = parent mastermind = M.mind - RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETED), .proc/game_over) + RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING), .proc/game_over) RegisterSignal(M, COMSIG_MOB_KEY_CHANGE, .proc/switch_player) RegisterSignal(mastermind, COMSIG_MIND_TRANSFER, .proc/switch_player) you_die_in_the_game_you_die_for_real = yolo @@ -32,7 +32,7 @@ current_mind = M.mind quit_action.Grant(M) RegisterSignal(quit_action, COMSIG_ACTION_TRIGGER, .proc/revert_to_reality) - RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETED), .proc/game_over) + RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING), .proc/game_over) RegisterSignal(M, COMSIG_MOB_GHOSTIZE, .proc/be_a_quitter) RegisterSignal(M, COMSIG_MOB_KEY_CHANGE, .proc/pass_me_the_remote) RegisterSignal(current_mind, COMSIG_MIND_TRANSFER, .proc/pass_me_the_remote) @@ -42,7 +42,7 @@ /datum/component/virtual_reality/UnregisterFromParent() quit_action.Remove(parent) - UnregisterSignal(parent, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETED, COMSIG_MOB_KEY_CHANGE, COMSIG_MOB_GHOSTIZE)) + UnregisterSignal(parent, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING, COMSIG_MOB_KEY_CHANGE, COMSIG_MOB_GHOSTIZE)) UnregisterSignal(current_mind, COMSIG_MIND_TRANSFER) UnregisterSignal(quit_action, COMSIG_ACTION_TRIGGER) current_mind = null diff --git a/code/datums/elements/_element.dm b/code/datums/elements/_element.dm new file mode 100644 index 0000000000..f12835d2e2 --- /dev/null +++ b/code/datums/elements/_element.dm @@ -0,0 +1,29 @@ +/datum/element + var/element_flags = NONE + +/datum/element/proc/Attach(datum/target) + if(type == /datum/element) + return ELEMENT_INCOMPATIBLE + if(element_flags & ELEMENT_DETACH) + RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/Detach) + +/datum/element/proc/Detach(datum/source, force) + UnregisterSignal(source, COMSIG_PARENT_QDELETING) + +/datum/element/Destroy(force) + if(!force) + return QDEL_HINT_LETMELIVE + SSdcs.elements_by_type -= type + return ..() + +//DATUM PROCS + +/datum/proc/AddElement(eletype, ...) + var/datum/element/ele = SSdcs.GetElement(eletype) + args[1] = src + if(ele.Attach(arglist(args)) == ELEMENT_INCOMPATIBLE) + CRASH("Incompatible [eletype] assigned to a [type]! args: [json_encode(args)]") + +/datum/proc/RemoveElement(eletype) + var/datum/element/ele = SSdcs.GetElement(eletype) + ele.Detach(src) diff --git a/code/datums/components/cleaning.dm b/code/datums/elements/cleaning.dm similarity index 79% rename from code/datums/components/cleaning.dm rename to code/datums/elements/cleaning.dm index 5324a87fee..e4fb3edd48 100644 --- a/code/datums/components/cleaning.dm +++ b/code/datums/elements/cleaning.dm @@ -1,13 +1,15 @@ -/datum/component/cleaning - dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS +/datum/element/cleaning/Attach(datum/target) + . = ..() + if(!ismovableatom(target)) + return ELEMENT_INCOMPATIBLE + RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/Clean) -/datum/component/cleaning/Initialize() - if(!ismovableatom(parent)) - return COMPONENT_INCOMPATIBLE - RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/Clean) +/datum/element/cleaning/Detach(datum/target) + . = ..() + UnregisterSignal(target, COMSIG_MOVABLE_MOVED) -/datum/component/cleaning/proc/Clean() - var/atom/movable/AM = parent +/datum/element/cleaning/proc/Clean(datum/source) + var/atom/movable/AM = source var/turf/T = AM.loc SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK) for(var/A in T) @@ -43,4 +45,4 @@ cleaned_human.clean_blood() cleaned_human.wash_cream() cleaned_human.regenerate_icons() - to_chat(cleaned_human, "[src] cleans your face!") \ No newline at end of file + to_chat(cleaned_human, "[src] cleans your face!") diff --git a/code/datums/elements/earhealing.dm b/code/datums/elements/earhealing.dm new file mode 100644 index 0000000000..7477742673 --- /dev/null +++ b/code/datums/elements/earhealing.dm @@ -0,0 +1,37 @@ + +/datum/element/earhealing + element_flags = ELEMENT_DETACH + var/list/user_by_item = list() + +/datum/element/earhealing/New() + START_PROCESSING(SSdcs, src) + +/datum/element/earhealing/Attach(datum/target) + . = ..() + if(!isitem(target)) + return ELEMENT_INCOMPATIBLE + + RegisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED), .proc/equippedChanged) + +/datum/element/earhealing/Detach(datum/target) + . = ..() + UnregisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED)) + user_by_item -= target + +/datum/element/earhealing/proc/equippedChanged(datum/source, mob/living/carbon/user, slot) + if(slot == SLOT_EARS && istype(user)) + user_by_item[source] = user + else + user_by_item -= source + +/datum/element/earhealing/process() + for(var/i in user_by_item) + var/mob/living/carbon/user = user_by_item[i] + if(HAS_TRAIT(user, TRAIT_DEAF)) + continue + var/obj/item/organ/ears/ears = user.getorganslot(ORGAN_SLOT_EARS) + if(!ears) + continue + ears.deaf = max(ears.deaf - 0.25, (ears.damage < ears.maxHealth ? 0 : 1)) // Do not clear deafness if our ears are too damaged + ears.damage = max(ears.damage - 0.025, 0) + CHECK_TICK diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 5cf03e2684..0ded5f9912 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -91,7 +91,10 @@ if(current) // remove ourself from our old body's mind variable current.mind = null SStgui.on_transfer(current, new_character) - + if(iscarbon(current)) + var/mob/living/carbon/C = current + if(C.combatmode) + C.toggle_combat_mode(TRUE, TRUE) if(!language_holder) var/datum/language_holder/mob_holder = new_character.get_language_holder(shadow = FALSE) language_holder = mob_holder.copy(src) diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index 65a7c6a954..1a57cf5051 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -189,7 +189,13 @@ if(tod) var/tdelta = round(world.time - timeofdeath) if(tdelta < (DEFIB_TIME_LIMIT * 10)) - holder.icon_state = "huddefib" + var/obj/item/organ/heart/He = getorgan(/obj/item/organ/heart) + if(He) + holder.icon_state = "huddefib" + if(He.organ_flags & ORGAN_FAILING) + holder.icon_state = "huddefibheart" + else + holder.icon_state = "huddefibheart" return holder.icon_state = "huddead" else diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index 25edd0c68b..cd9500284b 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -510,7 +510,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) var/added_threat = starting_rule.scale_up(extra_rulesets_amount, threat) if (starting_rule.pre_execute()) spend_threat(starting_rule.cost + added_threat) - log_threat("[starting_rule.ruletype] - [starting_rule.name] -[starting_rule.cost + starting_rule.scaled_times * starting_rule.scaling_cost] threat") + log_threat("[starting_rule.ruletype] - [starting_rule.name] -[starting_rule.cost + starting_rule.scaled_times * starting_rule.scaling_cost] threat", verbose = TRUE) if(starting_rule.flags & HIGHLANDER_RULESET) highlander_executed = TRUE else if(starting_rule.flags & ONLY_RULESET) @@ -605,7 +605,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) new_rule.trim_candidates() if (new_rule.ready(forced)) spend_threat(new_rule.cost) - log_threat("[new_rule.ruletype] - [new_rule.name] -[new_rule.cost] threat") + log_threat("[new_rule.ruletype] - [new_rule.name] -[new_rule.cost] threat", verbose = TRUE) if (new_rule.execute()) // This should never fail since ready() returned 1 if(new_rule.flags & HIGHLANDER_RULESET) highlander_executed = TRUE @@ -626,7 +626,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) if (rule.execute()) log_game("DYNAMIC: Injected a [rule.ruletype == "latejoin" ? "latejoin" : "midround"] ruleset [rule.name].") spend_threat(rule.cost) - log_threat("[rule.ruletype] [rule.name] spent [rule.cost]") + log_threat("[rule.ruletype] [rule.name] spent [rule.cost]", verbose = TRUE) if(rule.flags & HIGHLANDER_RULESET) highlander_executed = TRUE else if(rule.flags & ONLY_RULESET) @@ -815,16 +815,19 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) /// Refund threat, but no more than threat_level. /datum/game_mode/dynamic/proc/refund_threat(regain) threat = min(threat_level,threat+regain) + log_threat("[regain] refunded. Threat is now [threat].", verbose = TRUE) /// Generate threat and increase the threat_level if it goes beyond, capped at 100 /datum/game_mode/dynamic/proc/create_threat(gain) threat = min(100, threat+gain) if(threat > threat_level) threat_level = threat + log_threat("[gain] created. Threat is now [threat] and threat level is now [threat_level].", verbose = TRUE) /// Expend threat, can't fall under 0. /datum/game_mode/dynamic/proc/spend_threat(cost) threat = max(threat-cost,0) + log_threat("[cost] spent. Threat is now [threat].", verbose = TRUE) /// Turns the value generated by lorentz distribution to threat value between 0 and 100. /datum/game_mode/dynamic/proc/lorentz_to_threat(x) diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 281f28688e..3f3bacc64f 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -12,6 +12,7 @@ density = FALSE state_open = TRUE circuit = /obj/item/circuitboard/machine/sleeper + req_access = list(ACCESS_CMO) //Used for reagent deletion and addition of non medicines var/efficiency = 1 var/min_health = -25 var/list/available_chems @@ -28,9 +29,27 @@ /obj/machinery/sleeper/Initialize() . = ..() + create_reagents(500, NO_REACT) occupant_typecache = GLOB.typecache_living update_icon() reset_chem_buttons() + RefreshParts() + add_inital_chems() + +/obj/machinery/sleeper/on_deconstruction() + var/obj/item/reagent_containers/sleeper_buffer/buffer = new (loc) + buffer.volume = reagents.maximum_volume + buffer.reagents.maximum_volume = reagents.maximum_volume + reagents.trans_to(buffer.reagents, reagents.total_volume) + +/obj/machinery/sleeper/proc/add_inital_chems() + for(var/i in available_chems) + var/datum/reagent/R = reagents.has_reagent(i) + if(!R) + reagents.add_reagent(i, (20)) + continue + if(R.volume < 20) + reagents.add_reagent(i, (20 - R.volume)) /obj/machinery/sleeper/RefreshParts() var/E @@ -47,6 +66,11 @@ available_chems |= possible_chems[i] reset_chem_buttons() + //Total container size 500 - 2000u + if(reagents) + reagents.maximum_volume = (500*E) + + /obj/machinery/sleeper/update_icon() icon_state = initial(icon_state) if(state_open) @@ -81,7 +105,42 @@ if (. & EMP_PROTECT_SELF) return if(is_operational() && occupant) + var/datum/reagent/R = pick(reagents.reagent_list) + inject_chem(R.id, occupant) open_machine() + //Is this too much? + if(severity == EMP_HEAVY) + var/chem = pick(available_chems) + available_chems -= chem + available_chems += get_random_reagent_id() + reset_chem_buttons() + +/obj/machinery/sleeper/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/reagent_containers/sleeper_buffer)) + var/obj/item/reagent_containers/sleeper_buffer/SB = I + if((SB.reagents.total_volume + reagents.total_volume) < reagents.maximum_volume) + SB.reagents.trans_to(reagents, SB.reagents.total_volume) + visible_message("[user] places the [SB] into the [src].") + qdel(SB) + return + else + SB.reagents.trans_to(reagents, SB.reagents.total_volume) + visible_message("[user] adds as much as they can to the [src] from the [SB].") + return + if(istype(I, /obj/item/reagent_containers)) + var/obj/item/reagent_containers/RC = I + if(RC.reagents.total_volume == 0) + to_chat(user, "The [I] is empty!") + for(var/datum/reagent/R in RC.reagents.reagent_list) + if((obj_flags & EMAGGED) || (allowed(usr))) + break + if(!istype(R, /datum/reagent/medicine)) + visible_message("The [src] gives out a hearty boop and rejects the [I]. The Sleeper's screen flashes with a pompous \"Medicines only, please.\"") + return + RC.reagents.trans_to(reagents, 1000) + visible_message("[user] adds as much as they can to the [src] from the [I].") + return + /obj/machinery/sleeper/MouseDrop_T(mob/target, mob/user) if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser()) @@ -141,18 +200,24 @@ ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "sleeper", name, 375, 550, master_ui, state) + ui = new(user, src, ui_key, "sleeper", name, 550, 700, master_ui, state) ui.open() /obj/machinery/sleeper/ui_data() var/list/data = list() data["occupied"] = occupant ? 1 : 0 data["open"] = state_open + data["efficiency"] = efficiency + data["current_vol"] = reagents.total_volume + data["tot_capacity"] = reagents.maximum_volume data["chems"] = list() for(var/chem in available_chems) - var/datum/reagent/R = GLOB.chemical_reagents_list[chem] - data["chems"] += list(list("name" = R.name, "id" = R.id, "allowed" = chem_allowed(chem))) + var/datum/reagent/R = reagents.has_reagent(chem) + R = GLOB.chemical_reagents_list[chem] + data["synthchems"] += list(list("name" = R.name, "id" = R.id, "synth_allowed" = synth_allowed(chem))) + for(var/datum/reagent/R in reagents.reagent_list) + data["chems"] += list(list("name" = R.name, "id" = R.id, "vol" = R.volume, "purity" = R.purity, "allowed" = chem_allowed(R.id))) data["occupant"] = list() var/mob/living/mob_occupant = occupant @@ -184,8 +249,15 @@ if(mob_occupant.reagents && mob_occupant.reagents.reagent_list.len) for(var/datum/reagent/R in mob_occupant.reagents.reagent_list) data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume)) + data["occupant"]["failing_organs"] = list() + var/mob/living/carbon/C = mob_occupant + if(C) + for(var/obj/item/organ/Or in C.getFailingOrgans()) + if(istype(Or, /obj/item/organ/brain)) + continue + data["occupant"]["failing_organs"] += list(list("name" = Or.name)) + if(mob_occupant.has_dna()) // Blood-stuff is mostly a copy-paste from the healthscanner. - var/mob/living/carbon/C = mob_occupant var/blood_id = C.get_blood_id() if(blood_id) data["occupant"]["blood"] = list() // We can start populating this list. @@ -196,7 +268,7 @@ blood_type = R.name else blood_type = blood_id - data["occupant"]["blood"]["maxBloodVolume"] = BLOOD_VOLUME_NORMAL + data["occupant"]["blood"]["maxBloodVolume"] = (BLOOD_VOLUME_NORMAL*C.blood_ratio) data["occupant"]["blood"]["currentBloodVolume"] = C.blood_volume data["occupant"]["blood"]["dangerBloodVolume"] = BLOOD_VOLUME_SAFE data["occupant"]["blood"]["bloodType"] = blood_type @@ -216,24 +288,49 @@ . = TRUE if("inject") var/chem = params["chem"] + var/amount = text2num(params["volume"]) if(!is_operational() || !mob_occupant) return if(mob_occupant.health < min_health && chem != "epinephrine") return - if(inject_chem(chem, usr)) + if(inject_chem(chem, usr, amount)) . = TRUE if(scrambled_chems && prob(5)) to_chat(usr, "Chemical system re-route detected, results may not be as expected!") + if("synth") + var/chem = params["chem"] + if(!is_operational()) + return + reagents.add_reagent(chem_buttons[chem], 10) //other_purity = 0.75 for when the mechanics are in + if("purge") + var/chem = params["chem"] + if(allowed(usr)) + if(!is_operational()) + return + reagents.remove_reagent(chem, 10) + return + if(chem in available_chems) + if(!is_operational()) + return + /*var/datum/reagent/R = reagents.has_reagent(chem) //For when purity effects are in + if(R.purity < 0.8)*/ + reagents.remove_reagent(chem, 10) + else + visible_message("Access Denied.") + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + /obj/machinery/sleeper/emag_act(mob/user) . = ..() + obj_flags |= EMAGGED scramble_chem_buttons() to_chat(user, "You scramble the sleeper's user interface!") return TRUE -/obj/machinery/sleeper/proc/inject_chem(chem, mob/user) - if((chem in available_chems) && chem_allowed(chem)) - occupant.reagents.add_reagent(chem_buttons[chem], 10) //emag effect kicks in here so that the "intended" chem is used for all checks, for extra FUUU +//trans to +/obj/machinery/sleeper/proc/inject_chem(chem, mob/user, volume = 10) + if(chem_allowed(chem)) + reagents.trans_id_to(occupant, chem, volume)//emag effect kicks in here so that the "intended" chem is used for all checks, for extra FUUU if(user) log_combat(user, occupant, "injected [chem] into", addition = "via [src]") return TRUE @@ -246,6 +343,14 @@ var/occ_health = mob_occupant.health > min_health || chem == "epinephrine" return amount && occ_health +/obj/machinery/sleeper/proc/synth_allowed(chem) + var/datum/reagent/R = reagents.has_reagent(chem) + if(!R) + return TRUE + if(R.volume < 50) + return TRUE + return FALSE + /obj/machinery/sleeper/proc/reset_chem_buttons() scrambled_chems = FALSE LAZYINITLIST(chem_buttons) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index b5cb066b3a..a8b4608b36 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -42,12 +42,6 @@ . = ..() GLOB.shuttle_caller_list += src -/obj/machinery/computer/communications/process() - if(..()) - var/ai_autoupdate = aistate != STATE_STATUSDISPLAY && aistate != STATE_CALLSHUTTLE && aistate != STATE_PURCHASE && aistate != STATE_VIEWMESSAGE - var/machine_user_autoupdate = state != STATE_STATUSDISPLAY && state != STATE_CALLSHUTTLE && state != STATE_PURCHASE && state != STATE_VIEWMESSAGE - updateDialog(machine_user_autoupdate,ai_autoupdate) - /obj/machinery/computer/communications/Topic(href, href_list) if(..()) return @@ -586,8 +580,6 @@ popup.set_content(dat) popup.open() - popup.set_content(dat) - popup.open() /obj/machinery/computer/communications/proc/get_javascript_header(form_id) var/dat = {"