diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index d19d1f7e9633..fbc851a6d5c4 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -225,8 +225,8 @@ ///////////////// -#define COMSIG_ENTER_AREA "enter_area" //from base of area/Entered(): (/area) -#define COMSIG_EXIT_AREA "exit_area" //from base of area/Exited(): (/area) +#define COMSIG_ENTER_AREA "enter_area" //from base of area/Entered(): (/area). Sent to "area-sensitive" movables, see __DEFINES/traits.dm for info. +#define COMSIG_EXIT_AREA "exit_area" //from base of area/Exited(): (/area). Sent to "area-sensitive" movables, see __DEFINES/traits.dm for info. #define COMSIG_CLICK "atom_click" //from base of atom/Click(): (location, control, params, mob/user) #define COMSIG_CLICK_SHIFT "shift_click" //from base of atom/ShiftClick(): (/mob) diff --git a/code/__DEFINES/important_recursive_contents.dm b/code/__DEFINES/important_recursive_contents.dm index 62be5b38e539..f1dc0bd3ea18 100644 --- a/code/__DEFINES/important_recursive_contents.dm +++ b/code/__DEFINES/important_recursive_contents.dm @@ -1,2 +1,4 @@ +///the area channel of the important_recursive_contents list, everything in here will be sent a signal when their last holding object changes areas +#define RECURSIVE_CONTENTS_AREA_SENSITIVE "recursive_contents_area_sensitive" ///the hearing channel of the important_recursive_contents list, everything in here will count as a hearing atom #define RECURSIVE_CONTENTS_HEARING_SENSITIVE "recursive_contents_hearing_sensitive" diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 69de29d4cd70..f1289d15bdbc 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -272,6 +272,13 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_HEARING_SENSITIVE "hearing_sensitive" +/* + * Used for movables that need to be updated, via COMSIG_ENTER_AREA and COMSIG_EXIT_AREA, when transitioning areas. + * Use [/atom/movable/proc/become_area_sensitive(trait_source)] to properly enable it. How you remove it isn't as important. + */ +#define TRAIT_AREA_SENSITIVE "area-sensitive" + +///Used for managing KEEP_TOGETHER in [/atom/var/appearance_flags] #define TRAIT_KEEP_TOGETHER "keep-together" // item traits @@ -426,6 +433,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_FISH_CASE_COMPATIBILE "fish_case_compatibile" /// Granted by prismwine #define TRAIT_REFLECTIVE "reflective" +/// Self-explainatory. +#define BEAUTY_ELEMENT_TRAIT "beauty_element" +#define MOOD_COMPONENT_TRAIT "mood_component" /// Trait granted by [mob/living/silicon/ai] /// Applied when the ai anchors itself diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 94039f138721..8e9a1dbc9979 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1558,3 +1558,14 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) return call(source, proctype)(arglist(arguments)) #define TURF_FROM_COORDS_LIST(List) (locate(List[1], List[2], List[3])) + +/proc/normalize_dir_to_cardinals(dir) + if(dir & NORTH) + return NORTH + if(dir & SOUTH) + return SOUTH + if(dir & EAST) + return EAST + if(dir & WEST) + return WEST + return 0 diff --git a/code/datums/components/beauty.dm b/code/datums/components/beauty.dm deleted file mode 100644 index fe3c06e3ad5a..000000000000 --- a/code/datums/components/beauty.dm +++ /dev/null @@ -1,38 +0,0 @@ -/datum/component/beauty - var/beauty = 0 - -/datum/component/beauty/Initialize(beautyamount) - if(!isatom(parent) || isarea(parent)) - return COMPONENT_INCOMPATIBLE - - beauty = beautyamount - - if(ismovable(parent)) - RegisterSignal(parent, COMSIG_ENTER_AREA, PROC_REF(enter_area)) - RegisterSignal(parent, COMSIG_EXIT_AREA, PROC_REF(exit_area)) - - var/area/A = get_area(parent) - if(A) - enter_area(null, A) - -/datum/component/beauty/proc/enter_area(datum/source, area/A) - SIGNAL_HANDLER - - if(A.outdoors) - return - A.totalbeauty += beauty - A.update_beauty() - -/datum/component/beauty/proc/exit_area(datum/source, area/A) - SIGNAL_HANDLER - - if(A.outdoors) - return - A.totalbeauty -= beauty - A.update_beauty() - -/datum/component/beauty/Destroy() - . = ..() - var/area/A = get_area(parent) - if(A) - exit_area(null, A) diff --git a/code/datums/components/fantasy/prefixes.dm b/code/datums/components/fantasy/prefixes.dm index 7445ab582bf5..bff1c6ec3dd0 100644 --- a/code/datums/components/fantasy/prefixes.dm +++ b/code/datums/components/fantasy/prefixes.dm @@ -66,3 +66,29 @@ var/obj/item/master = comp.parent comp.appliedComponents += master.AddComponent(/datum/component/lifesteal, comp.quality) return "vampiric [newName]" + +/datum/fantasy_affix/beautiful + placement = AFFIX_PREFIX + alignment = AFFIX_GOOD + +/datum/fantasy_affix/beautiful/apply(datum/component/fantasy/comp, newName) + var/obj/item/master = comp.parent + master.AddElement(/datum/element/beauty, max(comp.quality, 1) * 250) + return "[pick("aesthetic", "beautiful", "gorgeous", "pretty")] [newName]" + +/datum/fantasy_affix/beautiful/remove(datum/component/fantasy/comp) + var/obj/item/master = comp.parent + master.RemoveElement(/datum/element/beauty, max(comp.quality, 1) * 250) + +/datum/fantasy_affix/ugly + placement = AFFIX_PREFIX + alignment = AFFIX_EVIL + +/datum/fantasy_affix/ugly/apply(datum/component/fantasy/comp, newName) + var/obj/item/master = comp.parent + master.AddElement(/datum/element/beauty, min(comp.quality, -1) * 250) + return "[pick("fugly", "ugly", "grotesque", "hideous")] [newName]" + +/datum/fantasy_affix/ugly/remove(datum/component/fantasy/comp) + var/obj/item/master = comp.parent + master.RemoveElement(/datum/element/beauty, min(comp.quality, -1) * 250) diff --git a/code/datums/components/mood.dm b/code/datums/components/mood.dm index 64fc96146527..de334598f141 100644 --- a/code/datums/components/mood.dm +++ b/code/datums/components/mood.dm @@ -27,6 +27,7 @@ RegisterSignal(parent, COMSIG_JOB_RECEIVED, PROC_REF(register_job_signals)) var/mob/living/owner = parent + owner.become_area_sensitive(MOOD_COMPONENT_TRAIT) if(owner.hud_used) modify_hud() var/datum/hud/hud = owner.hud_used @@ -35,6 +36,9 @@ /datum/component/mood/Destroy() STOP_PROCESSING(SSmood, src) unmodify_hud() + + var/mob/living/owner = parent + owner.lose_area_sensitivity(MOOD_COMPONENT_TRAIT) return ..() /datum/component/mood/proc/register_job_signals(datum/source, job) diff --git a/code/datums/components/pellet_cloud.dm b/code/datums/components/pellet_cloud.dm index ae90dae17c55..e7f5174c9102 100644 --- a/code/datums/components/pellet_cloud.dm +++ b/code/datums/components/pellet_cloud.dm @@ -29,7 +29,7 @@ var/list/pellets = list() /// An associated list with the atom hit as the key and how many pellets they've eaten for the value, for printing aggregate messages var/list/targets_hit = list() - /// For grenades, any /mob/living's the grenade is moved onto, see [/datum/component/pellet_cloud/proc/handle_martyrs()] + /// LAZY LIST. For grenades, any /mob/living's the grenade is moved onto, see [/datum/component/pellet_cloud/proc/handle_martyrs()] var/list/bodies /// For grenades, tracking people who die covering a grenade for achievement purposes, see [/datum/component/pellet_cloud/proc/handle_martyrs()] var/list/purple_hearts @@ -65,7 +65,7 @@ purple_hearts = null pellets = null targets_hit = null - bodies = null + LAZYNULL(bodies) return ..() /datum/component/pellet_cloud/RegisterWithParent() @@ -288,5 +288,5 @@ /datum/component/pellet_cloud/proc/on_target_qdel(atom/target) UnregisterSignal(target, COMSIG_PARENT_QDELETING) targets_hit -= target - LAZYREMOVE(target, bodies) + LAZYREMOVE(bodies, target) purple_hearts -= target diff --git a/code/datums/components/weatherannouncer.dm b/code/datums/components/weatherannouncer.dm index 3821f9a1b559..a5e622d8669e 100644 --- a/code/datums/components/weatherannouncer.dm +++ b/code/datums/components/weatherannouncer.dm @@ -110,7 +110,7 @@ /datum/component/weather_announcer/proc/time_till_storm() var/datum/weather_controller/local_weather_controller = SSmapping.get_map_zone_weather_controller(parent) - if(!local_weather_controller.next_weather) + if(!local_weather_controller?.next_weather) return null for(var/type_index in local_weather_controller.current_weathers) var/datum/weather/check_weather = local_weather_controller.current_weathers[type_index] diff --git a/code/datums/elements/beauty.dm b/code/datums/elements/beauty.dm new file mode 100644 index 000000000000..88cd6eb3adea --- /dev/null +++ b/code/datums/elements/beauty.dm @@ -0,0 +1,76 @@ +/** + * Beauty element. It makes the indoor area the parent is in prettier or uglier depending on the beauty var value. + * Clean and well decorated areas lead to positive moodlets for passerbies; + * Shabbier, dirtier ones lead to negative moodlets EXCLUSIVE to characters with the snob quirk. + */ +/datum/element/beauty + element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH + id_arg_index = 2 + var/beauty = 0 + /** + * Assoc list of atoms as keys and number of time the same element instance has been attached to them as assoc value. + * So things don't get odd with same-valued yet dissimilar beauty modifiers being added to the same atom. + */ + var/beauty_counter = list() + +/datum/element/beauty/Attach(datum/target, beauty) + . = ..() + if(!isatom(target) || isarea(target)) + return ELEMENT_INCOMPATIBLE + + src.beauty = beauty + + if(!beauty_counter[target] && ismovable(target)) + var/atom/movable/mov_target = target + mov_target.become_area_sensitive(BEAUTY_ELEMENT_TRAIT) + RegisterSignal(mov_target, COMSIG_ENTER_AREA, PROC_REF(enter_area)) + RegisterSignal(mov_target, COMSIG_EXIT_AREA, PROC_REF(exit_area)) + + beauty_counter[target]++ + + var/area/current_area = get_area(target) + if(current_area && !current_area.outdoors) + current_area.totalbeauty += beauty + current_area.update_beauty() + +/datum/element/beauty/proc/enter_area(datum/source, area/new_area) + SIGNAL_HANDLER + + if(new_area.outdoors) + return + new_area.totalbeauty += beauty * beauty_counter[source] + new_area.update_beauty() + +/datum/element/beauty/proc/exit_area(datum/source, area/old_area) + SIGNAL_HANDLER + + if(old_area.outdoors) + return + old_area.totalbeauty -= beauty * beauty_counter[source] + old_area.update_beauty() + +/datum/element/beauty/Detach(datum/source) + if(!beauty_counter[source]) + return ..() + var/area/current_area = get_area(source) + if(QDELETED(source)) + . = ..() + UnregisterSignal(source, list(COMSIG_ENTER_AREA, COMSIG_EXIT_AREA)) + if(current_area) + exit_area(source, current_area) + beauty_counter -= source + var/atom/movable/movable_source = source + if(istype(movable_source)) + movable_source.lose_area_sensitivity(BEAUTY_ELEMENT_TRAIT) + else //lower the 'counter' down by one, update the area, and call parent if it's reached zero. + beauty_counter[source]-- + if(current_area && !current_area.outdoors) + current_area.totalbeauty -= beauty + current_area.update_beauty() + if(!beauty_counter[source]) + . = ..() + UnregisterSignal(source, list(COMSIG_ENTER_AREA, COMSIG_EXIT_AREA)) + beauty_counter -= source + var/atom/movable/movable_source = source + if(istype(movable_source)) + movable_source.lose_area_sensitivity(BEAUTY_ELEMENT_TRAIT) diff --git a/code/datums/materials/_material.dm b/code/datums/materials/_material.dm index 79d3a5e68a89..4f505cb2a3e7 100644 --- a/code/datums/materials/_material.dm +++ b/code/datums/materials/_material.dm @@ -65,7 +65,7 @@ Simple datum which is instanced once per type and is used for every object of sa source.name = "[name] [source.name]" if(beauty_modifier) - addtimer(CALLBACK(source, TYPE_PROC_REF(/datum, _AddComponent), list(/datum/component/beauty, beauty_modifier * amount)), 0) + source.AddElement(/datum/element/beauty, beauty_modifier * amount) if(istype(source, /obj)) //objs on_applied_obj(source, amount, material_flags) @@ -121,7 +121,7 @@ Simple datum which is instanced once per type and is used for every object of sa return ///This proc is called when the material is removed from an object. -/datum/material/proc/on_removed(atom/source, material_flags) +/datum/material/proc/on_removed(atom/source, amount, material_flags) if(material_flags & MATERIAL_COLOR) //Prevent changing things with pre-set colors, to keep colored toolboxes their looks for example if(color) source.remove_atom_colour(FIXED_COLOUR_PRIORITY, color) @@ -133,6 +133,9 @@ Simple datum which is instanced once per type and is used for every object of sa if(material_flags & MATERIAL_ADD_PREFIX) source.name = initial(source.name) + if(beauty_modifier) + source.RemoveElement(/datum/element/beauty, beauty_modifier * amount) + if(istype(source, /obj)) //objs on_removed_obj(source, material_flags) diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index bf540f08459f..98db1541c953 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -86,7 +86,7 @@ Unless you know what you're doing, only use the first three numbers. They're in . = ..() source.AddComponent(/datum/component/radioactive, amount / 20, source, 0) //half-life of 0 because we keep on going. -/datum/material/uranium/on_removed(atom/source, material_flags) +/datum/material/uranium/on_removed(atom/source, amount, material_flags) . = ..() qdel(source.GetComponent(/datum/component/radioactive)) @@ -109,7 +109,7 @@ Unless you know what you're doing, only use the first three numbers. They're in source.AddElement(/datum/element/firestacker, amount=1) source.AddComponent(/datum/component/explodable, 0, 0, amount / 2500, amount / 1250) -/datum/material/plasma/on_removed(atom/source, material_flags) +/datum/material/plasma/on_removed(atom/source, amount, material_flags) . = ..() source.RemoveElement(/datum/element/firestacker, amount=1) qdel(source.GetComponent(/datum/component/explodable)) diff --git a/code/datums/materials/meat.dm b/code/datums/materials/meat.dm index d8a9fb5cc01c..9539b2847774 100644 --- a/code/datums/materials/meat.dm +++ b/code/datums/materials/meat.dm @@ -14,7 +14,7 @@ turf_sound_override = FOOTSTEP_MEAT texture_layer_icon_state = "meat" -/datum/material/meat/on_removed(atom/source, material_flags) +/datum/material/meat/on_removed(atom/source, amount, material_flags) . = ..() qdel(source.GetComponent(/datum/component/edible)) diff --git a/code/datums/materials/pizza.dm b/code/datums/materials/pizza.dm index 6ab79e3a2065..aed6577a5af9 100644 --- a/code/datums/materials/pizza.dm +++ b/code/datums/materials/pizza.dm @@ -13,7 +13,7 @@ turf_sound_override = FOOTSTEP_MEAT texture_layer_icon_state = "pizza" -/datum/material/pizza/on_removed(atom/source, material_flags) +/datum/material/pizza/on_removed(atom/source, amount, material_flags) . = ..() qdel(source.GetComponent(/datum/component/edible)) diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 35712cb768ae..e8bdb66c1898 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -575,18 +575,21 @@ GLOBAL_LIST_EMPTY(teleportlocs) /** * Call back when an atom enters an area * - * Sends signals COMSIG_AREA_ENTERED and COMSIG_ENTER_AREA (to the atom) + * Sends signals COMSIG_AREA_ENTERED and COMSIG_ENTER_AREA (to a list of atoms) * * If the area has ambience, then it plays some ambience music to the ambience channel */ -/area/Entered(atom/movable/M, area/old_area) +/area/Entered(atom/movable/arrived, area/old_area) set waitfor = FALSE - SEND_SIGNAL(src, COMSIG_AREA_ENTERED, M, old_area) - SEND_SIGNAL(M, COMSIG_ENTER_AREA, src) //The atom that enters the area - if(!isliving(M)) + SEND_SIGNAL(src, COMSIG_AREA_ENTERED, arrived, old_area) + if(!LAZYACCESS(arrived.important_recursive_contents, RECURSIVE_CONTENTS_AREA_SENSITIVE)) + return + for(var/atom/movable/recipient as anything in arrived.important_recursive_contents[RECURSIVE_CONTENTS_AREA_SENSITIVE]) + SEND_SIGNAL(recipient, COMSIG_ENTER_AREA, src) + if(!isliving(arrived)) return - var/mob/living/L = M + var/mob/living/L = arrived if(!L.ckey) return @@ -608,11 +611,14 @@ GLOBAL_LIST_EMPTY(teleportlocs) /** * Called when an atom exits an area * - * Sends signals COMSIG_AREA_EXITED and COMSIG_EXIT_AREA (to the atom) + * Sends signals COMSIG_AREA_EXITED and COMSIG_EXIT_AREA (to a list of atoms) */ /area/Exited(atom/movable/gone, direction) SEND_SIGNAL(src, COMSIG_AREA_EXITED, gone, direction) - SEND_SIGNAL(gone, COMSIG_EXIT_AREA, src) //The atom that exits the area + if(!LAZYACCESS(gone.important_recursive_contents, RECURSIVE_CONTENTS_AREA_SENSITIVE)) + return + for(var/atom/movable/recipient as anything in gone.important_recursive_contents[RECURSIVE_CONTENTS_AREA_SENSITIVE]) + SEND_SIGNAL(recipient, COMSIG_EXIT_AREA, src) /** diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 350b80907f70..6c6849724bde 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1525,7 +1525,7 @@ if(custom_materials) //Only runs if custom materials existed at first. Should usually be the case but check anyways for(var/i in custom_materials) var/datum/material/custom_material = SSmaterials.GetMaterialRef(i) - custom_material.on_removed(src, material_flags) //Remove the current materials + custom_material.on_removed(src, custom_materials[i] * material_modifier, material_flags) //Remove the current materials if(!length(materials)) return diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 54ac77bb0a8c..96ba335e378c 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -630,6 +630,71 @@ return A.Bumped(src) +/atom/movable/Exited(atom/movable/gone, direction) + . = ..() + + if(!LAZYLEN(gone.important_recursive_contents)) + return + + var/list/nested_locs = get_nested_locs(src) + src + for(var/channel in gone.important_recursive_contents) + for(var/atom/movable/location as anything in nested_locs) + var/list/recursive_contents = location.important_recursive_contents // blue hedgehog velocity + recursive_contents[channel] -= gone.important_recursive_contents[channel] + ASSOC_UNSETEMPTY(recursive_contents, channel) + UNSETEMPTY(location.important_recursive_contents) + +/atom/movable/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs) + . = ..() + + if(!LAZYLEN(arrived.important_recursive_contents)) + return + + var/list/nested_locs = get_nested_locs(src) + src + for(var/channel in arrived.important_recursive_contents) + for(var/atom/movable/location as anything in nested_locs) + LAZYINITLIST(location.important_recursive_contents) + var/list/recursive_contents = location.important_recursive_contents // blue hedgehog velocity + LAZYINITLIST(recursive_contents[channel]) + recursive_contents[channel] |= arrived.important_recursive_contents[channel] + +/// See traits.dm. Use this in place of ADD_TRAIT. +/atom/movable/proc/become_area_sensitive(trait_source = TRAIT_GENERIC) + if(!HAS_TRAIT(src, TRAIT_AREA_SENSITIVE)) + for(var/atom/movable/location as anything in get_nested_locs(src) + src) + LAZYADDASSOCLIST(location.important_recursive_contents, RECURSIVE_CONTENTS_AREA_SENSITIVE, src) + ADD_TRAIT(src, TRAIT_AREA_SENSITIVE, trait_source) + +/atom/movable/proc/lose_area_sensitivity(trait_source = TRAIT_GENERIC) + if(!HAS_TRAIT(src, TRAIT_AREA_SENSITIVE)) + return + REMOVE_TRAIT(src, TRAIT_AREA_SENSITIVE, trait_source) + if(HAS_TRAIT(src, TRAIT_AREA_SENSITIVE)) + return + +///allows this movable to hear and adds itself to the important_recursive_contents list of itself and every movable loc its in +/atom/movable/proc/become_hearing_sensitive(trait_source = TRAIT_GENERIC) + ADD_TRAIT(src, TRAIT_HEARING_SENSITIVE, trait_source) + if(!HAS_TRAIT(src, TRAIT_HEARING_SENSITIVE)) + return + + for(var/atom/movable/location as anything in get_nested_locs(src) + src) + LAZYINITLIST(location.important_recursive_contents) + var/list/recursive_contents = location.important_recursive_contents // blue hedgehog velocity + recursive_contents[RECURSIVE_CONTENTS_HEARING_SENSITIVE] += list(src) + +/atom/movable/proc/lose_hearing_sensitivity(trait_source = TRAIT_GENERIC) + if(!HAS_TRAIT(src, TRAIT_HEARING_SENSITIVE)) + return + REMOVE_TRAIT(src, TRAIT_HEARING_SENSITIVE, trait_source) + if(HAS_TRAIT(src, TRAIT_HEARING_SENSITIVE)) + return + for(var/atom/movable/location as anything in get_nested_locs(src) + src) + var/list/recursive_contents = location.important_recursive_contents // blue hedgehog velocity + recursive_contents[RECURSIVE_CONTENTS_HEARING_SENSITIVE] -= src + ASSOC_UNSETEMPTY(recursive_contents, RECURSIVE_CONTENTS_HEARING_SENSITIVE) + UNSETEMPTY(location.important_recursive_contents) + ///Sets the anchored var and returns if it was sucessfully changed or not. /atom/movable/proc/set_anchored(anchorvalue) SHOULD_CALL_PARENT(TRUE) @@ -1181,54 +1246,3 @@ animate(pickup_animation, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING) sleep(1) animate(pickup_animation, alpha = 0, transform = matrix(), time = 1) - -/atom/movable/Exited(atom/movable/gone, direction) - . = ..() - - if(!LAZYLEN(gone.important_recursive_contents)) - return - - var/list/nested_locs = get_nested_locs(src) + src - for(var/channel in gone.important_recursive_contents) - for(var/atom/movable/location as anything in nested_locs) - var/list/recursive_contents = location.important_recursive_contents // blue hedgehog velocity - recursive_contents[channel] -= gone.important_recursive_contents[channel] - ASSOC_UNSETEMPTY(recursive_contents, channel) - UNSETEMPTY(location.important_recursive_contents) - -/atom/movable/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs) - . = ..() - - if(!LAZYLEN(arrived.important_recursive_contents)) - return - - var/list/nested_locs = get_nested_locs(src) + src - for(var/channel in arrived.important_recursive_contents) - for(var/atom/movable/location as anything in nested_locs) - LAZYINITLIST(location.important_recursive_contents) - var/list/recursive_contents = location.important_recursive_contents // blue hedgehog velocity - LAZYINITLIST(recursive_contents[channel]) - recursive_contents[channel] |= arrived.important_recursive_contents[channel] - -///allows this movable to hear and adds itself to the important_recursive_contents list of itself and every movable loc its in -/atom/movable/proc/become_hearing_sensitive(trait_source = TRAIT_GENERIC) - ADD_TRAIT(src, TRAIT_HEARING_SENSITIVE, trait_source) - if(!HAS_TRAIT(src, TRAIT_HEARING_SENSITIVE)) - return - - for(var/atom/movable/location as anything in get_nested_locs(src) + src) - LAZYINITLIST(location.important_recursive_contents) - var/list/recursive_contents = location.important_recursive_contents // blue hedgehog velocity - recursive_contents[RECURSIVE_CONTENTS_HEARING_SENSITIVE] += list(src) - -/atom/movable/proc/lose_hearing_sensitivity(trait_source = TRAIT_GENERIC) - if(!HAS_TRAIT(src, TRAIT_HEARING_SENSITIVE)) - return - REMOVE_TRAIT(src, TRAIT_HEARING_SENSITIVE, trait_source) - if(HAS_TRAIT(src, TRAIT_HEARING_SENSITIVE)) - return - for(var/atom/movable/location as anything in get_nested_locs(src) + src) - var/list/recursive_contents = location.important_recursive_contents // blue hedgehog velocity - recursive_contents[RECURSIVE_CONTENTS_HEARING_SENSITIVE] -= src - ASSOC_UNSETEMPTY(recursive_contents, RECURSIVE_CONTENTS_HEARING_SENSITIVE) - UNSETEMPTY(location.important_recursive_contents) diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index c81a58ad73b9..a17b9c705dc1 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -167,12 +167,14 @@ Class Procs: /obj/machinery/LateInitialize() . = ..() power_change() + become_area_sensitive(ROUNDSTART_TRAIT) RegisterSignal(src, COMSIG_ENTER_AREA, PROC_REF(power_change)) /obj/machinery/Destroy() GLOB.machines.Remove(src) end_processing() dropContents() + lose_area_sensitivity(ROUNDSTART_TRAIT) QDEL_NULL(circuit) QDEL_LIST(component_parts) return ..() diff --git a/code/game/objects/effects/contraband.dm b/code/game/objects/effects/contraband.dm index a6d2fff1571f..a86a74c2c3d4 100644 --- a/code/game/objects/effects/contraband.dm +++ b/code/game/objects/effects/contraband.dm @@ -97,7 +97,7 @@ name = "poster - [name]" desc = "A large piece of space-resistant printed paper. [desc]" - addtimer(CALLBACK(src, TYPE_PROC_REF(/datum, _AddComponent), list(/datum/component/beauty, 300)), 0) + AddElement(/datum/element/beauty, 300) /obj/structure/sign/poster/proc/randomise() var/obj/structure/sign/poster/selected diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index a0909bb0b994..4161403fefd9 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -30,8 +30,7 @@ COMSIG_ATOM_ENTERED = PROC_REF(on_entered), ) AddElement(/datum/element/connect_loc, loc_connections) - - addtimer(CALLBACK(src, TYPE_PROC_REF(/datum, _AddComponent), list(/datum/component/beauty, beauty)), 0) + AddElement(/datum/element/beauty, beauty) SSblackbox.record_feedback("tally", "station_mess_created", 1, name) diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index 1296e889181d..da08c87a5a35 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -66,13 +66,13 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \ else if(istype(W, /obj/item/stack/rods)) var/obj/item/stack/rods/V = W if (V.get_amount() >= 1 && get_amount() >= 1) - var/obj/item/stack/sheet/rglass/RG = new (get_turf(user)) - RG.add_fingerprint(user) + var/obj/item/stack/sheet/rglass/reinforced = new(get_turf(user)) || locate(/obj/item/stack/sheet/rglass) in get_turf(user) // Get the stack it's merged into if it is + reinforced.add_fingerprint(user) var/replace = user.get_inactive_held_item()==src V.use(1) use(1) if(QDELETED(src) && replace) - user.put_in_hands(RG) + user.put_in_hands(reinforced) else to_chat(user, "You need one rod and one sheet of glass to make reinforced glass!") return @@ -119,13 +119,13 @@ GLOBAL_LIST_INIT(pglass_recipes, list ( \ if(istype(W, /obj/item/stack/rods)) var/obj/item/stack/rods/V = W if (V.get_amount() >= 1 && get_amount() >= 1) - var/obj/item/stack/sheet/plasmarglass/RG = new (get_turf(user)) - RG.add_fingerprint(user) - var/replace = user.get_inactive_held_item()==src + var/obj/item/stack/sheet/plasmarglass/reinforced = new(get_turf(user)) || locate(/obj/item/stack/sheet/plasmarglass) in get_turf(user) // Get the stack it's merged into if it is + reinforced.add_fingerprint(user) + var/replace = user.get_inactive_held_item() == src V.use(1) use(1) if(QDELETED(src) && replace) - user.put_in_hands(RG) + user.put_in_hands(reinforced) else to_chat(user, "You need one rod and one sheet of plasma glass to make reinforced plasma glass!") return diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index c019471e3cdd..9e8d1e3c17b9 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -515,7 +515,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 /obj/item/statuebust/Initialize() . = ..() AddComponent(/datum/component/art, impressiveness) - addtimer(CALLBACK(src, TYPE_PROC_REF(/datum, _AddComponent), list(/datum/component/beauty, 1000)), 0) + AddElement(/datum/element/beauty, 1000) /obj/item/statuebust/hippocratic name = "hippocrates bust" diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 46090aa86658..f295bfab8950 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -205,6 +205,7 @@ ui_interact(user) /mob/proc/unset_machine() + SIGNAL_HANDLER if(!machine) return UnregisterSignal(machine, COMSIG_PARENT_QDELETING) @@ -216,6 +217,8 @@ return /mob/proc/set_machine(obj/O) + if(QDELETED(src) || QDELETED(O)) + return if(machine) unset_machine() machine = O diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index 50b578a3aee2..8ba938dae8ee 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -368,8 +368,8 @@ /obj/item/kirbyplants/ComponentInitialize() . = ..() AddComponent(/datum/component/tactical) - addtimer(CALLBACK(src, TYPE_PROC_REF(/datum, _AddComponent), list(/datum/component/beauty, 500)), 0) AddComponent(/datum/component/two_handed, require_twohands=TRUE, force_unwielded=10, force_wielded=10) + AddElement(/datum/element/beauty, 500) /obj/item/kirbyplants/random icon = 'icons/obj/flora/_flora.dmi' diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 7a8aec8a97f2..25822d69ff00 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -44,12 +44,16 @@ M.add_fingerprint(user) qdel(src) + return + else if(istype(W, /obj/item/pickaxe/drill/jackhammer)) to_chat(user, "You smash through the girder!") new /obj/item/stack/sheet/metal(get_turf(src)) W.play_tool_sound(src) qdel(src) + return + else if(istype(W, /obj/item/stack)) if(iswallturf(loc)) @@ -77,6 +81,8 @@ var/obj/structure/falsewall/iron/FW = new (loc) transfer_fingerprints_to(FW) qdel(src) + + return else if(S.get_amount() < 5) to_chat(user, "You need at least five rods to add plating!") @@ -111,6 +117,8 @@ var/obj/structure/falsewall/F = new (loc) transfer_fingerprints_to(F) qdel(src) + + return else if(S.get_amount() < 2) to_chat(user, "You need two sheets of metal to finish a wall!") @@ -141,6 +149,8 @@ var/obj/structure/falsewall/reinforced/FW = new (loc) transfer_fingerprints_to(FW) qdel(src) + + return else if(state == GIRDER_REINF) if(S.get_amount() < 1) @@ -185,6 +195,8 @@ var/obj/structure/FW = new F (loc) transfer_fingerprints_to(FW) qdel(src) + + return else if(S.get_amount() < 2) to_chat(user, "You need at least two sheets to add plating!") @@ -210,8 +222,6 @@ qdel(src) return - add_hiddenprint(user) - else if(istype(W, /obj/item/pipe)) var/obj/item/pipe/P = W if (P.pipe_type in list(0, 1, 5)) //simple pipes, simple bends, and simple manifolds. diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 56f50eb1768e..5bca53e84dd6 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -221,8 +221,8 @@ /obj/structure/grille/deconstruct(disassembled = TRUE) if(!loc) //if already qdel'd somehow, we do nothing return - if(!(flags_1&NODECONSTRUCT_1)) - var/obj/R = new rods_type(drop_location(), rods_amount) + if(!(flags_1 & NODECONSTRUCT_1)) + var/obj/R = new rods_type(drop_location(), rods_amount) || locate(rods_type) in drop_location() // if the rods get merged, find the stack transfer_fingerprints_to(R) qdel(src) ..() @@ -230,7 +230,7 @@ /obj/structure/grille/obj_break() if(!broken && !(flags_1 & NODECONSTRUCT_1)) new broken_type(src.loc) - var/obj/R = new rods_type(drop_location(), rods_broken) + var/obj/R = new rods_type(drop_location(), rods_broken) || locate(rods_type) in drop_location() // see above transfer_fingerprints_to(R) qdel(src) diff --git a/code/game/objects/structures/headpike.dm b/code/game/objects/structures/headpike.dm index aff870c6eedf..c42983a5e0e5 100644 --- a/code/game/objects/structures/headpike.dm +++ b/code/game/objects/structures/headpike.dm @@ -13,24 +13,53 @@ icon_state = "headpike-bone" bonespear = TRUE +/obj/structure/headpike/Initialize(mapload) + . = ..() + if(mapload) + CheckParts() + /obj/structure/headpike/CheckParts(list/parts_list) - ..() victim = locate(/obj/item/bodypart/head) in parts_list - update_appearance() - if(bonespear) - spear = locate(/obj/item/spear/bonespear) in parts_list - else - spear = locate(/obj/item/spear) in parts_list + if(!victim) //likely a mapspawned one + victim = new(src) + victim.real_name = random_unique_name(prob(50)) -/obj/structure/headpike/Initialize() - . = ..() - pixel_x = rand(-8, 8) + spear = locate(bonespear ? /obj/item/spear/bonespear : /obj/item/spear) in parts_list + if(!spear) + spear = bonespear ? new/obj/item/spear/bonespear(src) : new/obj/item/spear(src) + + update_appearance() + return ..() /obj/structure/headpike/Destroy() QDEL_NULL(victim) QDEL_NULL(spear) return ..() +/obj/structure/headpike/handle_atom_del(atom/A) + if(A == victim) + victim = null + if(A == spear) + spear = null + if(!QDELETED(src)) + deconstruct(TRUE) + return ..() + +/obj/structure/headpike/deconstruct(disassembled) + if(!disassembled) + return ..() + if(victim) + victim.forceMove(drop_location()) + victim = null + if(spear) + spear.forceMove(drop_location()) + spear = null + return ..() + +/obj/structure/headpike/Initialize() + . = ..() + pixel_x = rand(-8, 8) + /obj/structure/headpike/update_overlays() . = ..() var/obj/item/bodypart/head/H = locate() in contents @@ -45,12 +74,7 @@ if(.) return to_chat(user, "You take down [src].") - if(victim) - victim.forceMove(drop_location()) - victim = null - spear.forceMove(drop_location()) - spear = null - qdel(src) + deconstruct(TRUE) /obj/structure/headpike/update_name() name = "[victim.real_name] on a [spear]" diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm index a4155003dcdb..642c2c2efdd4 100644 --- a/code/game/objects/structures/statues.dm +++ b/code/game/objects/structures/statues.dm @@ -15,7 +15,7 @@ /obj/structure/statue/Initialize() . = ..() AddComponent(art_type, impressiveness) - addtimer(CALLBACK(src, TYPE_PROC_REF(/datum, _AddComponent), list(/datum/component/beauty, impressiveness * 75)), 0) + AddElement(/datum/element/beauty, impressiveness * 75) /obj/structure/statue/attackby(obj/item/W, mob/living/user, params) add_fingerprint(user) diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm index 07976f05631f..13e8ae7877c7 100644 --- a/code/game/turfs/change_turf.dm +++ b/code/game/turfs/change_turf.dm @@ -39,10 +39,6 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( /turf/open/copyTurf(turf/T, copy_air = FALSE) . = ..() if(isopenturf(T)) - var/datum/component/wet_floor/slip = GetComponent(/datum/component/wet_floor) - if(slip) - var/datum/component/wet_floor/WF = T.AddComponent(/datum/component/wet_floor) - WF.InheritComponent(slip) if(copy_air) var/turf/open/openTurf = T openTurf.air.copy_from(air) diff --git a/code/game/turfs/open/floor/reinf_floor.dm b/code/game/turfs/open/floor/reinf_floor.dm index 68a96846adbb..a164b159d6f6 100644 --- a/code/game/turfs/open/floor/reinf_floor.dm +++ b/code/game/turfs/open/floor/reinf_floor.dm @@ -40,6 +40,9 @@ /turf/open/floor/engine/crowbar_act(mob/living/user, obj/item/I) return +/turf/open/floor/engine/handle_decompression_floor_rip(sum) + return + /turf/open/floor/engine/wrench_act(mob/living/user, obj/item/I) ..() to_chat(user, "You begin removing the sheet...") diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index f28a9a898588..715139dfd6ba 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -197,6 +197,7 @@ FD.emergency_pressure_stop() /turf/proc/handle_decompression_floor_rip() + /turf/open/floor/handle_decompression_floor_rip(sum) if(sum > 20 && prob(clamp(sum / 10, 0, 30)) && !blocks_air) remove_tile() diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm index f5cfc93c6eee..dec456b8ef2f 100644 --- a/code/modules/awaymissions/mission_code/snowdin.dm +++ b/code/modules/awaymissions/mission_code/snowdin.dm @@ -225,7 +225,8 @@ if(plasma_parts.len) var/obj/item/bodypart/NB = pick(plasma_parts) //using the above-mentioned list to get a choice of limbs for dismember() to use PP.emote("scream") - NB.limb_id = "plasmaman"//change the species_id of the limb to that of a plasmaman + NB.limb_id = "plasmaman" //change the species_id of the limb to that of a plasmaman + NB.static_icon = 'icons/mob/species/plasmaman/bodyparts.dmi' NB.no_update = TRUE NB.change_bodypart_status() PP.visible_message( diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm index c0c316a1354a..61e416e9d4f1 100644 --- a/code/modules/cargo/centcom_podlauncher.dm +++ b/code/modules/cargo/centcom_podlauncher.dm @@ -684,8 +684,8 @@ return var/obj/structure/closet/supplypod/centcompod/toLaunch = DuplicateObject(temp_pod) //Duplicate the temp_pod (which we have been varediting or configuring with the UI) and store the result toLaunch.update_appearance()//we update_appearance() here so that the door doesnt "flicker on" right after it lands - var/shippingLane = GLOB.areas_by_type[/area/centcom/supplypod/supplypod_temp_holding] - toLaunch.forceMove(shippingLane) + var/area/shipping_lane = GLOB.areas_by_type[/area/centcom/supplypod/supplypod_temp_holding] + toLaunch.forceMove(pick(shipping_lane.contents)) if (launchClone) //We arent launching the actual items from the bay, rather we are creating clones and launching those if(launchRandomItem) var/launch_candidate = pick_n_take(launchList) diff --git a/code/modules/cargo/supplypod.dm b/code/modules/cargo/supplypod.dm index 16b43704df58..3ff822a4f943 100644 --- a/code/modules/cargo/supplypod.dm +++ b/code/modules/cargo/supplypod.dm @@ -81,8 +81,8 @@ /obj/structure/closet/supplypod/Initialize(mapload, customStyle = FALSE) . = ..() if (!loc) - var/shippingLane = GLOB.areas_by_type[/area/centcom/supplypod/supplypod_temp_holding] //temporary holder for supplypods mid-transit - forceMove(shippingLane) + var/area/shipping_lane = GLOB.areas_by_type[/area/centcom/supplypod/supplypod_temp_holding] //temporary holder for supplypods mid-transit + forceMove(pick(shipping_lane.contents)) if (customStyle) style = customStyle setStyle(style) //Upon initialization, give the supplypod an iconstate, name, and description based on the "style" variable. This system is important for the centcom_podlauncher to function correctly @@ -200,8 +200,8 @@ stay_after_drop = FALSE holder.pixel_z = initial(holder.pixel_z) holder.alpha = initial(holder.alpha) - var/shippingLane = GLOB.areas_by_type[/area/centcom/supplypod/supplypod_temp_holding] - forceMove(shippingLane) //Move to the centcom-z-level until the pod_landingzone says we can drop back down again + var/area/shipping_lane = GLOB.areas_by_type[/area/centcom/supplypod/supplypod_temp_holding] + forceMove(pick(shipping_lane.contents)) //Move to the centcom-z-level until the pod_landingzone says we can drop back down again if (!reverse_dropoff_coords) //If we're centcom-launched, the reverse dropoff turf will be a centcom loading bay. If we're an extraction pod, it should be the ninja jail. Thus, this shouldn't ever really happen. var/obj/error_landmark = locate(/obj/effect/landmark/error) in GLOB.landmarks_list var/turf/error_landmark_turf = get_turf(error_landmark) diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm index ede24c643c43..b1c01d16c636 100644 --- a/code/modules/events/spacevine.dm +++ b/code/modules/events/spacevine.dm @@ -368,13 +368,16 @@ /obj/structure/spacevine/attack_hand(mob/user) for(var/datum/spacevine_mutation/SM in mutations) SM.on_hit(src, user) - user_unbuckle_mob(user, user) - . = ..() + if(user.buckled == src) + user_unbuckle_mob(user, user) + return ..() /obj/structure/spacevine/attack_paw(mob/living/user) for(var/datum/spacevine_mutation/SM in mutations) SM.on_hit(src, user) - user_unbuckle_mob(user,user) + if(user.buckled == src) + user_unbuckle_mob(user, user) + return ..() /obj/structure/spacevine/attack_alien(mob/living/user) eat(user) diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index fe446513c521..96954cd59b4d 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -861,7 +861,7 @@ /obj/item/freeze_cube/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) icon_state = initial(icon_state) var/caught = hit_atom.hitby(src, FALSE, FALSE, throwingdatum=throwingdatum) - var/mob/thrown_by = thrownby + var/mob/thrown_by = thrownby.resolve() if(ismovable(hit_atom) && !caught && (!thrown_by || thrown_by && COOLDOWN_FINISHED(src, freeze_cooldown))) freeze(hit_atom) if(thrown_by && !caught) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 5d8c44bbc188..6fffc48e76a1 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -435,7 +435,12 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(!thearea) return - usr.abstract_move(pick(get_area_turfs(thearea))) + var/list/area_turfs = get_area_turfs(thearea) + + if(!length(area_turfs)) + return + + usr.abstract_move(pick(area_turfs)) update_parallax_contents() /mob/dead/observer/verb/follow() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index cd80b13bcda6..93276a6710a6 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -781,6 +781,16 @@ * Called when this human should be washed */ /mob/living/carbon/human/wash(clean_types) + // Check and wash stuff that can be covered + var/list/obscured = check_obscured_slots() + + // Wash hands if exposed + // This runs before the parent call since blood_in_hands should be cleared before the blood DNA is removed + if(!gloves && (clean_types & CLEAN_TYPE_BLOOD) && blood_in_hands > 0 && !(ITEM_SLOT_GLOVES in obscured)) + blood_in_hands = 0 + update_inv_gloves() + . = TRUE + . = ..() // Wash equipped stuff that cannot be covered @@ -792,9 +802,6 @@ update_inv_belt() . = TRUE - // Check and wash stuff that can be covered - var/list/obscured = check_obscured_slots() - if(w_uniform && !(ITEM_SLOT_ICLOTHING in obscured) && w_uniform.wash(clean_types)) update_inv_w_uniform() . = TRUE @@ -802,12 +809,6 @@ if(!is_mouth_covered() && clean_lips()) . = TRUE - // Wash hands if exposed - if(!gloves && (clean_types & CLEAN_TYPE_BLOOD) && blood_in_hands > 0 && !(ITEM_SLOT_GLOVES in obscured)) - blood_in_hands = 0 - update_inv_gloves() - . = TRUE - //Turns a mob black, flashes a skeleton overlay //Just like a cartoon! /mob/living/carbon/human/proc/electrocution_animation(anim_duration) diff --git a/code/modules/mob/living/carbon/human/species_types/vox.dm b/code/modules/mob/living/carbon/human/species_types/vox.dm index 1f3a00e8641b..fd03e184b9ba 100644 --- a/code/modules/mob/living/carbon/human/species_types/vox.dm +++ b/code/modules/mob/living/carbon/human/species_types/vox.dm @@ -104,16 +104,15 @@ return ..() /datum/species/vox/get_item_offsets_for_dir(dir, hand) - ////LEFT/RIGHT - switch(dir) - if(SOUTH) - return list(list("x" = 10, "y" = -1), list("x" = 8, "y" = -1)) - if(NORTH) - return list(list("x" = 9, "y" = 0), list("x" = 9, "y" = 0)) - if(EAST) - return list(list("x" = 18, "y" = 2), list("x" = 21, "y" = -1)) - if(WEST) - return list(list("x" = -5, "y" = -1), list("x" = -1, "y" = 2)) + //LEFT/RIGHT + if(dir & NORTH) + return list(list("x" = 9, "y" = 0), list("x" = 9, "y" = 0)) + if(dir & SOUTH) + return list(list("x" = 10, "y" = -1), list("x" = 8, "y" = -1)) + if(dir & EAST) + return list(list("x" = 18, "y" = 2), list("x" = 21, "y" = -1)) + if(dir & WEST) + return list(list("x" = -5, "y" = -1), list("x" = -1, "y" = 2)) /datum/action/innate/tail_hold name = "Tail Hold" @@ -174,11 +173,14 @@ owner.cut_overlay(held_item_overlay) held_item_overlay = null return + if(olddir == newdir && !force) return newdir ||= owner.dir + newdir = normalize_dir_to_cardinals(newdir) + owner.cut_overlay(held_item_overlay) var/dirtext = dir2text(newdir) var/icon_file = held_item.lefthand_file diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index a0e409c2053d..09445cef4c4e 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -191,7 +191,9 @@ There are several things that need to be remembered: bloody_overlay.icon_state = "bloodyhands_left" else if(has_right_hand(FALSE)) bloody_overlay.icon_state = "bloodyhands_right" - bloody_overlay.color = get_blood_dna_color(return_blood_DNA()) + var/list/blood_dna = return_blood_DNA() + if(length(blood_dna)) + bloody_overlay.color = get_blood_dna_color(return_blood_DNA()) overlays_standing[GLOVES_LAYER] = bloody_overlay //Bloody hands end diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index 2115a3c6aba4..8b6acd39ae34 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -1023,13 +1023,17 @@ Nothing else in the console has ID requirements. linked_imprinter.linked_console = null linked_imprinter = null if(ls["eject_design"]) //Eject the design disk. + if(QDELETED(d_disk)) + say("No Design Disk Inserted!") + return eject_disk("design",usr) screen = RDSCREEN_MENU - say("Ejecting [d_disk.name]") if(ls["eject_tech"]) //Eject the technology disk. + if(QDELETED(t_disk)) + say("No Technology Disk Inserted!") + return eject_disk("tech", usr) screen = RDSCREEN_MENU - say("Ejecting [t_disk.name]") if(ls["deconstruct"]) if(QDELETED(linked_destroy)) say("No Destructive Analyzer Linked!") diff --git a/code/modules/screen_alerts/_screen_alerts.dm b/code/modules/screen_alerts/_screen_alerts.dm index 08a21635ea93..e9d93a59735b 100644 --- a/code/modules/screen_alerts/_screen_alerts.dm +++ b/code/modules/screen_alerts/_screen_alerts.dm @@ -79,6 +79,8 @@ continue maptext = "[style_open][copytext_char(text_to_play, 1, letter)][style_close]" sleep(play_delay) + if(QDELETED(user)) + return addtimer(CALLBACK(src, PROC_REF(after_play), user), fade_out_delay) ///handles post-play effects like fade out after the fade out delay diff --git a/code/modules/shuttle/special.dm b/code/modules/shuttle/special.dm index fd18f0c5a1ee..c00a62546b3f 100644 --- a/code/modules/shuttle/special.dm +++ b/code/modules/shuttle/special.dm @@ -145,9 +145,14 @@ /mob/living/simple_animal/drone/snowflake/bardrone/Initialize() . = ..() access_card.access |= ACCESS_CENT_BAR + become_area_sensitive(ROUNDSTART_TRAIT) RegisterSignal(src, COMSIG_ENTER_AREA, PROC_REF(check_barstaff_godmode)) check_barstaff_godmode() +/mob/living/simple_animal/drone/snowflake/bardrone/Destroy() + lose_area_sensitivity(ROUNDSTART_TRAIT) + return ..() + /mob/living/simple_animal/hostile/alien/maid/barmaid gold_core_spawnable = NO_SPAWN name = "Barmaid" @@ -165,12 +170,14 @@ access_card.access = C.get_access() access_card.access |= ACCESS_CENT_BAR ADD_TRAIT(access_card, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) + become_area_sensitive(ROUNDSTART_TRAIT) RegisterSignal(src, COMSIG_ENTER_AREA, PROC_REF(check_barstaff_godmode)) check_barstaff_godmode() /mob/living/simple_animal/hostile/alien/maid/barmaid/Destroy() qdel(access_card) - . = ..() + lose_area_sensitivity(ROUNDSTART_TRAIT) + return ..() /mob/living/simple_animal/proc/check_barstaff_godmode() SIGNAL_HANDLER diff --git a/shiptest.dme b/shiptest.dme index 29479c092022..35a38e567054 100644 --- a/shiptest.dme +++ b/shiptest.dme @@ -451,7 +451,6 @@ #include "code\datums\components\armor_plate.dm" #include "code\datums\components\art.dm" #include "code\datums\components\bane.dm" -#include "code\datums\components\beauty.dm" #include "code\datums\components\beetlejuice.dm" #include "code\datums\components\bloodysoles.dm" #include "code\datums\components\butchering.dm" @@ -617,6 +616,7 @@ #include "code\datums\diseases\advance\symptoms\weight.dm" #include "code\datums\diseases\advance\symptoms\youth.dm" #include "code\datums\elements\_element.dm" +#include "code\datums\elements\beauty.dm" #include "code\datums\elements\bed_tucking.dm" #include "code\datums\elements\bsa_blocker.dm" #include "code\datums\elements\cleaning.dm"