diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index 3fcbfcc8e54..3a7cbc96fe0 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -25274,7 +25274,7 @@ dir = 9 }, /obj/structure/cable, -/obj/machinery/atmospherics/components/trinary/filter, +/obj/machinery/atmospherics/components/trinary/filter/critical, /turf/open/floor/iron/smooth, /area/station/engineering/supermatter/room) "jeg" = ( diff --git a/_maps/map_files/NorthStar/north_star.dmm b/_maps/map_files/NorthStar/north_star.dmm index 393b1a2a2de..8252794b3db 100644 --- a/_maps/map_files/NorthStar/north_star.dmm +++ b/_maps/map_files/NorthStar/north_star.dmm @@ -20971,20 +20971,6 @@ dir = 1 }, /area/station/command/bridge) -"fBE" = ( -/obj/structure/disposalpipe/segment{ - dir = 1 - }, -/obj/structure/cable, -/obj/machinery/door/airlock/mining/glass{ - name = "Mail Sorting" - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/any/supply/general, -/turf/open/floor/iron/smooth, -/area/station/cargo/storage) "fBM" = ( /obj/effect/turf_decal/delivery, /turf/open/floor/iron/dark, @@ -32703,6 +32689,13 @@ /obj/machinery/firealarm/directional/east, /turf/open/floor/catwalk_floor, /area/station/maintenance/floor3/starboard/fore) +"iDz" = ( +/obj/machinery/atmospherics/components/trinary/filter/critical{ + dir = 4 + }, +/obj/machinery/status_display/evac/directional/north, +/turf/open/floor/engine, +/area/station/engineering/supermatter/room) "iDP" = ( /obj/structure/cable/multilayer/multiz, /turf/open/floor/plating, @@ -75518,13 +75511,6 @@ /obj/structure/closet/emcloset/anchored, /turf/open/floor/pod/dark, /area/station/maintenance/floor3/port) -"tLH" = ( -/obj/machinery/atmospherics/components/trinary/filter{ - dir = 4 - }, -/obj/machinery/status_display/evac/directional/north, -/turf/open/floor/engine, -/area/station/engineering/supermatter/room) "tMd" = ( /obj/effect/turf_decal/siding/wood/corner{ dir = 1 @@ -86658,6 +86644,20 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/plating, /area/station/medical/abandoned) +"wEN" = ( +/obj/structure/disposalpipe/segment{ + dir = 1 + }, +/obj/structure/cable, +/obj/machinery/door/airlock/mining/glass{ + name = "Mail Sorting" + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/door/firedoor, +/obj/effect/mapping_helpers/airlock/access/any/supply/general, +/turf/open/floor/iron/smooth, +/area/station/cargo/storage) "wEQ" = ( /obj/structure/stairs/east, /turf/open/floor/pod/dark, @@ -119139,7 +119139,7 @@ cMA mnR acv hNz -fBE +wEN nlu aAZ iRK @@ -140228,7 +140228,7 @@ uyD uyD uyD uyD -tLH +iDz kfo mvg dEc diff --git a/code/__DEFINES/jobs.dm b/code/__DEFINES/jobs.dm index 7e09a7ea178..4b625097d23 100644 --- a/code/__DEFINES/jobs.dm +++ b/code/__DEFINES/jobs.dm @@ -236,9 +236,19 @@ #define JOB_CAN_BE_INTERN (1<<8) /// This job cannot have more slots opened by the Head of Personnel (but admins or other random events can still do this). #define JOB_CANNOT_OPEN_SLOTS (1<<9) +/// This job will not display on the job menu when there are no slots available, instead of appearing greyed out +#define JOB_HIDE_WHEN_EMPTY (1<<10) +/// This job cannot be signed up for at round start or recorded in your preferences +#define JOB_LATEJOIN_ONLY (1<<11) +/// This job is a head of staff. +#define JOB_HEAD_OF_STAFF (1<<12) /// Combination flag for jobs which are considered regular crew members of the station. #define STATION_JOB_FLAGS (JOB_ANNOUNCE_ARRIVAL|JOB_CREW_MANIFEST|JOB_EQUIP_RANK|JOB_CREW_MEMBER|JOB_NEW_PLAYER_JOINABLE|JOB_REOPEN_ON_ROUNDSTART_LOSS|JOB_ASSIGN_QUIRKS|JOB_CAN_BE_INTERN) +/// Combination flag for jobs which are considered heads of staff. +#define HEAD_OF_STAFF_JOB_FLAGS (JOB_BOLD_SELECT_TEXT|JOB_CANNOT_OPEN_SLOTS|JOB_HEAD_OF_STAFF) +/// Combination flag for jobs which are enabled by station traits. +#define STATION_TRAIT_JOB_FLAGS (JOB_CANNOT_OPEN_SLOTS|JOB_HIDE_WHEN_EMPTY|JOB_LATEJOIN_ONLY&~JOB_REOPEN_ON_ROUNDSTART_LOSS) #define FACTION_NONE "None" #define FACTION_STATION "Station" @@ -251,3 +261,6 @@ #define SUPERVISOR_HOS "the Head of Security" #define SUPERVISOR_QM "the Quartermaster" #define SUPERVISOR_RD "the Research Director" + +/// Mind traits that should be shared by every head of staff. has to be this way cause byond lists lol +#define HEAD_OF_STAFF_MIND_TRAITS TRAIT_FAST_TYING, TRAIT_HIGH_VALUE_RANSOM diff --git a/code/__DEFINES/mecha.dm b/code/__DEFINES/mecha.dm index 5a37f60aba6..0f900f72ee4 100644 --- a/code/__DEFINES/mecha.dm +++ b/code/__DEFINES/mecha.dm @@ -6,7 +6,7 @@ #define PANEL_OPEN (1<<0) #define ID_LOCK_ON (1<<1) -#define CANSTRAFE (1<<2) +#define CAN_STRAFE (1<<2) #define LIGHTS_ON (1<<3) #define SILICON_PILOT (1<<4) #define IS_ENCLOSED (1<<5) diff --git a/code/__DEFINES/organ_movement.dm b/code/__DEFINES/organ_movement.dm new file mode 100644 index 00000000000..16f003ede81 --- /dev/null +++ b/code/__DEFINES/organ_movement.dm @@ -0,0 +1,4 @@ +/// Delete the organ if replaced +#define DELETE_IF_REPLACED (1<<0) +/// When deleting a brain, we don't delete the identity and the player can keep playing +#define NO_ID_TRANSFER (1<<1) diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 09652b363a9..e0f042ccc45 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -491,6 +491,15 @@ /// Is the mob standing on an elevated surface? This prevents them from dropping down if not elevated first. #define TRAIT_ON_ELEVATED_SURFACE "on_elevated_surface" +/// Prevents you from twohanding weapons. +#define TRAIT_NO_TWOHANDING "no_twohanding" + +/// Halves the time of tying a tie. +#define TRAIT_FAST_TYING "fast_tying" + +/// Sells for more money on the pirate bounty pad. +#define TRAIT_HIGH_VALUE_RANSOM "high_value_ransom" + // METABOLISMS // Various jobs on the station have historically had better reactions // to various drinks and foodstuffs. Security liking donuts is a classic diff --git a/code/__DEFINES/traits/sources.dm b/code/__DEFINES/traits/sources.dm index f0b67a95b92..f9cdbe4326d 100644 --- a/code/__DEFINES/traits/sources.dm +++ b/code/__DEFINES/traits/sources.dm @@ -275,5 +275,7 @@ #define ANALYZER_TRAIT "analyzer_trait" +/// Trait from an organ being inside a bodypart +#define ORGAN_INSIDE_BODY_TRAIT "organ_inside_body" /// Trait when something was labelled by a pen. #define PEN_LABEL_TRAIT "pen_label" diff --git a/code/__DEFINES/~nova_defines/colony_fabricator_misc.dm b/code/__DEFINES/~nova_defines/colony_fabricator_misc.dm index 1b358da8b11..0ebd9a14240 100644 --- a/code/__DEFINES/~nova_defines/colony_fabricator_misc.dm +++ b/code/__DEFINES/~nova_defines/colony_fabricator_misc.dm @@ -35,4 +35,6 @@ GLOBAL_LIST_INIT(colonist_suit_allowed, list( /obj/item/resonator, /obj/item/t_scanner, /obj/item/analyzer, + /obj/item/storage/medkit, + /obj/item/fireaxe/metal_h2_axe, )) diff --git a/code/__DEFINES/~nova_defines/manufacturer_strings.dm b/code/__DEFINES/~nova_defines/manufacturer_strings.dm index 3e9baa97952..b9cdddc78b0 100644 --- a/code/__DEFINES/~nova_defines/manufacturer_strings.dm +++ b/code/__DEFINES/~nova_defines/manufacturer_strings.dm @@ -22,5 +22,6 @@ #define COMPANY_ABDUCTOR "It has [span_abductor("✌︎︎♌︎︎♎︎︎◆︎︎♍︎︎⧫︎︎❄︎♏︎♍︎♒︎")] engraved into it." #define COMPANY_FRONTIER "It has a small label with [span_engradio("Akhter Company Frontier Equipment")] printed on it, alongside various xerxian proof-marks." +#define COMPANY_KAHRAMAN "It has a [span_red("red label")] with [span_red("K - A - S")] printed on it, alongside various xerxian proof-marks." #define COMPANY_REMOVED "It has had [span_grey("all identifying marks scrubbed off")]." diff --git a/code/__HELPERS/announcements.dm b/code/__HELPERS/announcements.dm index 5d7d0f65408..7a27be43a75 100644 --- a/code/__HELPERS/announcements.dm +++ b/code/__HELPERS/announcements.dm @@ -18,7 +18,6 @@ * * sender_override - optional, modifies the sender of the announcement * * encode_title - if TRUE, the title will be HTML encoded * * encode_text - if TRUE, the text will be HTML encoded - * * color_override - optional, set a color for the announcement box */ /proc/send_ooc_announcement( @@ -43,25 +42,25 @@ if(!length(text)) return - announcement_strings += span_major_announcement_title(sender_override) - announcement_strings += span_subheader_announcement_text(title) - announcement_strings += span_ooc_announcement_text(text) - var/finalized_announcement = create_ooc_announcement_div(jointext(announcement_strings, "")) + announcement_strings += span_major_announcement_title(sender_override) + announcement_strings += span_subheader_announcement_text(title) + announcement_strings += span_ooc_announcement_text(text) + var/finalized_announcement = create_ooc_announcement_div(jointext(announcement_strings, "")) - if(islist(players)) - for(var/mob/target in players) - to_chat(target, finalized_announcement) - if(play_sound && target.client?.prefs.read_preference(/datum/preference/toggle/sound_announcements)) - SEND_SOUND(target, sound(sound_override)) - else - to_chat(world, finalized_announcement) + if(islist(players)) + for(var/mob/target in players) + to_chat(target, finalized_announcement) + if(play_sound && target.client?.prefs.read_preference(/datum/preference/toggle/sound_announcements)) + SEND_SOUND(target, sound(sound_override)) + else + to_chat(world, finalized_announcement) - if(!play_sound) - return + if(!play_sound) + return - for(var/mob/player in GLOB.player_list) - if(player.client?.prefs.read_preference(/datum/preference/toggle/sound_announcements)) - SEND_SOUND(player, sound(sound_override)) + for(var/mob/player in GLOB.player_list) + if(player.client?.prefs.read_preference(/datum/preference/toggle/sound_announcements)) + SEND_SOUND(player, sound(sound_override)) /** * Inserts a span styled message into an alert box div @@ -74,5 +73,12 @@ /proc/create_announcement_div(message, color = "default") return "
[message]
" +/** + * Inserts a span styled message into an OOC alert style div + * + * + * Arguments + * * message - required, the message contents + */ /proc/create_ooc_announcement_div(message) return "
[message]
" diff --git a/code/__HELPERS/areas.dm b/code/__HELPERS/areas.dm index 7b21ee3f0ef..dec768a6a0c 100644 --- a/code/__HELPERS/areas.dm +++ b/code/__HELPERS/areas.dm @@ -1,9 +1,11 @@ #define BP_MAX_ROOM_SIZE 300 -GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(/area/station/engineering/main, \ - /area/station/engineering/supermatter, \ - /area/station/engineering/atmospherics_engine, \ - /area/station/ai_monitored/turret_protected/ai)) +GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(list( + /area/station/engineering/main, + /area/station/engineering/supermatter, + /area/station/engineering/atmospherics_engine, + /area/station/ai_monitored/turret_protected/ai, +))) // Gets an atmos isolated contained space // Returns an associative list of turf|dirs pairs diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 99c7dd562ea..0aaca9a0907 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -271,7 +271,7 @@ if(!current_apc.cell || !SSmapping.level_trait(current_apc.z, ZTRAIT_STATION)) continue var/area/apc_area = current_apc.area - if(GLOB.typecache_powerfailure_safe_areas[apc_area.type]) + if(is_type_in_typecache(apc_area, GLOB.typecache_powerfailure_safe_areas)) continue var/duration = rand(duration_min,duration_max) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 19a062bb156..c35c591bc7c 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -707,11 +707,6 @@ GLOBAL_LIST_EMPTY(species_list) if(isliving(occupant)) mob_occupant = occupant - else if(isbodypart(occupant)) - var/obj/item/bodypart/head/head = occupant - - mob_occupant = head.brainmob - else if(isorgan(occupant)) var/obj/item/organ/internal/brain/brain = occupant mob_occupant = brain.brainmob diff --git a/code/__HELPERS/type_processing.dm b/code/__HELPERS/type_processing.dm index d2ab6d5e054..117067a0578 100644 --- a/code/__HELPERS/type_processing.dm +++ b/code/__HELPERS/type_processing.dm @@ -4,31 +4,84 @@ . = list() for(var/type in types) var/typename = "[type]" + // Longest paths comes first var/static/list/TYPES_SHORTCUTS = list( /obj/effect/decal/cleanable = "CLEANABLE", /obj/item/bodypart = "BODYPART", /obj/item/radio/headset = "HEADSET", - /obj/item/clothing/head/helmet/space = "SPESSHELMET", + /obj/item/clothing/accessory = "ACCESSORY", + /obj/item/clothing/mask/gas = "GASMASK", + /obj/item/clothing/mask = "MASK", + /obj/item/clothing/gloves = "GLOVES", + /obj/item/clothing/shoes = "SHOES", + /obj/item/clothing/under/plasmaman = "PLASMAMAN_SUIT", + /obj/item/clothing/under = "JUMPSUIT", + /obj/item/clothing/suit/armor = "ARMOR", + /obj/item/clothing/suit = "SUIT", + /obj/item/clothing/head/helmet = "HELMET", + /obj/item/clothing/head = "HEAD", + /obj/item/clothing/neck = "NECK", + /obj/item/clothing = "CLOTHING", + /obj/item/storage/backpack = "BACKPACK", + /obj/item/storage/belt = "BELT", /obj/item/book/manual = "MANUAL", - /obj/item/reagent_containers/cup/glass = "DRINK", //longest paths comes first + /obj/item/storage/pill_bottle = "PILL_BOTTLE", + /obj/item/reagent_containers/pill/patch = "MEDPATCH", + /obj/item/reagent_containers/pill = "PILL", + /obj/item/reagent_containers/hypospray/medipen = "MEDIPEN", + /obj/item/reagent_containers/cup/glass = "DRINK", /obj/item/food = "FOOD", /obj/item/reagent_containers = "REAGENT_CONTAINERS", /obj/machinery/atmospherics = "ATMOS_MECH", /obj/machinery/portable_atmospherics = "PORT_ATMOS", - /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack = "MECHA_MISSILE_RACK", + /obj/item/mecha_parts/mecha_equipment/weapon = "MECHA_WEAPON", /obj/item/mecha_parts/mecha_equipment = "MECHA_EQUIP", /obj/item/organ = "ORGAN", + /obj/item/mod/control = "MODSUIT", + /obj/item/mod/module = "MODSUIT_MOD", + /obj/item/gun/ballistic/automatic = "GUN_AUTOMATIC", + /obj/item/gun/ballistic/revolver = "GUN_REVOLVER", + /obj/item/gun/ballistic/rifle = "GUN_RIFLE", + /obj/item/gun/ballistic/shotgun = "GUN_SHOTGUN", + /obj/item/gun/ballistic = "GUN_BALLISTIC", + /obj/item/gun/energy/laser = "GUN_LASER", + /obj/item/gun/energy = "GUN_ENERGY", + /obj/item/gun/magic = "GUN_MAGIC", + /obj/item/gun = "GUN", + /obj/item/stack/sheet/mineral = "MINERAL_SHEET", + /obj/item/stack/sheet = "SHEET", + /obj/item/stack/ore = "ORE", + /obj/item/ai_module = "AI_LAW_MODULE", + /obj/item/circuitboard/machine = "MACHINE_BOARD", + /obj/item/circuitboard/computer = "COMPUTER_BOARD", + /obj/item/circuitboard = "CIRCUITBOARD", /obj/item = "ITEM", + /obj/structure/closet/crate/secure = "LOCKED_CRATE", + /obj/structure/closet/crate = "CRATE", + /obj/structure/closet/secure_closet = "LOCKED_CLOSET", + /obj/structure/closet = "CLOSET", + /obj/structure = "STRUCTURE", + /obj/machinery/door/airlock = "AIRLOCK", + /obj/machinery/door = "DOOR", + /obj/machinery/rnd/production = "RND_FABRICATOR", + /obj/machinery/computer/camera_advanced/shuttle_docker = "DOCKING_COMPUTER", + /obj/machinery/computer = "COMPUTER", + /obj/machinery/vending/wardrobe = "JOBDROBE", + /obj/machinery/vending = "VENDING", /obj/machinery = "MACHINERY", /obj/effect = "EFFECT", + /obj/projectile = "PROJECTILE", /obj = "O", /datum = "D", /turf/open = "OPEN", /turf/closed = "CLOSED", /turf = "T", + /mob/living/carbon/human = "HUMANOID", /mob/living/carbon = "CARBON", /mob/living/simple_animal = "SIMPLE", /mob/living/basic = "BASIC", + /mob/living/silicon/robot = "CYBORG", + /mob/living/silicon = "SILICON", /mob/living = "LIVING", /mob = "M", ) diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index d2ff2e7b542..276d4d7dce2 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -235,7 +235,7 @@ DEFINE_BITFIELD(internal_damage, list( DEFINE_BITFIELD(mecha_flags, list( "ID_LOCK_ON" = ID_LOCK_ON, - "CANSTRAFE" = CANSTRAFE, + "CAN_STRAFE" = CAN_STRAFE, "LIGHTS_ON" = LIGHTS_ON, "SILICON_PILOT" = SILICON_PILOT, "IS_ENCLOSED" = IS_ENCLOSED, diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index febe38f7022..7075bf9912f 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -188,6 +188,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_EXPANDED_FOV" = TRAIT_EXPANDED_FOV, "TRAIT_EXTROVERT" = TRAIT_EXTROVERT, "TRAIT_FAKEDEATH" = TRAIT_FAKEDEATH, + "TRAIT_FAST_TYING" = TRAIT_FAST_TYING, "TRAIT_FASTMED" = TRAIT_FASTMED, "TRAIT_FAT" = TRAIT_FAT, "TRAIT_FEARLESS" = TRAIT_FEARLESS, @@ -231,6 +232,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_HEAVY_DRINKER" = TRAIT_HEAVY_DRINKER, "TRAIT_HEAVY_SLEEPER" = TRAIT_HEAVY_SLEEPER, "TRAIT_HIDE_EXTERNAL_ORGANS" = TRAIT_HIDE_EXTERNAL_ORGANS, + "TRAIT_HIGH_VALUE_RANSOM" = TRAIT_HIGH_VALUE_RANSOM, "TRAIT_HOLY" = TRAIT_HOLY, "TRAIT_HOPELESSLY_ADDICTED" = TRAIT_HOPELESSLY_ADDICTED, "TRAIT_HOT_SPRING_CURSED" = TRAIT_HOT_SPRING_CURSED, @@ -307,6 +309,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_NO_SOUL" = TRAIT_NO_SOUL, "TRAIT_NO_STRIP" = TRAIT_NO_STRIP, "TRAIT_NO_TRANSFORM" = TRAIT_NO_TRANSFORM, + "TRAIT_NO_TWOHANDING" = TRAIT_NO_TWOHANDING, "TRAIT_NOCRITDAMAGE" = TRAIT_NOCRITDAMAGE, "TRAIT_NO_UNDERWEAR" = TRAIT_NO_UNDERWEAR, "TRAIT_NO_ZOMBIFY" = TRAIT_NO_ZOMBIFY, diff --git a/code/controllers/subsystem/dynamic/dynamic_rulesets_latejoin.dm b/code/controllers/subsystem/dynamic/dynamic_rulesets_latejoin.dm index 24347783847..5024737fa3e 100644 --- a/code/controllers/subsystem/dynamic/dynamic_rulesets_latejoin.dm +++ b/code/controllers/subsystem/dynamic/dynamic_rulesets_latejoin.dm @@ -136,7 +136,7 @@ return FALSE var/head_check = 0 for(var/mob/player in GLOB.alive_player_list) - if (player.mind.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND) + if (player.mind.assigned_role.job_flags & JOB_HEAD_OF_STAFF) head_check++ return (head_check >= required_heads_of_staff) diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 70c6e2a6523..38ef544e04c 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -743,7 +743,7 @@ SUBSYSTEM_DEF(job) /datum/controller/subsystem/job/proc/get_living_heads() . = list() for(var/datum/mind/head as anything in get_crewmember_minds()) - if(!(head.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND)) + if(!(head.assigned_role.job_flags & JOB_HEAD_OF_STAFF)) continue if(isnull(head.current) || head.current.stat == DEAD) continue @@ -753,7 +753,7 @@ SUBSYSTEM_DEF(job) /datum/controller/subsystem/job/proc/get_all_heads() . = list() for(var/datum/mind/head as anything in get_crewmember_minds()) - if(head.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND) + if(head.assigned_role.job_flags & JOB_HEAD_OF_STAFF) . += head /// Returns a list of minds of all security members who are alive diff --git a/code/datums/ai/_ai_controller.dm b/code/datums/ai/_ai_controller.dm index a13cc8b36fa..b525f66576c 100644 --- a/code/datums/ai/_ai_controller.dm +++ b/code/datums/ai/_ai_controller.dm @@ -435,6 +435,25 @@ multiple modular subtrees with behaviors blackboard[key] = thing post_blackboard_key_set(key) +/** + * Helper to force a key to be a certain thing no matter what's already there + * + * Useful for if you're overriding a list with a new list entirely, + * as otherwise it would throw a runtime error from trying to override a list + * + * Not necessary to use if you aren't dealing with lists, as set_blackboard_key will clear the existing value + * in that case already, but may be useful for clarity. + * + * * key - A blackboard key + * * thing - a value to set the blackboard key to. + */ +/datum/ai_controller/proc/override_blackboard_key(key, thing) + if(blackboard[key] == thing) + return + + clear_blackboard_key(key) + set_blackboard_key(key, thing) + /** * Sets the key at index thing to the passed value * diff --git a/code/datums/ai/generic/generic_behaviors.dm b/code/datums/ai/generic/generic_behaviors.dm index b769bc529e2..43e37f66e8c 100644 --- a/code/datums/ai/generic/generic_behaviors.dm +++ b/code/datums/ai/generic/generic_behaviors.dm @@ -360,6 +360,10 @@ continue if(thing.IsObscured()) continue + if(isitem(thing)) + var/obj/item/item = thing + if(item.item_flags & ABSTRACT) + continue possible_targets += thing if(!possible_targets.len) finish_action(controller, FALSE) diff --git a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm index f2b82e7a2c8..d64a4e3b57f 100644 --- a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm +++ b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm @@ -93,26 +93,26 @@ CRASH("External organ has no feature list, it will render invisible") ///Give the organ its color. Force will override the existing one. -/datum/bodypart_overlay/mutant/proc/inherit_color(obj/item/bodypart/ownerlimb, force) - if(isnull(ownerlimb)) +/datum/bodypart_overlay/mutant/proc/inherit_color(obj/item/bodypart/bodypart_owner, force) + if(isnull(bodypart_owner)) draw_color = null - alpha = 255 // NOVA EDIT - Mutant bodyparts transparency are based on limb transparency + alpha = 255 // NOVA EDIT ADDITION - Mutant bodyparts transparency are based on limb transparency return TRUE if(draw_color && !force) return FALSE - alpha = ownerlimb.alpha // NOVA EDIT - Mutant bodyparts transparency are based on limb transparency + alpha = bodypart_owner.alpha // NOVA EDIT ADDITION - Mutant bodyparts transparency are based on limb transparency switch(color_source) if(ORGAN_COLOR_OVERRIDE) - draw_color = override_color(ownerlimb.draw_color) + draw_color = override_color(bodypart_owner.draw_color) if(ORGAN_COLOR_INHERIT) - draw_color = ownerlimb.draw_color + draw_color = bodypart_owner.draw_color if(ORGAN_COLOR_HAIR) - if(!ishuman(ownerlimb.owner)) + if(!ishuman(bodypart_owner.owner)) return - var/mob/living/carbon/human/human_owner = ownerlimb.owner - var/obj/item/bodypart/head/my_head = human_owner.get_bodypart(BODY_ZONE_HEAD) //not always the same as ownerlimb + var/mob/living/carbon/human/human_owner = bodypart_owner.owner + var/obj/item/bodypart/head/my_head = human_owner.get_bodypart(BODY_ZONE_HEAD) //not always the same as bodypart_owner //head hair color takes priority, owner hair color is a backup if we lack a head or something if(my_head) draw_color = my_head.hair_color diff --git a/code/datums/components/crafting/crafting.dm b/code/datums/components/crafting/crafting.dm index e16ab582b77..832ad22698b 100644 --- a/code/datums/components/crafting/crafting.dm +++ b/code/datums/components/crafting/crafting.dm @@ -106,6 +106,10 @@ for(var/atom/movable/AM in range(radius_range, a)) if((AM.flags_1 & HOLOGRAM_1) || (blacklist && (AM.type in blacklist))) continue + if(isitem(AM)) + var/obj/item/item = AM + if(item.item_flags & ABSTRACT) //let's not tempt fate, shall we? + continue . += AM /datum/component/personal_crafting/proc/get_surroundings(atom/a, list/blacklist=null) diff --git a/code/datums/components/listen_and_repeat.dm b/code/datums/components/listen_and_repeat.dm index f3006d3111d..b2ba8674d79 100644 --- a/code/datums/components/listen_and_repeat.dm +++ b/code/datums/components/listen_and_repeat.dm @@ -82,7 +82,7 @@ if(!LAZYLEN(speech_buffer)) // what? well whatever let's just move on return - controller.set_blackboard_key(BB_EXPORTABLE_STRING_BUFFER_LIST, speech_buffer.Copy()) + controller.override_blackboard_key(BB_EXPORTABLE_STRING_BUFFER_LIST, speech_buffer.Copy()) #undef MAX_SPEECH_BUFFER_SIZE #undef RADIO_IGNORE_CHANCE diff --git a/code/datums/diseases/gastrolisis.dm b/code/datums/diseases/gastrolisis.dm index c3a24903b81..aab0fcded1d 100644 --- a/code/datums/diseases/gastrolisis.dm +++ b/code/datums/diseases/gastrolisis.dm @@ -40,7 +40,7 @@ var/obj/item/organ/internal/eyes/eyes = locate(/obj/item/organ/internal/eyes/snail) in affected_mob.organs if(!eyes && SPT_PROB(2.5, seconds_per_tick)) var/obj/item/organ/internal/eyes/snail/new_eyes = new() - new_eyes.Insert(affected_mob, drop_if_replaced = TRUE) + new_eyes.Insert(affected_mob) affected_mob.visible_message(span_warning("[affected_mob]'s eyes fall out, with snail eyes taking its place!"), \ span_userdanger("You scream in pain as your eyes are pushed out by your new snail eyes!")) affected_mob.emote("scream") diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 0eb811cc8bd..120c69bca1d 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -604,7 +604,6 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) update_body(is_creating = TRUE) update_mutations_overlay()// no lizard with human hulk overlay please. - /mob/proc/has_dna() return diff --git a/code/datums/elements/haunted.dm b/code/datums/elements/haunted.dm index d678083dd19..04f985c0d89 100644 --- a/code/datums/elements/haunted.dm +++ b/code/datums/elements/haunted.dm @@ -23,7 +23,6 @@ QDEL_NULL(master.ai_controller) REMOVE_TRAIT(master, TRAIT_MOVE_FLYING, ELEMENT_TRAIT(type)) master.RemoveElement(/datum/element/movetype_handler) - return ..() /atom/movable/proc/make_haunted(source, color) //if not haunted, make haunted if(!HAS_TRAIT(src, TRAIT_HAUNTED)) diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm index 92859902137..5ba64d31168 100644 --- a/code/datums/mutations/body.dm +++ b/code/datums/mutations/body.dm @@ -524,14 +524,16 @@ var/obj/item/organ/internal/brain/brain = owner.get_organ_slot(ORGAN_SLOT_BRAIN) if(brain) + brain.Remove(owner, special = TRUE) brain.zone = BODY_ZONE_CHEST + brain.Insert(owner, special = TRUE) var/obj/item/bodypart/head/head = owner.get_bodypart(BODY_ZONE_HEAD) if(head) owner.visible_message(span_warning("[owner]'s head splatters with a sickening crunch!"), ignored_mobs = list(owner)) new /obj/effect/gibspawner/generic(get_turf(owner), owner) - head.dismember(dam_type = BRUTE, silent = TRUE) head.drop_organs() + head.dismember(dam_type = BRUTE, silent = TRUE) qdel(head) RegisterSignal(owner, COMSIG_ATTEMPT_CARBON_ATTACH_LIMB, PROC_REF(abort_attachment)) @@ -539,14 +541,18 @@ . = ..() if(.) return TRUE - var/obj/item/organ/internal/brain/brain = owner.get_organ_slot(ORGAN_SLOT_BRAIN) - if(brain) //so this doesn't instantly kill you. we could delete the brain, but it lets people cure brain issues they /really/ shouldn't be - brain.zone = initial(brain.zone) + UnregisterSignal(owner, COMSIG_ATTEMPT_CARBON_ATTACH_LIMB) var/successful = owner.regenerate_limb(BODY_ZONE_HEAD) if(!successful) stack_trace("HARS mutation head regeneration failed! (usually caused by headless syndrome having a head)") return TRUE + var/obj/item/organ/internal/brain/brain = owner.get_organ_slot(ORGAN_SLOT_BRAIN) + if(brain) + brain.Remove(owner, special = TRUE) + brain.zone = initial(brain.zone) + brain.Insert(owner, special = TRUE) + owner.dna.species.regenerate_organs(owner, replace_current = FALSE, excluded_zones = list(BODY_ZONE_CHEST)) //replace_current needs to be FALSE to prevent weird adding and removing mutation healing owner.apply_damage(damage = 50, damagetype = BRUTE, def_zone = BODY_ZONE_HEAD) //and this to DISCOURAGE organ farming, or at least not make it free. owner.visible_message(span_warning("[owner]'s head returns with a sickening crunch!"), span_warning("Your head regrows with a sickening crack! Ouch.")) diff --git a/code/datums/quirks/negative_quirks/junkie.dm b/code/datums/quirks/negative_quirks/junkie.dm index 269f6d2d96e..2ce29f743c3 100644 --- a/code/datums/quirks/negative_quirks/junkie.dm +++ b/code/datums/quirks/negative_quirks/junkie.dm @@ -134,7 +134,7 @@ smoker_lungs = /obj/item/organ/internal/lungs/smoker_lungs if(!isnull(smoker_lungs)) smoker_lungs = new smoker_lungs - smoker_lungs.Insert(carbon_holder, special = TRUE, drop_if_replaced = FALSE) + smoker_lungs.Insert(carbon_holder, special = TRUE, movement_flags = DELETE_IF_REPLACED) /datum/quirk/item_quirk/junkie/smoker/process(seconds_per_tick) . = ..() diff --git a/code/datums/quirks/negative_quirks/prosthetic_organ.dm b/code/datums/quirks/negative_quirks/prosthetic_organ.dm index 6330035b5a7..0fd5061a787 100644 --- a/code/datums/quirks/negative_quirks/prosthetic_organ.dm +++ b/code/datums/quirks/negative_quirks/prosthetic_organ.dm @@ -49,7 +49,7 @@ medical_record_text = "During physical examination, patient was found to have a low-budget prosthetic [slot_string]. \ Removal of these organs is known to be dangerous to the patient as well as the practitioner." old_organ = human_holder.get_organ_slot(organ_slot) - if(prosthetic.Insert(human_holder, special = TRUE, drop_if_replaced = TRUE)) + if(prosthetic.Insert(human_holder, special = TRUE)) old_organ.moveToNullspace() STOP_PROCESSING(SSobj, old_organ) diff --git a/code/datums/quirks/negative_quirks/tin_man.dm b/code/datums/quirks/negative_quirks/tin_man.dm index a1e88288877..e6d411bc772 100644 --- a/code/datums/quirks/negative_quirks/tin_man.dm +++ b/code/datums/quirks/negative_quirks/tin_man.dm @@ -30,7 +30,7 @@ for(var/organ_slot in possible_organ_slots) var/organ_path = possible_organ_slots[organ_slot] var/obj/item/organ/new_organ = new organ_path() - new_organ.Insert(human_holder, special = TRUE, drop_if_replaced = FALSE) + new_organ.Insert(human_holder, special = TRUE, movement_flags = DELETE_IF_REPLACED) /datum/quirk/tin_man/post_add() to_chat(quirk_holder, span_boldannounce("Most of your internal organs have been replaced with surplus prosthetics. They are fragile and will easily come apart under duress. \ diff --git a/code/datums/station_traits/positive_traits.dm b/code/datums/station_traits/positive_traits.dm index 7b3ed0a0b15..c652c55400a 100644 --- a/code/datums/station_traits/positive_traits.dm +++ b/code/datums/station_traits/positive_traits.dm @@ -272,7 +272,7 @@ ai.eyeobj.relay_speech = TRUE //surveillance upgrade. the ai gets cybernetics too. return var/obj/item/organ/internal/cybernetic = new cybernetic_type() - cybernetic.Insert(spawned, special = TRUE, drop_if_replaced = FALSE) + cybernetic.Insert(spawned, special = TRUE, movement_flags = DELETE_IF_REPLACED) /datum/station_trait/luxury_escape_pods name = "Luxury Escape Pods" diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm index 50c93e7db8f..84f30ab7855 100644 --- a/code/datums/status_effects/neutral.dm +++ b/code/datums/status_effects/neutral.dm @@ -522,7 +522,7 @@ return if(prob(1))//low chance of the alternative reality returning to monkey var/obj/item/organ/external/tail/monkey/monkey_tail = new () - monkey_tail.Insert(human_mob, drop_if_replaced = FALSE) + monkey_tail.Insert(human_mob, movement_flags = DELETE_IF_REPLACED) var/datum/species/human_species = human_mob.dna?.species if(human_species) human_species.randomize_active_features(human_mob) diff --git a/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm b/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm index cbe6e1c31c7..afbb8404060 100644 --- a/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/carp_organs.dm @@ -48,7 +48,7 @@ AddElement(/datum/element/noticable_organ, "teeth are big and sharp.", BODY_ZONE_PRECISE_MOUTH) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/carp) -/obj/item/organ/internal/tongue/carp/on_insert(mob/living/carbon/tongue_owner) +/obj/item/organ/internal/tongue/carp/on_mob_insert(mob/living/carbon/tongue_owner, special, movement_flags) . = ..() if(!ishuman(tongue_owner)) return @@ -57,12 +57,14 @@ return var/datum/species/rec_species = human_receiver.dna.species rec_species.update_no_equip_flags(tongue_owner, rec_species.no_equip_flags | ITEM_SLOT_MASK) - var/obj/item/bodypart/head/head = human_receiver.get_bodypart(BODY_ZONE_HEAD) - head.unarmed_damage_low = 10 - head.unarmed_damage_high = 15 - head.unarmed_effectiveness = 15 -/obj/item/organ/internal/tongue/carp/on_remove(mob/living/carbon/tongue_owner) +/obj/item/organ/internal/tongue/carp/on_bodypart_insert(obj/item/bodypart/limb) + . = ..() + limb.unarmed_damage_low = 10 + limb.unarmed_damage_high = 15 + limb.unarmed_effectiveness = 15 + +/obj/item/organ/internal/tongue/carp/on_mob_remove(mob/living/carbon/tongue_owner) . = ..() if(!ishuman(tongue_owner)) return @@ -71,7 +73,10 @@ return var/datum/species/rec_species = human_receiver.dna.species rec_species.update_no_equip_flags(tongue_owner, initial(rec_species.no_equip_flags)) - var/obj/item/bodypart/head/head = human_receiver.get_bodypart(BODY_ZONE_HEAD) + +/obj/item/organ/internal/tongue/carp/on_bodypart_remove(obj/item/bodypart/head) + . = ..() + head.unarmed_damage_low = initial(head.unarmed_damage_low) head.unarmed_damage_high = initial(head.unarmed_damage_high) head.unarmed_effectiveness = initial(head.unarmed_effectiveness) @@ -110,13 +115,13 @@ AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/carp) AddElement(/datum/element/noticable_organ, "seem%PRONOUN_S unable to stay still.") -/obj/item/organ/internal/brain/carp/on_insert(mob/living/carbon/brain_owner) +/obj/item/organ/internal/brain/carp/on_mob_insert(mob/living/carbon/brain_owner) . = ..() cooldown_timer = addtimer(CALLBACK(src, PROC_REF(unsatisfied_nomad)), cooldown_time, TIMER_STOPPABLE|TIMER_OVERRIDE|TIMER_UNIQUE) RegisterSignal(brain_owner, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(satisfied_nomad)) //technically you could get around the mood issue by extracting and reimplanting the brain but it will be far easier to just go one z there and back -/obj/item/organ/internal/brain/carp/on_remove(mob/living/carbon/brain_owner) +/obj/item/organ/internal/brain/carp/on_mob_remove(mob/living/carbon/brain_owner) . = ..() UnregisterSignal(brain_owner, COMSIG_MOVABLE_Z_CHANGED) deltimer(cooldown_timer) diff --git a/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm b/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm index cb5347c8a51..58494346f62 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fox_organs.dm @@ -8,7 +8,7 @@ //NOVA EDIT REMOVAL BEGIN - CUSTOMIZATION /* -/obj/item/organ/internal/ears/fox/on_insert(mob/living/carbon/human/ear_owner) +/obj/item/organ/internal/ears/fox/on_mob_insert(mob/living/carbon/human/ear_owner) . = ..() if(istype(ear_owner) && ear_owner.dna) color = ear_owner.hair_color @@ -16,7 +16,7 @@ ear_owner.dna.update_uf_block(DNA_EARS_BLOCK) ear_owner.update_body() -/obj/item/organ/internal/ears/fox/on_remove(mob/living/carbon/human/ear_owner) +/obj/item/organ/internal/ears/fox/on_mob_remove(mob/living/carbon/human/ear_owner) . = ..() if(istype(ear_owner) && ear_owner.dna) color = ear_owner.hair_color diff --git a/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm b/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm index 6cd753eb760..477b461bdf3 100644 --- a/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/goliath_organs.dm @@ -66,7 +66,7 @@ AddElement(/datum/element/noticable_organ, "arm is just a mass of plate and tendrils.", BODY_ZONE_CHEST) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/goliath) -/obj/item/organ/internal/brain/goliath/on_insert(mob/living/carbon/brain_owner) +/obj/item/organ/internal/brain/goliath/on_mob_insert(mob/living/carbon/brain_owner) . = ..() if(!ishuman(brain_owner)) return @@ -78,7 +78,7 @@ hammer = new/obj/item/goliath_infuser_hammer brain_owner.put_in_hands(hammer) -/obj/item/organ/internal/brain/goliath/on_remove(mob/living/carbon/brain_owner) +/obj/item/organ/internal/brain/goliath/on_mob_remove(mob/living/carbon/brain_owner) . = ..() UnregisterSignal(brain_owner) if(!ishuman(brain_owner)) diff --git a/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm b/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm index 515c56622c4..2a5c776709c 100644 --- a/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/gondola_organs.dm @@ -33,7 +33,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah... AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/gondola) AddElement(/datum/element/noticable_organ, "radiate%PRONOUN_S an aura of serenity.") -/obj/item/organ/internal/heart/gondola/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/internal/heart/gondola/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() if(!(FACTION_HOSTILE in receiver.faction)) factions_to_remove += FACTION_HOSTILE @@ -41,7 +41,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah... factions_to_remove += FACTION_MINING receiver.faction |= list(FACTION_HOSTILE, FACTION_MINING) -/obj/item/organ/internal/heart/gondola/Remove(mob/living/carbon/heartless, special) +/obj/item/organ/internal/heart/gondola/Remove(mob/living/carbon/heartless, special, movement_flags) . = ..() for(var/faction in factions_to_remove) heartless.faction -= faction @@ -63,11 +63,11 @@ Fluoride Stare: After someone says 5 words, blah blah blah... AddElement(/datum/element/noticable_organ, "mouth is permanently affixed into a relaxed smile.", BODY_ZONE_PRECISE_MOUTH) AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/gondola) -/obj/item/organ/internal/tongue/gondola/Insert(mob/living/carbon/tongue_owner, special, drop_if_replaced) +/obj/item/organ/internal/tongue/gondola/Insert(mob/living/carbon/tongue_owner, special, movement_flags) . = ..() tongue_owner.add_mood_event("gondola_zen", /datum/mood_event/gondola_serenity) -/obj/item/organ/internal/tongue/gondola/Remove(mob/living/carbon/tongue_owner, special) +/obj/item/organ/internal/tongue/gondola/Remove(mob/living/carbon/tongue_owner, special, movement_flags) tongue_owner.clear_mood_event("gondola_zen") return ..() @@ -89,7 +89,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah... AddElement(/datum/element/noticable_organ, "right arm has small needles breaching the skin all over it.", BODY_ZONE_R_ARM) pax_hugs = new -/obj/item/organ/internal/liver/gondola/Insert(mob/living/carbon/liver_owner, special, drop_if_replaced) +/obj/item/organ/internal/liver/gondola/Insert(mob/living/carbon/liver_owner, special, movement_flags) . = ..() var/has_left = liver_owner.has_left_hand(check_disabled = FALSE) var/has_right = liver_owner.has_right_hand(check_disabled = FALSE) @@ -104,7 +104,7 @@ Fluoride Stare: After someone says 5 words, blah blah blah... RegisterSignal(liver_owner, COMSIG_HUMAN_EQUIPPING_ITEM, PROC_REF(on_owner_equipping_item)) RegisterSignal(liver_owner, COMSIG_LIVING_TRY_PULL, PROC_REF(on_owner_try_pull)) -/obj/item/organ/internal/liver/gondola/Remove(mob/living/carbon/liver_owner, special) +/obj/item/organ/internal/liver/gondola/Remove(mob/living/carbon/liver_owner, special, movement_flags) . = ..() pax_hugs.remove(liver_owner) UnregisterSignal(liver_owner, list(COMSIG_HUMAN_EQUIPPING_ITEM, COMSIG_LIVING_TRY_PULL)) diff --git a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm index 96c33871a40..092a4c7889a 100644 --- a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm @@ -63,7 +63,7 @@ AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/rat) AddElement(/datum/element/noticable_organ, "hunch%PRONOUN_ES over unnaturally!") -/obj/item/organ/internal/heart/rat/on_insert(mob/living/carbon/receiver) +/obj/item/organ/internal/heart/rat/on_mob_insert(mob/living/carbon/receiver) . = ..() if(!. || !ishuman(receiver)) return @@ -75,7 +75,7 @@ if(human_receiver.physiology) human_receiver.physiology.damage_resistance -= 50 -/obj/item/organ/internal/heart/rat/on_remove(mob/living/carbon/heartless, special) +/obj/item/organ/internal/heart/rat/on_mob_remove(mob/living/carbon/heartless, special) . = ..() if(!ishuman(heartless)) return @@ -113,11 +113,11 @@ if(message == "hi?") speech_args[SPEECH_MESSAGE] = "Um... cheesed to meet you?" -/obj/item/organ/internal/tongue/rat/on_insert(mob/living/carbon/tongue_owner, special, drop_if_replaced) +/obj/item/organ/internal/tongue/rat/on_mob_insert(mob/living/carbon/tongue_owner, special, movement_flags) . = ..() RegisterSignal(tongue_owner, COMSIG_CARBON_ITEM_GIVEN, PROC_REF(its_on_the_mouse)) -/obj/item/organ/internal/tongue/rat/on_remove(mob/living/carbon/tongue_owner) +/obj/item/organ/internal/tongue/rat/on_mob_remove(mob/living/carbon/tongue_owner) . = ..() UnregisterSignal(tongue_owner, COMSIG_CARBON_ITEM_GIVEN) diff --git a/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm b/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm index f10c9b039f2..0644bca0354 100644 --- a/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm @@ -71,7 +71,7 @@ QDEL_NULL(roach_shell) return ..() -/obj/item/organ/internal/heart/roach/on_insert(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/heart/roach/on_mob_insert(mob/living/carbon/organ_owner, special) . = ..() if(!ishuman(organ_owner)) return @@ -82,11 +82,11 @@ RegisterSignal(human_owner, COMSIG_MOB_AFTER_APPLY_DAMAGE, PROC_REF(do_block_effect)) human_owner.physiology.knockdown_mod *= 3 - var/obj/item/bodypart/chest/chest = human_owner.get_bodypart(BODY_ZONE_CHEST) - chest.add_bodypart_overlay(roach_shell) - human_owner.update_body_parts() +/obj/item/organ/internal/heart/roach/on_bodypart_insert(obj/item/bodypart/limb) + . = ..() + limb.add_bodypart_overlay(roach_shell) -/obj/item/organ/internal/heart/roach/on_remove(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/heart/roach/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() if(!ishuman(organ_owner) || QDELETED(organ_owner)) return @@ -96,9 +96,10 @@ UnregisterSignal(human_owner, list(COMSIG_MOB_APPLY_DAMAGE_MODIFIERS, COMSIG_MOB_AFTER_APPLY_DAMAGE)) human_owner.physiology.knockdown_mod /= 3 - var/obj/item/bodypart/chest/chest = human_owner.get_bodypart(BODY_ZONE_CHEST) - chest.remove_bodypart_overlay(roach_shell) - human_owner.update_body_parts() +/obj/item/organ/internal/heart/roach/on_bodypart_remove(obj/item/bodypart/limb) + . = ..() + + limb.remove_bodypart_overlay(roach_shell) /** * Signal proc for [COMSIG_MOB_APPLY_DAMAGE_MODIFIERS] @@ -193,7 +194,7 @@ . = ..() AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/roach) -/obj/item/organ/internal/liver/roach/on_insert(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/liver/roach/on_mob_insert(mob/living/carbon/organ_owner, special) . = ..() if(!ishuman(organ_owner)) return @@ -201,13 +202,13 @@ var/mob/living/carbon/human/human_owner = owner human_owner.physiology.tox_mod *= 2 -/obj/item/organ/internal/liver/roach/on_remove(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/liver/roach/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() if(!ishuman(organ_owner) || QDELETED(organ_owner)) return var/mob/living/carbon/human/human_owner = organ_owner - human_owner.physiology.tox_mod /= 2 + human_owner.physiology.tox_mod *= 0.5 /// Roach appendix: /// No appendicitus! weee! diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index 6d272de65b3..76b1b73ba53 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -558,7 +558,7 @@ DEFINE_BITFIELD(turret_flags, list( // If we aren't shooting heads then return a threatcount of 0 if (!(turret_flags & TURRET_FLAG_SHOOT_HEADS)) var/datum/job/apparent_job = SSjob.GetJob(perp.get_assignment()) - if(apparent_job?.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND) + if(apparent_job?.job_flags & JOB_HEAD_OF_STAFF) return 0 if(turret_flags & TURRET_FLAG_AUTH_WEAPONS) //check for weapon authorization diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index f2f5b1b0fec..a4deb63ae21 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -157,6 +157,10 @@ var/obj/item/mmi/as_mmi = thing if(istype(thing, /obj/item/organ/internal/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || istype(thing, /obj/item/dullahan_relay)) living_detected = TRUE + if(isitem(as_object)) + var/obj/item/as_item = as_object + if(as_item.item_flags & ABSTRACT) //also catches organs and bodyparts *stares* + continue nom += thing else if(isliving(thing)) living_detected = TRUE diff --git a/code/game/objects/items/body_egg.dm b/code/game/objects/items/body_egg.dm index f95b9f2e164..d244d8c55cc 100644 --- a/code/game/objects/items/body_egg.dm +++ b/code/game/objects/items/body_egg.dm @@ -15,7 +15,7 @@ if(iscarbon(loc)) Insert(loc) -/obj/item/organ/internal/body_egg/Insert(mob/living/carbon/egg_owner, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/body_egg/Insert(mob/living/carbon/egg_owner, special = FALSE, movement_flags = DELETE_IF_REPLACED) . = ..() if(!.) return @@ -23,7 +23,7 @@ egg_owner.med_hud_set_status() INVOKE_ASYNC(src, PROC_REF(AddInfectionImages), egg_owner) -/obj/item/organ/internal/body_egg/Remove(mob/living/carbon/egg_owner, special = FALSE) +/obj/item/organ/internal/body_egg/Remove(mob/living/carbon/egg_owner, special, movement_flags) . = ..() egg_owner.remove_traits(list(TRAIT_XENO_HOST, TRAIT_XENO_IMMUNE), ORGAN_TRAIT) egg_owner.med_hud_set_status() diff --git a/code/game/objects/items/food/mexican.dm b/code/game/objects/items/food/mexican.dm index b4e32587bc6..396e351ff4b 100644 --- a/code/game/objects/items/food/mexican.dm +++ b/code/game/objects/items/food/mexican.dm @@ -305,6 +305,7 @@ /datum/reagent/consumable/nutriment/vitamin = 6, /datum/reagent/consumable/nutriment/protein = 4, ) + trash_type = /obj/item/reagent_containers/cup/bowl tastes = list("mashed beans" = 1, "onion" = 3,) foodtypes = VEGETABLES | FRIED w_class = WEIGHT_CLASS_SMALL @@ -319,6 +320,7 @@ /datum/reagent/consumable/nutriment = 6, /datum/reagent/consumable/nutriment/vitamin = 6, ) + trash_type = /obj/item/reagent_containers/cup/bowl tastes = list("zesty rice" = 1, "tomato sauce" = 3,) foodtypes = VEGETABLES w_class = WEIGHT_CLASS_SMALL diff --git a/code/game/objects/items/robot/items/storage.dm b/code/game/objects/items/robot/items/storage.dm index 4995c7d9df6..c12f816fa15 100644 --- a/code/game/objects/items/robot/items/storage.dm +++ b/code/game/objects/items/robot/items/storage.dm @@ -58,22 +58,22 @@ /obj/item/borg/apparatus/pre_attack(atom/atom, mob/living/user, params) if(!stored) // Borgs should not be grabbing their own modules - if(!istype(atom.loc, /mob/living/silicon/robot)) - var/itemcheck = FALSE - for(var/storable_type in storable) - if(istype(atom, storable_type)) - itemcheck = TRUE - break - if(itemcheck) - var/obj/item/item = atom - item.forceMove(src) - stored = item - RegisterSignal(stored, COMSIG_ATOM_UPDATED_ICON, PROC_REF(on_stored_updated_icon)) - update_appearance() - return TRUE - else - stored.melee_attack_chain(user, atom, params) - return TRUE + if(istype(atom.loc, /mob/living/silicon/robot) || istype(atom.loc, /obj/item/robot_model) || HAS_TRAIT(atom, TRAIT_NODROP)) + stored.melee_attack_chain(user, atom, params) + return TRUE + + var/itemcheck = FALSE + for(var/storable_type in storable) + if(istype(atom, storable_type)) + itemcheck = TRUE + break + if(itemcheck) + var/obj/item/item = atom + item.forceMove(src) + stored = item + RegisterSignal(stored, COMSIG_ATOM_UPDATED_ICON, PROC_REF(on_stored_updated_icon)) + update_appearance() + return TRUE return ..() /** diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 9ec5f22746d..4ccc93ff213 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -75,7 +75,11 @@ return patient.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE) /// In which we print the message that we're starting to heal someone, then we try healing them. Does the do_after whether or not it can actually succeed on a targeted mob -/obj/item/stack/medical/proc/try_heal(mob/living/patient, mob/user, silent = FALSE) +/obj/item/stack/medical/proc/try_heal(mob/living/patient, mob/user, silent = FALSE, looping = FALSE) + if(!try_heal_checks(patient, user, heal_brute, heal_burn, looping)) + return + var/new_self_delay = looping ? clamp((self_delay-(1 SECONDS)), 0, self_delay) : self_delay + var/new_other_delay = looping ? clamp((other_delay-(1 SECONDS)), 0, other_delay) : other_delay if(patient == user) if(!silent) user.visible_message( @@ -84,7 +88,7 @@ ) if(!do_after( user, - self_delay, + new_self_delay, patient, extra_checks = CALLBACK(src, PROC_REF(can_heal), patient, user), )) @@ -98,7 +102,7 @@ ) if(!do_after( user, - other_delay, + new_other_delay, patient, extra_checks = CALLBACK(src, PROC_REF(can_heal), patient, user), )) @@ -111,7 +115,7 @@ return if(!can_heal(patient, user)) return - try_heal(patient, user, silent = TRUE) + try_heal(patient, user, silent = TRUE, looping = TRUE) /// Apply the actual effects of the healing if it's a simple animal, goes to [/obj/item/stack/medical/proc/heal_carbon] if it's a carbon, returns TRUE if it works, FALSE if it doesn't /obj/item/stack/medical/proc/heal(mob/living/patient, mob/user) @@ -132,8 +136,11 @@ return heal_carbon(patient, user, heal_brute, heal_burn) patient.balloon_alert(user, "can't heal that!") -/// The healing effects on a carbon patient. Since we have extra details for dealing with bodyparts, we get our own fancy proc. Still returns TRUE on success and FALSE on fail -/obj/item/stack/medical/proc/heal_carbon(mob/living/carbon/patient, mob/user, brute, burn) +/obj/item/stack/medical/proc/try_heal_checks(mob/living/carbon/patient, mob/user, brute, burn, looping = FALSE) + if(looping) + balloon_alert(user, "assessing damage...") + if(!do_after(user, 1 SECONDS, patient)) + return FALSE var/obj/item/bodypart/affecting = patient.get_bodypart(check_zone(user.zone_selected)) if(!affecting) //Missing limb? patient.balloon_alert(user, "no [parse_zone(user.zone_selected)]!") @@ -141,18 +148,25 @@ if(!IS_ORGANIC_LIMB(affecting)) //Limb must be organic to be healed - RR patient.balloon_alert(user, "it's not organic!") return FALSE - if(affecting.brute_dam && brute || affecting.burn_dam && burn) - user.visible_message( - span_infoplain(span_green("[user] applies [src] on [patient]'s [parse_zone(affecting.body_zone)].")), - span_infoplain(span_green("You apply [src] on [patient]'s [parse_zone(affecting.body_zone)].")) - ) - var/previous_damage = affecting.get_damage() - if(affecting.heal_damage(brute, burn)) - patient.update_damage_overlays() - post_heal_effects(max(previous_damage - affecting.get_damage(), 0), patient, user) - return TRUE - patient.balloon_alert(user, "can't heal that!") - return FALSE + if(!(affecting.brute_dam && brute) && !(affecting.burn_dam && burn)) + patient.balloon_alert(user, "can't heal [affecting]!") + return FALSE + return TRUE + +/// The healing effects on a carbon patient. Since we have extra details for dealing with bodyparts, we get our own fancy proc. Still returns TRUE on success and FALSE on fail +/obj/item/stack/medical/proc/heal_carbon(mob/living/carbon/patient, mob/user, brute, burn) + var/obj/item/bodypart/affecting = patient.get_bodypart(check_zone(user.zone_selected)) + if(!try_heal_checks(patient, user, brute, burn)) + return FALSE + user.visible_message( + span_infoplain(span_green("[user] applies [src] on [patient]'s [parse_zone(affecting.body_zone)].")), + span_infoplain(span_green("You apply [src] on [patient]'s [parse_zone(affecting.body_zone)].")) + ) + var/previous_damage = affecting.get_damage() + if(affecting.heal_damage(brute, burn)) + patient.update_damage_overlays() + post_heal_effects(max(previous_damage - affecting.get_damage(), 0), patient, user) + return TRUE ///Override this proc for special post heal effects. /obj/item/stack/medical/proc/post_heal_effects(amount_healed, mob/living/carbon/healed_mob, mob/user) @@ -203,7 +217,7 @@ gauzed_bodypart = null // gauze is only relevant for wounds, which are handled in the wounds themselves -/obj/item/stack/medical/gauze/try_heal(mob/living/patient, mob/user, silent) +/obj/item/stack/medical/gauze/try_heal(mob/living/patient, mob/user, silent, looping) var/treatment_delay = (user == patient ? self_delay : other_delay) @@ -375,7 +389,7 @@ return ..() icon_state = "regen_mesh_closed" -/obj/item/stack/medical/mesh/try_heal(mob/living/patient, mob/user, silent = FALSE) +/obj/item/stack/medical/mesh/try_heal(mob/living/patient, mob/user, silent = FALSE, looping) if(!is_open) balloon_alert(user, "open it first!") return diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm index 9265dc7cb4e..bc4e0a94c16 100644 --- a/code/game/objects/items/tools/crowbar.dm +++ b/code/game/objects/items/tools/crowbar.dm @@ -235,7 +235,7 @@ var/mech_dir = mech.dir mech.balloon_alert(user, "prying open...") playsound(mech, 'sound/machines/airlock_alien_prying.ogg', 100, TRUE) - if(!use_tool(mech, user, mech.enclosed ? 5 SECONDS : 3 SECONDS, volume = 0, extra_checks = CALLBACK(src, PROC_REF(extra_checks), mech, mech_dir))) + if(!use_tool(mech, user, (mech.mecha_flags & IS_ENCLOSED) ? 5 SECONDS : 3 SECONDS, volume = 0, extra_checks = CALLBACK(src, PROC_REF(extra_checks), mech, mech_dir))) mech.balloon_alert(user, "interrupted!") return user.log_message("pried open [mech], located at [loc_name(mech)], which is currently occupied by [mech.occupants.Join(", ")].", LOG_ATTACK) diff --git a/code/game/turfs/open/lava.dm b/code/game/turfs/open/lava.dm index 7c7c321f0e2..1a174723d85 100644 --- a/code/game/turfs/open/lava.dm +++ b/code/game/turfs/open/lava.dm @@ -420,7 +420,7 @@ if(BODY_ZONE_HEAD) plasmalimb = new /obj/item/bodypart/head/plasmaman - burn_human.del_and_replace_bodypart(plasmalimb) + burn_human.del_and_replace_bodypart(plasmalimb, special = TRUE) burn_human.update_body_parts() burn_human.emote("scream") burn_human.visible_message(span_warning("[burn_human]'s [burn_limb.plaintext_zone] melts down to the bone!"), \ diff --git a/code/modules/admin/verbs/admin.dm b/code/modules/admin/verbs/admin.dm index d97ad84273e..d78014e84d2 100644 --- a/code/modules/admin/verbs/admin.dm +++ b/code/modules/admin/verbs/admin.dm @@ -174,10 +174,8 @@ if(confirm != "Yes") return - for(var/obj/item/W in M) - if(!M.dropItemToGround(W)) - qdel(W) - M.regenerate_icons() + M.drop_everything(del_on_drop = FALSE, force = TRUE, del_if_nodrop = TRUE) + M.regenerate_icons() log_admin("[key_name(usr)] made [key_name(M)] drop everything!") var/msg = "[key_name_admin(usr)] made [ADMIN_LOOKUPFLW(M)] drop everything!" diff --git a/code/modules/admin/verbs/anonymousnames.dm b/code/modules/admin/verbs/anonymousnames.dm index 6f01b88f113..9a71d68637a 100644 --- a/code/modules/admin/verbs/anonymousnames.dm +++ b/code/modules/admin/verbs/anonymousnames.dm @@ -155,7 +155,7 @@ GLOBAL_DATUM(current_anonymous_theme, /datum/anonymous_theme) priority_announce("As punishment for this station's poor productivity when compared to neighbor stations, names and identities will be restricted until further notice.", "Finance Report", SSstation.announcer.get_rand_alert_sound()) /datum/anonymous_theme/employees/anonymous_name(mob/target) - var/is_head_of_staff = target.mind.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND + var/is_head_of_staff = target.mind.assigned_role.job_flags & JOB_HEAD_OF_STAFF var/name = "[is_head_of_staff ? "Manager" : "Employee"] " for(var/i in 1 to 6) if(prob(30) || i == 1) diff --git a/code/modules/admin/verbs/secrets.dm b/code/modules/admin/verbs/secrets.dm index d49c7715462..f9879428ddf 100644 --- a/code/modules/admin/verbs/secrets.dm +++ b/code/modules/admin/verbs/secrets.dm @@ -506,8 +506,8 @@ GLOBAL_DATUM(everyone_a_traitor, /datum/everyone_is_a_traitor_controller) if(H.dna.features["tail_human"] == "None" || H.dna.features["ears"] == "None") var/obj/item/organ/internal/ears/cat/ears = new var/obj/item/organ/external/tail/cat/tail = new - ears.Insert(H, drop_if_replaced=FALSE) - tail.Insert(H, drop_if_replaced=FALSE) + ears.Insert(H, movement_flags = DELETE_IF_REPLACED) + tail.Insert(H, movement_flags = DELETE_IF_REPLACED) var/list/honorifics = list("[MALE]" = list("kun"), "[FEMALE]" = list("chan","tan"), "[NEUTER]" = list("san"), "[PLURAL]" = list("san")) //John Robust -> Robust-kun var/list/names = splittext(H.real_name," ") var/forename = names.len > 1 ? names[2] : names[1] diff --git a/code/modules/antagonists/abductor/equipment/gland.dm b/code/modules/antagonists/abductor/equipment/gland.dm index e29388c9fd6..960851280e3 100644 --- a/code/modules/antagonists/abductor/equipment/gland.dm +++ b/code/modules/antagonists/abductor/equipment/gland.dm @@ -84,7 +84,7 @@ active_mind_control = FALSE return TRUE -/obj/item/organ/internal/heart/gland/Remove(mob/living/carbon/gland_owner, special = FALSE) +/obj/item/organ/internal/heart/gland/Remove(mob/living/carbon/gland_owner, special, movement_flags) . = ..() active = FALSE if(initial(uses) == 1) @@ -93,7 +93,7 @@ hud.remove_atom_from_hud(gland_owner) clear_mind_control() -/obj/item/organ/internal/heart/gland/Insert(mob/living/carbon/gland_owner, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/heart/gland/Insert(mob/living/carbon/gland_owner, special = FALSE, movement_flags = DELETE_IF_REPLACED) . = ..() if(!.) return diff --git a/code/modules/antagonists/abductor/equipment/glands/electric.dm b/code/modules/antagonists/abductor/equipment/glands/electric.dm index a3107af0217..a5ec2cfde21 100644 --- a/code/modules/antagonists/abductor/equipment/glands/electric.dm +++ b/code/modules/antagonists/abductor/equipment/glands/electric.dm @@ -7,11 +7,11 @@ mind_control_uses = 2 mind_control_duration = 900 -/obj/item/organ/internal/heart/gland/electric/on_insert(mob/living/carbon/gland_owner) +/obj/item/organ/internal/heart/gland/electric/on_mob_insert(mob/living/carbon/gland_owner) . = ..() ADD_TRAIT(gland_owner, TRAIT_SHOCKIMMUNE, ABDUCTOR_GLAND_TRAIT) -/obj/item/organ/internal/heart/gland/electric/on_remove(mob/living/carbon/gland_owner) +/obj/item/organ/internal/heart/gland/electric/on_mob_remove(mob/living/carbon/gland_owner) . = ..() REMOVE_TRAIT(gland_owner, TRAIT_SHOCKIMMUNE, ABDUCTOR_GLAND_TRAIT) diff --git a/code/modules/antagonists/abductor/equipment/glands/slime.dm b/code/modules/antagonists/abductor/equipment/glands/slime.dm index 60e680bc2a9..853f0bb6473 100644 --- a/code/modules/antagonists/abductor/equipment/glands/slime.dm +++ b/code/modules/antagonists/abductor/equipment/glands/slime.dm @@ -7,12 +7,12 @@ mind_control_uses = 1 mind_control_duration = 2400 -/obj/item/organ/internal/heart/gland/slime/on_insert(mob/living/carbon/gland_owner) +/obj/item/organ/internal/heart/gland/slime/on_mob_insert(mob/living/carbon/gland_owner) . = ..() gland_owner.faction |= FACTION_SLIME gland_owner.grant_language(/datum/language/slime, source = LANGUAGE_GLAND) -/obj/item/organ/internal/heart/gland/slime/on_remove(mob/living/carbon/gland_owner) +/obj/item/organ/internal/heart/gland/slime/on_mob_remove(mob/living/carbon/gland_owner) . = ..() gland_owner.faction -= FACTION_SLIME gland_owner.remove_language(/datum/language/slime, source = LANGUAGE_GLAND) diff --git a/code/modules/antagonists/changeling/powers/headcrab.dm b/code/modules/antagonists/changeling/powers/headcrab.dm index f608d1620b8..30970832df0 100644 --- a/code/modules/antagonists/changeling/powers/headcrab.dm +++ b/code/modules/antagonists/changeling/powers/headcrab.dm @@ -6,10 +6,12 @@ chemical_cost = 20 dna_cost = 1 req_human = TRUE + req_stat = DEAD + ignores_fakedeath = TRUE /datum/action/changeling/headcrab/sting_action(mob/living/user) set waitfor = FALSE - var/confirm = tgui_alert(user, "Are we sure we wish to kill ourself and create a headslug?", "Last Resort", list("Yes", "No")) + var/confirm = tgui_alert(user, "Are we sure we wish to destroy our body and create a headslug?", "Last Resort", list("Yes", "No")) if(confirm != "Yes") return @@ -23,9 +25,9 @@ if(!eyes || blinded_human.is_blind()) continue to_chat(blinded_human, span_userdanger("You are blinded by a shower of blood!")) - blinded_human.Stun(2 SECONDS) + blinded_human.Stun(4 SECONDS) blinded_human.set_eye_blur_if_lower(40 SECONDS) - blinded_human.adjust_confusion(3 SECONDS) + blinded_human.adjust_confusion(12 SECONDS) for(var/mob/living/silicon/blinded_silicon in range(2,user)) to_chat(blinded_silicon, span_userdanger("Your sensors are disabled by a shower of blood!")) @@ -39,6 +41,7 @@ . = TRUE addtimer(CALLBACK(src, PROC_REF(spawn_headcrab), stored_mind, user_turf, organs), 1 SECONDS) +/// Creates the headrab to occupy /datum/action/changeling/headcrab/proc/spawn_headcrab(datum/mind/stored_mind, turf/spawn_location, list/organs) var/mob/living/basic/headslug/crab = new(spawn_location) for(var/obj/item/organ/I in organs) diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index c445e73e90e..bed29dbefd5 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -222,52 +222,58 @@ structure_check() searches for nearby cultist structures required for the invoca /obj/effect/rune/convert/invoke(list/invokers) if(rune_in_use) return + var/list/myriad_targets = list() - var/turf/T = get_turf(src) - for(var/mob/living/M in T) - if(!IS_CULTIST(M)) - myriad_targets |= M - if(!length(myriad_targets)) + for(var/mob/living/non_cultist in loc) + if(!IS_CULTIST(non_cultist)) + myriad_targets += non_cultist + + if(!length(myriad_targets) && !try_spawn_sword()) fail_invoke() - log_game("Offer rune failed - no eligible targets.") return + rune_in_use = TRUE visible_message(span_warning("[src] pulses blood red!")) var/oldcolor = color color = RUNE_COLOR_DARKRED - var/mob/living/L = pick(myriad_targets) - - var/mob/living/F = invokers[1] - var/datum/antagonist/cult/C = F.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - var/datum/team/cult/Cult_team = C.cult_team - var/is_convertable = is_convertable_to_cult(L, C.cult_team) - if(L.stat != DEAD && is_convertable) - invocation = "Mah'weyh pleggh at e'ntrath!" - ..() - if(is_convertable) - do_convert(L, invokers, Cult_team) + + if(length(myriad_targets)) + var/mob/living/new_convertee = pick(myriad_targets) + var/mob/living/first_invoker = invokers[1] + var/datum/antagonist/cult/first_invoker_datum = first_invoker.mind.has_antag_datum(/datum/antagonist/cult) + var/datum/team/cult/cult_team = first_invoker_datum.get_team() + + var/is_convertable = is_convertable_to_cult(new_convertee, cult_team) + if(new_convertee.stat != DEAD && is_convertable) + invocation = "Mah'weyh pleggh at e'ntrath!" + ..() + do_convert(new_convertee, invokers, cult_team) + + else + invocation = "Barhah hra zar'garis!" + ..() + do_sacrifice(new_convertee, invokers, cult_team) + + cult_team.check_size() // Triggers the eye glow or aura effects if the cult has grown large enough relative to the crew + else - invocation = "Barhah hra zar'garis!" - ..() - do_sacrifice(L, invokers) - animate(src, color = oldcolor, time = 5) - addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_atom_colour)), 5) - Cult_team.check_size() // Triggers the eye glow or aura effects if the cult has grown large enough relative to the crew + do_invoke_glow() + + animate(src, color = oldcolor, time = 0.5 SECONDS) + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_atom_colour)), 0.5 SECONDS) rune_in_use = FALSE /obj/effect/rune/convert/proc/do_convert(mob/living/convertee, list/invokers, datum/team/cult/cult_team) ASSERT(convertee.mind) if(length(invokers) < 2) - for(var/M in invokers) - to_chat(M, span_warning("You need at least two invokers to convert [convertee]!")) - log_game("Offer rune with [convertee] on it failed - tried conversion with one invoker.") + for(var/invoker in invokers) + to_chat(invoker, span_warning("You need at least two invokers to convert [convertee]!")) return FALSE if(convertee.can_block_magic(MAGIC_RESISTANCE|MAGIC_RESISTANCE_HOLY, charge_cost = 0)) //No charge_cost because it can be spammed - for(var/M in invokers) - to_chat(M, span_warning("Something is shielding [convertee]'s mind!")) - log_game("Offer rune with [convertee] on it failed - convertee had anti-magic.") + for(var/invoker in invokers) + to_chat(invoker, span_warning("Something is shielding [convertee]'s mind!")) return FALSE var/brutedamage = convertee.getBruteLoss() @@ -314,19 +320,11 @@ structure_check() searches for nearby cultist structures required for the invoca convertee.name = convertee.real_name return TRUE -/obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers) - var/mob/living/first_invoker = invokers[1] - if(!first_invoker) - return FALSE - var/datum/antagonist/cult/C = first_invoker.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - if(!C) - return FALSE - +/obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers, datum/team/cult/cult_team) var/big_sac = FALSE - if((((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || C.cult_team.is_sacrifice_target(sacrificial.mind)) && length(invokers) < 3) - for(var/M in invokers) - to_chat(M, span_cultitalic("[sacrificial] is too greatly linked to the world! You need three acolytes!")) - log_game("Offer rune with [sacrificial] on it failed - not enough acolytes and target is living or sac target") + if((((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || cult_team.is_sacrifice_target(sacrificial.mind)) && length(invokers) < 3) + for(var/invoker in invokers) + to_chat(invoker, span_cultitalic("[sacrificial] is too greatly linked to the world! You need three acolytes!")) return FALSE var/signal_result = SEND_SIGNAL(sacrificial, COMSIG_LIVING_CULT_SACRIFICED, invokers) @@ -335,7 +333,7 @@ structure_check() searches for nearby cultist structures required for the invoca if(sacrificial.mind) LAZYADD(GLOB.sacrificed, WEAKREF(sacrificial.mind)) - for(var/datum/objective/sacrifice/sac_objective in C.cult_team.objectives) + for(var/datum/objective/sacrifice/sac_objective in cult_team.objectives) if(sac_objective.target == sacrificial.mind) sac_objective.sacced = TRUE sac_objective.clear_sacrifice() @@ -344,7 +342,7 @@ structure_check() searches for nearby cultist structures required for the invoca else LAZYADD(GLOB.sacrificed, WEAKREF(sacrificial)) - new /obj/effect/temp_visual/cult/sac(get_turf(src)) + new /obj/effect/temp_visual/cult/sac(loc) if(!(signal_result & SILENCE_SACRIFICE_MESSAGE)) for(var/invoker in invokers) @@ -357,26 +355,70 @@ structure_check() searches for nearby cultist structures required for the invoca to_chat(invoker, span_cultlarge("\"I accept this meager sacrifice.\"")) if(iscyborg(sacrificial)) - var/construct_class = show_radial_menu(first_invoker, sacrificial, GLOB.construct_radial_images, require_near = TRUE, tooltips = TRUE) + var/construct_class = show_radial_menu(invokers[1], sacrificial, GLOB.construct_radial_images, require_near = TRUE, tooltips = TRUE) if(QDELETED(sacrificial) || !construct_class) return FALSE sacrificial.grab_ghost() - make_new_construct_from_class(construct_class, THEME_CULT, sacrificial, first_invoker, TRUE, get_turf(src)) + make_new_construct_from_class(construct_class, THEME_CULT, sacrificial, invokers[1], TRUE, get_turf(src)) var/mob/living/silicon/robot/sacriborg = sacrificial sacrificial.log_message("was sacrificed as a cyborg.", LOG_GAME) sacriborg.mmi = null qdel(sacrificial) return TRUE - var/obj/item/soulstone/stone = new /obj/item/soulstone(get_turf(src)) + + var/obj/item/soulstone/stone = new(loc) if(sacrificial.mind && !HAS_TRAIT(sacrificial, TRAIT_SUICIDED)) - stone.capture_soul(sacrificial, first_invoker, TRUE) + stone.capture_soul(sacrificial, invokers[1], forced = TRUE) if(sacrificial) playsound(sacrificial, 'sound/magic/disintegrate.ogg', 100, TRUE) sacrificial.investigate_log("has been sacrificially gibbed by the cult.", INVESTIGATE_DEATHS) sacrificial.gib(DROP_ALL_REMAINS) + + try_spawn_sword() // after sharding and gibbing, which potentially dropped a null rod return TRUE +/// Tries to convert a null rod over the rune to a cult sword +/obj/effect/rune/convert/proc/try_spawn_sword() + for(var/obj/item/nullrod/rod in loc) + if(rod.anchored || (rod.resistance_flags & INDESTRUCTIBLE)) + continue + + var/num_slain = LAZYLEN(rod.cultists_slain) + var/displayed_message = "[rod] glows an unholy red and begins to transform..." + if(GET_ATOM_BLOOD_DNA_LENGTH(rod)) + displayed_message += " The blood of [num_slain] fallen cultist[num_slain == 1 ? "":"s"] is absorbed into [rod]!" + + rod.visible_message(span_cultitalic(displayed_message)) + switch(num_slain) + if(0, 1) + animate_spawn_sword(rod, /obj/item/melee/cultblade/dagger) + if(2) + animate_spawn_sword(rod, /obj/item/melee/cultblade) + else + animate_spawn_sword(rod, /obj/item/cult_bastard) + return TRUE + + return FALSE + +/// Does an animation of a null rod transforming into a cult sword +/obj/effect/rune/convert/proc/animate_spawn_sword(obj/item/nullrod/former_rod, new_blade_typepath) + playsound(src, 'sound/effects/magic.ogg', 33, vary = TRUE, extrarange = SILENCED_SOUND_EXTRARANGE, frequency = 0.66) + former_rod.anchored = TRUE + former_rod.Shake() + animate(former_rod, alpha = 0, transform = matrix(former_rod.transform).Scale(0.01), time = 2 SECONDS, easing = BOUNCE_EASING, flags = ANIMATION_PARALLEL) + QDEL_IN(former_rod, 2 SECONDS) + + var/obj/item/new_blade = new new_blade_typepath(loc) + var/matrix/blade_matrix_on_spawn = matrix(new_blade.transform) + new_blade.name = "converted [new_blade.name]" + new_blade.anchored = TRUE + new_blade.alpha = 0 + new_blade.transform = matrix(new_blade.transform).Scale(0.01) + new_blade.Shake() + animate(new_blade, alpha = 255, transform = blade_matrix_on_spawn, time = 2 SECONDS, easing = BOUNCE_EASING, flags = ANIMATION_PARALLEL) + addtimer(VARSET_CALLBACK(new_blade, anchored, FALSE), 2 SECONDS) + /obj/effect/rune/empower cultist_name = "Empower" cultist_desc = "allows cultists to prepare greater amounts of blood magic at far less of a cost." diff --git a/code/modules/antagonists/fugitive/fugitive_outfits.dm b/code/modules/antagonists/fugitive/fugitive_outfits.dm index ba1fe87bfbb..3efab657101 100644 --- a/code/modules/antagonists/fugitive/fugitive_outfits.dm +++ b/code/modules/antagonists/fugitive/fugitive_outfits.dm @@ -67,7 +67,7 @@ if(visualsOnly) return var/obj/item/organ/internal/eyes/robotic/glow/eyes = new() - eyes.Insert(H, drop_if_replaced = FALSE) + eyes.Insert(H, movement_flags = DELETE_IF_REPLACED) /datum/outfit/invisible_man name = "Invisible Man" diff --git a/code/modules/antagonists/heretic/heretic_antag.dm b/code/modules/antagonists/heretic/heretic_antag.dm index 1b73918ba62..44111fb0ea8 100644 --- a/code/modules/antagonists/heretic/heretic_antag.dm +++ b/code/modules/antagonists/heretic/heretic_antag.dm @@ -231,7 +231,6 @@ RegisterSignal(our_mob, COMSIG_MOB_ITEM_AFTERATTACK, PROC_REF(on_item_afterattack)) RegisterSignal(our_mob, COMSIG_MOB_LOGIN, PROC_REF(fix_influence_network)) RegisterSignal(our_mob, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(after_fully_healed)) - RegisterSignal(our_mob, COMSIG_LIVING_CULT_SACRIFICED, PROC_REF(on_cult_sacrificed)) /datum/antagonist/heretic/remove_innate_effects(mob/living/mob_override) var/mob/living/our_mob = mob_override || owner.current @@ -247,7 +246,6 @@ COMSIG_MOB_ITEM_AFTERATTACK, COMSIG_MOB_LOGIN, COMSIG_LIVING_POST_FULLY_HEAL, - COMSIG_LIVING_CULT_SACRIFICED )) /datum/antagonist/heretic/on_body_transfer(mob/living/old_body, mob/living/new_body) @@ -395,15 +393,6 @@ var/datum/heretic_knowledge/living_heart/heart_knowledge = get_knowledge(/datum/heretic_knowledge/living_heart) heart_knowledge.on_research(source, src) -/// Signal proc for [COMSIG_LIVING_CULT_SACRIFICED] to reward cultists for sacrificing a heretic -/datum/antagonist/heretic/proc/on_cult_sacrificed(mob/living/source, list/invokers) - SIGNAL_HANDLER - - new /obj/item/cult_bastard(source.loc) - for(var/mob/living/cultist as anything in invokers) - to_chat(cultist, span_cultlarge("\"A follower of the forgotten gods! You must be rewarded for such a valuable sacrifice.\"")) - return SILENCE_SACRIFICE_MESSAGE - /** * Create our objectives for our heretic. */ @@ -414,7 +403,7 @@ var/num_heads = 0 for(var/mob/player in GLOB.alive_player_list) - if(player.mind.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND) + if(player.mind.assigned_role.job_flags & JOB_HEAD_OF_STAFF) num_heads++ var/datum/objective/minor_sacrifice/sac_objective = new() diff --git a/code/modules/antagonists/heretic/knowledge/blade_lore.dm b/code/modules/antagonists/heretic/knowledge/blade_lore.dm index 03b9a716d53..257f87d7c9f 100644 --- a/code/modules/antagonists/heretic/knowledge/blade_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/blade_lore.dm @@ -227,10 +227,7 @@ During this process, you will rapidly regenerate stamina and quickly recover from stuns, however, you will be unable to attack. \ This spell can be cast in rapid succession, but doing so will increase the cooldown." gain_text = "In the flurry of death, he found peace within himself. Despite insurmountable odds, he forged on." - next_knowledge = list( - /datum/heretic_knowledge/duel_stance, - /datum/heretic_knowledge/rifle, - ) + next_knowledge = list(/datum/heretic_knowledge/duel_stance) spell_to_add = /datum/action/cooldown/spell/realignment cost = 1 route = PATH_BLADE @@ -250,6 +247,7 @@ /datum/heretic_knowledge/reroll_targets, /datum/heretic_knowledge/rune_carver, /datum/heretic_knowledge/crucible, + /datum/heretic_knowledge/rifle, ) cost = 1 route = PATH_BLADE diff --git a/code/modules/antagonists/heretic/knowledge/lock_lore.dm b/code/modules/antagonists/heretic/knowledge/lock_lore.dm index cf425563c13..99629365679 100644 --- a/code/modules/antagonists/heretic/knowledge/lock_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/lock_lore.dm @@ -103,27 +103,12 @@ ) result_atoms = list(/obj/item/card/id/advanced/heretic) next_knowledge = list( - /datum/heretic_knowledge/limited_amount/concierge_rite, + /datum/heretic_knowledge/mark/lock_mark, /datum/heretic_knowledge/spell/mind_gate, ) cost = 1 route = PATH_LOCK -/datum/heretic_knowledge/limited_amount/concierge_rite // item that creates 3 max at a time heretic only barriers, probably should limit to 1 only, holy people can also pass - name = "Concierge's Rite" - desc = "Allows you to transmute a white crayon, a wooden plank, and a multitool to create a Labyrinth Handbook. \ - It can materialize a barricade at range that only you and people resistant to magic can pass. 3 uses." - gain_text = "The Concierge scribbled my name into the Handbook. \"Welcome to your new home, fellow Steward.\"" - required_atoms = list( - /obj/item/toy/crayon/white = 1, - /obj/item/stack/sheet/mineral/wood = 1, - /obj/item/multitool = 1, - ) - result_atoms = list(/obj/item/heretic_labyrinth_handbook) - next_knowledge = list(/datum/heretic_knowledge/mark/lock_mark) - cost = 1 - route = PATH_LOCK - /datum/heretic_knowledge/mark/lock_mark name = "Mark of Lock" desc = "Your Mansus Grasp now applies the Mark of Lock. \ @@ -135,7 +120,22 @@ mark_type = /datum/status_effect/eldritch/lock /datum/heretic_knowledge/knowledge_ritual/lock + next_knowledge = list(/datum/heretic_knowledge/limited_amount/concierge_rite) + route = PATH_LOCK + +/datum/heretic_knowledge/limited_amount/concierge_rite // item that creates 3 max at a time heretic only barriers, probably should limit to 1 only, holy people can also pass + name = "Concierge's Rite" + desc = "Allows you to transmute a white crayon, a wooden plank, and a multitool to create a Labyrinth Handbook. \ + It can materialize a barricade at range that only you and people resistant to magic can pass. 3 uses." + gain_text = "The Concierge scribbled my name into the Handbook. \"Welcome to your new home, fellow Steward.\"" + required_atoms = list( + /obj/item/toy/crayon/white = 1, + /obj/item/stack/sheet/mineral/wood = 1, + /obj/item/multitool = 1, + ) + result_atoms = list(/obj/item/heretic_labyrinth_handbook) next_knowledge = list(/datum/heretic_knowledge/spell/burglar_finesse) + cost = 1 route = PATH_LOCK /datum/heretic_knowledge/spell/burglar_finesse @@ -203,8 +203,7 @@ for(var/mob/living/carbon/human/body in atoms) if(body.stat != DEAD) continue - var/obj/item/bodypart/chest = body.get_bodypart(BODY_ZONE_CHEST) - if(LAZYLEN(chest.get_organs())) + if(LAZYLEN(body.get_organs_for_zone(BODY_ZONE_CHEST))) to_chat(user, span_hierophant_warning("[body] has organs in their chest.")) continue diff --git a/code/modules/antagonists/heretic/knowledge/rust_lore.dm b/code/modules/antagonists/heretic/knowledge/rust_lore.dm index 6817dc9de44..8d577b1992a 100644 --- a/code/modules/antagonists/heretic/knowledge/rust_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/rust_lore.dm @@ -161,10 +161,7 @@ Anyone overtop the wall will be throw aside (or upwards) and sustain damage." gain_text = "Images of foreign and ominous structures began to dance in my mind. Covered head to toe in thick rust, \ they no longer looked man made. Or perhaps they never were in the first place." - next_knowledge = list( - /datum/heretic_knowledge/spell/area_conversion, - /datum/heretic_knowledge/rifle, - ) + next_knowledge = list(/datum/heretic_knowledge/spell/area_conversion) spell_to_add = /datum/action/cooldown/spell/pointed/rust_construction cost = 1 route = PATH_RUST @@ -179,6 +176,7 @@ /datum/heretic_knowledge/reroll_targets, /datum/heretic_knowledge/curse/corrosion, /datum/heretic_knowledge/crucible, + /datum/heretic_knowledge/rifle, ) spell_to_add = /datum/action/cooldown/spell/aoe/rust_conversion cost = 1 diff --git a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm index b66ec468e71..797d754ea0b 100644 --- a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm +++ b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_knowledge.dm @@ -130,7 +130,7 @@ // First target, any command. for(var/datum/mind/head_mind as anything in shuffle(valid_targets)) - if(head_mind.assigned_role?.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND) + if(head_mind.assigned_role?.job_flags & JOB_HEAD_OF_STAFF) final_targets += head_mind valid_targets -= head_mind break @@ -187,8 +187,8 @@ heretic_datum.remove_sacrifice_target(sacrifice) var/feedback = "Your patrons accept your offer" - var/sac_department_flag = sacrifice.mind?.assigned_role?.departments_bitflags | sacrifice.last_mind?.assigned_role?.departments_bitflags - if(sac_department_flag & DEPARTMENT_BITFLAG_COMMAND) + var/sac_job_flag = sacrifice.mind?.assigned_role?.job_flags | sacrifice.last_mind?.assigned_role?.job_flags + if(sac_job_flag & JOB_HEAD_OF_STAFF) heretic_datum.knowledge_points++ heretic_datum.high_value_sacrifices++ feedback += " graciously" diff --git a/code/modules/antagonists/heretic/knowledge/side_blade_rust.dm b/code/modules/antagonists/heretic/knowledge/side_blade_rust.dm index d7dfd75a144..e8c14d16abe 100644 --- a/code/modules/antagonists/heretic/knowledge/side_blade_rust.dm +++ b/code/modules/antagonists/heretic/knowledge/side_blade_rust.dm @@ -46,8 +46,8 @@ gain_text = "I met an old man in an anique shop who wielded a very unusual weapon. \ I could not purchase it at the time, but they showed me how they made it ages ago." next_knowledge = list( - /datum/heretic_knowledge/spell/realignment, - /datum/heretic_knowledge/spell/rust_construction, + /datum/heretic_knowledge/duel_stance, + /datum/heretic_knowledge/spell/area_conversion, /datum/heretic_knowledge/rifle_ammo, ) required_atoms = list( diff --git a/code/modules/antagonists/heretic/knowledge/starting_lore.dm b/code/modules/antagonists/heretic/knowledge/starting_lore.dm index eb766392290..f1b5f7f55ea 100644 --- a/code/modules/antagonists/heretic/knowledge/starting_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/starting_lore.dm @@ -237,6 +237,7 @@ GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge()) cost = 1 route = PATH_START priority = MAX_KNOWLEDGE_PRIORITY - 3 // Least priority out of the starting knowledges, as it's an optional boon. + var/static/list/non_mob_bindings = typecacheof(list(/obj/item/stack/sheet/leather, /obj/item/stack/sheet/animalhide)) /datum/heretic_knowledge/codex_cicatrix/parse_required_item(atom/item_path, number_of_things) if(item_path == /obj/item/pen) @@ -248,12 +249,16 @@ GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge()) if(!.) return FALSE - for(var/mob/living/body in atoms) - if(body.stat != DEAD) - continue - - selected_atoms += body - return TRUE + for(var/thingy in atoms) + if(is_type_in_typecache(thingy, non_mob_bindings)) + selected_atoms += thingy + return TRUE + else if(isliving(thingy)) + var/mob/living/body = thingy + if(body.stat != DEAD) + continue + selected_atoms += body + return TRUE return FALSE /datum/heretic_knowledge/codex_cicatrix/cleanup_atoms(list/selected_atoms) diff --git a/code/modules/antagonists/heretic/transmutation_rune.dm b/code/modules/antagonists/heretic/transmutation_rune.dm index 31c252eacf1..2479ec715e0 100644 --- a/code/modules/antagonists/heretic/transmutation_rune.dm +++ b/code/modules/antagonists/heretic/transmutation_rune.dm @@ -80,6 +80,10 @@ for(var/atom/close_atom as anything in range(1, src)) if(!ismovable(close_atom)) continue + if(isitem(close_atom)) + var/obj/item/close_item = close_atom + if(close_item.item_flags & ABSTRACT) //woops sacrificed your own head + continue if(close_atom.invisibility) continue if(close_atom == user) diff --git a/code/modules/antagonists/highlander/highlander.dm b/code/modules/antagonists/highlander/highlander.dm index 98659ef1941..077bd2158b8 100644 --- a/code/modules/antagonists/highlander/highlander.dm +++ b/code/modules/antagonists/highlander/highlander.dm @@ -52,9 +52,8 @@ if(!istype(H)) return - for(var/obj/item/I in H) - if(!H.dropItemToGround(I)) - qdel(I) + H.drop_everything(del_on_drop = FALSE, force = TRUE, del_if_nodrop = TRUE) + H.regenerate_icons() H.revive(ADMIN_HEAL_ALL) H.equip_to_slot_or_del(new /obj/item/clothing/under/costume/kilt/highlander(H), ITEM_SLOT_ICLOTHING) diff --git a/code/modules/antagonists/nightmare/nightmare_organs.dm b/code/modules/antagonists/nightmare/nightmare_organs.dm index 50bfd8e1619..c06f1e322a2 100644 --- a/code/modules/antagonists/nightmare/nightmare_organs.dm +++ b/code/modules/antagonists/nightmare/nightmare_organs.dm @@ -15,7 +15,7 @@ ///Our associated terrorize spell, for antagonist nightmares var/datum/action/cooldown/spell/pointed/terrorize/terrorize_spell -/obj/item/organ/internal/brain/shadow/nightmare/on_insert(mob/living/carbon/brain_owner) +/obj/item/organ/internal/brain/shadow/nightmare/on_mob_insert(mob/living/carbon/brain_owner) . = ..() if(brain_owner.dna.species.id != SPECIES_NIGHTMARE) @@ -29,7 +29,7 @@ terrorize_spell = new(src) terrorize_spell.Grant(brain_owner) -/obj/item/organ/internal/brain/shadow/nightmare/on_remove(mob/living/carbon/brain_owner) +/obj/item/organ/internal/brain/shadow/nightmare/on_mob_remove(mob/living/carbon/brain_owner) . = ..() QDEL_NULL(our_jaunt) QDEL_NULL(terrorize_spell) @@ -91,13 +91,13 @@ user.temporarilyRemoveItemFromInventory(src, TRUE) Insert(user) -/obj/item/organ/internal/heart/nightmare/on_insert(mob/living/carbon/heart_owner, special) +/obj/item/organ/internal/heart/nightmare/on_mob_insert(mob/living/carbon/heart_owner, special) . = ..() if(special != HEART_SPECIAL_SHADOWIFY) blade = new/obj/item/light_eater heart_owner.put_in_hands(blade) -/obj/item/organ/internal/heart/nightmare/on_remove(mob/living/carbon/heart_owner, special) +/obj/item/organ/internal/heart/nightmare/on_mob_remove(mob/living/carbon/heart_owner, special) . = ..() respawn_progress = 0 if(blade && special != HEART_SPECIAL_SHADOWIFY) diff --git a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm index cd1ad0b02c0..84f3a151dd2 100644 --- a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm +++ b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm @@ -395,7 +395,7 @@ return 0 else if(FACTION_PIRATE in ransomee.faction) //can't ransom your fellow pirates to CentCom! return 0 - else if(ransomee.mind.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND) + else if(HAS_TRAIT(ransomee, TRAIT_HIGH_VALUE_RANSOM)) return 3000 else return 1000 diff --git a/code/modules/antagonists/revolution/revolution.dm b/code/modules/antagonists/revolution/revolution.dm index 6ee5ba5dcc7..708f94c3fc3 100644 --- a/code/modules/antagonists/revolution/revolution.dm +++ b/code/modules/antagonists/revolution/revolution.dm @@ -12,7 +12,7 @@ var/deconversion_source /datum/antagonist/rev/can_be_owned(datum/mind/new_owner) - if(new_owner.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND) + if(new_owner.assigned_role.job_flags & JOB_HEAD_OF_STAFF) return FALSE if(new_owner.unconvertable) return FALSE diff --git a/code/modules/antagonists/traitor/objectives/assassination.dm b/code/modules/antagonists/traitor/objectives/assassination.dm index f3b76874213..9fae7ed3352 100644 --- a/code/modules/antagonists/traitor/objectives/assassination.dm +++ b/code/modules/antagonists/traitor/objectives/assassination.dm @@ -201,10 +201,10 @@ continue //removes heads of staff from being targets from non heads of staff assassinations, and vice versa if(heads_of_staff) - if(!(possible_target.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND)) + if(!(possible_target.assigned_role.job_flags & JOB_HEAD_OF_STAFF)) continue else - if((possible_target.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND)) + if((possible_target.assigned_role.job_flags & JOB_HEAD_OF_STAFF)) continue possible_targets += possible_target for(var/datum/traitor_objective/target_player/objective as anything in possible_duplicates) diff --git a/code/modules/antagonists/traitor/objectives/eyesnatching.dm b/code/modules/antagonists/traitor/objectives/eyesnatching.dm index 5cf95e90384..5773c4e90e0 100644 --- a/code/modules/antagonists/traitor/objectives/eyesnatching.dm +++ b/code/modules/antagonists/traitor/objectives/eyesnatching.dm @@ -74,10 +74,10 @@ continue if(heads_of_staff) - if(!(possible_target.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND)) + if(!(possible_target.assigned_role.job_flags & JOB_HEAD_OF_STAFF)) continue else - if(possible_target.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND) + if(possible_target.assigned_role.job_flags & JOB_HEAD_OF_STAFF) continue var/mob/living/carbon/human/targets_current = possible_target.current diff --git a/code/modules/antagonists/traitor/objectives/infect.dm b/code/modules/antagonists/traitor/objectives/infect.dm index b1bb868e903..3ea27192c17 100644 --- a/code/modules/antagonists/traitor/objectives/infect.dm +++ b/code/modules/antagonists/traitor/objectives/infect.dm @@ -102,10 +102,10 @@ continue //removes heads of staff from being targets from non heads of staff assassinations, and vice versa if(heads_of_staff) - if(!(possible_target.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND)) + if(!(possible_target.assigned_role.job_flags & JOB_HEAD_OF_STAFF)) continue else - if((possible_target.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND)) + if((possible_target.assigned_role.job_flags & JOB_HEAD_OF_STAFF)) continue possible_targets += possible_target for(var/datum/traitor_objective/target_player/objective as anything in possible_duplicates) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 3be90e397c6..8aa3258c120 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -624,7 +624,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) /datum/preferences/proc/should_be_random_hardcore(datum/job/job, datum/mind/mind) if(!read_preference(/datum/preference/toggle/random_hardcore)) return FALSE - if(job.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND) //No command staff + if(job.job_flags & JOB_HEAD_OF_STAFF) //No heads of staff return FALSE for(var/datum/antagonist/antag as anything in mind.antag_datums) if(antag.get_team()) //No team antags diff --git a/code/modules/client/preferences/language.dm b/code/modules/client/preferences/language.dm index d26f9a15ffb..7e8e6cb7113 100644 --- a/code/modules/client/preferences/language.dm +++ b/code/modules/client/preferences/language.dm @@ -20,7 +20,7 @@ //we add uncommon as it's foreigner-only. var/datum/language/uncommon/uncommon_language = /datum/language/uncommon values += initial(uncommon_language.name) - values += /datum/language/common::name // NOVA EDIT ADDITION START - Let's you select common + values += /datum/language/common::name // NOVA EDIT ADDITION START - Lets you select common for(var/datum/language/language_type as anything in GLOB.uncommon_roundstart_languages) if(initial(language_type.name) in values) diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index b87a3f7b221..a4c6393ed6f 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -81,10 +81,10 @@ var/tie_timer_actual = tie_timer // Mirrors give you a boost to your tying speed. I realize this stacks and I think that's hilarious. for(var/obj/structure/mirror/reflection in view(2, user)) - tie_timer_actual /= 1.25 + tie_timer_actual *= 0.8 // Heads of staff are experts at tying their ties. - if(user.mind?.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND) - tie_timer_actual /= 2 + if(HAS_TRAIT(user, TRAIT_FAST_TYING)) + tie_timer_actual *= 0.5 // Tie/Untie our tie if(!do_after(user, tie_timer_actual)) to_chat(user, span_notice("Your fingers fumble away from [src] as your concentration breaks.")) diff --git a/code/modules/food_and_drinks/machinery/microwave.dm b/code/modules/food_and_drinks/machinery/microwave.dm index 0471f5e92ef..c4cc6d378e3 100644 --- a/code/modules/food_and_drinks/machinery/microwave.dm +++ b/code/modules/food_and_drinks/machinery/microwave.dm @@ -486,7 +486,7 @@ /obj/machinery/microwave/CtrlClick(mob/user) . = ..() - if(cell_powered && !isnull(cell) && anchored) + if(user.can_perform_action(src) && cell_powered && !isnull(cell) && anchored) user.put_in_hands(cell) balloon_alert(user, "removed cell") cell = null diff --git a/code/modules/food_and_drinks/machinery/smartfridge.dm b/code/modules/food_and_drinks/machinery/smartfridge.dm index c4ec48f4dd6..ae06fb93f83 100644 --- a/code/modules/food_and_drinks/machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/machinery/smartfridge.dm @@ -6,6 +6,7 @@ desc = "Keeps cold things cold and hot things cold." icon = 'icons/obj/machines/smartfridge.dmi' icon_state = "smartfridge" + base_icon_state = "plant" layer = BELOW_OBJ_LAYER density = TRUE circuit = /obj/item/circuitboard/machine/smartfridge @@ -17,8 +18,6 @@ var/base_build_path = /obj/machinery/smartfridge /// Maximum number of items that can be loaded into the machine var/max_n_of_items = 1500 - /// The overlay for this fridge when it is filled with stuff - var/contents_icon_state = "plant" /// List of items that the machine starts with upon spawn var/list/initial_contents /// If the machine shows an approximate number of its contents on its sprite @@ -226,9 +225,10 @@ /obj/machinery/smartfridge/update_overlays() . = ..() + var/initial_icon_state = initial(icon_state) var/shown_contents_length = visible_items() if(visible_contents && shown_contents_length) - var/content_level = "[initial(icon_state)]-[contents_icon_state]" + var/content_level = "[initial_icon_state]-[base_icon_state]" switch(shown_contents_length) if(1 to 25) content_level += "-1" @@ -238,10 +238,10 @@ content_level += "-3" . += mutable_appearance(icon, content_level) - . += mutable_appearance(icon, "[initial(icon_state)]-glass[(machine_stat & BROKEN) ? "-broken" : ""]") + . += mutable_appearance(icon, "[initial_icon_state]-glass[(machine_stat & BROKEN) ? "-broken" : ""]") if(!machine_stat && has_emissive) - . += emissive_appearance(icon, "[initial(icon_state)]-light-mask", src, alpha = src.alpha) + . += emissive_appearance(icon, "[initial_icon_state]-light-mask", src, alpha = src.alpha) /obj/machinery/smartfridge/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) switch(damage_type) @@ -584,7 +584,7 @@ name = "drink showcase" desc = "A refrigerated storage unit for tasty tasty alcohol." base_build_path = /obj/machinery/smartfridge/drinks - contents_icon_state = "drink" + base_icon_state = "drink" /obj/machinery/smartfridge/drinks/accept_check(obj/item/weapon) //not an item or valid container @@ -604,7 +604,7 @@ /obj/machinery/smartfridge/food desc = "A refrigerated storage unit for food." base_build_path = /obj/machinery/smartfridge/food - contents_icon_state = "food" + base_icon_state = "food" /obj/machinery/smartfridge/food/accept_check(obj/item/weapon) if(weapon.w_class >= WEIGHT_CLASS_BULKY) @@ -622,7 +622,7 @@ name = "smart slime extract storage" desc = "A refrigerated storage unit for slime extracts." base_build_path = /obj/machinery/smartfridge/extract - contents_icon_state = "slime" + base_icon_state = "slime" /obj/machinery/smartfridge/extract/accept_check(obj/item/weapon) return (istype(weapon, /obj/item/slime_extract) || istype(weapon, /obj/item/slime_scanner)) @@ -637,7 +637,7 @@ name = "smart petri dish storage" desc = "A refrigerated storage unit for petri dishes." base_build_path = /obj/machinery/smartfridge/petri - contents_icon_state = "petri" + base_icon_state = "petri" /obj/machinery/smartfridge/petri/accept_check(obj/item/weapon) return istype(weapon, /obj/item/petri_dish) @@ -653,7 +653,7 @@ desc = "A refrigerated storage unit for organ storage." max_n_of_items = 20 //vastly lower to prevent processing too long base_build_path = /obj/machinery/smartfridge/organ - contents_icon_state = "organ" + base_icon_state = "organ" /// The rate at which this fridge will repair damaged organs var/repair_rate = 0 @@ -706,7 +706,7 @@ name = "smart chemical storage" desc = "A refrigerated storage unit for medicine storage." base_build_path = /obj/machinery/smartfridge/chemistry - contents_icon_state = "chem" + base_icon_state = "chem" /obj/machinery/smartfridge/chemistry/accept_check(obj/item/weapon) // not an item or reagent container @@ -757,7 +757,7 @@ name = "smart virus storage" desc = "A refrigerated storage unit for volatile sample storage." base_build_path = /obj/machinery/smartfridge/chemistry/virology - contents_icon_state = "viro" + base_icon_state = "viro" /obj/machinery/smartfridge/chemistry/virology/preloaded initial_contents = list( diff --git a/code/modules/hallucination/delusions.dm b/code/modules/hallucination/delusions.dm index 2ef224ddf97..106988f7327 100644 --- a/code/modules/hallucination/delusions.dm +++ b/code/modules/hallucination/delusions.dm @@ -18,8 +18,13 @@ var/delusion_icon_file /// The icon state of the delusion image var/delusion_icon_state - /// Do we use a generated icon? If yes no icon file or state needed. - var/dynamic_icon = FALSE + + /// Do we use an appearance/generated icon? If yes no icon file or state needed. + var/dynamic_delusion = FALSE + /// Appearance to use as a source for our image + /// If this exists we'll ignore the icon/state from above + var/mutable_appearance/delusion_appearance + /// The name of the delusion image var/delusion_name @@ -96,7 +101,11 @@ return TRUE /datum/hallucination/delusion/proc/make_delusion_image(mob/over_who) - var/image/funny_image = image(delusion_icon_file, over_who, dynamic_icon ? "" : delusion_icon_state) + var/image/funny_image + if(delusion_appearance) + funny_image = image(delusion_appearance, over_who) + else + funny_image = image(delusion_icon_file, over_who, delusion_icon_state) funny_image.name = delusion_name funny_image.override = TRUE return funny_image @@ -197,14 +206,14 @@ return funny_image /datum/hallucination/delusion/preset/syndies + dynamic_delusion = TRUE random_hallucination_weight = 1 - dynamic_icon = TRUE delusion_name = "Syndicate" affects_others = TRUE affects_us = FALSE /datum/hallucination/delusion/preset/syndies/make_delusion_image(mob/over_who) - delusion_icon_file = getFlatIcon(get_dynamic_human_appearance( + delusion_appearance = get_dynamic_human_appearance( mob_spawn_path = pick( /obj/effect/mob_spawn/corpse/human/syndicatesoldier, /obj/effect/mob_spawn/corpse/human/syndicatecommando, @@ -217,7 +226,7 @@ /obj/item/gun/ballistic/automatic/c20r, /obj/item/gun/ballistic/shotgun/bulldog, ), - )) + ) return ..() @@ -241,18 +250,19 @@ // Hallucination used by heretic paintings /datum/hallucination/delusion/preset/heretic + dynamic_delusion = TRUE random_hallucination_weight = 0 - dynamic_icon = TRUE delusion_name = "Heretic" affects_others = TRUE affects_us = FALSE duration = 11 SECONDS /datum/hallucination/delusion/preset/heretic/make_delusion_image(mob/over_who) - var/static/icon/heretic_icon - if(isnull(heretic_icon)) - heretic_icon = getFlatIcon(get_dynamic_human_appearance(/datum/outfit/heretic, r_hand = NO_REPLACE)) - delusion_icon_file = heretic_icon + // This code is dummy hot for DUMB reasons so let's not make a mob constantly yeah? + var/static/mutable_appearance/heretic_appearance + if(isnull(heretic_appearance)) + heretic_appearance = get_dynamic_human_appearance(/datum/outfit/heretic, r_hand = NO_REPLACE) + delusion_appearance = heretic_appearance return ..() /datum/hallucination/delusion/preset/heretic/gate diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index ce3f55da9b5..19f592910f2 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -103,7 +103,7 @@ /// List of family heirlooms this job can get with the family heirloom quirk. List of types. var/list/family_heirlooms - /// All values = (JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_BOLD_SELECT_TEXT | JOB_ASSIGN_QUIRKS | JOB_CAN_BE_INTERN | JOB_CANNOT_OPEN_SLOTS) + /// All values = (JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_BOLD_SELECT_TEXT | JOB_ASSIGN_QUIRKS | JOB_CAN_BE_INTERN | JOB_CANNOT_OPEN_SLOTS | JOB_HEAD_OF_STAFF) var/job_flags = NONE /// Multiplier for general usage of the voice of god. @@ -533,7 +533,7 @@ if(!player_client) return // Disconnected while checking for the appearance ban. - var/require_human = CONFIG_GET(flag/enforce_human_authority) && (job.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND) + var/require_human = CONFIG_GET(flag/enforce_human_authority) && (job.job_flags & JOB_HEAD_OF_STAFF) if(require_human) var/all_authority_require_human = CONFIG_GET(flag/enforce_human_authority_on_everyone) if(!all_authority_require_human && job.ignore_human_authority) diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm index 954ec3f1726..b5d715ab679 100755 --- a/code/modules/jobs/job_types/captain.dm +++ b/code/modules/jobs/job_types/captain.dm @@ -23,6 +23,7 @@ paycheck = PAYCHECK_COMMAND paycheck_department = ACCOUNT_CMD // NOVA EDIT - Original: paycheck_department = ACCOUNT_SEC + mind_traits = list(HEAD_OF_STAFF_MIND_TRAITS) liver_traits = list(TRAIT_ROYAL_METABOLISM) display_order = JOB_DISPLAY_ORDER_CAPTAIN @@ -42,7 +43,7 @@ /obj/item/skillchip/sabrage = 5, ) - job_flags = STATION_JOB_FLAGS | JOB_BOLD_SELECT_TEXT | JOB_CANNOT_OPEN_SLOTS + job_flags = STATION_JOB_FLAGS | HEAD_OF_STAFF_JOB_FLAGS rpg_title = "Star Duke" voice_of_god_power = 1.4 //Command staff has authority diff --git a/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm b/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm index 13f05add3ec..97688417aac 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm @@ -20,6 +20,8 @@ var/chaplain_spawnable = TRUE /// Short description of what this item is capable of, for radial menu uses. var/menu_description = "A standard chaplain's weapon. Fits in pockets. Can be worn on the belt." + /// Lazylist, tracks refs()s to all cultists which have been crit or killed by this nullrod. + var/list/cultists_slain /obj/item/nullrod/Initialize(mapload) . = ..() @@ -66,6 +68,27 @@ user.visible_message(span_suicide("[user] is killing [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to get closer to god!")) return (BRUTELOSS|FIRELOSS) +/obj/item/nullrod/attack(mob/living/target_mob, mob/living/user, params) + if(!user.mind?.holy_role) + return ..() + if(!IS_CULTIST(target_mob) || istype(target_mob, /mob/living/carbon/human/cult_ghost)) + return ..() + + var/old_stat = target_mob.stat + . = ..() + if(old_stat < target_mob.stat) + LAZYOR(cultists_slain, REF(target_mob)) + return . + +/obj/item/nullrod/examine(mob/user) + . = ..() + if(!IS_CULTIST(user) || !GET_ATOM_BLOOD_DNA_LENGTH(src)) + return + + var/num_slain = LAZYLEN(cultists_slain) + . += span_cultitalic("It has the blood of [num_slain] fallen cultist[num_slain == 1 ? "" : "s"] on it. \ + Offering it to Nar'sie will transform it into a [num_slain >= 3 ? "powerful" : "standard"] cult weapon.") + /obj/item/nullrod/godhand name = "god hand" desc = "This hand of yours glows with an awesome power!" diff --git a/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm b/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm index 6832e3d66d4..74b1cdcf627 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain_vorpal_scythe.dm @@ -10,7 +10,7 @@ If the scythe isn't empowered when you sheath it, you take a heap of damage and desc = "This shard seems to be directly linked to some sinister entity. It might be your god! It also gives you a really horrible rash when you hold onto it for too long." items_to_create = list(/obj/item/vorpalscythe) -/obj/item/organ/internal/cyberimp/arm/shard/scythe/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/internal/cyberimp/arm/shard/scythe/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() if(receiver.mind) ADD_TRAIT(receiver.mind, TRAIT_MORBID, ORGAN_TRAIT) diff --git a/code/modules/jobs/job_types/chief_engineer.dm b/code/modules/jobs/job_types/chief_engineer.dm index fcb26731ca1..fd568464bb6 100644 --- a/code/modules/jobs/job_types/chief_engineer.dm +++ b/code/modules/jobs/job_types/chief_engineer.dm @@ -27,6 +27,7 @@ paycheck = PAYCHECK_COMMAND paycheck_department = ACCOUNT_ENG + mind_traits = list(HEAD_OF_STAFF_MIND_TRAITS) liver_traits = list(TRAIT_ENGINEER_METABOLISM, TRAIT_ROYAL_METABOLISM) display_order = JOB_DISPLAY_ORDER_CHIEF_ENGINEER @@ -43,7 +44,7 @@ /obj/effect/spawner/random/engineering/tool_advanced = 3 ) rpg_title = "Head Crystallomancer" - job_flags = STATION_JOB_FLAGS | JOB_BOLD_SELECT_TEXT | JOB_CANNOT_OPEN_SLOTS + job_flags = STATION_JOB_FLAGS | HEAD_OF_STAFF_JOB_FLAGS voice_of_god_power = 1.4 //Command staff has authority diff --git a/code/modules/jobs/job_types/chief_medical_officer.dm b/code/modules/jobs/job_types/chief_medical_officer.dm index 998c19a215d..e20ef7c19ed 100644 --- a/code/modules/jobs/job_types/chief_medical_officer.dm +++ b/code/modules/jobs/job_types/chief_medical_officer.dm @@ -27,6 +27,7 @@ paycheck = PAYCHECK_COMMAND paycheck_department = ACCOUNT_MED + mind_traits = list(HEAD_OF_STAFF_MIND_TRAITS) liver_traits = list(TRAIT_MEDICAL_METABOLISM, TRAIT_ROYAL_METABOLISM) display_order = JOB_DISPLAY_ORDER_CHIEF_MEDICAL_OFFICER @@ -40,7 +41,7 @@ ) family_heirlooms = list(/obj/item/storage/medkit/ancient/heirloom, /obj/item/scalpel, /obj/item/hemostat, /obj/item/circular_saw, /obj/item/retractor, /obj/item/cautery, /obj/item/statuebust/hippocratic) rpg_title = "High Cleric" - job_flags = STATION_JOB_FLAGS | JOB_BOLD_SELECT_TEXT | JOB_CANNOT_OPEN_SLOTS + job_flags = STATION_JOB_FLAGS | HEAD_OF_STAFF_JOB_FLAGS voice_of_god_power = 1.4 //Command staff has authority diff --git a/code/modules/jobs/job_types/head_of_personnel.dm b/code/modules/jobs/job_types/head_of_personnel.dm index c8a36586292..e863a782d9b 100644 --- a/code/modules/jobs/job_types/head_of_personnel.dm +++ b/code/modules/jobs/job_types/head_of_personnel.dm @@ -28,6 +28,7 @@ paycheck_department = ACCOUNT_SRV bounty_types = CIV_JOB_RANDOM + mind_traits = list(HEAD_OF_STAFF_MIND_TRAITS) liver_traits = list(TRAIT_ROYAL_METABOLISM) display_order = JOB_DISPLAY_ORDER_HEAD_OF_PERSONNEL @@ -39,7 +40,7 @@ family_heirlooms = list(/obj/item/reagent_containers/cup/glass/trophy/silver_cup) rpg_title = "Guild Questgiver" - job_flags = STATION_JOB_FLAGS | JOB_BOLD_SELECT_TEXT | JOB_CANNOT_OPEN_SLOTS + job_flags = STATION_JOB_FLAGS | HEAD_OF_STAFF_JOB_FLAGS voice_of_god_power = 1.4 //Command staff has authority diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm index 825add17d89..afb39bf7c1a 100644 --- a/code/modules/jobs/job_types/head_of_security.dm +++ b/code/modules/jobs/job_types/head_of_security.dm @@ -24,6 +24,7 @@ /datum/job_department/command, ) + mind_traits = list(HEAD_OF_STAFF_MIND_TRAITS) liver_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM, TRAIT_ROYAL_METABOLISM) paycheck = PAYCHECK_COMMAND @@ -34,7 +35,7 @@ family_heirlooms = list(/obj/item/book/manual/wiki/security_space_law) rpg_title = "Guard Leader" - job_flags = STATION_JOB_FLAGS | JOB_BOLD_SELECT_TEXT | JOB_CANNOT_OPEN_SLOTS + job_flags = STATION_JOB_FLAGS | HEAD_OF_STAFF_JOB_FLAGS voice_of_god_power = 1.4 //Command staff has authority diff --git a/code/modules/jobs/job_types/quartermaster.dm b/code/modules/jobs/job_types/quartermaster.dm index 0ca4b0a1052..858ce8b6455 100644 --- a/code/modules/jobs/job_types/quartermaster.dm +++ b/code/modules/jobs/job_types/quartermaster.dm @@ -20,6 +20,7 @@ paycheck = PAYCHECK_COMMAND paycheck_department = ACCOUNT_CAR + mind_traits = list(HEAD_OF_STAFF_MIND_TRAITS) liver_traits = list(TRAIT_ROYAL_METABOLISM) // finally upgraded display_order = JOB_DISPLAY_ORDER_QUARTERMASTER @@ -33,7 +34,7 @@ /obj/item/circuitboard/machine/emitter = 3 ) rpg_title = "Steward" - job_flags = STATION_JOB_FLAGS | JOB_BOLD_SELECT_TEXT | JOB_CANNOT_OPEN_SLOTS + job_flags = STATION_JOB_FLAGS | HEAD_OF_STAFF_JOB_FLAGS voice_of_god_power = 1.4 //Command staff has authority ignore_human_authority = TRUE diff --git a/code/modules/jobs/job_types/research_director.dm b/code/modules/jobs/job_types/research_director.dm index f2994388838..1142ba033ff 100644 --- a/code/modules/jobs/job_types/research_director.dm +++ b/code/modules/jobs/job_types/research_director.dm @@ -28,6 +28,7 @@ paycheck = PAYCHECK_COMMAND paycheck_department = ACCOUNT_SCI + mind_traits = list(HEAD_OF_STAFF_MIND_TRAITS) liver_traits = list(TRAIT_ROYAL_METABOLISM, TRAIT_BALLMER_SCIENTIST) display_order = JOB_DISPLAY_ORDER_RESEARCH_DIRECTOR @@ -41,7 +42,7 @@ family_heirlooms = list(/obj/item/toy/plush/slimeplushie) rpg_title = "Archmagister" - job_flags = STATION_JOB_FLAGS | JOB_BOLD_SELECT_TEXT | JOB_CANNOT_OPEN_SLOTS + job_flags = STATION_JOB_FLAGS | HEAD_OF_STAFF_JOB_FLAGS voice_of_god_power = 1.4 //Command staff has authority diff --git a/code/modules/jobs/job_types/personal_ai.dm b/code/modules/jobs/job_types/spawner/personal_ai.dm similarity index 100% rename from code/modules/jobs/job_types/personal_ai.dm rename to code/modules/jobs/job_types/spawner/personal_ai.dm diff --git a/code/modules/jobs/job_types/positronic_brain.dm b/code/modules/jobs/job_types/spawner/positronic_brain.dm similarity index 100% rename from code/modules/jobs/job_types/positronic_brain.dm rename to code/modules/jobs/job_types/spawner/positronic_brain.dm diff --git a/code/modules/jobs/job_types/servant_golem.dm b/code/modules/jobs/job_types/spawner/servant_golem.dm similarity index 100% rename from code/modules/jobs/job_types/servant_golem.dm rename to code/modules/jobs/job_types/spawner/servant_golem.dm diff --git a/code/modules/library/skill_learning/skillchip.dm b/code/modules/library/skill_learning/skillchip.dm index a58fbec7c75..2ef7a20e680 100644 --- a/code/modules/library/skill_learning/skillchip.dm +++ b/code/modules/library/skill_learning/skillchip.dm @@ -106,7 +106,7 @@ return "Skillchip is not active." // Should not happen. Holding brain is destroyed and the chip hasn't had its state set appropriately. - if(QDELETED(holding_brain)) + if(!holding_brain) stack_trace("Skillchip's owner is null or qdeleted brain.") return "Skillchip cannot detect viable brain." diff --git a/code/modules/mining/equipment/monster_organs/monster_organ.dm b/code/modules/mining/equipment/monster_organs/monster_organ.dm index 61d795c764a..d8e4bfae986 100644 --- a/code/modules/mining/equipment/monster_organs/monster_organ.dm +++ b/code/modules/mining/equipment/monster_organs/monster_organ.dm @@ -69,7 +69,7 @@ deltimer(decay_timer) return ..() -/obj/item/organ/internal/monster_core/Insert(mob/living/carbon/target_carbon, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/monster_core/Insert(mob/living/carbon/target_carbon, special = FALSE, movement_flags) . = ..() if(!.) return @@ -83,7 +83,7 @@ target_carbon.visible_message(span_notice("[src] stabilizes as it's inserted.")) return TRUE -/obj/item/organ/internal/monster_core/Remove(mob/living/carbon/target_carbon, special = 0) +/obj/item/organ/internal/monster_core/Remove(mob/living/carbon/target_carbon, special, movement_flags) if (!inert && !special) owner.visible_message(span_notice("[src] rapidly decays as it's removed.")) go_inert() diff --git a/code/modules/mining/equipment/monster_organs/rush_gland.dm b/code/modules/mining/equipment/monster_organs/rush_gland.dm index 3554d67b2a6..b3932afdaab 100644 --- a/code/modules/mining/equipment/monster_organs/rush_gland.dm +++ b/code/modules/mining/equipment/monster_organs/rush_gland.dm @@ -21,11 +21,11 @@ if (owner.health <= HEALTH_DANGER_ZONE) trigger_organ_action() -/obj/item/organ/internal/monster_core/rush_gland/on_insert(mob/living/carbon/organ_owner) +/obj/item/organ/internal/monster_core/rush_gland/on_mob_insert(mob/living/carbon/organ_owner) . = ..() RegisterSignal(organ_owner, COMSIG_GOLIATH_TENTACLED_GRABBED, PROC_REF(trigger_organ_action)) -/obj/item/organ/internal/monster_core/rush_gland/on_remove(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/monster_core/rush_gland/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() UnregisterSignal(organ_owner, COMSIG_GOLIATH_TENTACLED_GRABBED) diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 139218e4572..219d8e357e7 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -485,6 +485,19 @@ DEFAULT_QUEUE_OR_CALL_VERB(VERB_CALLBACK(src, PROC_REF(execute_quick_equip))) +/// Safely drop everything, without deconstructing the mob +/mob/proc/drop_everything(del_on_drop, force, del_if_nodrop) + . = list() + for(var/obj/item/item in src) + if(!dropItemToGround(item, force)) + if(del_if_nodrop && !(item.item_flags & ABSTRACT)) + qdel(item) + if(del_on_drop) + qdel(item) + //Anything thats not deleted and isn't in the mob, so everything that is succesfully dropped to the ground, is returned + if(!QDELETED(item) && !(item in src)) + . += item + ///proc extender of [/mob/verb/quick_equip] used to make the verb queuable if the server is overloaded /mob/proc/execute_quick_equip() var/obj/item/I = get_active_held_item() @@ -505,8 +518,6 @@ /mob/proc/getBeltSlot() return ITEM_SLOT_BELT - - //Inventory.dm is -kind of- an ok place for this I guess //This is NOT for dismemberment, as the user still technically has 2 "hands" diff --git a/code/modules/mob/living/basic/lavaland/legion/legion.dm b/code/modules/mob/living/basic/lavaland/legion/legion.dm index 080f397226e..3a18a0703e6 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion.dm @@ -83,7 +83,7 @@ return // Congratulations you have won a special prize: cancer var/obj/item/organ/internal/legion_tumour/cancer = new() - cancer.Insert(consumed, special = TRUE, drop_if_replaced = FALSE) + cancer.Insert(consumed, special = TRUE, movement_flags = DELETE_IF_REPLACED) /// A Legion which only drops skeletons instead of corpses which might have fun loot, so it cannot be farmed diff --git a/code/modules/mob/living/basic/lavaland/legion/legion_tumour.dm b/code/modules/mob/living/basic/lavaland/legion/legion_tumour.dm index 078af57de2a..55c1e6426b3 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion_tumour.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion_tumour.dm @@ -50,7 +50,7 @@ animate(transform = matrix(), time = 0.5 SECONDS / speed_divider, easing = SINE_EASING | EASE_IN) animate(transform = matrix(), time = 2 SECONDS / speed_divider) -/obj/item/organ/internal/legion_tumour/Remove(mob/living/carbon/egg_owner, special) +/obj/item/organ/internal/legion_tumour/Remove(mob/living/carbon/egg_owner, special, movement_flags) . = ..() stage = 0 elapsed_time = 0 diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_migration.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_migration.dm index c7bee5a36e9..27fdb25ee22 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_migration.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_migration.dm @@ -10,33 +10,30 @@ /datum/ai_planning_subtree/carp_migration /datum/ai_planning_subtree/carp_migration/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - . = ..() - // If there's a rift nearby take a ride, then cancel everything else because it's not valid any more - var/obj/effect/temp_visual/lesser_carp_rift/entrance/rift = locate(/obj/effect/temp_visual/lesser_carp_rift/entrance) in orange(controller.pawn, CARP_PORTAL_SEARCH_RANGE) - if (rift) + for(var/obj/effect/temp_visual/lesser_carp_rift/entrance/rift in orange(controller.pawn, CARP_PORTAL_SEARCH_RANGE)) controller.queue_behavior(/datum/ai_behavior/travel_towards_atom, get_turf(rift)) return SUBTREE_RETURN_FINISH_PLANNING - var/list/migration_points = controller.blackboard[BB_CARP_MIGRATION_PATH] - if (!length(migration_points)) - return - + // We have a destination, try to approach it var/turf/moving_to = controller.blackboard[BB_CARP_MIGRATION_TARGET] + if(!isnull(moving_to)) + var/turf/next_step = get_step_towards(controller.pawn, moving_to) + // Attempt to teleport around if we're blocked + if(next_step.is_blocked_turf(exclude_mobs = TRUE)) + controller.queue_behavior(/datum/ai_behavior/make_carp_rift/towards/unvalidated, BB_CARP_RIFT, BB_CARP_MIGRATION_TARGET) + controller.queue_behavior(/datum/ai_behavior/attack_obstructions/carp, BB_CARP_MIGRATION_TARGET) + controller.queue_behavior(/datum/ai_behavior/step_towards_turf, BB_CARP_MIGRATION_TARGET) + // We've gotten close enough to it, clear it so we can select a new point (or do nothing) + if(get_dist(controller.pawn, moving_to) <= CARP_DESTINATION_SEARCH_RANGE) + controller.clear_blackboard_key(BB_CARP_MIGRATION_TARGET) + return SUBTREE_RETURN_FINISH_PLANNING - // If we don't have a target or are close enough to it, pick a new one - if (isnull(moving_to) || get_dist(controller.pawn, moving_to) <= CARP_DESTINATION_SEARCH_RANGE) + // We have a path to follow but no destination, select one + if(length(controller.blackboard[BB_CARP_MIGRATION_PATH])) controller.queue_behavior(/datum/ai_behavior/find_next_carp_migration_step, BB_CARP_MIGRATION_PATH, BB_CARP_MIGRATION_TARGET) return SUBTREE_RETURN_FINISH_PLANNING - var/turf/next_step = get_step_towards(controller.pawn, moving_to) - if (next_step.is_blocked_turf(exclude_mobs = TRUE)) - controller.queue_behavior(/datum/ai_behavior/make_carp_rift/towards/unvalidated, BB_CARP_RIFT, BB_CARP_MIGRATION_TARGET) - controller.queue_behavior(/datum/ai_behavior/attack_obstructions/carp, BB_CARP_MIGRATION_TARGET) - controller.queue_behavior(/datum/ai_behavior/step_towards_turf, BB_CARP_MIGRATION_TARGET) - - return SUBTREE_RETURN_FINISH_PLANNING - /** * # Find next carp migration step * Records the next turf we want to travel to into the blackboard for other actions @@ -45,14 +42,13 @@ /datum/ai_behavior/find_next_carp_migration_step/perform(seconds_per_tick, datum/ai_controller/controller, path_key, target_key) var/list/blackboard_points = controller.blackboard[path_key] - var/list/potential_migration_points = blackboard_points.Copy() - while (length(potential_migration_points)) - var/turf/potential_destination = popleft(potential_migration_points) - if (!isnull(potential_destination) && get_dist(controller.pawn, potential_destination) > CARP_DESTINATION_SEARCH_RANGE) - controller.set_blackboard_key(target_key, potential_destination) + for(var/turf/migration_point as anything in blackboard_points) + // By the end of this loop we will either have a valid migration point set, or an empty list in our blackboard + blackboard_points -= migration_point + if(get_dist(controller.pawn, migration_point) > CARP_DESTINATION_SEARCH_RANGE) + controller.set_blackboard_key(target_key, migration_point) finish_action(controller, succeeded = TRUE) return - controller.set_blackboard_key(path_key, potential_migration_points.Copy()) finish_action(controller, succeeded = FALSE) diff --git a/code/modules/mob/living/basic/space_fauna/demon/demon_items.dm b/code/modules/mob/living/basic/space_fauna/demon/demon_items.dm index 8cdd7a6cf53..1cc7549f0ea 100644 --- a/code/modules/mob/living/basic/space_fauna/demon/demon_items.dm +++ b/code/modules/mob/living/basic/space_fauna/demon/demon_items.dm @@ -33,13 +33,13 @@ user.temporarilyRemoveItemFromInventory(src, TRUE) src.Insert(user) //Consuming the heart literally replaces your heart with a demon heart. H A R D C O R E -/obj/item/organ/internal/heart/demon/on_insert(mob/living/carbon/heart_owner) +/obj/item/organ/internal/heart/demon/on_mob_insert(mob/living/carbon/heart_owner) . = ..() // Gives a non-eat-people crawl to the new owner var/datum/action/cooldown/spell/jaunt/bloodcrawl/crawl = new(heart_owner) crawl.Grant(heart_owner) -/obj/item/organ/internal/heart/demon/on_remove(mob/living/carbon/heart_owner, special = FALSE) +/obj/item/organ/internal/heart/demon/on_mob_remove(mob/living/carbon/heart_owner, special = FALSE) . = ..() var/datum/action/cooldown/spell/jaunt/bloodcrawl/crawl = locate() in heart_owner.actions qdel(crawl) diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index bc0d2e3d8e8..0818532cc4d 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -286,7 +286,7 @@ return /datum/reagent/blood /mob/living/carbon/human/get_blood_id() - if(HAS_TRAIT(src, TRAIT_HUSK)) + if(HAS_TRAIT(src, TRAIT_HUSK) || !dna) return if(check_holidays(APRIL_FOOLS) && is_clown_job(mind?.assigned_role)) return /datum/reagent/colorful_reagent diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index ab870461965..a613e2ad839 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -46,7 +46,14 @@ // Brain size logic transform = transform.Scale(brain_size) -/obj/item/organ/internal/brain/Insert(mob/living/carbon/brain_owner, special = FALSE, drop_if_replaced = TRUE, no_id_transfer = FALSE) +/obj/item/organ/internal/brain/examine() + . = ..() + if(brain_size < 1) + . += span_notice("It is a bit on the smaller side...") + if(brain_size > 1) + . += span_notice("It is bigger than average...") + +/obj/item/organ/internal/brain/mob_insert(mob/living/carbon/brain_owner, special = FALSE, movement_flags) . = ..() if(!.) return @@ -54,7 +61,7 @@ name = initial(name) // Special check for if you're trapped in a body you can't control because it's owned by a ling. - if(brain_owner?.mind?.has_antag_datum(/datum/antagonist/changeling) && !no_id_transfer) + if(brain_owner?.mind?.has_antag_datum(/datum/antagonist/changeling) && !(movement_flags & NO_ID_TRANSFER)) if(brainmob && !(brain_owner.stat == DEAD || (HAS_TRAIT(brain_owner, TRAIT_DEATHCOMA)))) to_chat(brainmob, span_danger("You can't feel your body! You're still just a brain!")) forceMove(brain_owner) @@ -101,25 +108,11 @@ //Update the body's icon so it doesnt appear debrained anymore brain_owner.update_body_parts() -/obj/item/organ/internal/brain/on_insert(mob/living/carbon/organ_owner, special) - // Are we inserting into a new mob from a head? - // If yes, we want to quickly steal the brainmob from the head before we do anything else. - // This is usually stuff like reattaching dismembered/amputated heads. - if(istype(loc, /obj/item/bodypart/head)) - var/obj/item/bodypart/head/brain_holder = loc - if(brain_holder.brainmob) - brainmob = brain_holder.brainmob - brain_holder.brainmob = null - brainmob.container = null - brainmob.forceMove(src) - - return ..() - -/obj/item/organ/internal/brain/Remove(mob/living/carbon/brain_owner, special = 0, no_id_transfer = FALSE) +/obj/item/organ/internal/brain/mob_remove(mob/living/carbon/organ_owner, special, movement_flags) // Delete skillchips first as parent proc sets owner to null, and skillchips need to know the brain's owner. - if(!QDELETED(brain_owner) && length(skillchips)) + if(!QDELETED(organ_owner) && length(skillchips)) if(!special) - to_chat(brain_owner, span_notice("You feel your skillchips enable emergency power saving mode, deactivating as your brain leaves your body...")) + to_chat(organ_owner, span_notice("You feel your skillchips enable emergency power saving mode, deactivating as your brain leaves your body...")) for(var/chip in skillchips) var/obj/item/skillchip/skillchip = chip // Run the try_ proc with force = TRUE. @@ -132,10 +125,11 @@ BT.on_lose(TRUE) BT.owner = null - if((!gc_destroyed || (owner && !owner.gc_destroyed)) && !no_id_transfer) - transfer_identity(brain_owner) - brain_owner.update_body_parts() - brain_owner.clear_mood_event("brain_damage") + if((!gc_destroyed || (owner && !owner.gc_destroyed)) && !(movement_flags & NO_ID_TRANSFER)) + transfer_identity(organ_owner) + if(!special) + organ_owner.update_body_parts() + organ_owner.clear_mood_event("brain_damage") /obj/item/organ/internal/brain/proc/transfer_identity(mob/living/L) name = "[L.name]'s [initial(name)]" @@ -416,11 +410,11 @@ icon_state = "random_fly_4" organ_traits = list(TRAIT_ADVANCEDTOOLUSER, TRAIT_LITERATE, TRAIT_CAN_STRIP) -/obj/item/organ/internal/brain/lustrous/before_organ_replacement(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/brain/lustrous/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() organ_owner.cure_trauma_type(/datum/brain_trauma/special/bluespace_prophet, TRAUMA_RESILIENCE_ABSOLUTE) -/obj/item/organ/internal/brain/lustrous/on_insert(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/brain/lustrous/on_mob_insert(mob/living/carbon/organ_owner, special) . = ..() organ_owner.gain_trauma(/datum/brain_trauma/special/bluespace_prophet, TRAUMA_RESILIENCE_ABSOLUTE) @@ -579,6 +573,6 @@ /// Brains REALLY like ghosting people. we need special tricks to avoid that, namely removing the old brain with no_id_transfer /obj/item/organ/internal/brain/replace_into(mob/living/carbon/new_owner) var/obj/item/organ/internal/brain/old_brain = new_owner.get_organ_slot(ORGAN_SLOT_BRAIN) - old_brain.Remove(new_owner, special = TRUE, no_id_transfer = TRUE) + old_brain.Remove(new_owner, special = TRUE, movement_flags = NO_ID_TRANSFER) qdel(old_brain) - return Insert(new_owner, special = TRUE, drop_if_replaced = FALSE, no_id_transfer = TRUE) + return Insert(new_owner, special = TRUE, movement_flags = NO_ID_TRANSFER | DELETE_IF_REPLACED) diff --git a/code/modules/mob/living/carbon/alien/organs.dm b/code/modules/mob/living/carbon/alien/organs.dm index a29b126dd8d..66f555b639a 100644 --- a/code/modules/mob/living/carbon/alien/organs.dm +++ b/code/modules/mob/living/carbon/alien/organs.dm @@ -69,14 +69,14 @@ else owner.adjustPlasma(0.1 * plasma_rate * delta_time) -/obj/item/organ/internal/alien/plasmavessel/on_insert(mob/living/carbon/organ_owner) +/obj/item/organ/internal/alien/plasmavessel/on_mob_insert(mob/living/carbon/organ_owner) . = ..() if(isalien(organ_owner)) var/mob/living/carbon/alien/target_alien = organ_owner target_alien.updatePlasmaDisplay() RegisterSignal(organ_owner, COMSIG_MOB_GET_STATUS_TAB_ITEMS, PROC_REF(get_status_tab_item)) -/obj/item/organ/internal/alien/plasmavessel/on_remove(mob/living/carbon/organ_owner) +/obj/item/organ/internal/alien/plasmavessel/on_mob_remove(mob/living/carbon/organ_owner) . = ..() if(isalien(organ_owner)) var/mob/living/carbon/alien/organ_owner_alien = organ_owner @@ -95,18 +95,18 @@ zone = BODY_ZONE_HEAD slot = ORGAN_SLOT_XENO_HIVENODE w_class = WEIGHT_CLASS_TINY + organ_traits = list(TRAIT_XENO_IMMUNE) actions_types = list(/datum/action/cooldown/alien/whisper) /// Indicates if the queen died recently, aliens are heavily weakened while this is active. var/recent_queen_death = FALSE -/obj/item/organ/internal/alien/hivenode/on_insert(mob/living/carbon/organ_owner) +/obj/item/organ/internal/alien/hivenode/on_mob_insert(mob/living/carbon/organ_owner) . = ..() organ_owner.faction |= ROLE_ALIEN - ADD_TRAIT(organ_owner, TRAIT_XENO_IMMUNE, ORGAN_TRAIT) -/obj/item/organ/internal/alien/hivenode/Remove(mob/living/carbon/organ_owner, special = FALSE) - organ_owner.faction -= ROLE_ALIEN - REMOVE_TRAIT(organ_owner, TRAIT_XENO_IMMUNE, ORGAN_TRAIT) +/obj/item/organ/internal/alien/hivenode/on_mob_remove(mob/living/carbon/organ_owner, special = FALSE) + if(organ_owner) + organ_owner.faction -= ROLE_ALIEN return ..() //When the alien queen dies, all aliens suffer a penalty as punishment for failing to protect her. @@ -232,11 +232,11 @@ stomach_contents -= source UnregisterSignal(source, list(COMSIG_MOVABLE_MOVED, COMSIG_LIVING_DEATH, COMSIG_QDELETING)) -/obj/item/organ/internal/stomach/alien/Insert(mob/living/carbon/stomach_owner, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/stomach/alien/Insert(mob/living/carbon/stomach_owner, special, movement_flags) RegisterSignal(stomach_owner, COMSIG_ATOM_RELAYMOVE, PROC_REF(something_moved)) return ..() -/obj/item/organ/internal/stomach/alien/Remove(mob/living/carbon/stomach_owner, special = FALSE) +/obj/item/organ/internal/stomach/alien/Remove(mob/living/carbon/stomach_owner, special, movement_flags) UnregisterSignal(stomach_owner, COMSIG_ATOM_RELAYMOVE) return ..() diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index fb4828e457f..65a40a08805 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1007,7 +1007,6 @@ for(var/obj/item/bodypart/bodypart_path as anything in bodyparts_paths) var/real_body_part_path = overrides?[initial(bodypart_path.body_zone)] || bodypart_path var/obj/item/bodypart/bodypart_instance = new real_body_part_path() - bodypart_instance.set_owner(src) add_bodypart(bodypart_instance) /// Called when a new hand is added @@ -1024,8 +1023,12 @@ /mob/living/carbon/proc/add_bodypart(obj/item/bodypart/new_bodypart) SHOULD_NOT_OVERRIDE(TRUE) + new_bodypart.on_adding(src) bodyparts += new_bodypart - new_bodypart.set_owner(src) + new_bodypart.update_owner(src) + + for(var/obj/item/organ/organ in new_bodypart) + organ.mob_insert(src) switch(new_bodypart.body_part) if(LEG_LEFT, LEG_RIGHT) @@ -1040,10 +1043,17 @@ synchronize_bodytypes() ///Proc to hook behavior on bodypart removals. Do not directly call. You're looking for [/obj/item/bodypart/proc/drop_limb()]. -/mob/living/carbon/proc/remove_bodypart(obj/item/bodypart/old_bodypart) +/mob/living/carbon/proc/remove_bodypart(obj/item/bodypart/old_bodypart, special) SHOULD_NOT_OVERRIDE(TRUE) - old_bodypart.on_removal() + if(special) + for(var/obj/item/organ/organ in old_bodypart) + organ.bodypart_remove(limb_owner = src, movement_flags = NO_ID_TRANSFER) + else + for(var/obj/item/organ/organ in old_bodypart) + organ.mob_remove(src, special) + + old_bodypart.on_removal(src) bodyparts -= old_bodypart switch(old_bodypart.body_part) @@ -1449,3 +1459,8 @@ our_splatter.blood_dna_info = get_blood_dna_list() var/turf/targ = get_ranged_target_turf(src, splatter_direction, splatter_strength) our_splatter.fly_towards(targ, splatter_strength) + +/mob/living/carbon/dropItemToGround(obj/item/item, force = FALSE, silent = FALSE, invdrop = TRUE) + if(item && ((item in organs) || (item in bodyparts))) //let's not do this, aight? + return FALSE + return ..() diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index 78b8554361b..85a6b06a2d3 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -28,9 +28,9 @@ add_memory_in_range(src, 7, /datum/memory/witness_gib, protagonist = src) if(drop_bitflags & DROP_ITEMS) for(var/obj/item/W in src) - dropItemToGround(W) - if(prob(50)) - step(W, pick(GLOB.alldirs)) + if(dropItemToGround(W)) + if(prob(50)) + step(W, pick(GLOB.alldirs)) var/atom/Tsec = drop_location() for(var/mob/M in src) M.forceMove(Tsec) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 7c41119b0c2..0de67ef055d 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -375,19 +375,17 @@ GLOBAL_LIST_EMPTY(features_by_species) health_pct = (existing_organ.maxHealth - existing_organ.damage) / existing_organ.maxHealth if(slot == ORGAN_SLOT_BRAIN) var/obj/item/organ/internal/brain/existing_brain = existing_organ - if(!existing_brain.decoy_override) - existing_brain.before_organ_replacement(new_organ) - existing_brain.Remove(organ_holder, special = TRUE, no_id_transfer = TRUE) - QDEL_NULL(existing_organ) + existing_brain.before_organ_replacement(new_organ) + existing_brain.Remove(organ_holder, special = TRUE, movement_flags = NO_ID_TRANSFER) else existing_organ.before_organ_replacement(new_organ) existing_organ.Remove(organ_holder, special = TRUE) - QDEL_NULL(existing_organ) - if(isnull(existing_organ) && should_have && !(new_organ.zone in excluded_zones)) + QDEL_NULL(existing_organ) + if(isnull(existing_organ) && should_have && !(new_organ.zone in excluded_zones) && organ_holder.get_bodypart(deprecise_zone(new_organ.zone))) used_neworgan = TRUE new_organ.set_organ_damage(new_organ.maxHealth * (1 - health_pct)) - new_organ.Insert(organ_holder, special = TRUE, drop_if_replaced = FALSE) + new_organ.Insert(organ_holder, special = TRUE, movement_flags = DELETE_IF_REPLACED) if(!used_neworgan) QDEL_NULL(new_organ) @@ -430,7 +428,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(current_organ) current_organ.before_organ_replacement(replacement) // organ.Insert will qdel any current organs in that slot, so we don't need to. - replacement.Insert(organ_holder, special=TRUE, drop_if_replaced=FALSE) + replacement.Insert(organ_holder, special=TRUE, movement_flags = DELETE_IF_REPLACED) /datum/species/proc/worn_items_fit_body_check(mob/living/carbon/wearer) for(var/obj/item/equipped_item in wearer.get_all_worn_items()) @@ -497,7 +495,7 @@ GLOBAL_LIST_EMPTY(features_by_species) //Load a persons preferences from DNA var/obj/item/organ/external/new_organ = SSwardrobe.provide_type(organ_path) - new_organ.Insert(human, special=TRUE, drop_if_replaced=FALSE) + new_organ.Insert(human, special=TRUE, movement_flags = DELETE_IF_REPLACED) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index d2f3576b6a9..5dffbcd26c0 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -13,6 +13,7 @@ mob_biotypes = MOB_ORGANIC|MOB_HUMANOID can_be_shoved_into = TRUE initial_language_holder = /datum/language_holder/empty // We get stuff from our species + flags_1 = PREVENT_CONTENTS_EXPLOSION_1 maxHealth = HUMAN_MAXHEALTH //NOVA EDIT ADDITION health = HUMAN_MAXHEALTH //NOVA EDIT ADDITION diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm index 1db30b11dbe..2ec02dee2b4 100644 --- a/code/modules/mob/living/carbon/human/species_types/felinid.dm +++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm @@ -43,7 +43,7 @@ target_human.dna.features["ears"] = "Cat" if(target_human.dna.features["ears"] == "Cat") var/obj/item/organ/internal/ears/cat/ears = new - ears.Insert(target_human, drop_if_replaced = FALSE) + ears.Insert(target_human, movement_flags = DELETE_IF_REPLACED) else mutantears = /obj/item/organ/internal/ears return ..() @@ -95,8 +95,8 @@ // Humans get converted directly to felinids, and the key is handled in on_species_gain. // Now when we get mob.dna.features[feature_key], it returns None, which is why the tail is invisible. // stored_feature_id is only set once (the first time an organ is inserted), so this should be safe. - kitty_ears.Insert(soon_to_be_felinid, special = TRUE, drop_if_replaced = FALSE) - kitty_tail.Insert(soon_to_be_felinid, special = TRUE, drop_if_replaced = FALSE) + kitty_ears.Insert(soon_to_be_felinid, special = TRUE, movement_flags = DELETE_IF_REPLACED) + kitty_tail.Insert(soon_to_be_felinid, special = TRUE, movement_flags = DELETE_IF_REPLACED) if(!silent) to_chat(soon_to_be_felinid, span_boldnotice("Something is nya~t right.")) playsound(get_turf(soon_to_be_felinid), 'sound/effects/meow1.ogg', 50, TRUE, -1) @@ -119,16 +119,16 @@ for(var/external_organ in target_species.external_organs) if(ispath(external_organ, /obj/item/organ/external/tail)) var/obj/item/organ/external/tail/new_tail = new external_organ() - new_tail.Insert(purrbated_human, special = TRUE, drop_if_replaced = FALSE) + new_tail.Insert(purrbated_human, special = TRUE, movement_flags = DELETE_IF_REPLACED) // Don't forget the spines we removed earlier else if(ispath(external_organ, /obj/item/organ/external/spines)) var/obj/item/organ/external/spines/new_spines = new external_organ() - new_spines.Insert(purrbated_human, special = TRUE, drop_if_replaced = FALSE) + new_spines.Insert(purrbated_human, special = TRUE, movement_flags = DELETE_IF_REPLACED) var/obj/item/organ/internal/ears/old_ears = purrbated_human.get_organ_slot(ORGAN_SLOT_EARS) if(istype(old_ears, /obj/item/organ/internal/ears/cat)) var/obj/item/organ/new_ears = new target_species.mutantears() - new_ears.Insert(purrbated_human, special = TRUE, drop_if_replaced = FALSE) + new_ears.Insert(purrbated_human, special = TRUE, movement_flags = DELETE_IF_REPLACED) if(!silent) to_chat(purrbated_human, span_boldnotice("You are no longer a cat.")) diff --git a/code/modules/mob/living/carbon/human/species_types/monkeys.dm b/code/modules/mob/living/carbon/human/species_types/monkeys.dm index 00003a5240b..3c176ff4388 100644 --- a/code/modules/mob/living/carbon/human/species_types/monkeys.dm +++ b/code/modules/mob/living/carbon/human/species_types/monkeys.dm @@ -167,11 +167,11 @@ build_all_button_icons() -/obj/item/organ/internal/brain/primate/on_insert(mob/living/carbon/primate) +/obj/item/organ/internal/brain/primate/on_mob_insert(mob/living/carbon/primate) . = ..() RegisterSignal(primate, COMSIG_MOVABLE_CROSS, PROC_REF(on_crossed), TRUE) -/obj/item/organ/internal/brain/primate/on_remove(mob/living/carbon/primate) +/obj/item/organ/internal/brain/primate/on_mob_remove(mob/living/carbon/primate) . = ..() UnregisterSignal(primate, COMSIG_MOVABLE_CROSS) diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm index 6e56b13055b..427f1f5f71b 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -203,11 +203,11 @@ name = "vampire heart" color = "#1C1C1C" -/obj/item/organ/internal/heart/vampire/on_insert(mob/living/carbon/receiver) +/obj/item/organ/internal/heart/vampire/on_mob_insert(mob/living/carbon/receiver) . = ..() RegisterSignal(receiver, COMSIG_MOB_GET_STATUS_TAB_ITEMS, PROC_REF(get_status_tab_item)) -/obj/item/organ/internal/heart/vampire/on_remove(mob/living/carbon/heartless) +/obj/item/organ/internal/heart/vampire/on_mob_remove(mob/living/carbon/heartless) . = ..() UnregisterSignal(heartless, COMSIG_MOB_GET_STATUS_TAB_ITEMS) diff --git a/code/modules/mob/mob_lists.dm b/code/modules/mob/mob_lists.dm index 75904737c3f..9fd097a1fd6 100644 --- a/code/modules/mob/mob_lists.dm +++ b/code/modules/mob/mob_lists.dm @@ -53,8 +53,6 @@ GLOB.keyloop_list |= src else if(stat != DEAD || !SSlag_switch?.measures[DISABLE_DEAD_KEYLOOP]) GLOB.keyloop_list |= src - if(!SSticker.HasRoundStarted()) - return if(stat == DEAD) add_to_current_dead_players() else @@ -65,8 +63,6 @@ SHOULD_CALL_PARENT(TRUE) GLOB.player_list -= src GLOB.keyloop_list -= src - if(!SSticker.HasRoundStarted()) - return if(stat == DEAD) remove_from_current_dead_players() else @@ -75,13 +71,9 @@ ///Adds the cliented mob reference to either the list of dead player-mobs or to the list of observers, depending on how they joined the game. /mob/proc/add_to_current_dead_players() - if(!SSticker.HasRoundStarted()) - return GLOB.dead_player_list |= src /mob/dead/observer/add_to_current_dead_players() - if(!SSticker.HasRoundStarted()) - return if(started_as_observer) GLOB.current_observers_list |= src return @@ -92,13 +84,9 @@ ///Removes the mob reference from either the list of dead player-mobs or from the list of observers, depending on how they joined the game. /mob/proc/remove_from_current_dead_players() - if(!SSticker.HasRoundStarted()) - return GLOB.dead_player_list -= src /mob/dead/observer/remove_from_current_dead_players() - if(!SSticker.HasRoundStarted()) - return if(started_as_observer) GLOB.current_observers_list -= src return @@ -107,16 +95,12 @@ ///Adds the cliented mob reference to the list of living player-mobs. If the mob is an antag, it adds it to the list of living antag player-mobs. /mob/proc/add_to_current_living_players() - if(!SSticker.HasRoundStarted()) - return GLOB.alive_player_list |= src if(mind && (mind.special_role || length(mind.antag_datums))) add_to_current_living_antags() ///Removes the mob reference from the list of living player-mobs. If the mob is an antag, it removes it from the list of living antag player-mobs. /mob/proc/remove_from_current_living_players() - if(!SSticker.HasRoundStarted()) - return GLOB.alive_player_list -= src if(LAZYLEN(mind?.antag_datums)) remove_from_current_living_antags() @@ -124,9 +108,6 @@ ///Adds the cliented mob reference to the list of living antag player-mobs. /mob/proc/add_to_current_living_antags() - if(!SSticker.HasRoundStarted()) - return - if (length(mind.antag_datums) == 0) return @@ -137,6 +118,4 @@ ///Removes the mob reference from the list of living antag player-mobs. /mob/proc/remove_from_current_living_antags() - if(!SSticker.HasRoundStarted()) - return GLOB.current_living_antags -= src diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 068c6c98366..ca82e13e803 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -127,8 +127,6 @@ /mob/living/carbon/human/AIize(client/preference_source, transfer_after = TRUE) if(HAS_TRAIT(src, TRAIT_NO_TRANSFORM)) return - for(var/t in bodyparts) - qdel(t) return ..() @@ -173,11 +171,8 @@ ADD_TRAIT(src, TRAIT_NO_TRANSFORM, TEMPORARY_TRANSFORMATION_TRAIT) Paralyze(1, ignore_canstun = TRUE) - for(var/obj/item/W in src) - if(delete_items) - qdel(W) - else - dropItemToGround(W) + drop_everything(delete_items) + regenerate_icons() icon = null SetInvisibility(INVISIBILITY_MAXIMUM) diff --git a/code/modules/mob_spawn/corpses/mining_corpses.dm b/code/modules/mob_spawn/corpses/mining_corpses.dm index 8b7ad474b16..972bb5c3fa5 100644 --- a/code/modules/mob_spawn/corpses/mining_corpses.dm +++ b/code/modules/mob_spawn/corpses/mining_corpses.dm @@ -27,7 +27,7 @@ /obj/effect/mob_spawn/corpse/human/legioninfested/special(mob/living/carbon/human/spawned_human) . = ..() var/obj/item/organ/internal/legion_tumour/cancer = new() - cancer.Insert(spawned_human, special = TRUE, drop_if_replaced = FALSE) + cancer.Insert(spawned_human, special = TRUE, movement_flags = DELETE_IF_REPLACED) /// Returns the outfit worn by our corpse /obj/effect/mob_spawn/corpse/human/legioninfested/proc/select_outfit() diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index d4b4239b9cb..d240dd64c22 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -429,10 +429,9 @@ return TRUE /obj/item/gun/ballistic/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0) - if(magazine && chambered.loaded_projectile && can_misfire && misfire_probability > 0) - if(prob(misfire_probability)) - if(blow_up(user)) - to_chat(user, span_userdanger("[src] misfires!")) + if(target != user && chambered.loaded_projectile && can_misfire && prob(misfire_probability) && blow_up(user)) + to_chat(user, span_userdanger("[src] misfires!")) + return if (sawn_off) bonus_spread += SAWN_OFF_ACC_PENALTY @@ -700,11 +699,7 @@ GLOBAL_LIST_INIT(gun_saw_types, typecacheof(list( ///used for sawing guns, causes the gun to fire without the input of the user /obj/item/gun/ballistic/proc/blow_up(mob/user) - . = FALSE - for(var/obj/item/ammo_casing/AC in magazine.stored_ammo) - if(AC.loaded_projectile) - process_fire(user, user, FALSE) - . = TRUE + return chambered && process_fire(user, user, FALSE) /obj/item/gun/ballistic/proc/instant_reload() SIGNAL_HANDLER diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 4fd6e42d12f..ea069d51fc5 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -2849,7 +2849,7 @@ /datum/reagent/eldritch/on_mob_life(mob/living/carbon/drinker, seconds_per_tick, times_fired) . = ..() var/need_mob_update = FALSE - if(IS_HERETIC(drinker)) + if(IS_HERETIC_OR_MONSTER(drinker)) drinker.adjust_drowsiness(-10 * REM * seconds_per_tick) drinker.AdjustAllImmobility(-40 * REM * seconds_per_tick) need_mob_update += drinker.adjustStaminaLoss(-10 * REM * seconds_per_tick, updating_stamina = FALSE) diff --git a/code/modules/reagents/reagent_containers/cups/glassbottle.dm b/code/modules/reagents/reagent_containers/cups/glassbottle.dm index 76cae5ce1ad..83754dd571f 100644 --- a/code/modules/reagents/reagent_containers/cups/glassbottle.dm +++ b/code/modules/reagents/reagent_containers/cups/glassbottle.dm @@ -601,9 +601,11 @@ if(!do_after(user, 2 SECONDS, src)) //takes longer because you are supposed to take the foil off the bottle first return - ///The bonus to success chance that the user gets for being a command role - var/command_bonus = user.mind?.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND ? 20 : 0 - ///The bonus to success chance that the user gets for having a sabrage skillchip installed/otherwise having the trait through other means + //The bonus to success chance that the user gets for being a command role + var/obj/item/organ/internal/liver/liver = user.get_organ_slot(ORGAN_SLOT_LIVER) + var/command_bonus = (!isnull(liver) && HAS_TRAIT(liver, TRAIT_ROYAL_METABOLISM)) ? 20 : 0 + + //The bonus to success chance that the user gets for having a sabrage skillchip installed/otherwise having the trait through other means var/skillchip_bonus = HAS_TRAIT(user, TRAIT_SABRAGE_PRO) ? 35 : 0 //calculate success chance. example: captain's sabre - 15 force = 75% chance var/sabrage_chance = (attacking_item.force * sabrage_success_percentile) + command_bonus + skillchip_bonus diff --git a/code/modules/religion/burdened/psyker.dm b/code/modules/religion/burdened/psyker.dm index 5e9b0f0327b..f43e33aa25a 100644 --- a/code/modules/religion/burdened/psyker.dm +++ b/code/modules/religion/burdened/psyker.dm @@ -10,12 +10,12 @@ organ_traits = list(TRAIT_ADVANCEDTOOLUSER, TRAIT_LITERATE, TRAIT_CAN_STRIP, TRAIT_ANTIMAGIC_NO_SELFBLOCK) w_class = WEIGHT_CLASS_NORMAL -/obj/item/organ/internal/brain/psyker/on_insert(mob/living/carbon/inserted_into) +/obj/item/organ/internal/brain/psyker/on_mob_insert(mob/living/carbon/inserted_into) . = ..() inserted_into.AddComponent(/datum/component/echolocation, blocking_trait = TRAIT_DUMB, echo_group = "psyker", echo_icon = "psyker", color_path = /datum/client_colour/psyker) inserted_into.AddComponent(/datum/component/anti_magic, antimagic_flags = MAGIC_RESISTANCE_MIND) -/obj/item/organ/internal/brain/psyker/on_remove(mob/living/carbon/removed_from) +/obj/item/organ/internal/brain/psyker/on_mob_remove(mob/living/carbon/removed_from) . = ..() qdel(removed_from.GetComponent(/datum/component/echolocation)) qdel(removed_from.GetComponent(/datum/component/anti_magic)) @@ -82,9 +82,9 @@ qdel(old_head) var/obj/item/organ/internal/brain/psyker/psyker_brain = new() old_brain.before_organ_replacement(psyker_brain) - old_brain.Remove(src, special = TRUE, no_id_transfer = TRUE) + old_brain.Remove(src, special = TRUE, movement_flags = NO_ID_TRANSFER) qdel(old_brain) - psyker_brain.Insert(src, special = TRUE, drop_if_replaced = FALSE) + psyker_brain.Insert(src, special = TRUE, movement_flags = DELETE_IF_REPLACED) if(old_eyes) qdel(old_eyes) return TRUE diff --git a/code/modules/spells/spell_types/self/summonitem.dm b/code/modules/spells/spell_types/self/summonitem.dm index 62d6b078161..ab99f35271d 100644 --- a/code/modules/spells/spell_types/self/summonitem.dm +++ b/code/modules/spells/spell_types/self/summonitem.dm @@ -138,7 +138,6 @@ item_to_retrieve = null break - SEND_SIGNAL(holding_mark, COMSIG_MAGIC_RECALL, caster, item_to_retrieve) holding_mark.dropItemToGround(item_to_retrieve) else if(isobj(item_to_retrieve.loc)) @@ -157,15 +156,6 @@ infinite_recursion += 1 - else - // Organs are usually stored in nullspace - if(isorgan(item_to_retrieve)) - var/obj/item/organ/organ = item_to_retrieve - if(organ.owner) - // If this code ever runs I will be happy - log_combat(caster, organ.owner, "magically removed [organ.name] from", addition = "COMBAT MODE: [uppertext(caster.combat_mode)]") - organ.Remove(organ.owner) - if(!item_to_retrieve) return @@ -176,6 +166,8 @@ else item_to_retrieve.forceMove(caster.drop_location()) item_to_retrieve.loc.visible_message(span_warning("[item_to_retrieve] suddenly appears!")) + + SEND_SIGNAL(item_to_retrieve, COMSIG_MAGIC_RECALL, caster, item_to_retrieve) playsound(get_turf(item_to_retrieve), 'sound/magic/summonitems_generic.ogg', 50, TRUE) /datum/action/cooldown/spell/summonitem/abductor diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index fdeb50114a3..e51d083ddc4 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -6,6 +6,7 @@ w_class = WEIGHT_CLASS_SMALL icon = 'icons/mob/human/bodyparts.dmi' icon_state = "" //Leave this blank! Bodyparts are built using overlays + flags_1 = PREVENT_CONTENTS_EXPLOSION_1 //actually mindblowing /// The icon for Organic limbs using greyscale VAR_PROTECTED/icon_greyscale = DEFAULT_BODYPART_ICON_ORGANIC ///The icon for non-greyscale limbs @@ -19,7 +20,7 @@ layer = BELOW_MOB_LAYER //so it isn't hidden behind objects when on the floor grind_results = list(/datum/reagent/bone_dust = 10, /datum/reagent/consumable/liquidgibs = 5) // robotic bodyparts and chests/heads cannot be ground /// The mob that "owns" this limb - /// DO NOT MODIFY DIRECTLY. Use set_owner() + /// DO NOT MODIFY DIRECTLY. Use update_owner() var/mob/living/carbon/owner /// If this limb can be scarred. @@ -155,9 +156,6 @@ /// If something is currently grasping this bodypart and trying to staunch bleeding (see [/obj/item/hand_item/self_grasp]) var/obj/item/hand_item/self_grasp/grasped_by - ///A list of all the external organs we've got stored to draw horns, wings and stuff with (special because we are actually in the limbs unlike normal organs :/ ) - ///If someone ever comes around to making all organs exist in the bodyparts, you can just remove this and use a typed loop - var/list/obj/item/organ/external/external_organs = list() ///A list of all bodypart overlays to draw var/list/bodypart_overlays = list() @@ -232,31 +230,40 @@ refresh_bleed_rate() /obj/item/bodypart/Destroy() - if(owner) - owner.remove_bodypart(src) - set_owner(null) + if(owner && !QDELETED(owner)) + forced_removal(special = FALSE, dismembered = TRUE, move_to_floor = FALSE) + update_owner(null) for(var/wound in wounds) qdel(wound) // wounds is a lazylist, and each wound removes itself from it on deletion. if(length(wounds)) stack_trace("[type] qdeleted with [length(wounds)] uncleared wounds") wounds.Cut() - if(length(external_organs)) - for(var/obj/item/organ/external/external_organ as anything in external_organs) - external_organs -= external_organ - qdel(external_organ) // It handles removing its references to this limb on its own. + owner = null + + for(var/atom/movable/movable in contents) + qdel(movable) - external_organs = list() QDEL_LIST_ASSOC_VAL(feature_offsets) return ..() -/obj/item/bodypart/forceMove(atom/destination) //Please. Never forcemove a limb if its's actually in use. This is only for borgs. - SHOULD_CALL_PARENT(TRUE) +/obj/item/bodypart/ex_act(severity, target) + if(owner) //trust me bro you dont want this + return FALSE + return ..() - . = ..() - if(isturf(destination)) - update_icon_dropped() + +/obj/item/bodypart/proc/on_forced_removal(atom/old_loc, dir, forced, list/old_locs) + SIGNAL_HANDLER + + forced_removal(special = FALSE, dismembered = TRUE, move_to_floor = FALSE) + +/// In-case someone, somehow only teleports someones limb +/obj/item/bodypart/proc/forced_removal(special, dismembered, move_to_floor) + drop_limb(special, dismembered, move_to_floor) + + update_icon_dropped() /obj/item/bodypart/examine(mob/user) SHOULD_CALL_PARENT(TRUE) @@ -407,31 +414,24 @@ var/atom/drop_loc = drop_location() if(IS_ORGANIC_LIMB(src)) playsound(drop_loc, 'sound/misc/splort.ogg', 50, TRUE, -1) - QDEL_NULL(current_gauze) - for(var/obj/item/organ/bodypart_organ as anything in get_organs()) - bodypart_organ.transfer_to_limb(src, owner) - for(var/obj/item/organ/external/external as anything in external_organs) - external.remove_from_limb() - external.forceMove(drop_loc) - for(var/obj/item/item_in_bodypart in src) - item_in_bodypart.forceMove(drop_loc) - - update_icon_dropped() -///since organs aren't actually stored in the bodypart themselves while attached to a person, we have to query the owner for what we should have -/obj/item/bodypart/proc/get_organs() - SHOULD_CALL_PARENT(TRUE) - RETURN_TYPE(/list) + QDEL_NULL(current_gauze) - if(!owner) - return FALSE + for(var/obj/item/organ/bodypart_organ in contents) + if(bodypart_organ.organ_flags & ORGAN_UNREMOVABLE) + continue + if(owner) + bodypart_organ.Remove(bodypart_organ.owner) + else + if(bodypart_organ.bodypart_remove(src)) + if(drop_loc) //can be null if being deleted + bodypart_organ.forceMove(get_turf(drop_loc)) - var/list/bodypart_organs - for(var/obj/item/organ/organ_check as anything in owner.organs) //internal organs inside the dismembered limb are dropped. - if(check_zone(organ_check.zone) == body_zone) - LAZYADD(bodypart_organs, organ_check) // this way if we don't have any, it'll just return null + if(drop_loc) //can be null during deletion + for(var/atom/movable/movable as anything in src) + movable.forceMove(drop_loc) - return bodypart_organs + update_icon_dropped() //Return TRUE to get whatever mob this is in to update health. /obj/item/bodypart/proc/on_life(seconds_per_tick, times_fired) @@ -760,70 +760,91 @@ owner.update_health_hud() //update the healthdoll owner.update_body() -///Proc to change the value of the `owner` variable and react to the event of its change. -/obj/item/bodypart/proc/set_owner(new_owner) - SHOULD_CALL_PARENT(TRUE) +/// Proc to change the value of the `owner` variable and react to the event of its change. +/obj/item/bodypart/proc/update_owner(new_owner) + SHOULD_NOT_OVERRIDE(TRUE) + if(owner == new_owner) return FALSE //`null` is a valid option, so we need to use a num var to make it clear no change was made. - var/mob/living/carbon/old_owner = owner - owner = new_owner - SEND_SIGNAL(src, COMSIG_BODYPART_CHANGED_OWNER, new_owner, old_owner) - var/needs_update_disabled = FALSE //Only really relevant if there's an owner - if(old_owner) - if(held_index) - old_owner.on_lost_hand(src) - if(old_owner.hud_used) - var/atom/movable/screen/inventory/hand/hand = old_owner.hud_used.hand_slots["[held_index]"] - if(hand) - hand.update_appearance() - old_owner.update_worn_gloves() - if(speed_modifier) - old_owner.update_bodypart_speed_modifier() - if(length(bodypart_traits)) - old_owner.remove_traits(bodypart_traits, bodypart_trait_source) - if(initial(can_be_disabled)) - if(HAS_TRAIT(old_owner, TRAIT_NOLIMBDISABLE)) - if(!owner || !HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE)) - set_can_be_disabled(initial(can_be_disabled)) - needs_update_disabled = TRUE - UnregisterSignal(old_owner, list( - SIGNAL_REMOVETRAIT(TRAIT_NOLIMBDISABLE), - SIGNAL_ADDTRAIT(TRAIT_NOLIMBDISABLE), - SIGNAL_REMOVETRAIT(TRAIT_NOBLOOD), - SIGNAL_ADDTRAIT(TRAIT_NOBLOOD), - )) - UnregisterSignal(old_owner, COMSIG_ATOM_RESTYLE) - if(owner) - if(held_index) - owner.on_added_hand(src, held_index) - if(owner.hud_used) - var/atom/movable/screen/inventory/hand/hand = owner.hud_used.hand_slots["[held_index]"] - if(hand) - hand.update_appearance() - owner.update_worn_gloves() - if(speed_modifier) - owner.update_bodypart_speed_modifier() - if(length(bodypart_traits)) - owner.add_traits(bodypart_traits, bodypart_trait_source) - if(initial(can_be_disabled)) - if(HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE)) - set_can_be_disabled(FALSE) - needs_update_disabled = FALSE - RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_NOLIMBDISABLE), PROC_REF(on_owner_nolimbdisable_trait_loss)) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_NOLIMBDISABLE), PROC_REF(on_owner_nolimbdisable_trait_gain)) - // Bleeding stuff - RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_NOBLOOD), PROC_REF(on_owner_nobleed_loss)) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_NOBLOOD), PROC_REF(on_owner_nobleed_gain)) - - if(needs_update_disabled) - update_disabled() - RegisterSignal(owner, COMSIG_ATOM_RESTYLE, PROC_REF(on_attempt_feature_restyle_mob)) + SEND_SIGNAL(src, COMSIG_BODYPART_CHANGED_OWNER, new_owner, owner) + + if(owner) + . = owner //return value is old owner + clear_ownership(owner) + if(new_owner) + apply_ownership(new_owner) refresh_bleed_rate() - return old_owner + return . + +/// Run all necessary procs to remove a limbs ownership and remove the appropriate signals and traits +/obj/item/bodypart/proc/clear_ownership(mob/living/carbon/old_owner) + SHOULD_CALL_PARENT(TRUE) + + owner = null + + if(speed_modifier) + old_owner.update_bodypart_speed_modifier() + if(length(bodypart_traits)) + old_owner.remove_traits(bodypart_traits, bodypart_trait_source) + + UnregisterSignal(old_owner, list( + SIGNAL_REMOVETRAIT(TRAIT_NOLIMBDISABLE), + SIGNAL_ADDTRAIT(TRAIT_NOLIMBDISABLE), + SIGNAL_REMOVETRAIT(TRAIT_NOBLOOD), + SIGNAL_ADDTRAIT(TRAIT_NOBLOOD), + )) + + UnregisterSignal(old_owner, COMSIG_ATOM_RESTYLE) + +/// Apply ownership of a limb to someone, giving the appropriate traits, updates and signals +/obj/item/bodypart/proc/apply_ownership(mob/living/carbon/new_owner) + SHOULD_CALL_PARENT(TRUE) + + owner = new_owner + + if(speed_modifier) + owner.update_bodypart_speed_modifier() + if(length(bodypart_traits)) + owner.add_traits(bodypart_traits, bodypart_trait_source) + + if(initial(can_be_disabled)) + if(HAS_TRAIT(owner, TRAIT_NOLIMBDISABLE)) + set_can_be_disabled(FALSE) + + // Listen to disable traits being added + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_NOLIMBDISABLE), PROC_REF(on_owner_nolimbdisable_trait_loss)) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_NOLIMBDISABLE), PROC_REF(on_owner_nolimbdisable_trait_gain)) + + // Listen to no blood traits being added + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_NOBLOOD), PROC_REF(on_owner_nobleed_loss)) + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_NOBLOOD), PROC_REF(on_owner_nobleed_gain)) + + if(can_be_disabled) + update_disabled() + + RegisterSignal(owner, COMSIG_ATOM_RESTYLE, PROC_REF(on_attempt_feature_restyle_mob)) + + forceMove(owner) + RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(on_forced_removal)) //this must be set after we moved, or we insta gib + +/// Called on addition of a bodypart +/obj/item/bodypart/proc/on_adding(mob/living/carbon/new_owner) + SHOULD_CALL_PARENT(TRUE) + + item_flags |= ABSTRACT + ADD_TRAIT(src, TRAIT_NODROP, ORGAN_INSIDE_BODY_TRAIT) + +/// Called on removal of a bodypart. +/obj/item/bodypart/proc/on_removal(mob/living/carbon/old_owner) + SHOULD_CALL_PARENT(TRUE) + + UnregisterSignal(src, COMSIG_MOVABLE_MOVED) + + item_flags &= ~ABSTRACT + REMOVE_TRAIT(src, TRAIT_NODROP, ORGAN_INSIDE_BODY_TRAIT) -/obj/item/bodypart/proc/on_removal() if(!length(bodypart_traits)) return diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index 34afbd625a6..293db57a74f 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -67,7 +67,7 @@ if(wounding_type != WOUND_BURN && isturf(chest_owner.loc) && can_bleed()) chest_owner.add_splatter_floor(chest_owner.loc) playsound(get_turf(chest_owner), 'sound/misc/splort.ogg', 80, TRUE) - for(var/obj/item/organ/organ as anything in chest_owner.organs) + for(var/obj/item/organ/organ in contents) // NOVA EDIT START - Non-spillable organs if(!organ.drop_when_organ_spilling) continue @@ -79,21 +79,13 @@ organ.forceMove(chest_owner.loc) . += organ - for(var/obj/item/organ/external/ext_organ as anything in src.external_organs) - if(!(ext_organ.organ_flags & ORGAN_UNREMOVABLE)) - ext_organ.Remove(chest_owner) - ext_organ.forceMove(chest_owner.loc) - . += ext_organ - if(cavity_item) cavity_item.forceMove(chest_owner.loc) . += cavity_item cavity_item = null - return . - ///limb removal. The "special" argument is used for swapping a limb with a new one without the effects of losing a limb kicking in. -/obj/item/bodypart/proc/drop_limb(special, dismembered) +/obj/item/bodypart/proc/drop_limb(special, dismembered, move_to_floor = TRUE) if(!owner) return var/atom/drop_loc = owner.drop_location() @@ -102,16 +94,13 @@ SEND_SIGNAL(src, COMSIG_BODYPART_REMOVED, owner, special, dismembered) update_limb(dropping_limb = TRUE) bodypart_flags &= ~BODYPART_IMPLANTED //limb is out and about, it can't really be considered an implant - owner.remove_bodypart(src) + owner.remove_bodypart(src, special) for(var/datum/scar/scar as anything in scars) scar.victim = null LAZYREMOVE(owner.all_scars, scar) - for(var/obj/item/organ/external/ext_organ as anything in external_organs) - ext_organ.transfer_to_limb(src, null) //Null is the second arg because the bodypart is being removed from it's owner. - - var/mob/living/carbon/phantom_owner = set_owner(null) // so we can still refer to the guy who lost their limb after said limb forgets 'em + var/mob/living/carbon/phantom_owner = update_owner(null) // so we can still refer to the guy who lost their limb after said limb forgets 'em for(var/datum/wound/wound as anything in wounds) wound.remove_wound(TRUE) @@ -135,27 +124,22 @@ to_chat(phantom_owner, span_warning("You feel your [mutation] deactivating from the loss of your [body_zone]!")) phantom_owner.dna.force_lose(mutation) - for(var/obj/item/organ/organ as anything in phantom_owner.organs) //internal organs inside the dismembered limb are dropped. - var/org_zone = check_zone(organ.zone) - if(org_zone != body_zone) - continue - organ.transfer_to_limb(src, phantom_owner) - update_icon_dropped() phantom_owner.update_health_hud() //update the healthdoll phantom_owner.update_body() phantom_owner.update_body_parts() - if(!drop_loc) // drop_loc = null happens when a "dummy human" used for rendering icons on prefs screen gets its limbs replaced. - qdel(src) - return - if(bodypart_flags & BODYPART_PSEUDOPART) drop_organs(phantom_owner) //Psuedoparts shouldn't have organs, but just in case qdel(src) return - forceMove(drop_loc) + if(move_to_floor) + if(!drop_loc) // drop_loc = null happens when a "dummy human" used for rendering icons on prefs screen gets its limbs replaced. + qdel(src) + return + forceMove(drop_loc) + SEND_SIGNAL(phantom_owner, COMSIG_CARBON_POST_REMOVE_LIMB, src, special, dismembered) /** @@ -205,48 +189,53 @@ var/datum/wound/loss/dismembering = new return dismembering.apply_dismember(src, wounding_type) -///Transfers the organ to the limb, and to the limb's owner, if it has one. This is done on drop_limb(). -/obj/item/organ/proc/transfer_to_limb(obj/item/bodypart/bodypart, mob/living/carbon/bodypart_owner) - Remove(bodypart_owner) - add_to_limb(bodypart) - -///Adds the organ to a bodypart, used in transfer_to_limb() -/obj/item/organ/proc/add_to_limb(obj/item/bodypart/bodypart) - forceMove(bodypart) - -///Removes the organ from the limb, placing it into nullspace. -/obj/item/organ/proc/remove_from_limb() - moveToNullspace() - -/obj/item/organ/internal/brain/transfer_to_limb(obj/item/bodypart/head/head, mob/living/carbon/human/head_owner) - Remove(head_owner) //Changeling brain concerns are now handled in Remove - forceMove(head) - head.brain = src - if(brainmob) - head.brainmob = brainmob - brainmob = null - head.brainmob.forceMove(head) - head.brainmob.set_stat(DEAD) - -/obj/item/organ/internal/eyes/transfer_to_limb(obj/item/bodypart/head/head, mob/living/carbon/human/head_owner) - head.eyes = src - ..() - -/obj/item/organ/internal/ears/transfer_to_limb(obj/item/bodypart/head/head, mob/living/carbon/human/head_owner) - head.ears = src - ..() - -/obj/item/organ/internal/tongue/transfer_to_limb(obj/item/bodypart/head/head, mob/living/carbon/human/head_owner) - head.tongue = src - ..() - -/obj/item/bodypart/chest/drop_limb(special) +/obj/item/organ/internal/eyes/on_bodypart_insert(obj/item/bodypart/head/head) + if(istype(head)) + head.eyes = src + return ..() + +/obj/item/organ/internal/ears/on_bodypart_insert(obj/item/bodypart/head/head) + if(istype(head)) + head.ears = src + return ..() + +/obj/item/organ/internal/tongue/on_bodypart_insert(obj/item/bodypart/head/head) + if(istype(head)) + head.tongue = src + return ..() + +/obj/item/organ/internal/brain/on_bodypart_insert(obj/item/bodypart/head/head) + if(istype(head)) + head.brain = src + return ..() + +/obj/item/organ/internal/eyes/on_bodypart_remove(obj/item/bodypart/head/head) + if(istype(head)) + head.eyes = null + return ..() + +/obj/item/organ/internal/ears/on_bodypart_remove(obj/item/bodypart/head/head) + if(istype(head)) + head.ears = null + return ..() + +/obj/item/organ/internal/tongue/on_bodypart_remove(obj/item/bodypart/head/head) + if(istype(head)) + head.tongue = null + return ..() + +/obj/item/organ/internal/brain/on_bodypart_remove(obj/item/bodypart/head/head) + if(istype(head)) + head.brain = null + return ..() + +/obj/item/bodypart/chest/drop_limb(special, dismembered, move_to_floor = TRUE) if(special) return ..() //if this is not a special drop, this is a mistake return FALSE -/obj/item/bodypart/arm/drop_limb(special) +/obj/item/bodypart/arm/drop_limb(special, dismembered, move_to_floor = TRUE) var/mob/living/carbon/arm_owner = owner if(special || !arm_owner) @@ -269,7 +258,7 @@ arm_owner.update_worn_gloves() //to remove the bloody hands overlay return ..() -/obj/item/bodypart/leg/drop_limb(special) +/obj/item/bodypart/leg/drop_limb(special, dismembered, move_to_floor = TRUE) if(owner && !special) if(owner.legcuffed) owner.legcuffed.forceMove(owner.drop_location()) //At this point bodypart is still in nullspace @@ -280,7 +269,7 @@ owner.dropItemToGround(owner.shoes, TRUE) return ..() -/obj/item/bodypart/head/drop_limb(special) +/obj/item/bodypart/head/drop_limb(special, dismembered, move_to_floor = TRUE) if(!special) //Drop all worn head items for(var/obj/item/head_item as anything in list(owner.glasses, owner.ears, owner.wear_mask, owner.head)) @@ -336,8 +325,6 @@ SEND_SIGNAL(new_limb_owner, COMSIG_CARBON_ATTACH_LIMB, src, special) SEND_SIGNAL(src, COMSIG_BODYPART_ATTACHED, new_limb_owner, special) - moveToNullspace() - set_owner(new_limb_owner) new_limb_owner.add_bodypart(src) LAZYREMOVE(new_limb_owner.body_zone_dismembered_by, body_zone) @@ -350,8 +337,10 @@ qdel(attach_surgery) break - for(var/obj/item/organ/limb_organ in contents) - limb_organ.Insert(new_limb_owner, TRUE) + for(var/obj/item/organ/organ as anything in new_limb_owner.organs) + if(deprecise_zone(organ.zone) != body_zone) + continue + organ.bodypart_insert(src) for(var/datum/wound/wound as anything in wounds) // we have to remove the wound from the limb wound list first, so that we can reapply it fresh with the new person @@ -391,15 +380,6 @@ if(!.) return - if(brain) - brain = null - if(tongue) - tongue = null - if(ears) - ears = null - if(eyes) - eyes = null - if(old_real_name) new_head_owner.real_name = old_real_name real_name = new_head_owner.real_name diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index 8d4d48bfe6c..e6e805664d3 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -26,7 +26,6 @@ unarmed_effectiveness = 0 bodypart_trait_source = HEAD_TRAIT - var/mob/living/brain/brainmob //The current occupant. var/obj/item/organ/internal/brain/brain //The brain organ var/obj/item/organ/internal/eyes/eyes var/obj/item/organ/internal/ears/ears @@ -93,12 +92,6 @@ var/datum/worn_feature_offset/worn_face_offset /obj/item/bodypart/head/Destroy() - QDEL_NULL(brainmob) //order is sensitive, see warning in Exited() below - QDEL_NULL(brain) - QDEL_NULL(eyes) - QDEL_NULL(ears) - QDEL_NULL(tongue) - QDEL_NULL(worn_ears_offset) QDEL_NULL(worn_glasses_offset) QDEL_NULL(worn_mask_offset) @@ -110,11 +103,6 @@ if(gone == brain) brain = null update_icon_dropped() - if(!QDELETED(brainmob)) //this shouldn't happen without badminnery. - message_admins("Brainmob: ([ADMIN_LOOKUPFLW(brainmob)]) was left stranded in [src] at [ADMIN_VERBOSEJMP(src)] without a brain!") - brainmob.log_message(", brainmob, was left stranded in [src] without a brain", LOG_GAME) - if(gone == brainmob) - brainmob = null if(gone == eyes) eyes = null update_icon_dropped() @@ -129,12 +117,12 @@ if(show_organs_on_examine && IS_ORGANIC_LIMB(src)) if(!brain) . += span_info("The brain has been removed from [src].") - else if(brain.suicided || (brainmob && HAS_TRAIT(brainmob, TRAIT_SUICIDED))) + else if(brain.suicided || (brain.brainmob && HAS_TRAIT(brain.brainmob, TRAIT_SUICIDED))) . += span_info("There's a miserable expression on [real_name]'s face; they must have really hated life. There's no hope of recovery.") - else if(brainmob?.health <= HEALTH_THRESHOLD_DEAD) - . += span_info("It's leaking some kind of... clear fluid? The brain inside must be in pretty bad shape.") - else if(brainmob) - if(brainmob.key || brainmob.get_ghost(FALSE, TRUE)) + else if(brain.brainmob) + if(brain.brainmob?.health <= HEALTH_THRESHOLD_DEAD) + . += span_info("It's leaking some kind of... clear fluid? The brain inside must be in pretty bad shape.") + if(brain.brainmob.key || brain.brainmob.get_ghost(FALSE, TRUE)) . += span_info("Its muscles are twitching slightly... It seems to have some life still in it.") else . += span_info("It's completely lifeless. Perhaps there'll be a chance for them later.") @@ -158,33 +146,12 @@ return ..() /obj/item/bodypart/head/drop_organs(mob/user, violent_removal) - var/atom/drop_loc = drop_location() - for(var/obj/item/head_item in src) - if(head_item == brain) - if(user) - user.visible_message(span_warning("[user] saws [src] open and pulls out a brain!"), span_notice("You saw [src] open and pull out a brain.")) - if(brainmob) - brainmob.container = null - brain.brainmob = brainmob - brainmob = null - if(violent_removal && prob(rand(80, 100))) //ghetto surgery can damage the brain. - to_chat(user, span_warning("[brain] was damaged in the process!")) - brain.set_organ_damage(brain.maxHealth) - brain.forceMove(drop_loc) - brain = null - update_icon_dropped() - else - if(istype(head_item, /obj/item/reagent_containers/pill)) - for(var/datum/action/item_action/hands_free/activate_pill/pill_action in head_item.actions) - qdel(pill_action) - else if(isorgan(head_item)) - var/obj/item/organ/organ = head_item - if(organ.organ_flags & ORGAN_UNREMOVABLE) - continue - head_item.forceMove(drop_loc) - eyes = null - ears = null - tongue = null + if(user) + user.visible_message(span_warning("[user] saws [src] open and pulls out a brain!"), span_notice("You saw [src] open and pull out a brain.")) + if(brain && violent_removal && prob(90)) //ghetto surgery can damage the brain. + to_chat(user, span_warning("[brain] was damaged in the process!")) + brain.set_organ_damage(brain.maxHealth) + update_limb() return ..() diff --git a/code/modules/surgery/bodyparts/head_hair_and_lips.dm b/code/modules/surgery/bodyparts/head_hair_and_lips.dm index 15d4db296ee..4b23b9cc256 100644 --- a/code/modules/surgery/bodyparts/head_hair_and_lips.dm +++ b/code/modules/surgery/bodyparts/head_hair_and_lips.dm @@ -39,7 +39,7 @@ //HIDDEN CHECKS END if(owner) - if(!hair_hidden && !owner.get_organ_slot(ORGAN_SLOT_BRAIN) && !HAS_TRAIT(owner, TRAIT_NO_DEBRAIN_OVERLAY)) + if(!hair_hidden && !owner.get_organ_slot(ORGAN_SLOT_BRAIN) && !HAS_TRAIT(owner, TRAIT_NO_DEBRAIN_OVERLAY) && !istype(src, /obj/item/bodypart/head/robot/synth)) // NOVA EDIT CHANGE - ORIGINAL: if(!hair_hidden && !owner.get_organ_slot(ORGAN_SLOT_BRAIN) && !HAS_TRAIT(owner, TRAIT_NO_DEBRAIN_OVERLAY)) show_debrained = TRUE else show_debrained = FALSE @@ -49,7 +49,7 @@ else show_eyeless = FALSE else - if(!hair_hidden && !brain) + if(!hair_hidden && !brain && !istype(src, /obj/item/bodypart/head/robot/synth)) // NOVA EDIT CHANGE - ORIGINAL: if(!hair_hidden && !brain) show_debrained = TRUE else show_debrained = FALSE diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index c93fdf10b47..52671b5fbc1 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -15,6 +15,7 @@ /mob/living/carbon/proc/del_and_replace_bodypart(obj/item/bodypart/new_limb, special) var/obj/item/bodypart/old_limb = get_bodypart(new_limb.body_zone) if(old_limb) + old_limb.drop_limb(special = TRUE) qdel(old_limb) new_limb.try_attach_limb(src, special = special) @@ -172,7 +173,7 @@ /mob/living/carbon/proc/synchronize_bodytypes() var/all_limb_flags = NONE for(var/obj/item/bodypart/limb as anything in bodyparts) - for(var/obj/item/organ/external/ext_organ as anything in limb.external_organs) + for(var/obj/item/organ/external/ext_organ in limb) all_limb_flags |= ext_organ.external_bodytypes all_limb_flags |= limb.bodytype diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index 25f1ab985b6..c657e89cefd 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -35,8 +35,18 @@ /// Which functional (i.e. flightpotion) wing types (if any) does this bodypart support? If count is >1 a radial menu is used to choose between all icons in list var/list/wing_types = list(/obj/item/organ/external/wings/functional/angel) +/obj/item/bodypart/chest/forced_removal(dismembered, special, move_to_floor) + var/mob/living/carbon/old_owner = owner + ..(special = TRUE) //special because we're self destructing + + //If someones chest is teleported away, they die pretty hard + if(!old_owner) + return + message_admins("[ADMIN_LOOKUPFLW(old_owner)] was gibbed after their chest teleported to [ADMIN_VERBOSEJMP(loc)].") + old_owner.gib(DROP_ALL_REMAINS) + /obj/item/bodypart/chest/can_dismember(obj/item/item) - if(owner.stat < HARD_CRIT || !get_organs()) + if(owner.stat < HARD_CRIT || !contents.len) return FALSE return ..() @@ -127,6 +137,40 @@ QDEL_NULL(held_hand_offset) return ..() +/// We need to clear out hand hud items and appearance, so do that here +/obj/item/bodypart/arm/clear_ownership(mob/living/carbon/old_owner) + ..() + + old_owner.update_worn_gloves() + + if(!held_index) + return + + old_owner.on_lost_hand(src) + + if(!old_owner.hud_used) + return + + var/atom/movable/screen/inventory/hand/hand = old_owner.hud_used.hand_slots["[held_index]"] + hand?.update_appearance() + +/// We need to add hand hud items and appearance, so do that here +/obj/item/bodypart/arm/apply_ownership(mob/living/carbon/new_owner) + ..() + + new_owner.update_worn_gloves() + + if(!held_index) + return + + new_owner.on_added_hand(src, held_index) + + if(!new_owner.hud_used) + return + + var/atom/movable/screen/inventory/hand/hand = new_owner.hud_used.hand_slots["[held_index]"] + hand.update_appearance() + /obj/item/bodypart/arm/left name = "left arm" desc = "Did you know that the word 'sinister' stems originally from the \ @@ -143,27 +187,22 @@ px_y = 0 bodypart_trait_source = LEFT_ARM_TRAIT - -/obj/item/bodypart/arm/left/set_owner(new_owner) - . = ..() - if(. == FALSE) - return - if(owner) - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM)) - ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) - RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_loss)) - else - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_gain)) - if(.) - var/mob/living/carbon/old_owner = . - if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_L_ARM)) - UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM)) - if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM)) - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) - else - UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM)) - +/obj/item/bodypart/arm/left/apply_ownership(mob/living/carbon/new_owner) + if(HAS_TRAIT(new_owner, TRAIT_PARALYSIS_L_ARM)) + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) + RegisterSignal(new_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_loss)) + else + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) + RegisterSignal(new_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_gain)) + ..() + +/obj/item/bodypart/arm/left/clear_ownership(mob/living/carbon/old_owner) + if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_L_ARM)) + UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM)) + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_ARM) + else + UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM)) + ..() ///Proc to react to the owner gaining the TRAIT_PARALYSIS_L_ARM trait. /obj/item/bodypart/arm/left/proc/on_owner_paralysis_gain(mob/living/carbon/source) @@ -172,7 +211,6 @@ UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM)) RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_loss)) - ///Proc to react to the owner losing the TRAIT_PARALYSIS_L_ARM trait. /obj/item/bodypart/arm/left/proc/on_owner_paralysis_loss(mob/living/carbon/source) SIGNAL_HANDLER @@ -180,7 +218,6 @@ UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_ARM)) RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_ARM), PROC_REF(on_owner_paralysis_gain)) - /obj/item/bodypart/arm/left/set_disabled(new_disabled) . = ..() if(isnull(.) || !owner) @@ -200,7 +237,6 @@ var/atom/movable/screen/inventory/hand/hand_screen_object = owner.hud_used.hand_slots["[held_index]"] hand_screen_object?.update_appearance() - /obj/item/bodypart/arm/left/monkey icon = 'icons/mob/human/species/monkey/bodyparts.dmi' icon_static = 'icons/mob/human/species/monkey/bodyparts.dmi' @@ -233,7 +269,6 @@ should_draw_greyscale = FALSE appendage_noun = "scythe-like hand" - /obj/item/bodypart/arm/right name = "right arm" desc = "Over 87% of humans are right handed. That figure is much lower \ @@ -249,26 +284,22 @@ px_y = 0 bodypart_trait_source = RIGHT_ARM_TRAIT -/obj/item/bodypart/arm/right/set_owner(new_owner) - . = ..() - if(. == FALSE) - return - if(owner) - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM)) - ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) - RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_loss)) - else - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_gain)) - if(.) - var/mob/living/carbon/old_owner = . - if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_R_ARM)) - UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM)) - if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM)) - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) - else - UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM)) - +/obj/item/bodypart/arm/right/apply_ownership(mob/living/carbon/new_owner) + if(HAS_TRAIT(new_owner, TRAIT_PARALYSIS_R_ARM)) + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) + RegisterSignal(new_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_loss)) + else + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) + RegisterSignal(new_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_gain)) + ..() + +/obj/item/bodypart/arm/right/clear_ownership(mob/living/carbon/old_owner) + if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_R_ARM)) + UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM)) + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_ARM) + else + UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM)) + ..() ///Proc to react to the owner gaining the TRAIT_PARALYSIS_R_ARM trait. /obj/item/bodypart/arm/right/proc/on_owner_paralysis_gain(mob/living/carbon/source) @@ -277,7 +308,6 @@ UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM)) RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_loss)) - ///Proc to react to the owner losing the TRAIT_PARALYSIS_R_ARM trait. /obj/item/bodypart/arm/right/proc/on_owner_paralysis_loss(mob/living/carbon/source) SIGNAL_HANDLER @@ -285,7 +315,6 @@ UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_ARM)) RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_ARM), PROC_REF(on_owner_paralysis_gain)) - /obj/item/bodypart/arm/right/set_disabled(new_disabled) . = ..() if(isnull(.) || !owner) @@ -305,7 +334,6 @@ var/atom/movable/screen/inventory/hand/hand_screen_object = owner.hud_used.hand_slots["[held_index]"] hand_screen_object?.update_appearance() - /obj/item/bodypart/arm/right/monkey icon = 'icons/mob/human/species/monkey/bodyparts.dmi' icon_static = 'icons/mob/human/species/monkey/bodyparts.dmi' @@ -375,35 +403,30 @@ can_be_disabled = TRUE bodypart_trait_source = LEFT_LEG_TRAIT -/obj/item/bodypart/leg/left/set_owner(new_owner) - . = ..() - if(. == FALSE) - return - if(owner) - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG)) - ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) - RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG), PROC_REF(on_owner_paralysis_loss)) - else - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG), PROC_REF(on_owner_paralysis_gain)) - if(.) - var/mob/living/carbon/old_owner = . - if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_L_LEG)) - UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG)) - if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG)) - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) - else - UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG)) - - -///Proc to react to the owner gaining the TRAIT_PARALYSIS_L_LEG trait. +/obj/item/bodypart/leg/left/apply_ownership(mob/living/carbon/new_owner) + if(HAS_TRAIT(new_owner, TRAIT_PARALYSIS_L_LEG)) + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) + RegisterSignal(new_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG), PROC_REF(on_owner_paralysis_loss)) + else + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) + RegisterSignal(new_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG), PROC_REF(on_owner_paralysis_gain)) + ..() + +/obj/item/bodypart/leg/left/clear_ownership(mob/living/carbon/old_owner) + if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_L_LEG)) + UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG)) + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) + else + UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG)) + ..() + +///Proc to react to the owner gaining the TRAIT_PARALYSIS_L_ARM trait. /obj/item/bodypart/leg/left/proc/on_owner_paralysis_gain(mob/living/carbon/source) SIGNAL_HANDLER ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_L_LEG) UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG)) RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG), PROC_REF(on_owner_paralysis_loss)) - ///Proc to react to the owner losing the TRAIT_PARALYSIS_L_LEG trait. /obj/item/bodypart/leg/left/proc/on_owner_paralysis_loss(mob/living/carbon/source) SIGNAL_HANDLER @@ -411,7 +434,6 @@ UnregisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_L_LEG)) RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_L_LEG), PROC_REF(on_owner_paralysis_gain)) - /obj/item/bodypart/leg/left/set_disabled(new_disabled) . = ..() if(isnull(.) || !owner) @@ -469,26 +491,22 @@ px_y = 12 bodypart_trait_source = RIGHT_LEG_TRAIT -/obj/item/bodypart/leg/right/set_owner(new_owner) - . = ..() - if(. == FALSE) - return - if(owner) - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG)) - ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) - RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG), PROC_REF(on_owner_paralysis_loss)) - else - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) - RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG), PROC_REF(on_owner_paralysis_gain)) - if(.) - var/mob/living/carbon/old_owner = . - if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_R_LEG)) - UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG)) - if(!owner || !HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG)) - REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) - else - UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG)) - +/obj/item/bodypart/leg/right/apply_ownership(mob/living/carbon/new_owner) + if(HAS_TRAIT(new_owner, TRAIT_PARALYSIS_R_LEG)) + ADD_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) + RegisterSignal(new_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG), PROC_REF(on_owner_paralysis_loss)) + else + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) + RegisterSignal(new_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG), PROC_REF(on_owner_paralysis_gain)) + ..() + +/obj/item/bodypart/leg/right/clear_ownership(mob/living/carbon/old_owner) + if(HAS_TRAIT(old_owner, TRAIT_PARALYSIS_R_LEG)) + UnregisterSignal(old_owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG)) + REMOVE_TRAIT(src, TRAIT_PARALYSIS, TRAIT_PARALYSIS_R_LEG) + else + UnregisterSignal(old_owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG)) + ..() ///Proc to react to the owner gaining the TRAIT_PARALYSIS_R_LEG trait. /obj/item/bodypart/leg/right/proc/on_owner_paralysis_gain(mob/living/carbon/source) @@ -497,7 +515,6 @@ UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_PARALYSIS_R_LEG)) RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_PARALYSIS_R_LEG), PROC_REF(on_owner_paralysis_loss)) - ///Proc to react to the owner losing the TRAIT_PARALYSIS_R_LEG trait. /obj/item/bodypart/leg/right/proc/on_owner_paralysis_loss(mob/living/carbon/source) SIGNAL_HANDLER diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index 574ab49987b..7f514ecdaf4 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -518,17 +518,16 @@ ) return ..() -/obj/item/bodypart/arm/left/golem/set_owner(new_owner) +/obj/item/bodypart/arm/left/golem/clear_ownership(mob/living/carbon/old_owner) . = ..() - if (. == FALSE) - return - if (owner) - owner.AddComponentFrom(REF(src), /datum/component/shovel_hands) - if (isnull(.)) - return - var/mob/living/carbon/old_owner = . + old_owner.RemoveComponentSource(REF(src), /datum/component/shovel_hands) +/obj/item/bodypart/arm/left/golem/apply_ownership(mob/living/carbon/new_owner) + . = ..() + + new_owner.AddComponentFrom(REF(src), /datum/component/shovel_hands) + /obj/item/bodypart/arm/right/golem icon = 'icons/mob/human/species/golems.dmi' icon_static = 'icons/mob/human/species/golems.dmi' @@ -552,17 +551,16 @@ ) return ..() -/obj/item/bodypart/arm/right/golem/set_owner(new_owner) +/obj/item/bodypart/arm/right/golem/clear_ownership(mob/living/carbon/old_owner) . = ..() - if (. == FALSE) - return - if (owner) - owner.AddComponentFrom(REF(src), /datum/component/shovel_hands) - if (isnull(.)) - return - var/mob/living/carbon/old_owner = . + old_owner.RemoveComponentSource(REF(src), /datum/component/shovel_hands) +/obj/item/bodypart/arm/right/golem/apply_ownership(mob/living/carbon/new_owner) + . = ..() + + new_owner.AddComponentFrom(REF(src), /datum/component/shovel_hands) + /obj/item/bodypart/leg/left/golem icon = 'icons/mob/human/species/golems.dmi' icon_static = 'icons/mob/human/species/golems.dmi' diff --git a/code/modules/surgery/organs/_organ.dm b/code/modules/surgery/organs/_organ.dm index a3feba76fec..d7f08a7be35 100644 --- a/code/modules/surgery/organs/_organ.dm +++ b/code/modules/surgery/organs/_organ.dm @@ -6,6 +6,8 @@ throwforce = 0 /// The mob that owns this organ. var/mob/living/carbon/owner = null + /// Reference to the limb we're inside of + var/obj/item/bodypart/bodypart_owner /// The cached info about the blood this organ belongs to var/list/blood_dna_info = list("Synthetic DNA" = "O+") // not every organ spawns inside a person /// The body zone this organ is supposed to inhabit. @@ -77,134 +79,16 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) volume = reagent_vol,\ after_eat = CALLBACK(src, PROC_REF(OnEatFrom))) - if(!IS_ROBOTIC_ORGAN(src)) - add_blood_DNA(blood_dna_info) - -/* - * Insert the organ into the select mob. - * - * receiver - the mob who will get our organ - * special - "quick swapping" an organ out - when TRUE, the mob will be unaffected by not having that organ for the moment - * drop_if_replaced - if there's an organ in the slot already, whether we drop it afterwards - */ -/obj/item/organ/proc/Insert(mob/living/carbon/receiver, special = FALSE, drop_if_replaced = TRUE) - SHOULD_CALL_PARENT(TRUE) - - if(!iscarbon(receiver) || owner == receiver) - return FALSE - - var/obj/item/organ/replaced = receiver.get_organ_slot(slot) - if(replaced) - replaced.Remove(receiver, special = TRUE) - if(drop_if_replaced) - replaced.forceMove(get_turf(receiver)) - else - qdel(replaced) - - receiver.organs |= src - receiver.organs_slot[slot] = src - owner = receiver - - if(!IS_ROBOTIC_ORGAN(src) && (organ_flags & ORGAN_VIRGIN)) - blood_dna_info = receiver.get_blood_dna_list() - // need to remove the synethic blood DNA that is initialized - // wash also adds the blood dna again - wash(CLEAN_TYPE_BLOOD) - organ_flags &= ~ORGAN_VIRGIN - - - // Apply unique side-effects. Return value does not matter. - on_insert(receiver, special) - - return TRUE - -/// Called after the organ is inserted into a mob. -/// Adds Traits, Actions, and Status Effects on the mob in which the organ is impanted. -/// Override this proc to create unique side-effects for inserting your organ. Must be called by overrides. -/obj/item/organ/proc/on_insert(mob/living/carbon/organ_owner, special) - SHOULD_CALL_PARENT(TRUE) - - moveToNullspace() - - for(var/trait in organ_traits) - ADD_TRAIT(organ_owner, trait, REF(src)) - - for(var/datum/action/action as anything in actions) - action.Grant(organ_owner) - - for(var/datum/status_effect/effect as anything in organ_effects) - organ_owner.apply_status_effect(effect, type) - - RegisterSignal(owner, COMSIG_ATOM_EXAMINE, PROC_REF(on_owner_examine)) - SEND_SIGNAL(src, COMSIG_ORGAN_IMPLANTED, organ_owner) - SEND_SIGNAL(organ_owner, COMSIG_CARBON_GAIN_ORGAN, src, special) - -/* - * Remove the organ from the select mob. - * - * * organ_owner - the mob who owns our organ, that we're removing the organ from. - * * special - "quick swapping" an organ out - when TRUE, the mob will be unaffected by not having that organ for the moment - */ -/obj/item/organ/proc/Remove(mob/living/carbon/organ_owner, special = FALSE) - SHOULD_CALL_PARENT(TRUE) - - organ_owner.organs -= src - if(organ_owner.organs_slot[slot] == src) - organ_owner.organs_slot.Remove(slot) - - owner = null - - // Apply or reset unique side-effects. Return value does not matter. - on_remove(organ_owner, special) - - return TRUE - -/// Called after the organ is removed from a mob. -/// Removes Traits, Actions, and Status Effects on the mob in which the organ was impanted. -/// Override this proc to create unique side-effects for removing your organ. Must be called by overrides. -/obj/item/organ/proc/on_remove(mob/living/carbon/organ_owner, special) - SHOULD_CALL_PARENT(TRUE) - - if(!iscarbon(organ_owner)) - stack_trace("Organ removal should not be happening on non carbon mobs: [organ_owner]") - - for(var/trait in organ_traits) - REMOVE_TRAIT(organ_owner, trait, REF(src)) - - for(var/datum/action/action as anything in actions) - action.Remove(organ_owner) - - for(var/datum/status_effect/effect as anything in organ_effects) - organ_owner.remove_status_effect(effect, type) - - UnregisterSignal(organ_owner, COMSIG_ATOM_EXAMINE) - SEND_SIGNAL(src, COMSIG_ORGAN_REMOVED, organ_owner) - SEND_SIGNAL(organ_owner, COMSIG_CARBON_LOSE_ORGAN, src, special) - - // We don't need to readd things to the organ if it's getting deleted - if(QDELING(src)) - return - - if(!IS_ROBOTIC_ORGAN(src) && !(item_flags & NO_BLOOD_ON_ITEM)) - AddElement(/datum/element/decal/blood) - - var/list/diseases = organ_owner.get_static_viruses() - if(!LAZYLEN(diseases)) - return - - var/list/datum/disease/diseases_to_add = list() - for(var/datum/disease/disease as anything in diseases) - // robotic organs are immune to disease unless 'inorganic biology' symptom is present - if(IS_ROBOTIC_ORGAN(src) && !(disease.infectable_biotypes & MOB_ROBOTIC)) - continue - - // admin or special viruses that should not be reproduced - if(disease.spread_flags & (DISEASE_SPREAD_SPECIAL | DISEASE_SPREAD_NON_CONTAGIOUS)) - continue - - diseases_to_add += disease - if(LAZYLEN(diseases_to_add)) - AddComponent(/datum/component/infective, diseases_to_add) +/obj/item/organ/Destroy() + if(bodypart_owner && !owner && !QDELETED(bodypart_owner)) + bodypart_remove(bodypart_owner) + else if(owner) + // The special flag is important, because otherwise mobs can die + // while undergoing transformation into different mobs. + Remove(owner, special=TRUE) + else + STOP_PROCESSING(SSobj, src) + return ..() /// Add a Trait to an organ that it will give its owner. /obj/item/organ/proc/add_organ_trait(trait) @@ -241,15 +125,6 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) /obj/item/organ/proc/on_find(mob/living/finder) return -/** - * Proc that gets called when the organ is surgically removed by someone, can be used for special effects - * Currently only used so surplus organs can explode when surgically removed. - */ -/obj/item/organ/proc/on_surgical_removal(mob/living/user, mob/living/carbon/old_owner, target_zone, obj/item/tool) - SHOULD_CALL_PARENT(TRUE) - SEND_SIGNAL(src, COMSIG_ORGAN_SURGICALLY_REMOVED, user, old_owner, target_zone, tool) - RemoveElement(/datum/element/decal/blood) - /obj/item/organ/wash(clean_types) . = ..() @@ -452,4 +327,4 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) /// Tries to replace the existing organ on the passed mob with this one, with special handling for replacing a brain without ghosting target /obj/item/organ/proc/replace_into(mob/living/carbon/new_owner) - return Insert(new_owner, special = TRUE, drop_if_replaced = FALSE) + return Insert(new_owner, special = TRUE, movement_flags = DELETE_IF_REPLACED) diff --git a/code/modules/surgery/organs/external/_external_organ.dm b/code/modules/surgery/organs/external/_external_organ.dm index dcc713a0991..5b9f9d67347 100644 --- a/code/modules/surgery/organs/external/_external_organ.dm +++ b/code/modules/surgery/organs/external/_external_organ.dm @@ -12,8 +12,6 @@ ///The overlay datum that actually draws stuff on the limb var/datum/bodypart_overlay/mutant/bodypart_overlay - ///Reference to the limb we're inside of - var/obj/item/bodypart/ownerlimb ///If not null, overrides the appearance with this sprite accessory datum var/sprite_accessory_override @@ -25,7 +23,7 @@ ///Set to EXTERNAL_BEHIND, EXTERNAL_FRONT or EXTERNAL_ADJACENT if you want to draw one of those layers as the object sprite. FALSE to use your own ///This will not work if it doesn't have a limb to generate it's icon with var/use_mob_sprite_as_obj_sprite = FALSE - ///Does this organ have any bodytypes to pass to it's ownerlimb? + ///Does this organ have any bodytypes to pass to it's bodypart_owner? var/external_bodytypes = NONE ///Which flags does a 'modification tool' need to have to restyle us, if it all possible (located in code/_DEFINES/mobs) var/restyle_flags = NONE @@ -59,23 +57,10 @@ if(restyle_flags) RegisterSignal(src, COMSIG_ATOM_RESTYLE, PROC_REF(on_attempt_feature_restyle)) -/obj/item/organ/external/Destroy() - if(owner) - Remove(owner, special = TRUE) - else if(ownerlimb) - remove_from_limb() - - return ..() - -/obj/item/organ/external/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/external/mob_insert(mob/living/carbon/receiver, special, movement_flags) if(!should_external_organ_apply_to(type, receiver)) stack_trace("adding a [type] to a [receiver.type] when it shouldn't be!") - var/obj/item/bodypart/limb = receiver.get_bodypart(deprecise_zone(zone)) - - if(!limb) - return FALSE - . = ..() if(!.) @@ -91,54 +76,28 @@ // NOVA EDIT CHANGE END bodypart_overlay.imprint_on_next_insertion = FALSE - ownerlimb = limb - add_to_limb(ownerlimb) - if(external_bodytypes) receiver.synchronize_bodytypes() receiver.update_body_parts() -/obj/item/organ/external/Remove(mob/living/carbon/organ_owner, special, moving) - . = ..() - - if(ownerlimb) - remove_from_limb() - if(!moving && use_mob_sprite_as_obj_sprite) //so we're being taken out and dropped - update_appearance(UPDATE_OVERLAYS) - - if(organ_owner) +/obj/item/organ/external/mob_remove(mob/living/carbon/organ_owner, special, moving) + if(!special) + organ_owner.synchronize_bodytypes() organ_owner.update_body_parts() + return ..() +/obj/item/organ/external/on_bodypart_insert(obj/item/bodypart/bodypart) + bodypart.add_bodypart_overlay(bodypart_overlay) + return ..() -/obj/item/organ/external/on_remove(mob/living/carbon/organ_owner, special) - . = ..() - color = bodypart_overlay.draw_color // so a pink felinid doesn't drop a gray tail - -///Transfers the organ to the limb, and to the limb's owner, if it has one. -/obj/item/organ/external/transfer_to_limb(obj/item/bodypart/bodypart, mob/living/carbon/bodypart_owner) - if(owner) - Remove(owner, moving = TRUE) - else if(ownerlimb) - remove_from_limb() +/obj/item/organ/external/on_bodypart_remove(obj/item/bodypart/bodypart) + bodypart.remove_bodypart_overlay(bodypart_overlay) - if(bodypart_owner) - Insert(bodypart_owner, TRUE) - else - add_to_limb(bodypart) - -/obj/item/organ/external/add_to_limb(obj/item/bodypart/bodypart) - bodypart.external_organs += src - ownerlimb = bodypart - ownerlimb.add_bodypart_overlay(bodypart_overlay) - return ..() + if(use_mob_sprite_as_obj_sprite) + update_appearance(UPDATE_OVERLAYS) -/obj/item/organ/external/remove_from_limb() - ownerlimb.external_organs -= src - ownerlimb.remove_bodypart_overlay(bodypart_overlay) - if(ownerlimb.owner && external_bodytypes) - ownerlimb.owner.synchronize_bodytypes() - ownerlimb = null + color = bodypart_overlay.draw_color // so a pink felinid doesn't drop a gray tail return ..() /proc/should_external_organ_apply_to(obj/item/organ/external/organpath, mob/living/carbon/target) @@ -172,8 +131,8 @@ if(owner) //are we in a person? owner.update_body_parts() - else if(ownerlimb) //are we in a limb? - ownerlimb.update_icon_dropped() + else if(bodypart_owner) //are we in a limb? + bodypart_owner.update_icon_dropped() //else if(use_mob_sprite_as_obj_sprite) //are we out in the world, unprotected by flesh? /obj/item/organ/external/on_life(seconds_per_tick, times_fired) @@ -188,7 +147,7 @@ //Build the mob sprite and use it as our overlay for(var/external_layer in bodypart_overlay.all_layers) if(bodypart_overlay.layers & external_layer) - . += bodypart_overlay.get_overlay(external_layer, ownerlimb) + . += bodypart_overlay.get_overlay(external_layer, bodypart_owner) ///The horns of a lizard! /obj/item/organ/external/horns @@ -294,16 +253,17 @@ ///Store our old datum here for if our antennae are healed var/original_sprite_datum -/obj/item/organ/external/antennae/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/external/antennae/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() if(!.) return RegisterSignal(receiver, COMSIG_HUMAN_BURNING, PROC_REF(try_burn_antennae)) RegisterSignal(receiver, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(heal_antennae)) -/obj/item/organ/external/antennae/Remove(mob/living/carbon/organ_owner, special, moving) +/obj/item/organ/external/antennae/Remove(mob/living/carbon/organ_owner, special, movement_flags) . = ..() - UnregisterSignal(organ_owner, list(COMSIG_HUMAN_BURNING, COMSIG_LIVING_POST_FULLY_HEAL)) + if(organ_owner) + UnregisterSignal(organ_owner, list(COMSIG_HUMAN_BURNING, COMSIG_LIVING_POST_FULLY_HEAL)) ///check if our antennae can burn off ;_; /obj/item/organ/external/antennae/proc/try_burn_antennae(mob/living/carbon/human/human) diff --git a/code/modules/surgery/organs/external/restyling.dm b/code/modules/surgery/organs/external/restyling.dm index 454e4395ae6..7d6be1b6d58 100644 --- a/code/modules/surgery/organs/external/restyling.dm +++ b/code/modules/surgery/organs/external/restyling.dm @@ -31,7 +31,7 @@ ///Asks the external organs inside the limb if they can restyle /obj/item/bodypart/proc/attempt_feature_restyle(atom/source, mob/living/trimmer, atom/movable/original_target, body_zone, restyle_type, style_speed) var/list/valid_features = list() - for(var/obj/item/organ/external/feature in external_organs) + for(var/obj/item/organ/external/feature in contents) if(feature.restyle_flags & restyle_type) valid_features.Add(feature) diff --git a/code/modules/surgery/organs/external/spines.dm b/code/modules/surgery/organs/external/spines.dm index 600ed619e68..86bc8c800a1 100644 --- a/code/modules/surgery/organs/external/spines.dm +++ b/code/modules/surgery/organs/external/spines.dm @@ -16,13 +16,13 @@ ///A two-way reference between the tail and the spines because of wagging sprites. Bruh. var/obj/item/organ/external/tail/lizard/paired_tail -/obj/item/organ/external/spines/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/external/spines/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() if(.) paired_tail = locate(/obj/item/organ/external/tail/lizard) in receiver.organs //We want specifically a lizard tail, so we don't use the slot. paired_tail?.paired_spines = src -/obj/item/organ/external/spines/Remove(mob/living/carbon/organ_owner, special, moving) +/obj/item/organ/external/spines/Remove(mob/living/carbon/organ_owner, special, movement_flags) . = ..() if(paired_tail) paired_tail.paired_spines = null diff --git a/code/modules/surgery/organs/external/tails.dm b/code/modules/surgery/organs/external/tails.dm index a3105b81b4a..5c620eea161 100644 --- a/code/modules/surgery/organs/external/tails.dm +++ b/code/modules/surgery/organs/external/tails.dm @@ -18,7 +18,7 @@ ///The original owner of this tail var/original_owner //Yay, snowflake code! -/obj/item/organ/external/tail/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/external/tail/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() if(.) RegisterSignal(receiver, COMSIG_ORGAN_WAG_TAIL, PROC_REF(wag)) @@ -32,15 +32,12 @@ else if(type in receiver.dna.species.external_organs) receiver.add_mood_event("wrong_tail_regained", /datum/mood_event/tail_regained_wrong) -/obj/item/organ/external/tail/Remove(mob/living/carbon/organ_owner, special, moving) +/obj/item/organ/external/tail/on_mob_remove(mob/living/carbon/organ_owner, special) + . = ..() + if(wag_flags & WAG_WAGGING) wag(organ_owner, start = FALSE) - return ..() - -/obj/item/organ/external/tail/on_remove(mob/living/carbon/organ_owner, special) - . = ..() - UnregisterSignal(organ_owner, COMSIG_ORGAN_WAG_TAIL) if(type in organ_owner.dna.species.external_organs) @@ -141,13 +138,13 @@ ///A reference to the paired_spines, since for some fucking reason tail spines are tied to the spines themselves. var/obj/item/organ/external/spines/paired_spines -/obj/item/organ/external/tail/lizard/Insert(mob/living/carbon/reciever, special, drop_if_replaced) +/obj/item/organ/external/tail/lizard/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() if(.) - paired_spines = ownerlimb.owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_SPINES) + paired_spines = bodypart_owner.owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_SPINES) paired_spines?.paired_tail = src -/obj/item/organ/external/tail/lizard/Remove(mob/living/carbon/organ_owner, special, moving) +/obj/item/organ/external/tail/lizard/Remove(mob/living/carbon/organ_owner, special, movement_flags) . = ..() if(paired_spines) paired_spines.paired_tail = null diff --git a/code/modules/surgery/organs/external/wings/functional_wings.dm b/code/modules/surgery/organs/external/wings/functional_wings.dm index 58b9a709d87..d1f1eff6fc1 100644 --- a/code/modules/surgery/organs/external/wings/functional_wings.dm +++ b/code/modules/surgery/organs/external/wings/functional_wings.dm @@ -29,13 +29,13 @@ // grind_results = list(/datum/reagent/flightpotion = 5) food_reagents = list(/datum/reagent/flightpotion = 5) -/obj/item/organ/external/wings/functional/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/external/wings/functional/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() if(. && isnull(fly)) fly = new fly.Grant(receiver) -/obj/item/organ/external/wings/functional/Remove(mob/living/carbon/organ_owner, special, moving) +/obj/item/organ/external/wings/functional/Remove(mob/living/carbon/organ_owner, special, movement_flags) . = ..() fly.Remove(organ_owner) diff --git a/code/modules/surgery/organs/external/wings/moth_wings.dm b/code/modules/surgery/organs/external/wings/moth_wings.dm index 88c1d5670fb..db1a14ca05d 100644 --- a/code/modules/surgery/organs/external/wings/moth_wings.dm +++ b/code/modules/surgery/organs/external/wings/moth_wings.dm @@ -14,13 +14,13 @@ ///Store our old datum here for if our burned wings are healed var/original_sprite_datum -/obj/item/organ/external/wings/moth/on_insert(mob/living/carbon/receiver) +/obj/item/organ/external/wings/moth/on_mob_insert(mob/living/carbon/receiver) . = ..() RegisterSignal(receiver, COMSIG_HUMAN_BURNING, PROC_REF(try_burn_wings)) RegisterSignal(receiver, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(heal_wings)) RegisterSignal(receiver, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(update_float_move)) -/obj/item/organ/external/wings/moth/on_remove(mob/living/carbon/organ_owner) +/obj/item/organ/external/wings/moth/on_mob_remove(mob/living/carbon/organ_owner) . = ..() UnregisterSignal(organ_owner, list(COMSIG_HUMAN_BURNING, COMSIG_LIVING_POST_FULLY_HEAL, COMSIG_MOVABLE_PRE_MOVE)) REMOVE_TRAIT(organ_owner, TRAIT_FREE_FLOAT_MOVEMENT, REF(src)) diff --git a/code/modules/surgery/organs/internal/_internal_organ.dm b/code/modules/surgery/organs/internal/_internal_organ.dm index ecab1c93da9..9f67fb3d899 100644 --- a/code/modules/surgery/organs/internal/_internal_organ.dm +++ b/code/modules/surgery/organs/internal/_internal_organ.dm @@ -5,19 +5,8 @@ . = ..() START_PROCESSING(SSobj, src) -/obj/item/organ/internal/Destroy() - if(owner) - // The special flag is important, because otherwise mobs can die - // while undergoing transformation into different mobs. - Remove(owner, special=TRUE) - else - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/item/organ/internal/Insert(mob/living/carbon/receiver, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags) . = ..() - if(!. || !owner) - return // organs_slot must ALWAYS be ordered in the same way as organ_process_order // Otherwise life processing breaks down @@ -25,18 +14,16 @@ STOP_PROCESSING(SSobj, src) -/obj/item/organ/internal/Remove(mob/living/carbon/organ_owner, special = FALSE) +/obj/item/organ/internal/on_mob_remove(mob/living/carbon/organ_owner, special = FALSE) . = ..() - if(organ_owner) - if((organ_flags & ORGAN_VITAL) && !special && !(organ_owner.status_flags & GODMODE)) - if(organ_owner.stat != DEAD) - organ_owner.investigate_log("has been killed by losing a vital organ ([src]).", INVESTIGATE_DEATHS) - organ_owner.death() + if((organ_flags & ORGAN_VITAL) && !special && !(organ_owner.status_flags & GODMODE)) + if(organ_owner.stat != DEAD) + organ_owner.investigate_log("has been killed by losing a vital organ ([src]).", INVESTIGATE_DEATHS) + organ_owner.death() START_PROCESSING(SSobj, src) - /obj/item/organ/internal/process(seconds_per_tick, times_fired) on_death(seconds_per_tick, times_fired) //Kinda hate doing it like this, but I really don't want to call process directly. diff --git a/code/modules/surgery/organs/internal/appendix/_appendix.dm b/code/modules/surgery/organs/internal/appendix/_appendix.dm index ee87d674dc4..e5190f1282e 100644 --- a/code/modules/surgery/organs/internal/appendix/_appendix.dm +++ b/code/modules/surgery/organs/internal/appendix/_appendix.dm @@ -76,12 +76,12 @@ /obj/item/organ/internal/appendix/get_availability(datum/species/owner_species, mob/living/owner_mob) return owner_species.mutantappendix -/obj/item/organ/internal/appendix/on_remove(mob/living/carbon/organ_owner) +/obj/item/organ/internal/appendix/on_mob_remove(mob/living/carbon/organ_owner) . = ..() REMOVE_TRAIT(organ_owner, TRAIT_DISEASELIKE_SEVERITY_MEDIUM, type) organ_owner.med_hud_set_status() -/obj/item/organ/internal/appendix/on_insert(mob/living/carbon/organ_owner) +/obj/item/organ/internal/appendix/on_mob_insert(mob/living/carbon/organ_owner) . = ..() if(inflamation_stage) ADD_TRAIT(organ_owner, TRAIT_DISEASELIKE_SEVERITY_MEDIUM, type) diff --git a/code/modules/surgery/organs/internal/appendix/appendix_golem.dm b/code/modules/surgery/organs/internal/appendix/appendix_golem.dm index ede8dfa1e6b..5510b4bf967 100644 --- a/code/modules/surgery/organs/internal/appendix/appendix_golem.dm +++ b/code/modules/surgery/organs/internal/appendix/appendix_golem.dm @@ -12,7 +12,7 @@ . = ..() smelter = new(src) -/obj/item/organ/internal/appendix/golem/on_insert(mob/living/carbon/organ_owner) +/obj/item/organ/internal/appendix/golem/on_mob_insert(mob/living/carbon/organ_owner) . = ..() RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(check_for_lava)) @@ -25,7 +25,7 @@ if (smelter.owner != owner) smelter.Grant(owner) -/obj/item/organ/internal/appendix/golem/on_remove(mob/living/carbon/organ_owner) +/obj/item/organ/internal/appendix/golem/on_mob_remove(mob/living/carbon/organ_owner) UnregisterSignal(organ_owner, COMSIG_MOVABLE_MOVED) smelter?.Remove(organ_owner) // Might have been deleted by Destroy already return ..() diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm index 94a4aba90b3..463e34977ee 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm @@ -76,7 +76,7 @@ to_chat(user, span_notice("You modify [src] to be installed on the [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm.")) update_appearance() -/obj/item/organ/internal/cyberimp/arm/on_insert(mob/living/carbon/arm_owner) +/obj/item/organ/internal/cyberimp/arm/on_mob_insert(mob/living/carbon/arm_owner) . = ..() var/side = zone == BODY_ZONE_R_ARM? RIGHT_HANDS : LEFT_HANDS hand = arm_owner.hand_bodyparts[side] @@ -84,7 +84,7 @@ RegisterSignal(hand, COMSIG_ITEM_ATTACK_SELF, PROC_REF(on_item_attack_self)) //If the limb gets an attack-self, open the menu. Only happens when hand is empty RegisterSignal(arm_owner, COMSIG_KB_MOB_DROPITEM_DOWN, PROC_REF(dropkey)) //We're nodrop, but we'll watch for the drop hotkey anyway and then stow if possible. -/obj/item/organ/internal/cyberimp/arm/on_remove(mob/living/carbon/arm_owner) +/obj/item/organ/internal/cyberimp/arm/on_mob_remove(mob/living/carbon/arm_owner) . = ..() Retract() if(hand) @@ -379,14 +379,14 @@ ///How long will the implant malfunction if it is EMP'd var/emp_base_duration = 9 SECONDS -/obj/item/organ/internal/cyberimp/arm/muscle/Insert(mob/living/carbon/receiver, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/cyberimp/arm/muscle/on_mob_insert(mob/living/carbon/arm_owner) . = ..() - if(ishuman(receiver)) //Sorry, only humans - RegisterSignal(receiver, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand)) + if(ishuman(arm_owner)) //Sorry, only humans + RegisterSignal(arm_owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand)) -/obj/item/organ/internal/cyberimp/arm/muscle/Remove(mob/living/carbon/implant_owner, special = 0) +/obj/item/organ/internal/cyberimp/arm/muscle/on_mob_remove(mob/living/carbon/arm_owner) . = ..() - UnregisterSignal(implant_owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK) + UnregisterSignal(arm_owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK) /obj/item/organ/internal/cyberimp/arm/muscle/emp_act(severity) . = ..() diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm b/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm index d97df1d043b..513f0794c31 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm @@ -181,7 +181,7 @@ /datum/effect_system/trail_follow/ion \ ) -/obj/item/organ/internal/cyberimp/chest/thrusters/Remove(mob/living/carbon/thruster_owner, special = 0) +/obj/item/organ/internal/cyberimp/chest/thrusters/Remove(mob/living/carbon/thruster_owner, special, movement_flags) if(on) deactivate(silent = TRUE) ..() diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm b/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm index 869d4cc1c9e..cec0241ece3 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm @@ -31,7 +31,7 @@ hud.show_to(eye_owner) toggled_on = TRUE -/obj/item/organ/internal/cyberimp/eyes/hud/Insert(mob/living/carbon/eye_owner, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/cyberimp/eyes/hud/Insert(mob/living/carbon/eye_owner, special = FALSE, movement_flags) . = ..() if(!.) return @@ -42,7 +42,7 @@ ADD_TRAIT(eye_owner, HUD_trait, ORGAN_TRAIT) toggled_on = TRUE -/obj/item/organ/internal/cyberimp/eyes/hud/Remove(mob/living/carbon/eye_owner, special = FALSE) +/obj/item/organ/internal/cyberimp/eyes/hud/Remove(mob/living/carbon/eye_owner, special, movement_flags) . = ..() if(HUD_type) var/datum/atom_hud/hud = GLOB.huds[HUD_type] diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm index f0578832969..67a02e71d7e 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm @@ -87,7 +87,7 @@ stored_items = list() -/obj/item/organ/internal/cyberimp/brain/anti_drop/Remove(mob/living/carbon/implant_owner, special = 0) +/obj/item/organ/internal/cyberimp/brain/anti_drop/Remove(mob/living/carbon/implant_owner, special, movement_flags) if(active) ui_action_click() ..() @@ -113,11 +113,11 @@ var/stun_cap_amount = 40 -/obj/item/organ/internal/cyberimp/brain/anti_stun/on_remove(mob/living/carbon/implant_owner) +/obj/item/organ/internal/cyberimp/brain/anti_stun/on_mob_remove(mob/living/carbon/implant_owner) . = ..() UnregisterSignal(implant_owner, signalCache) -/obj/item/organ/internal/cyberimp/brain/anti_stun/on_insert(mob/living/carbon/receiver) +/obj/item/organ/internal/cyberimp/brain/anti_stun/on_mob_insert(mob/living/carbon/receiver) . = ..() RegisterSignals(receiver, signalCache, PROC_REF(on_signal)) diff --git a/code/modules/surgery/organs/internal/ears/_ears.dm b/code/modules/surgery/organs/internal/ears/_ears.dm index b864e0f5b67..d0255d5a060 100644 --- a/code/modules/surgery/organs/internal/ears/_ears.dm +++ b/code/modules/surgery/organs/internal/ears/_ears.dm @@ -70,7 +70,7 @@ //NOVA EDIT REMOVAL BEGIN - CUSTOMIZATION /* -/obj/item/organ/internal/ears/cat/on_insert(mob/living/carbon/human/ear_owner) +/obj/item/organ/internal/ears/cat/on_mob_insert(mob/living/carbon/human/ear_owner) . = ..() if(istype(ear_owner) && ear_owner.dna) color = ear_owner.hair_color @@ -78,7 +78,7 @@ ear_owner.dna.update_uf_block(DNA_EARS_BLOCK) ear_owner.update_body() -/obj/item/organ/internal/ears/cat/on_remove(mob/living/carbon/human/ear_owner) +/obj/item/organ/internal/ears/cat/on_mob_remove(mob/living/carbon/human/ear_owner) . = ..() if(istype(ear_owner) && ear_owner.dna) color = ear_owner.hair_color @@ -91,13 +91,13 @@ name = "penguin ears" desc = "The source of a penguin's happy feet." -/obj/item/organ/internal/ears/penguin/on_insert(mob/living/carbon/human/ear_owner) +/obj/item/organ/internal/ears/penguin/on_mob_insert(mob/living/carbon/human/ear_owner) . = ..() if(istype(ear_owner)) to_chat(ear_owner, span_notice("You suddenly feel like you've lost your balance.")) ear_owner.AddElement(/datum/element/waddling) -/obj/item/organ/internal/ears/penguin/on_remove(mob/living/carbon/human/ear_owner) +/obj/item/organ/internal/ears/penguin/on_mob_remove(mob/living/carbon/human/ear_owner) . = ..() if(istype(ear_owner)) to_chat(ear_owner, span_notice("Your sense of balance comes back to you.")) @@ -126,11 +126,11 @@ // The original idea was to use signals to do this not traits. Unfortunately, the star effect used for whispers applies before any relevant signals // This seems like the least invasive solution -/obj/item/organ/internal/ears/cybernetic/whisper/on_insert(mob/living/carbon/ear_owner) +/obj/item/organ/internal/ears/cybernetic/whisper/on_mob_insert(mob/living/carbon/ear_owner) . = ..() ADD_TRAIT(ear_owner, TRAIT_GOOD_HEARING, ORGAN_TRAIT) -/obj/item/organ/internal/ears/cybernetic/whisper/on_remove(mob/living/carbon/ear_owner) +/obj/item/organ/internal/ears/cybernetic/whisper/on_mob_remove(mob/living/carbon/ear_owner) . = ..() REMOVE_TRAIT(ear_owner, TRAIT_GOOD_HEARING, ORGAN_TRAIT) @@ -142,11 +142,11 @@ // Same sensitivity as felinid ears damage_multiplier = 2 -/obj/item/organ/internal/ears/cybernetic/xray/on_insert(mob/living/carbon/ear_owner) +/obj/item/organ/internal/ears/cybernetic/xray/on_mob_insert(mob/living/carbon/ear_owner) . = ..() ADD_TRAIT(ear_owner, TRAIT_XRAY_HEARING, ORGAN_TRAIT) -/obj/item/organ/internal/ears/cybernetic/xray/on_remove(mob/living/carbon/ear_owner) +/obj/item/organ/internal/ears/cybernetic/xray/on_mob_remove(mob/living/carbon/ear_owner) . = ..() REMOVE_TRAIT(ear_owner, TRAIT_XRAY_HEARING, ORGAN_TRAIT) diff --git a/code/modules/surgery/organs/internal/eyes/_eyes.dm b/code/modules/surgery/organs/internal/eyes/_eyes.dm index f8b3286ff22..e52b772479e 100644 --- a/code/modules/surgery/organs/internal/eyes/_eyes.dm +++ b/code/modules/surgery/organs/internal/eyes/_eyes.dm @@ -52,7 +52,7 @@ /// Native FOV that will be applied if a config is enabled var/native_fov = NONE //NOVA EDIT CHANGE - ORIGINAL: var/native_fov = FOV_90_DEGREES -/obj/item/organ/internal/eyes/Insert(mob/living/carbon/eye_recipient, special = FALSE, drop_if_replaced = FALSE) +/obj/item/organ/internal/eyes/Insert(mob/living/carbon/eye_recipient, special = FALSE, movement_flags = DELETE_IF_REPLACED) // If we don't do this before everything else, heterochromia will be reset leading to eye_color_right no longer being accurate if(ishuman(eye_recipient)) var/mob/living/carbon/human/human_recipient = eye_recipient @@ -99,7 +99,7 @@ if(call_update) affected_human.update_body() -/obj/item/organ/internal/eyes/Remove(mob/living/carbon/eye_owner, special = FALSE) +/obj/item/organ/internal/eyes/Remove(mob/living/carbon/eye_owner, special, movement_flags) . = ..() if(ishuman(eye_owner)) var/mob/living/carbon/human/human_owner = eye_owner @@ -109,7 +109,8 @@ human_owner.eye_color_right = old_eye_color_right if(native_fov) eye_owner.remove_fov_trait(type) - human_owner.update_body() + if(!special) + human_owner.update_body() // Cure blindness from eye damage eye_owner.cure_blind(EYE_DAMAGE) @@ -353,11 +354,11 @@ eye_color_right = "000" sight_flags = SEE_MOBS | SEE_OBJS | SEE_TURFS -/obj/item/organ/internal/eyes/robotic/xray/on_insert(mob/living/carbon/eye_owner) +/obj/item/organ/internal/eyes/robotic/xray/on_mob_insert(mob/living/carbon/eye_owner) . = ..() ADD_TRAIT(eye_owner, TRAIT_XRAY_VISION, ORGAN_TRAIT) -/obj/item/organ/internal/eyes/robotic/xray/on_remove(mob/living/carbon/eye_owner) +/obj/item/organ/internal/eyes/robotic/xray/on_mob_remove(mob/living/carbon/eye_owner) . = ..() REMOVE_TRAIT(eye_owner, TRAIT_XRAY_VISION, ORGAN_TRAIT) @@ -385,7 +386,7 @@ /obj/item/organ/internal/eyes/robotic/flashlight/emp_act(severity) return -/obj/item/organ/internal/eyes/robotic/flashlight/on_insert(mob/living/carbon/victim) +/obj/item/organ/internal/eyes/robotic/flashlight/on_mob_insert(mob/living/carbon/victim) . = ..() if(!eye) eye = new /obj/item/flashlight/eyelight() @@ -394,7 +395,7 @@ eye.update_brightness(victim) victim.become_blind(FLASHLIGHT_EYES) -/obj/item/organ/internal/eyes/robotic/flashlight/on_remove(mob/living/carbon/victim) +/obj/item/organ/internal/eyes/robotic/flashlight/on_mob_remove(mob/living/carbon/victim) . = ..() eye.set_light_on(FALSE) eye.update_brightness(victim) @@ -451,18 +452,18 @@ deactivate(close_ui = TRUE) /// Set the initial color of the eyes on insert to be the mob's previous eye color. -/obj/item/organ/internal/eyes/robotic/glow/Insert(mob/living/carbon/eye_recipient, special = FALSE, drop_if_replaced = FALSE) +/obj/item/organ/internal/eyes/robotic/glow/Insert(mob/living/carbon/eye_recipient, special = FALSE, movement_flags = DELETE_IF_REPLACED) . = ..() left_eye_color_string = old_eye_color_left right_eye_color_string = old_eye_color_right update_mob_eye_color(eye_recipient) -/obj/item/organ/internal/eyes/robotic/glow/on_insert(mob/living/carbon/eye_recipient) +/obj/item/organ/internal/eyes/robotic/glow/on_mob_insert(mob/living/carbon/eye_recipient) . = ..() deactivate(close_ui = TRUE) eye.forceMove(eye_recipient) -/obj/item/organ/internal/eyes/robotic/glow/on_remove(mob/living/carbon/eye_owner) +/obj/item/organ/internal/eyes/robotic/glow/on_mob_remove(mob/living/carbon/eye_owner) deactivate(eye_owner, close_ui = TRUE) if(!QDELETED(eye)) eye.forceMove(src) @@ -750,7 +751,7 @@ high_light_cutoff = list(30, 35, 50) var/obj/item/flashlight/eyelight/adapted/adapt_light -/obj/item/organ/internal/eyes/night_vision/maintenance_adapted/on_insert(mob/living/carbon/eye_owner) +/obj/item/organ/internal/eyes/night_vision/maintenance_adapted/on_mob_insert(mob/living/carbon/eye_owner) . = ..() //add lighting if(!adapt_light) @@ -769,7 +770,7 @@ apply_organ_damage(-10) //heal quickly . = ..() -/obj/item/organ/internal/eyes/night_vision/maintenance_adapted/Remove(mob/living/carbon/unadapted, special = FALSE) +/obj/item/organ/internal/eyes/night_vision/maintenance_adapted/on_mob_remove(mob/living/carbon/unadapted, special = FALSE) //remove lighting adapt_light.set_light_on(FALSE) adapt_light.update_brightness(unadapted) diff --git a/code/modules/surgery/organs/internal/heart/_heart.dm b/code/modules/surgery/organs/internal/heart/_heart.dm index 1d3da14fa00..2773f588b24 100644 --- a/code/modules/surgery/organs/internal/heart/_heart.dm +++ b/code/modules/surgery/organs/internal/heart/_heart.dm @@ -33,7 +33,7 @@ . = ..() icon_state = "[base_icon_state]-[beating ? "on" : "off"]" -/obj/item/organ/internal/heart/Remove(mob/living/carbon/heartless, special = 0) +/obj/item/organ/internal/heart/Remove(mob/living/carbon/heartless, special, movement_flags) . = ..() if(!special) addtimer(CALLBACK(src, PROC_REF(stop_if_unowned)), 12 SECONDS) @@ -146,12 +146,14 @@ else return ..() -/obj/item/organ/internal/heart/cursed/on_insert(mob/living/carbon/accursed) +/obj/item/organ/internal/heart/cursed/on_mob_insert(mob/living/carbon/accursed) . = ..() + accursed.AddComponent(/datum/component/manual_heart, pump_delay = pump_delay, blood_loss = blood_loss, heal_brute = heal_brute, heal_burn = heal_burn, heal_oxy = heal_oxy) -/obj/item/organ/internal/heart/cursed/Remove(mob/living/carbon/accursed, special = FALSE) +/obj/item/organ/internal/heart/cursed/on_mob_remove(mob/living/carbon/accursed, special = FALSE) . = ..() + qdel(accursed.GetComponent(/datum/component/manual_heart)) /obj/item/organ/internal/heart/cybernetic diff --git a/code/modules/surgery/organs/internal/heart/heart_ethereal.dm b/code/modules/surgery/organs/internal/heart/heart_ethereal.dm index 78ee55b0b28..50659115872 100644 --- a/code/modules/surgery/organs/internal/heart/heart_ethereal.dm +++ b/code/modules/surgery/organs/internal/heart/heart_ethereal.dm @@ -21,7 +21,7 @@ add_atom_colour(ethereal_color, FIXED_COLOUR_PRIORITY) update_appearance() -/obj/item/organ/internal/heart/ethereal/Insert(mob/living/carbon/heart_owner, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/heart/ethereal/Insert(mob/living/carbon/heart_owner, special = FALSE, movement_flags) . = ..() if(!.) return @@ -29,7 +29,7 @@ RegisterSignal(heart_owner, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(on_owner_fully_heal)) RegisterSignal(heart_owner, COMSIG_QDELETING, PROC_REF(owner_deleted)) -/obj/item/organ/internal/heart/ethereal/Remove(mob/living/carbon/heart_owner, special = FALSE) +/obj/item/organ/internal/heart/ethereal/Remove(mob/living/carbon/heart_owner, special, movement_flags) UnregisterSignal(heart_owner, list(COMSIG_MOB_STATCHANGE, COMSIG_LIVING_POST_FULLY_HEAL, COMSIG_QDELETING)) REMOVE_TRAIT(heart_owner, TRAIT_CORPSELOCKED, SPECIES_TRAIT) stop_crystalization_process(heart_owner) diff --git a/code/modules/surgery/organs/internal/liver/_liver.dm b/code/modules/surgery/organs/internal/liver/_liver.dm index c8515582ac1..d1d0df8f362 100644 --- a/code/modules/surgery/organs/internal/liver/_liver.dm +++ b/code/modules/surgery/organs/internal/liver/_liver.dm @@ -61,12 +61,12 @@ qdel(GetComponent(/datum/component/squeak)) /// Registers COMSIG_SPECIES_HANDLE_CHEMICAL from owner -/obj/item/organ/internal/liver/on_insert(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/liver/on_mob_insert(mob/living/carbon/organ_owner, special) . = ..() RegisterSignal(organ_owner, COMSIG_SPECIES_HANDLE_CHEMICAL, PROC_REF(handle_chemical)) /// Unregisters COMSIG_SPECIES_HANDLE_CHEMICAL from owner -/obj/item/organ/internal/liver/on_remove(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/liver/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() UnregisterSignal(organ_owner, COMSIG_SPECIES_HANDLE_CHEMICAL) @@ -134,7 +134,7 @@ return var/obj/belly = owner.get_organ_slot(ORGAN_SLOT_STOMACH) - var/list/cached_reagents = owner.reagents.reagent_list + var/list/cached_reagents = owner.reagents?.reagent_list var/liver_damage = 0 var/provide_pain_message = HAS_NO_TOXIN @@ -152,7 +152,7 @@ if(provide_pain_message != HAS_PAINFUL_TOXIN) provide_pain_message = toxin.silent_toxin ? HAS_SILENT_TOXIN : HAS_PAINFUL_TOXIN - owner.reagents.metabolize(owner, seconds_per_tick, times_fired, can_overdose = TRUE) + owner.reagents?.metabolize(owner, seconds_per_tick, times_fired, can_overdose = TRUE) if(liver_damage) apply_organ_damage(min(liver_damage * seconds_per_tick , MAX_TOXIN_LIVER_DAMAGE * seconds_per_tick)) diff --git a/code/modules/surgery/organs/internal/lungs/_lungs.dm b/code/modules/surgery/organs/internal/lungs/_lungs.dm index 2e99f70d989..874ec320648 100644 --- a/code/modules/surgery/organs/internal/lungs/_lungs.dm +++ b/code/modules/surgery/organs/internal/lungs/_lungs.dm @@ -153,7 +153,7 @@ add_gas_reaction(/datum/gas/zauker, while_present = PROC_REF(too_much_zauker)) ///Simply exists so that you don't keep any alerts from your previous lack of lungs. -/obj/item/organ/internal/lungs/Insert(mob/living/carbon/receiver, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/lungs/Insert(mob/living/carbon/receiver, special = FALSE, movement_flags) . = ..() if(!.) return . @@ -163,7 +163,7 @@ receiver.clear_alert(ALERT_NOT_ENOUGH_PLASMA) receiver.clear_alert(ALERT_NOT_ENOUGH_N2O) -/obj/item/organ/internal/lungs/Remove(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/lungs/Remove(mob/living/carbon/organ_owner, special, movement_flags) . = ..() // This is very "manual" I realize, but it's useful to ensure cleanup for gases we're removing happens // Avoids stuck alerts and such diff --git a/code/modules/surgery/organs/internal/stomach/_stomach.dm b/code/modules/surgery/organs/internal/stomach/_stomach.dm index a1d615041e2..7916606f2df 100644 --- a/code/modules/surgery/organs/internal/stomach/_stomach.dm +++ b/code/modules/surgery/organs/internal/stomach/_stomach.dm @@ -55,7 +55,7 @@ var/mob/living/carbon/body = owner // digest food, sent all reagents that can metabolize to the body - for(var/datum/reagent/bit as anything in reagents.reagent_list) + for(var/datum/reagent/bit as anything in reagents?.reagent_list) // If the reagent does not metabolize then it will sit in the stomach // This has an effect on items like plastic causing them to take up space in the stomach @@ -93,7 +93,7 @@ return //We are checking if we have nutriment in a damaged stomach. - var/datum/reagent/nutri = locate(/datum/reagent/consumable/nutriment) in reagents.reagent_list + var/datum/reagent/nutri = locate(/datum/reagent/consumable/nutriment) in reagents?.reagent_list //No nutriment found lets exit out if(!nutri) return @@ -263,7 +263,7 @@ disgusted.throw_alert(ALERT_DISGUST, /atom/movable/screen/alert/disgusted) disgusted.add_mood_event("disgust", /datum/mood_event/disgusted) -/obj/item/organ/internal/stomach/Remove(mob/living/carbon/stomach_owner, special = 0) +/obj/item/organ/internal/stomach/Remove(mob/living/carbon/stomach_owner, special, movement_flags) if(ishuman(stomach_owner)) var/mob/living/carbon/human/human_owner = owner human_owner.clear_alert(ALERT_DISGUST) diff --git a/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm b/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm index c1632f33329..68f9d9428a0 100644 --- a/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm +++ b/code/modules/surgery/organs/internal/stomach/stomach_ethereal.dm @@ -13,12 +13,12 @@ adjust_charge(-ETHEREAL_CHARGE_FACTOR * seconds_per_tick) handle_charge(owner, seconds_per_tick, times_fired) -/obj/item/organ/internal/stomach/ethereal/on_insert(mob/living/carbon/stomach_owner) +/obj/item/organ/internal/stomach/ethereal/on_mob_insert(mob/living/carbon/stomach_owner) . = ..() RegisterSignal(stomach_owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, PROC_REF(charge)) RegisterSignal(stomach_owner, COMSIG_LIVING_ELECTROCUTE_ACT, PROC_REF(on_electrocute)) -/obj/item/organ/internal/stomach/ethereal/on_remove(mob/living/carbon/stomach_owner) +/obj/item/organ/internal/stomach/ethereal/on_mob_remove(mob/living/carbon/stomach_owner) . = ..() UnregisterSignal(stomach_owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT) UnregisterSignal(stomach_owner, COMSIG_LIVING_ELECTROCUTE_ACT) diff --git a/code/modules/surgery/organs/internal/stomach/stomach_golem.dm b/code/modules/surgery/organs/internal/stomach/stomach_golem.dm index 5f721fa52b1..a1f5ce6c70e 100644 --- a/code/modules/surgery/organs/internal/stomach/stomach_golem.dm +++ b/code/modules/surgery/organs/internal/stomach/stomach_golem.dm @@ -11,11 +11,11 @@ /// How slow are you if you have absolutely nothing in the tank? var/max_hunger_slowdown = 4 -/obj/item/organ/internal/stomach/golem/on_insert(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/stomach/golem/on_mob_insert(mob/living/carbon/organ_owner, special) . = ..() RegisterSignal(owner, COMSIG_CARBON_ATTEMPT_EAT, PROC_REF(try_eating)) -/obj/item/organ/internal/stomach/golem/on_remove(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/stomach/golem/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() UnregisterSignal(organ_owner, COMSIG_CARBON_ATTEMPT_EAT) organ_owner.remove_movespeed_modifier(/datum/movespeed_modifier/golem_hunger) diff --git a/code/modules/surgery/organs/internal/tongue/_tongue.dm b/code/modules/surgery/organs/internal/tongue/_tongue.dm index c0dcf47fbea..50e4e8fa478 100644 --- a/code/modules/surgery/organs/internal/tongue/_tongue.dm +++ b/code/modules/surgery/organs/internal/tongue/_tongue.dm @@ -125,7 +125,7 @@ food_taste_reaction = FOOD_LIKED return food_taste_reaction -/obj/item/organ/internal/tongue/Insert(mob/living/carbon/tongue_owner, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/tongue/Insert(mob/living/carbon/tongue_owner, special = FALSE, movement_flags) . = ..() if(!.) return @@ -144,7 +144,7 @@ ADD_TRAIT(tongue_owner, TRAIT_AGEUSIA, ORGAN_TRAIT) apply_tongue_effects() -/obj/item/organ/internal/tongue/Remove(mob/living/carbon/tongue_owner, special = FALSE) +/obj/item/organ/internal/tongue/Remove(mob/living/carbon/tongue_owner, special, movement_flags) . = ..() temp_say_mod = "" UnregisterSignal(tongue_owner, COMSIG_MOB_SAY) diff --git a/code/modules/surgery/organs/organ_movement.dm b/code/modules/surgery/organs/organ_movement.dm new file mode 100644 index 00000000000..bee717fb764 --- /dev/null +++ b/code/modules/surgery/organs/organ_movement.dm @@ -0,0 +1,230 @@ +// There are two kinds of organ movement: mob movement and limb movement +// If you pull someones brain out, you remove it from the mob and the limb +// If you take someones head off, you remove it from the mob but not the limb +// If you remove the brain from an already decapitated head, you remove it from the limb but not the mob + +// Keep the seperation of limb removal and mob removal absolute + +/* + * Insert the organ into the select mob. + * + * receiver - the mob who will get our organ + * special - "quick swapping" an organ out - when TRUE, the mob will be unaffected by not having that organ for the moment + * movement_flags - Flags for how we behave in movement. See DEFINES/organ_movement for flags + */ +/obj/item/organ/proc/Insert(mob/living/carbon/receiver, special = FALSE, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + mob_insert(receiver, special, movement_flags) + bodypart_insert(limb_owner = receiver, movement_flags = movement_flags) + + return TRUE + +/* + * Remove the organ from the select mob. + * + * * organ_owner - the mob who owns our organ, that we're removing the organ from. Can be null + * * special - "quick swapping" an organ out - when TRUE, the mob will be unaffected by not having that organ for the moment + */ +/obj/item/organ/proc/Remove(mob/living/carbon/organ_owner, special = FALSE, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + mob_remove(organ_owner, special, movement_flags) + bodypart_remove(limb_owner = organ_owner, movement_flags = movement_flags) + +/* + * Insert the organ into the select mob. + * + * receiver - the mob who will get our organ + * special - "quick swapping" an organ out - when TRUE, the mob will be unaffected by not having that organ for the moment + * movement_flags - Flags for how we behave in movement. See DEFINES/organ_movement for flags + */ +/obj/item/organ/proc/mob_insert(mob/living/carbon/receiver, special, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + if(!iscarbon(receiver)) + stack_trace("Tried to insert organ into non-carbon: [receiver.type]") + return + + if(owner == receiver) + stack_trace("Organ receiver is already organ owner") + return + + var/obj/item/organ/replaced = receiver.get_organ_slot(slot) + if(replaced) + replaced.Remove(receiver, special = TRUE) + if(movement_flags & DELETE_IF_REPLACED) + qdel(replaced) + else + replaced.forceMove(get_turf(receiver)) + + if(!IS_ROBOTIC_ORGAN(src) && (organ_flags & ORGAN_VIRGIN)) + blood_dna_info = receiver.get_blood_dna_list() + // need to remove the synethic blood DNA that is initialized + // wash also adds the blood dna again + wash(CLEAN_TYPE_BLOOD) + organ_flags &= ~ORGAN_VIRGIN + + receiver.organs |= src + receiver.organs_slot[slot] = src + owner = receiver + + on_mob_insert(receiver, special) + + return TRUE + +/// Called after the organ is inserted into a mob. +/// Adds Traits, Actions, and Status Effects on the mob in which the organ is impanted. +/// Override this proc to create unique side-effects for inserting your organ. Must be called by overrides. +/obj/item/organ/proc/on_mob_insert(mob/living/carbon/organ_owner, special = FALSE, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + for(var/trait in organ_traits) + ADD_TRAIT(organ_owner, trait, REF(src)) + + for(var/datum/action/action as anything in actions) + action.Grant(organ_owner) + + for(var/datum/status_effect/effect as anything in organ_effects) + organ_owner.apply_status_effect(effect, type) + + RegisterSignal(owner, COMSIG_ATOM_EXAMINE, PROC_REF(on_owner_examine)) + SEND_SIGNAL(src, COMSIG_ORGAN_IMPLANTED, organ_owner) + SEND_SIGNAL(organ_owner, COMSIG_CARBON_GAIN_ORGAN, src, special) + +/// Insert an organ into a limb, assume the limb as always detached and include no owner operations here (except the get_bodypart helper here I guess) +/// Give EITHER a limb OR a limb owner +/obj/item/organ/proc/bodypart_insert(obj/item/bodypart/bodypart, mob/living/carbon/limb_owner, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + if(limb_owner) + bodypart = limb_owner.get_bodypart(deprecise_zone(zone)) + + // The true movement + forceMove(bodypart) + bodypart.contents |= src + bodypart_owner = bodypart + + RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(forced_removal)) + + // Apply unique side-effects. Return value does not matter. + on_bodypart_insert(bodypart) + + return TRUE + +/// Add any limb specific effects you might want here +/obj/item/organ/proc/on_bodypart_insert(obj/item/bodypart/limb, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + item_flags |= ABSTRACT + ADD_TRAIT(src, TRAIT_NODROP, ORGAN_INSIDE_BODY_TRAIT) + +/* + * Remove the organ from the select mob. + * + * * organ_owner - the mob who owns our organ, that we're removing the organ from. Can be null + * * special - "quick swapping" an organ out - when TRUE, the mob will be unaffected by not having that organ for the moment + */ +/obj/item/organ/proc/mob_remove(mob/living/carbon/organ_owner, special = FALSE, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + if(organ_owner) + if(organ_owner.organs_slot[slot] == src) + organ_owner.organs_slot.Remove(slot) + organ_owner.organs -= src + + owner = null + + on_mob_remove(organ_owner, special) + + return TRUE + +/// Called after the organ is removed from a mob. +/// Removes Traits, Actions, and Status Effects on the mob in which the organ was impanted. +/// Override this proc to create unique side-effects for removing your organ. Must be called by overrides. +/obj/item/organ/proc/on_mob_remove(mob/living/carbon/organ_owner, special = FALSE, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + if(!iscarbon(organ_owner)) + stack_trace("Organ removal should not be happening on non carbon mobs: [organ_owner]") + + for(var/trait in organ_traits) + REMOVE_TRAIT(organ_owner, trait, REF(src)) + + for(var/datum/action/action as anything in actions) + action.Remove(organ_owner) + + for(var/datum/status_effect/effect as anything in organ_effects) + organ_owner.remove_status_effect(effect, type) + + UnregisterSignal(organ_owner, COMSIG_ATOM_EXAMINE) + SEND_SIGNAL(src, COMSIG_ORGAN_REMOVED, organ_owner) + SEND_SIGNAL(organ_owner, COMSIG_CARBON_LOSE_ORGAN, src, special) + + var/list/diseases = organ_owner.get_static_viruses() + if(!LAZYLEN(diseases)) + return + + var/list/datum/disease/diseases_to_add = list() + for(var/datum/disease/disease as anything in diseases) + // robotic organs are immune to disease unless 'inorganic biology' symptom is present + if(IS_ROBOTIC_ORGAN(src) && !(disease.infectable_biotypes & MOB_ROBOTIC)) + continue + + // admin or special viruses that should not be reproduced + if(disease.spread_flags & (DISEASE_SPREAD_SPECIAL | DISEASE_SPREAD_NON_CONTAGIOUS)) + continue + + diseases_to_add += disease + + if(LAZYLEN(diseases_to_add)) + AddComponent(/datum/component/infective, diseases_to_add) + +/// Called to remove an organ from a limb. Do not put any mob operations here (except the bodypart_getter at the start) +/// Give EITHER a limb OR a limb_owner +/obj/item/organ/proc/bodypart_remove(obj/item/bodypart/limb, mob/living/carbon/limb_owner, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + if(!isnull(limb_owner)) + limb = limb_owner.get_bodypart(deprecise_zone(zone)) + + UnregisterSignal(src, COMSIG_MOVABLE_MOVED) //DONT MOVE THIS!!!! we moves the organ right after, so we unregister before we move them physically + + // The true movement is here + moveToNullspace() + bodypart_owner.contents -= src + bodypart_owner = null + + on_bodypart_remove(limb) + + return TRUE + +/// Called on limb removal to remove limb specific limb effects or statusses +/obj/item/organ/proc/on_bodypart_remove(obj/item/bodypart/limb, movement_flags) + SHOULD_CALL_PARENT(TRUE) + + if(!IS_ROBOTIC_ORGAN(src) && !(item_flags & NO_BLOOD_ON_ITEM) && !QDELING(src)) + AddElement(/datum/element/decal/blood) + + item_flags &= ~ABSTRACT + REMOVE_TRAIT(src, TRAIT_NODROP, ORGAN_INSIDE_BODY_TRAIT) + +/// In space station videogame, nothing is sacred. If somehow an organ is removed unexpectedly, handle it properly +/obj/item/organ/proc/forced_removal() + SIGNAL_HANDLER + + if(owner) + Remove(owner) + else if(bodypart_owner) + bodypart_remove(bodypart_owner) + else + stack_trace("Force removed an already removed organ!") + +/** + * Proc that gets called when the organ is surgically removed by someone, can be used for special effects + * Currently only used so surplus organs can explode when surgically removed. + */ +/obj/item/organ/proc/on_surgical_removal(mob/living/user, mob/living/carbon/old_owner, target_zone, obj/item/tool) + SHOULD_CALL_PARENT(TRUE) + SEND_SIGNAL(src, COMSIG_ORGAN_SURGICALLY_REMOVED, user, old_owner, target_zone, tool) + RemoveElement(/datum/element/decal/blood) diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 84039c9bb66..a97246f908e 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -195,6 +195,7 @@ #include "objectives.dm" #include "operating_table.dm" #include "orderable_items.dm" +#include "organ_bodypart_shuffle.dm" #include "organ_set_bonus.dm" #include "organs.dm" #include "outfit_sanity.dm" diff --git a/code/modules/unit_tests/hallucination_icons.dm b/code/modules/unit_tests/hallucination_icons.dm index 6477e94714c..c9f9cf8237c 100644 --- a/code/modules/unit_tests/hallucination_icons.dm +++ b/code/modules/unit_tests/hallucination_icons.dm @@ -19,7 +19,7 @@ // Test preset delusion hallucinations for invalid image setups for(var/datum/hallucination/delusion/preset/hallucination as anything in subtypesof(/datum/hallucination/delusion/preset)) - if(initial(hallucination.dynamic_icon)) + if(initial(hallucination.dynamic_delusion)) continue var/icon = initial(hallucination.delusion_icon_file) var/icon_state = initial(hallucination.delusion_icon_state) diff --git a/code/modules/unit_tests/heretic_rituals.dm b/code/modules/unit_tests/heretic_rituals.dm index 4ac5bce8d3d..b55136cface 100644 --- a/code/modules/unit_tests/heretic_rituals.dm +++ b/code/modules/unit_tests/heretic_rituals.dm @@ -66,7 +66,10 @@ if(islist(ritual_item_path)) ritual_item_path = pick(ritual_item_path) for(var/i in 1 to amount_to_create) - created_atoms += new ritual_item_path(get_turf(our_heretic)) + var/obj/item/item = new ritual_item_path(get_turf(our_heretic)) + if(isitem(item)) + item.item_flags &= ~ABSTRACT + created_atoms += item // Now, we can ACTUALLY run the ritual. Let's do it. // Attempt to run the knowledge via the sacrifice rune. @@ -106,6 +109,10 @@ for(var/atom/thing as anything in nearby_atoms) if(!ismovable(thing)) continue + if(isitem(thing)) + var/obj/item/item = thing + if(item.item_flags & ABSTRACT) //bodyparts and stuff will get registered otherwise + continue // There are atoms around the rune still, and there shouldn't be. // All component atoms were consumed, and all resulting atoms were cleaned up. diff --git a/code/modules/unit_tests/human_through_recycler.dm b/code/modules/unit_tests/human_through_recycler.dm index 7d554d72690..c51b9a0e30b 100644 --- a/code/modules/unit_tests/human_through_recycler.dm +++ b/code/modules/unit_tests/human_through_recycler.dm @@ -17,8 +17,13 @@ TEST_ASSERT_EQUAL(damage_incurred, chewer.crush_damage, "Assistant did not take the expected amount of brute damage ([chewer.crush_damage]) from the emagged recycler! Took ([damage_incurred]) instead.") TEST_ASSERT(chewer.bloody, "The emagged recycler did not become bloody after crushing the assistant!") + var/list/bad_contents = assistant.contents + for(var/obj/item/item in assistant.contents) + if(item.item_flags & ABSTRACT) + bad_contents -= item + // Now, let's test to see if all of their clothing got properly deleted. - TEST_ASSERT_EQUAL(length(assistant.contents), 0, "Assistant still has items in its contents after being put through an emagged recycler!") + TEST_ASSERT_EQUAL(length(bad_contents), 0, "Assistant still has items in its contents after being put through an emagged recycler!") // Consistent Assistants will always have the following: ID, PDA, backpack, a uniform, a headset, and a pair of shoes. If any of these are still present, then the recycler did not properly delete the assistant's clothing. // However, let's check for EVERYTHING just in case, because we don't want to miss anything. // This is just what we expect to be deleted. diff --git a/code/modules/unit_tests/ling_decap.dm b/code/modules/unit_tests/ling_decap.dm index 0c964f9a043..5d6f01caf9a 100644 --- a/code/modules/unit_tests/ling_decap.dm +++ b/code/modules/unit_tests/ling_decap.dm @@ -9,7 +9,7 @@ var/obj/item/bodypart/head/noggin = ling.get_bodypart(BODY_ZONE_HEAD) noggin.dismember() TEST_ASSERT_NULL(ling.get_bodypart(BODY_ZONE_HEAD), "Changeling failed to be decapitated.") - TEST_ASSERT_NULL(noggin.brainmob.mind, "Changeling's mind was moved to their head after decapitation, but it should have remained in their body.") + TEST_ASSERT_NULL(noggin.brain.brainmob.mind, "Changeling's mind was moved to their brain after decapitation, but it should have remained in their body.") var/obj/item/organ/internal/brain/oldbrain = noggin.brain noggin.drop_organs() @@ -33,7 +33,7 @@ var/obj/item/bodypart/head/noggin = normal_guy.get_bodypart(BODY_ZONE_HEAD) noggin.dismember() - TEST_ASSERT_EQUAL(noggin.brainmob.mind, my_guys_mind, "Dummy's mind was not moved to their head after decapitation.") + TEST_ASSERT_EQUAL(noggin.brain.brainmob.mind, my_guys_mind, "Dummy's mind was not moved to their brain after decapitation.") var/obj/item/organ/internal/brain/oldbrain = noggin.brain noggin.drop_organs() diff --git a/code/modules/unit_tests/organ_bodypart_shuffle.dm b/code/modules/unit_tests/organ_bodypart_shuffle.dm new file mode 100644 index 00000000000..842dd1c6c13 --- /dev/null +++ b/code/modules/unit_tests/organ_bodypart_shuffle.dm @@ -0,0 +1,34 @@ +/// Moves organs in and out of bodyparts, and moves the bodyparts around to see if someone didn't fuck up their movement +/datum/unit_test/organ_bodypart_shuffle + +/datum/unit_test/organ_bodypart_shuffle/Run() + var/mob/living/carbon/human/hollow_boy = allocate(/mob/living/carbon/human/consistent) + + // Test if organs are all properly updating when forcefully removed + var/list/removed_organs = list() + + for(var/obj/item/organ/organ as anything in hollow_boy.organs) + organ.moveToNullspace() + removed_organs += organ + + for(var/obj/item/organ/organ as anything in removed_organs) + TEST_ASSERT(!(organ in hollow_boy.organs), "Organ '[organ.name] remained inside human after forceMove into nullspace.") + TEST_ASSERT(organ.loc == null, "Organ '[organ.name] did not move to nullspace after being forced to.") + TEST_ASSERT(!(organ.owner), "Organ '[organ.name] kept reference to human after forceMove into nullspace.") + TEST_ASSERT(!(organ.bodypart_owner), "Organ '[organ.name] kept reference to bodypart after forceMove into nullspace.") + + for(var/obj/item/bodypart/bodypart as anything in hollow_boy.bodyparts) + bodypart = new bodypart.type() //fresh, duplice bodypart with no insides + for(var/obj/item/organ/organ as anything in removed_organs) + if(bodypart.body_zone != deprecise_zone(organ.zone)) + continue + organ.bodypart_insert(bodypart) // Put all the old organs back in + bodypart.replace_limb(hollow_boy) //so stick new bodyparts on them with their old organs + // Check if, after we put the old organs in a new limb, and after we put that new limb on the mob, if the organs came with + for(var/obj/item/organ/organ as anything in removed_organs) //technically readded organ now + if(bodypart.body_zone != deprecise_zone(organ.zone)) + continue + TEST_ASSERT(organ in hollow_boy.organs, "Organ '[organ.name] was put in an empty bodypart that replaced a humans, but the organ did not come with.") + + // Test if bodyparts are all properly updating when forcefully removed + hollow_boy = allocate(/mob/living/carbon/human/consistent) //freshly filled with wet insides diff --git a/code/modules/unit_tests/organ_set_bonus.dm b/code/modules/unit_tests/organ_set_bonus.dm index 06d9ba9f2e5..e89769fe7cf 100644 --- a/code/modules/unit_tests/organ_set_bonus.dm +++ b/code/modules/unit_tests/organ_set_bonus.dm @@ -31,7 +31,7 @@ // Attempt to insert entire list of mutant organs for the given infusion_entry. for(var/obj/item/organ/organ as anything in output_organs) organ = new organ() - TEST_ASSERT(organ.Insert(lab_rat, special = TRUE, drop_if_replaced = FALSE), "The organ `[organ.type]` for `[infuser_entry.type]` was not inserted in the mob when expected, Insert() returned falsy when TRUE was expected.") + TEST_ASSERT(organ.Insert(lab_rat, special = TRUE, movement_flags = DELETE_IF_REPLACED), "The organ `[organ.type]` for `[infuser_entry.type]` was not inserted in the mob when expected, Insert() returned falsy when TRUE was expected.") inserted_organs += organ // Search for added Status Effect. diff --git a/code/modules/unit_tests/organs.dm b/code/modules/unit_tests/organs.dm index 4ba51e0870c..1da3808ba39 100644 --- a/code/modules/unit_tests/organs.dm +++ b/code/modules/unit_tests/organs.dm @@ -25,14 +25,10 @@ )) /datum/unit_test/organ_sanity/Run() - for(var/obj/item/organ/organ_type as anything in subtypesof(/obj/item/organ)) + for(var/obj/item/organ/organ_type as anything in subtypesof(/obj/item/organ) - test_organ_blacklist) organ_test_insert(organ_type) /datum/unit_test/organ_sanity/proc/organ_test_insert(obj/item/organ/organ_type) - // Skip prototypes. - if(test_organ_blacklist[organ_type]) - return - // Appropriate mob (Human) which will receive organ. var/mob/living/carbon/human/lab_rat = allocate(/mob/living/carbon/human/consistent) var/obj/item/organ/test_organ = new organ_type() @@ -41,8 +37,8 @@ var/mob/living/basic/pet/dog/lab_dog = allocate(/mob/living/basic/pet/dog/corgi) var/obj/item/organ/reject_organ = new organ_type() - TEST_ASSERT(test_organ.Insert(lab_rat, special = TRUE, drop_if_replaced = FALSE), TEST_ORGAN_INSERT_MESSAGE(test_organ, "should return TRUE to indicate success.")) - TEST_ASSERT(!reject_organ.Insert(lab_dog, special = TRUE, drop_if_replaced = FALSE), TEST_ORGAN_INSERT_MESSAGE(test_organ, "shouldn't return TRUE when inserting into a basic mob (Corgi).")) + TEST_ASSERT(test_organ.Insert(lab_rat, special = TRUE, movement_flags = DELETE_IF_REPLACED), TEST_ORGAN_INSERT_MESSAGE(test_organ, "should return TRUE to indicate success.")) + TEST_ASSERT(!reject_organ.Insert(lab_dog, special = TRUE, movement_flags = DELETE_IF_REPLACED), TEST_ORGAN_INSERT_MESSAGE(test_organ, "shouldn't return TRUE when inserting into a basic mob (Corgi).")) // Species change swaps out all the organs, making test_organ un-usable by this point. if(species_changing_organs[test_organ.type]) diff --git a/code/modules/unit_tests/species_change_organs.dm b/code/modules/unit_tests/species_change_organs.dm index e0555aa89bc..41d55047f03 100644 --- a/code/modules/unit_tests/species_change_organs.dm +++ b/code/modules/unit_tests/species_change_organs.dm @@ -12,7 +12,7 @@ dummy.gain_trauma(/datum/brain_trauma/severe/blindness) // Give a cyber heart var/obj/item/organ/internal/heart/cybernetic/cyber_heart = allocate(/obj/item/organ/internal/heart/cybernetic) - cyber_heart.Insert(dummy, special = TRUE, drop_if_replaced = FALSE) + cyber_heart.Insert(dummy, special = TRUE, movement_flags = DELETE_IF_REPLACED) // Give one of their organs a bit of damage var/obj/item/organ/internal/appendix/existing_appendix = dummy.get_organ_slot(ORGAN_SLOT_APPENDIX) existing_appendix.set_organ_damage(25) diff --git a/code/modules/unit_tests/tail_wag.dm b/code/modules/unit_tests/tail_wag.dm index 0d828557953..ceb82e98c0d 100644 --- a/code/modules/unit_tests/tail_wag.dm +++ b/code/modules/unit_tests/tail_wag.dm @@ -6,7 +6,7 @@ /datum/unit_test/tail_wag/Run() var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent) var/obj/item/organ/external/tail/cat/dummy_tail = allocate(/obj/item/organ/external/tail/cat) - dummy_tail.Insert(dummy, special = TRUE, drop_if_replaced = FALSE) + dummy_tail.Insert(dummy, special = TRUE, movement_flags = DELETE_IF_REPLACED) // SANITY TEST @@ -74,7 +74,7 @@ // TESTING MOB DEATH // put it back and start wagging again - dummy_tail.Insert(dummy, special = TRUE, drop_if_replaced = FALSE) + dummy_tail.Insert(dummy, special = TRUE, movement_flags = DELETE_IF_REPLACED) SEND_SIGNAL(dummy, COMSIG_ORGAN_WAG_TAIL, TRUE) if(!(dummy_tail.wag_flags & WAG_WAGGING)) TEST_FAIL("Tail did not start wagging when it should have!") diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm index d971b82a856..dc7304a1388 100644 --- a/code/modules/vehicles/mecha/_mecha.dm +++ b/code/modules/vehicles/mecha/_mecha.dm @@ -54,7 +54,7 @@ /// Keeps track of the mech's servo motor var/obj/item/stock_parts/servo/servo ///Contains flags for the mecha - var/mecha_flags = CANSTRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE + var/mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE ///Spark effects are handled by this datum var/datum/effect_system/spark_spread/spark_system @@ -70,8 +70,6 @@ var/bumpsmash = FALSE ///////////ATMOS - ///Whether the pilot is hidden from the outside viewers and whether the cabin can be sealed to be airtight - var/enclosed = TRUE ///Whether the cabin exchanges gases with the environment var/cabin_sealed = FALSE ///Internal air mix datum @@ -397,7 +395,7 @@ /obj/vehicle/sealed/mecha/generate_actions() initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_eject) - if(enclosed) + if(mecha_flags & IS_ENCLOSED) initialize_controller_action_type(/datum/action/vehicle/sealed/mecha/mech_toggle_cabin_seal, VEHICLE_CONTROL_SETTINGS) if(can_use_overclock) initialize_passenger_action_type(/datum/action/vehicle/sealed/mecha/mech_overclock) @@ -468,7 +466,7 @@ . += span_warning("It's missing a capacitor.") if(!scanmod) . += span_warning("It's missing a scanning module.") - if(enclosed) + if(mecha_flags & IS_ENCLOSED) return if(mecha_flags & SILICON_PILOT) . += span_notice("[src] appears to be piloting itself...") @@ -574,7 +572,7 @@ /obj/vehicle/sealed/mecha/proc/process_occupants(seconds_per_tick) for(var/mob/living/occupant as anything in occupants) - if(!enclosed && occupant?.incapacitated()) //no sides mean it's easy to just sorta fall out if you're incapacitated. + if(!(mecha_flags & IS_ENCLOSED) && occupant?.incapacitated()) //no sides mean it's easy to just sorta fall out if you're incapacitated. mob_exit(occupant, randomstep = TRUE) //bye bye continue if(cell && cell.maxcharge) @@ -725,12 +723,12 @@ ///////////////////////////////////// /obj/vehicle/sealed/mecha/remove_air(amount) - if(enclosed && cabin_sealed) + if((mecha_flags & IS_ENCLOSED) && cabin_sealed) return cabin_air.remove(amount) return ..() /obj/vehicle/sealed/mecha/return_air() - if(enclosed && cabin_sealed) + if((mecha_flags & IS_ENCLOSED) && cabin_sealed) return cabin_air return ..() @@ -749,7 +747,7 @@ ///makes cabin unsealed, dumping cabin air outside or airtight filling the cabin with external air mix /obj/vehicle/sealed/mecha/proc/set_cabin_seal(mob/user, cabin_sealed) - if(!enclosed) + if(!(mecha_flags & IS_ENCLOSED)) balloon_alert(user, "cabin can't be sealed!") log_message("Tried to seal cabin. This mech can't be airtight.", LOG_MECHA) return diff --git a/code/modules/vehicles/mecha/combat/gygax.dm b/code/modules/vehicles/mecha/combat/gygax.dm index 223ab66ca31..82fd77f2289 100644 --- a/code/modules/vehicles/mecha/combat/gygax.dm +++ b/code/modules/vehicles/mecha/combat/gygax.dm @@ -47,7 +47,7 @@ force = 30 accesses = list(ACCESS_SYNDICATE) wreckage = /obj/structure/mecha_wreckage/gygax/dark - mecha_flags = ID_LOCK_ON | CANSTRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE + mecha_flags = ID_LOCK_ON | CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE max_equip_by_category = list( MECHA_L_ARM = 1, MECHA_R_ARM = 1, diff --git a/code/modules/vehicles/mecha/combat/honker.dm b/code/modules/vehicles/mecha/combat/honker.dm index dddcb7e8225..a7c9f018d28 100644 --- a/code/modules/vehicles/mecha/combat/honker.dm +++ b/code/modules/vehicles/mecha/combat/honker.dm @@ -13,7 +13,7 @@ exit_delay = 40 accesses = list(ACCESS_MECH_SCIENCE, ACCESS_THEATRE) wreckage = /obj/structure/mecha_wreckage/honker - mecha_flags = CANSTRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE + mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE mech_type = EXOSUIT_MODULE_HONK max_equip_by_category = list( MECHA_L_ARM = 1, @@ -47,7 +47,7 @@ max_temperature = 35000 accesses = list(ACCESS_SYNDICATE) wreckage = /obj/structure/mecha_wreckage/honker/dark - mecha_flags = ID_LOCK_ON | CANSTRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE + mecha_flags = ID_LOCK_ON | CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE max_equip_by_category = list( MECHA_L_ARM = 1, MECHA_R_ARM = 1, diff --git a/code/modules/vehicles/mecha/combat/marauder.dm b/code/modules/vehicles/mecha/combat/marauder.dm index 2fe8da4bdc7..750223a85d7 100644 --- a/code/modules/vehicles/mecha/combat/marauder.dm +++ b/code/modules/vehicles/mecha/combat/marauder.dm @@ -12,7 +12,7 @@ resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF accesses = list(ACCESS_CENT_SPECOPS) wreckage = /obj/structure/mecha_wreckage/marauder - mecha_flags = CANSTRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE + mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE mech_type = EXOSUIT_MODULE_MARAUDER force = 45 max_equip_by_category = list( @@ -117,7 +117,7 @@ base_icon_state = "mauler" accesses = list(ACCESS_SYNDICATE) wreckage = /obj/structure/mecha_wreckage/mauler - mecha_flags = ID_LOCK_ON | CANSTRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE + mecha_flags = ID_LOCK_ON | CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE max_equip_by_category = list( MECHA_L_ARM = 1, MECHA_R_ARM = 1, diff --git a/code/modules/vehicles/mecha/combat/reticence.dm b/code/modules/vehicles/mecha/combat/reticence.dm index bff5ecbd97b..ea8c72cae23 100644 --- a/code/modules/vehicles/mecha/combat/reticence.dm +++ b/code/modules/vehicles/mecha/combat/reticence.dm @@ -12,7 +12,7 @@ exit_delay = 40 wreckage = /obj/structure/mecha_wreckage/reticence accesses = list(ACCESS_MECH_SCIENCE, ACCESS_THEATRE) - mecha_flags = CANSTRAFE | IS_ENCLOSED | HAS_LIGHTS | QUIET_STEPS | QUIET_TURNS | MMI_COMPATIBLE + mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | QUIET_STEPS | QUIET_TURNS | MMI_COMPATIBLE mech_type = EXOSUIT_MODULE_RETICENCE max_equip_by_category = list( MECHA_L_ARM = 1, diff --git a/code/modules/vehicles/mecha/combat/savannah_ivanov.dm b/code/modules/vehicles/mecha/combat/savannah_ivanov.dm index c784219e3c3..237a0d971b0 100644 --- a/code/modules/vehicles/mecha/combat/savannah_ivanov.dm +++ b/code/modules/vehicles/mecha/combat/savannah_ivanov.dm @@ -19,7 +19,7 @@ base_icon_state = "savannah_ivanov" icon_state = "savannah_ivanov_0_0" //does not include mmi compatibility - mecha_flags = CANSTRAFE | IS_ENCLOSED | HAS_LIGHTS + mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS mech_type = EXOSUIT_MODULE_SAVANNAH movedelay = 3 max_integrity = 450 //really tanky, like damn diff --git a/code/modules/vehicles/mecha/mecha_actions.dm b/code/modules/vehicles/mecha/mecha_actions.dm index 43301c19605..2b410bd60c7 100644 --- a/code/modules/vehicles/mecha/mecha_actions.dm +++ b/code/modules/vehicles/mecha/mecha_actions.dm @@ -101,7 +101,7 @@ toggle_strafe() /obj/vehicle/sealed/mecha/proc/toggle_strafe() - if(!(mecha_flags & CANSTRAFE)) + if(!(mecha_flags & CAN_STRAFE)) to_chat(occupants, "this mecha doesn't support strafing!") return diff --git a/code/modules/vehicles/mecha/mecha_control_console.dm b/code/modules/vehicles/mecha/mecha_control_console.dm index 3dd69d4ba93..635ec9425b1 100644 --- a/code/modules/vehicles/mecha/mecha_control_console.dm +++ b/code/modules/vehicles/mecha/mecha_control_console.dm @@ -29,7 +29,7 @@ name = M.name, integrity = round((M.get_integrity() / M.max_integrity) * 100), charge = M.cell ? round(M.cell.percent()) : null, - airtank = M.enclosed ? M.return_pressure() : null, + airtank = (M.mecha_flags & IS_ENCLOSED) ? M.return_pressure() : null, pilot = M.return_drivers(), location = get_area_name(M, TRUE), emp_recharging = MT.recharging, @@ -97,7 +97,7 @@ var/answer = {"Name: [chassis.name]
Integrity: [round((chassis.get_integrity()/chassis.max_integrity * 100), 0.01)]%
Cell Charge: [isnull(cell_charge) ? "Not Found":"[chassis.cell.percent()]%"]
- Cabin Pressure: [chassis.enclosed ? "[round(chassis.return_pressure(), 0.01)] kPa" : "Not Sealed"]
+ Cabin Pressure: [(chassis.mecha_flags & IS_ENCLOSED) ? "[round(chassis.return_pressure(), 0.01)] kPa" : "Not Sealed"]
Pilot: [english_list(chassis.return_drivers(), nothing_text = "None")]
Location: [get_area_name(chassis, TRUE) || "Unknown"]"} if(istype(chassis, /obj/vehicle/sealed/mecha/ripley)) diff --git a/code/modules/vehicles/mecha/mecha_defense.dm b/code/modules/vehicles/mecha/mecha_defense.dm index 746039e7552..e88ce2925ac 100644 --- a/code/modules/vehicles/mecha/mecha_defense.dm +++ b/code/modules/vehicles/mecha/mecha_defense.dm @@ -115,18 +115,15 @@ return ..() /obj/vehicle/sealed/mecha/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit) //wrapper - . = ..() - if(. != BULLET_ACT_HIT) - return . - //allows bullets to hit the pilot of open-canopy mechs - if(!enclosed \ + if(!(mecha_flags & IS_ENCLOSED) \ && LAZYLEN(occupants) \ && !(mecha_flags & SILICON_PILOT) \ && (def_zone == BODY_ZONE_HEAD || def_zone == BODY_ZONE_CHEST)) - for(var/mob/living/hitmob as anything in occupants) - hitmob.bullet_act(hitting_projectile, def_zone, piercing_hit) //If the sides are open, the occupant can be hit - return BULLET_ACT_HIT + var/mob/living/hitmob = pick(occupants) + return hitmob.bullet_act(hitting_projectile, def_zone, piercing_hit) //If the sides are open, the occupant can be hit + + . = ..() log_message("Hit by projectile. Type: [hitting_projectile]([hitting_projectile.damage_type]).", LOG_MECHA, color="red") // yes we *have* to run the armor calc proc here I love tg projectile code too @@ -138,6 +135,7 @@ armour_penetration = hitting_projectile.armour_penetration, ), def_zone) + /obj/vehicle/sealed/mecha/ex_act(severity, target) log_message("Affected by explosion of severity: [severity].", LOG_MECHA, color="red") return ..() @@ -199,7 +197,7 @@ /obj/vehicle/sealed/mecha/fire_act() //Check if we should ignite the pilot of an open-canopy mech . = ..() - if(enclosed || mecha_flags & SILICON_PILOT) + if(mecha_flags & IS_ENCLOSED || mecha_flags & SILICON_PILOT) return for(var/mob/living/cookedalive as anything in occupants) if(cookedalive.fire_stacks < 5) diff --git a/code/modules/vehicles/mecha/mecha_ui.dm b/code/modules/vehicles/mecha/mecha_ui.dm index 76d8b4613fa..826a746c849 100644 --- a/code/modules/vehicles/mecha/mecha_ui.dm +++ b/code/modules/vehicles/mecha/mecha_ui.dm @@ -97,7 +97,7 @@ data["capacitor_rating"] = capacitor?.rating data["weapons_safety"] = weapons_safety - data["enclosed"] = enclosed + data["enclosed"] = mecha_flags & IS_ENCLOSED data["cabin_sealed"] = cabin_sealed data["cabin_temp"] = round(cabin_air.temperature - T0C) data["cabin_pressure"] = round(cabin_air.return_pressure()) diff --git a/code/modules/vehicles/mecha/working/ripley.dm b/code/modules/vehicles/mecha/working/ripley.dm index 9bc6ea75751..711da429cca 100644 --- a/code/modules/vehicles/mecha/working/ripley.dm +++ b/code/modules/vehicles/mecha/working/ripley.dm @@ -17,11 +17,11 @@ MECHA_POWER = 1, MECHA_ARMOR = 1, ) + mecha_flags = CAN_STRAFE | HAS_LIGHTS | MMI_COMPATIBLE wreckage = /obj/structure/mecha_wreckage/ripley mech_type = EXOSUIT_MODULE_RIPLEY possible_int_damage = MECHA_INT_FIRE|MECHA_INT_CONTROL_LOST|MECHA_INT_SHORT_CIRCUIT accesses = list(ACCESS_MECH_ENGINE, ACCESS_MECH_SCIENCE, ACCESS_MECH_MINING) - enclosed = FALSE //Normal ripley has an open cockpit design enter_delay = 10 //can enter in a quarter of the time of other mechs exit_delay = 10 /// Custom Ripley step and turning sounds (from TGMC) @@ -75,10 +75,10 @@ movedelay = 4 max_temperature = 30000 max_integrity = 250 + mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE possible_int_damage = MECHA_INT_FIRE|MECHA_INT_TEMP_CONTROL|MECHA_CABIN_AIR_BREACH|MECHA_INT_CONTROL_LOST|MECHA_INT_SHORT_CIRCUIT armor_type = /datum/armor/mecha_ripley_mk2 wreckage = /obj/structure/mecha_wreckage/ripley/mk2 - enclosed = TRUE enter_delay = 40 silicon_icon_state = null @@ -186,7 +186,7 @@ /obj/vehicle/sealed/mecha/ripley/paddy/preset accesses = list(ACCESS_SECURITY) - mecha_flags = CANSTRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE | ID_LOCK_ON + mecha_flags = CAN_STRAFE | HAS_LIGHTS | MMI_COMPATIBLE | ID_LOCK_ON equip_by_category = list( MECHA_L_ARM = /obj/item/mecha_parts/mecha_equipment/weapon/energy/disabler, MECHA_R_ARM = /obj/item/mecha_parts/mecha_equipment/weapon/paddy_claw, @@ -206,7 +206,7 @@ lights_power = 7 wreckage = /obj/structure/mecha_wreckage/ripley/deathripley step_energy_drain = 0 - enclosed = TRUE + mecha_flags = CAN_STRAFE | IS_ENCLOSED | HAS_LIGHTS | MMI_COMPATIBLE enter_delay = 40 silicon_icon_state = null equip_by_category = list( diff --git a/code/modules/vending/cartridge.dm b/code/modules/vending/cartridge.dm index dabf334c1f9..7c4a2c9578d 100644 --- a/code/modules/vending/cartridge.dm +++ b/code/modules/vending/cartridge.dm @@ -13,7 +13,7 @@ /obj/item/computer_disk/ordnance = 10, /obj/item/computer_disk/quartermaster = 10, /obj/item/computer_disk/command/captain = 3, - /obj/item/modular_computer/pda/heads = 10, + /obj/item/modular_computer/pda = 10, ) refill_canister = /obj/item/vending_refill/cart default_price = PAYCHECK_COMMAND diff --git a/code/modules/wiremod/shell/brain_computer_interface.dm b/code/modules/wiremod/shell/brain_computer_interface.dm index c30c7e629f2..f41d4fa8bf1 100644 --- a/code/modules/wiremod/shell/brain_computer_interface.dm +++ b/code/modules/wiremod/shell/brain_computer_interface.dm @@ -20,11 +20,6 @@ new /obj/item/circuit_component/bci_core, ), SHELL_CAPACITY_SMALL, starting_circuit = circuit) -/obj/item/organ/internal/cyberimp/bci/on_insert(mob/living/carbon/receiver) - . = ..() - // Organs are put in nullspace, but this breaks circuit interactions - forceMove(receiver) - /obj/item/organ/internal/cyberimp/bci/say(message, bubble_type, list/spans, sanitize, datum/language/language, ignore_spam, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null) if (owner) // Otherwise say_dead will be called. diff --git a/code/modules/zombie/organs.dm b/code/modules/zombie/organs.dm index 7514b6cdc6b..2ed2bf541d8 100644 --- a/code/modules/zombie/organs.dm +++ b/code/modules/zombie/organs.dm @@ -23,24 +23,24 @@ GLOB.zombie_infection_list -= src . = ..() -/obj/item/organ/internal/zombie_infection/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/zombie_infection/on_mob_insert(mob/living/carbon/M, special = FALSE, movement_flags) . = ..() START_PROCESSING(SSobj, src) -/obj/item/organ/internal/zombie_infection/Remove(mob/living/carbon/M, special = FALSE) +/obj/item/organ/internal/zombie_infection/on_mob_remove(mob/living/carbon/M, special = FALSE) . = ..() STOP_PROCESSING(SSobj, src) - if(iszombie(M) && old_species && !special && !QDELETED(src)) + if(iszombie(M) && old_species && !special) M.set_species(old_species) if(timer_id) deltimer(timer_id) -/obj/item/organ/internal/zombie_infection/on_insert(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/zombie_infection/on_mob_insert(mob/living/carbon/organ_owner, special) . = ..() RegisterSignal(organ_owner, COMSIG_LIVING_DEATH, PROC_REF(organ_owner_died)) -/obj/item/organ/internal/zombie_infection/on_remove(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/zombie_infection/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() UnregisterSignal(organ_owner, COMSIG_LIVING_DEATH) diff --git a/html/changelogs/AutoChangeLog-pr-374.yml b/html/changelogs/AutoChangeLog-pr-374.yml new file mode 100644 index 00000000000..401e41a87c1 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-374.yml @@ -0,0 +1,4 @@ +author: "vinylspiders" +delete-after: True +changes: + - image: "resprited CTF ID Cards" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-377.yml b/html/changelogs/AutoChangeLog-pr-377.yml new file mode 100644 index 00000000000..2bad1a89660 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-377.yml @@ -0,0 +1,4 @@ +author: "vinylspiders" +delete-after: True +changes: + - balance: "Last Resort can now be used while unconscious or dead. balance: Last Resort stuns bystanders for slightly longer. /:cl:" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-380.yml b/html/changelogs/AutoChangeLog-pr-380.yml new file mode 100644 index 00000000000..b17766563f0 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-380.yml @@ -0,0 +1,4 @@ +author: "vinylspiders" +delete-after: True +changes: + - bugfix: "Fixes AIize and borgize gibbing you" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-387.yml b/html/changelogs/AutoChangeLog-pr-387.yml new file mode 100644 index 00000000000..3700cae411e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-387.yml @@ -0,0 +1,5 @@ +author: "vinylspiders" +delete-after: True +changes: + - bugfix: "bridge assistant no longer passes some head of staff checks" + - qol: "if you steal a command member's liver, you can now sabre better! /:cl:" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80583.yml b/html/changelogs/AutoChangeLog-pr-80583.yml new file mode 100644 index 00000000000..579b1ef5f26 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80583.yml @@ -0,0 +1,5 @@ +author: "Melbert" +delete-after: True +changes: + - balance: "Blood cultists can now convert a Null Rod into a cult weapon on an offer rune. The strength of the weapon it is converted into depends on how many cultists the Chaplain crit / killed with it. At five or more, it will turn into a Bastard Sword. Note, sacrificing someone holding a Null Rod will automatically convert it after they are gibbed." + - balance: "Heretics no longer produce a Bastard Sword upon cult conversion. They are still immune to cult stun and cannot be converted by blood cultists." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80698.yml b/html/changelogs/AutoChangeLog-pr-80698.yml new file mode 100644 index 00000000000..0fc7f31ec1a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80698.yml @@ -0,0 +1,4 @@ +author: "13spacemen" +delete-after: True +changes: + - qol: "If you can't heal a body part, you won't get a healing time delay. No more spending 5 seconds healing a body part only to get a \"can't heal that\" message." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80792.yml b/html/changelogs/AutoChangeLog-pr-80792.yml new file mode 100644 index 00000000000..ace39411425 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80792.yml @@ -0,0 +1,4 @@ +author: "OrionTheFox" +delete-after: True +changes: + - image: "Resprited a majority of undershirts" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80796.yml b/html/changelogs/AutoChangeLog-pr-80796.yml new file mode 100644 index 00000000000..22e5f807d69 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80796.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed misfiring for firearms like tinkered detective revolvers." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80824.yml b/html/changelogs/AutoChangeLog-pr-80824.yml new file mode 100644 index 00000000000..2d234eae5aa --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80824.yml @@ -0,0 +1,4 @@ +author: "SyncIt21" +delete-after: True +changes: + - bugfix: "ejecting cells from microwaves via ctrl click now requires player proximity." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80825.yml b/html/changelogs/AutoChangeLog-pr-80825.yml new file mode 100644 index 00000000000..5f6bfd9559d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80825.yml @@ -0,0 +1,4 @@ +author: "SyncIt21" +delete-after: True +changes: + - code_imp: "smart fridge content overlay now uses `base_icon_state` instead of a separate var" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80828.yml b/html/changelogs/AutoChangeLog-pr-80828.yml new file mode 100644 index 00000000000..ad2f0cb624e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80828.yml @@ -0,0 +1,5 @@ +author: "Melbert" +delete-after: True +changes: + - bugfix: "Carps now migrate slightly better, probably." + - bugfix: "And Poly now talks better, probably." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80832.yml b/html/changelogs/AutoChangeLog-pr-80832.yml new file mode 100644 index 00000000000..419a4da7b32 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80832.yml @@ -0,0 +1,4 @@ +author: "Melbert" +delete-after: True +changes: + - admin: "Several types are now more accessible via the \"spawn\" verb (and friends), meaning you can type 'Spawn\" Modsuit' or 'Spawn \"Jumpsuit' in the command bar and it'll just give you a list of modsuits or jumpsuits to pick from." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80835.yml b/html/changelogs/AutoChangeLog-pr-80835.yml new file mode 100644 index 00000000000..20f91b17106 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80835.yml @@ -0,0 +1,4 @@ +author: "zxaber" +delete-after: True +changes: + - bugfix: "The various borg apparatuses can no longer pick up other internal borg tools." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80836.yml b/html/changelogs/AutoChangeLog-pr-80836.yml new file mode 100644 index 00000000000..54945abcadf --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80836.yml @@ -0,0 +1,4 @@ +author: "JohnFulpWillard" +delete-after: True +changes: + - bugfix: "The HoP's cartridge vending machine now sells regular PDAs instead of base command ones." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80837.yml b/html/changelogs/AutoChangeLog-pr-80837.yml new file mode 100644 index 00000000000..da2da2857ed --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80837.yml @@ -0,0 +1,4 @@ +author: "JohnFulpWillard" +delete-after: True +changes: + - bugfix: "Eldritch reagent (the one that heals heretics) now heal heretic monsters rather than kill them." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80840.yml b/html/changelogs/AutoChangeLog-pr-80840.yml new file mode 100644 index 00000000000..01f8fd224d8 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80840.yml @@ -0,0 +1,4 @@ +author: "JohnFulpWillard" +delete-after: True +changes: + - bugfix: "Refried beans and Spanish rice now lets you take the bowl back after eating it." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80844.yml b/html/changelogs/AutoChangeLog-pr-80844.yml new file mode 100644 index 00000000000..5d871a14596 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80844.yml @@ -0,0 +1,4 @@ +author: "zxaber" +delete-after: True +changes: + - bugfix: "Ripley MK-Is and Paddys now correctly make incoming projectiles hit the pilot again." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80849.yml b/html/changelogs/AutoChangeLog-pr-80849.yml new file mode 100644 index 00000000000..b5d830accb2 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80849.yml @@ -0,0 +1,4 @@ +author: "LT3" +delete-after: True +changes: + - bugfix: "Unencoded server admin announcements will now actually broadcast" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80855.yml b/html/changelogs/AutoChangeLog-pr-80855.yml new file mode 100644 index 00000000000..152f5645488 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80855.yml @@ -0,0 +1,5 @@ +author: "Melbert" +delete-after: True +changes: + - bugfix: "Lionhunter Rifle is now available at the same point as Mawed Crucible, making it available to all paths again." + - bugfix: "Lock knowledge now goes the correct order. Mark -> Ritual -> Unique item, rather than backwards." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80856.yml b/html/changelogs/AutoChangeLog-pr-80856.yml new file mode 100644 index 00000000000..d7740a63e1a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80856.yml @@ -0,0 +1,6 @@ +author: "IndieanaJones" +delete-after: True +changes: + - bugfix: "Dynamic midround rolls will properly consider roundstart players as part of the living population again, allowing antagonists with a minimum population value to spawn when they should be able to." + - bugfix: "Players who observe before roundstart can be considered for midround ghost roles again." + - bugfix: "Some antagonists which had elements that scale with living station population now function properly again." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80857.yml b/html/changelogs/AutoChangeLog-pr-80857.yml new file mode 100644 index 00000000000..6a9a8a4ab53 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80857.yml @@ -0,0 +1,4 @@ +author: "jlsnow301" +delete-after: True +changes: + - admin: "Fixed the bluescreen in the centcom pod launcher." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80858.yml b/html/changelogs/AutoChangeLog-pr-80858.yml new file mode 100644 index 00000000000..f3d7581ba89 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80858.yml @@ -0,0 +1,4 @@ +author: "jlsnow301" +delete-after: True +changes: + - bugfix: "Medical records console should be useable again" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80862.yml b/html/changelogs/AutoChangeLog-pr-80862.yml new file mode 100644 index 00000000000..bb6e2eb327b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80862.yml @@ -0,0 +1,4 @@ +author: "Absolucy" +delete-after: True +changes: + - bugfix: "Fixed the Codex Cicatrix always requiring a dead body, despite the description saying leather or a hide would work too." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80863.yml b/html/changelogs/AutoChangeLog-pr-80863.yml new file mode 100644 index 00000000000..3fed04e52bc --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80863.yml @@ -0,0 +1,4 @@ +author: "FlufflesTheDog" +delete-after: True +changes: + - bugfix: "Certain areas are now properly protected against grid check. Namely the supermatter should consistently be protected." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-98.yml b/html/changelogs/AutoChangeLog-pr-98.yml new file mode 100644 index 00000000000..f59fc33dbb9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-98.yml @@ -0,0 +1,10 @@ +author: "Paxilmaniac" +delete-after: True +changes: + - balance: "Kahraman Heavy Industries no longer sells base mining equipment that the station can just get. Instead their selection has been updated with a new selection of exploration and mining equipment fit for the frontier." + - rscadd: "Step aside colony core, there's a new sheriff in town. The organic materials printer, a green machine you make from a pile of flatpack parts from cargo. With a little input of plant matter, you can print yourself some grade A frontier equipment, or some organic materials, its up to you." + - rscadd: "There's a new piece of kit for marking your locations, the GPS beacon. Coming in a small size deployable item, it can be turned into an anchored, stationary GPS marker that you can use and rename to your liking. Don't like where it is? No worry, just pack it back up and move it elsewhere." + - rscadd: "Bluespace miners are so last codebase. Check out the hip new mining device from Kahraman: the Ore Thumper. Set one up outdoors with some wired power, and watch it slam away at the ground. After it works for long enough, the pressure built up by all that slamming will make deeply buried ore come to the surface." + - rscadd: "Looking for some frontier fashion? Some top notch kit? Kahraman has you covered with the new frontier clothing lineup. Now you too can buy equipment completely overrated for your cushy station adventures." + - sound: "New sounds added for the new ore thumper, as well as a neat new radio sound effect for the new frontier headset." + - image: "New sprites for the new machines, clothing, and whatever else in Kahraman are made by me, paxilmaniac, how dreamy." \ No newline at end of file diff --git a/html/changelogs/archive/2023-12.yml b/html/changelogs/archive/2023-12.yml index 57265cc0bb5..37bdb29ffbd 100644 --- a/html/changelogs/archive/2023-12.yml +++ b/html/changelogs/archive/2023-12.yml @@ -926,6 +926,7 @@ 2023-12-28: KannaLisvern: - rscadd: Added a new ERP emote. *lewdmoan + - qol: Removed Bluespace Crystals and Diamonds from medical emergency bed's recipe. Nerev4r: - rscadd: Due to increased availability of calcium supplements in Sector 13 due to Deep Spacer lobbying, snailpeople have found their shells to be more suited @@ -940,11 +941,21 @@ - balance: Shotgun shells, ESPECIALLY skyrat's shotgun shells, have been rebalanced to not either be useless or insane in every situation, see pr for details. - image: New sprites for some projectiles, like flechettes and whatnot + - qol: The names and descriptions of every paxilmaniac weapon have been improved + to be shorter (names) and mention at least what bullet the weapon fires (description) + - qol: Every weapon with an extended description has a hint in its normal examine + telling you that you can look further to get more info on the weapon + - code_imp: Two instances of now-deleted weapons paths (which i found out about + through someone getting one in a christmas tree) existing due to manufacturer + examines of all things have been cleaned up, players wont notice this one i + think Rhials: - bugfix: Icebox escape pods will now land randomly on the surface, instead of only in certain ruins. - qol: Wizard apprentices now spawn on the same tile as the contract that summoned them. + - qol: Obsessed crewmembers are now displayed in the orbit panel. + - qol: The Paradox Clone orbit menu tab is now white. Neat! zeroisthebiggay: - bugfix: '''A whole bunch of spiders in a SWAT suit'' to ''A whole bunch of spiders in a MODsuit''' @@ -1047,8 +1058,6 @@ This doesn''t affect 4/5 base /tg/ station maps.' - rscadd: 'New quirk for those who hate their appendix: Appendicitis Survivor! A positive (-2) quirk.' - KannaLisvern: - - qol: Removed Bluespace Crystals and Diamonds from medical emergency bed's recipe. LT3: - qol: TGUI will now wait longer trying to reconnect to a new round Lutowski: @@ -1062,18 +1071,6 @@ NovaBot13: - rscdel: Removes the wires from canisters. It's a cool idea, but cheap controlled maxcaps are bad actually - Paxilmaniac: - - qol: The names and descriptions of every paxilmaniac weapon have been improved - to be shorter (names) and mention at least what bullet the weapon fires (description) - - qol: Every weapon with an extended description has a hint in its normal examine - telling you that you can look further to get more info on the weapon - - code_imp: Two instances of now-deleted weapons paths (which i found out about - through someone getting one in a christmas tree) existing due to manufacturer - examines of all things have been cleaned up, players wont notice this one i - think - Rhials: - - qol: Obsessed crewmembers are now displayed in the orbit panel. - - qol: The Paradox Clone orbit menu tab is now white. Neat! Ryll/Shaps: - balance: Yawns are less likely to propagate goobliner: diff --git a/icons/mob/clothing/underwear.dmi b/icons/mob/clothing/underwear.dmi index d231b955bab..cd5564fe211 100644 Binary files a/icons/mob/clothing/underwear.dmi and b/icons/mob/clothing/underwear.dmi differ diff --git a/modular_nova/master_files/code/datums/quirks/neutral_quirks/lungs.dm b/modular_nova/master_files/code/datums/quirks/neutral_quirks/lungs.dm index 1e1fa2cc5f8..57247a3aa47 100644 --- a/modular_nova/master_files/code/datums/quirks/neutral_quirks/lungs.dm +++ b/modular_nova/master_files/code/datums/quirks/neutral_quirks/lungs.dm @@ -30,7 +30,7 @@ if (lungs != lungs_added && lungs != lungs_holding) qdel(lungs_holding) return - lungs_holding.Insert(carbon_holder, special = TRUE, drop_if_replaced = FALSE) + lungs_holding.Insert(carbon_holder, special = TRUE, movement_flags = DELETE_IF_REPLACED) lungs_holding.organ_flags &= ~ORGAN_FROZEN /datum/quirk/equipping/lungs/on_equip_item(obj/item/equipped, success) diff --git a/modular_nova/master_files/code/datums/traits/neutral.dm b/modular_nova/master_files/code/datums/traits/neutral.dm index ca1c43a5f39..52adfb141a5 100644 --- a/modular_nova/master_files/code/datums/traits/neutral.dm +++ b/modular_nova/master_files/code/datums/traits/neutral.dm @@ -248,7 +248,7 @@ GLOBAL_VAR_INIT(DNR_trait_overlay, generate_DNR_trait_overlay()) var/obj/item/organ/internal/tongue/dog/new_tongue = new(get_turf(human_holder)) new_tongue.copy_traits_from(human_holder.get_organ_slot(ORGAN_SLOT_TONGUE)) - new_tongue.Insert(human_holder, special = TRUE, drop_if_replaced = FALSE) + new_tongue.Insert(human_holder, special = TRUE, movement_flags = DELETE_IF_REPLACED) /datum/quirk/item_quirk/avian name = "Avian Traits" @@ -263,7 +263,7 @@ GLOBAL_VAR_INIT(DNR_trait_overlay, generate_DNR_trait_overlay()) var/obj/item/organ/internal/tongue/avian/new_tongue = new(get_turf(human_holder)) new_tongue.copy_traits_from(human_holder.get_organ_slot(ORGAN_SLOT_TONGUE)) - new_tongue.Insert(human_holder, special = TRUE, drop_if_replaced = FALSE) + new_tongue.Insert(human_holder, special = TRUE, movement_flags = DELETE_IF_REPLACED) /datum/quirk/sensitivesnout name = "Sensitive Snout" diff --git a/modular_nova/master_files/code/modules/client/preferences/brain.dm b/modular_nova/master_files/code/modules/client/preferences/brain.dm index cdf60e3f59a..1f446e7d893 100644 --- a/modular_nova/master_files/code/modules/client/preferences/brain.dm +++ b/modular_nova/master_files/code/modules/client/preferences/brain.dm @@ -27,7 +27,7 @@ new_brain.modular_persistence = old_brain.modular_persistence old_brain.modular_persistence = null - new_brain.Insert(target, drop_if_replaced = FALSE) + new_brain.mob_insert(target, movement_flags = DELETE_IF_REPLACED) // Prefs can be applied to mindless mobs, let's not try to move the non-existent mind back in! if(!keep_me_safe) diff --git a/modular_nova/master_files/icons/mob/clothing/modsuit/mod_clothing_mutant.dmi b/modular_nova/master_files/icons/mob/clothing/modsuit/mod_clothing_mutant.dmi index 79f9697d849..368d63d14bc 100644 Binary files a/modular_nova/master_files/icons/mob/clothing/modsuit/mod_clothing_mutant.dmi and b/modular_nova/master_files/icons/mob/clothing/modsuit/mod_clothing_mutant.dmi differ diff --git a/modular_nova/modules/company_imports/code/armament_datums/kahraman_industries.dm b/modular_nova/modules/company_imports/code/armament_datums/kahraman_industries.dm index f15da1c1750..b392ab14c2c 100644 --- a/modular_nova/modules/company_imports/code/armament_datums/kahraman_industries.dm +++ b/modular_nova/modules/company_imports/code/armament_datums/kahraman_industries.dm @@ -2,110 +2,108 @@ category = KAHRAMAN_INDUSTRIES_NAME company_bitflag = CARGO_COMPANY_KAHRAMAN -// Mining PPE, SEVAs and hardhats, have you passed your OSHA inspection today? - -/datum/armament_entry/company_import/kahraman/ppe - subcategory = "FOHSA Certified Protective Equipment" - -/datum/armament_entry/company_import/kahraman/ppe/weldhat - item_type = /obj/item/clothing/head/utility/hardhat/welding/orange - cost = PAYCHECK_CREW * 1.5 - -/datum/armament_entry/company_import/kahraman/ppe/gasmask - item_type = /obj/item/clothing/mask/gas/alt +/// Kahraman-made machines +/datum/armament_entry/company_import/kahraman/machinery + subcategory = "Machinery" + +/datum/armament_entry/company_import/kahraman/machinery/biogenerator + item_type = /obj/item/flatpacked_machine/organics_printer + description = "An advanced machine seen in frontier outposts and colonies capable of turning organic plant matter into \ + reagents and items of use that a fabricator can't typically make." + cost = CARGO_CRATE_VALUE * 3 + +/datum/armament_entry/company_import/kahraman/machinery/ore_thumper + item_type = /obj/item/flatpacked_machine/ore_thumper + description = "A frame with a heavy block of metal suspended atop a pipe. \ + Must be deployed outdoors and given a wired power connection. \ + Forces pressurized gas into the ground which brings up buried resources." + cost = CARGO_CRATE_VALUE * 5 + +/datum/armament_entry/company_import/kahraman/machinery/gps_beacon + item_type = /obj/item/flatpacked_machine/gps_beacon + description = "A packed GPS beacon, can be deployed and anchored into the ground to \ + provide and unobstructed homing beacon for wayward travelers across the galaxy." cost = PAYCHECK_LOWER -/datum/armament_entry/company_import/kahraman/ppe/hazard_vest - item_type = /obj/item/clothing/suit/hazardvest - cost = PAYCHECK_CREW - -/datum/armament_entry/company_import/kahraman/ppe/seva_mask - item_type = /obj/item/clothing/mask/gas/seva - cost = PAYCHECK_CREW * 1.5 +// Occupational health and safety? Never heard of her. -/datum/armament_entry/company_import/kahraman/ppe/seva_suit - item_type = /obj/item/clothing/suit/hooded/seva - cost = PAYCHECK_COMMAND * 2 +/datum/armament_entry/company_import/kahraman/ppe + subcategory = "Protective Equipment" -/datum/armament_entry/company_import/kahraman/ppe/sensors_cuffs - item_type = /obj/item/kheiral_cuffs - cost = PAYCHECK_COMMAND * 5 +/datum/armament_entry/company_import/kahraman/ppe/hazard_mod + item_type = /obj/item/mod/control/pre_equipped/frontier_colonist + cost = PAYCHECK_COMMAND * 6.5 -// Hand held mining equipment +/datum/armament_entry/company_import/kahraman/ppe/gas_mask + item_type = /obj/item/clothing/mask/gas/atmos/frontier_colonist + cost = PAYCHECK_COMMAND -/datum/armament_entry/company_import/kahraman/mining_tool - subcategory = "Powered Mining Equipment" +/datum/armament_entry/company_import/kahraman/ppe/headset + item_type = /obj/item/radio/headset/headset_frontier_colonist + cost = PAYCHECK_COMMAND * 1.5 -/datum/armament_entry/company_import/kahraman/mining_tool/drill - item_type = /obj/item/pickaxe/drill +/datum/armament_entry/company_import/kahraman/ppe/flak_vest + item_type = /obj/item/clothing/suit/frontier_colonist_flak cost = PAYCHECK_COMMAND -/datum/armament_entry/company_import/kahraman/mining_tool/resonator - item_type = /obj/item/resonator +/datum/armament_entry/company_import/kahraman/ppe/tanker_helmet + item_type = /obj/item/clothing/head/frontier_colonist_helmet cost = PAYCHECK_COMMAND -/datum/armament_entry/company_import/kahraman/mining_tool/pka - item_type = /obj/item/gun/energy/recharge/kinetic_accelerator - cost = PAYCHECK_COMMAND +// Work clothing -/datum/armament_entry/company_import/kahraman/mining_tool/cutter - item_type = /obj/item/gun/energy/plasmacutter - cost = PAYCHECK_COMMAND +/datum/armament_entry/company_import/kahraman/work_clothing + subcategory = "Clothing" -/datum/armament_entry/company_import/kahraman/mining_tool/diamond_drill - item_type = /obj/item/pickaxe/drill/diamonddrill - cost = PAYCHECK_COMMAND * 2 +/datum/armament_entry/company_import/kahraman/work_clothing/jumpsuit + item_type = /obj/item/clothing/under/frontier_colonist + cost = PAYCHECK_CREW -/datum/armament_entry/company_import/kahraman/mining_tool/advanced_cutter - item_type = /obj/item/gun/energy/plasmacutter/adv - cost = PAYCHECK_COMMAND * 4 +/datum/armament_entry/company_import/kahraman/work_clothing/jacket + item_type = /obj/item/clothing/suit/jacket/frontier_colonist + cost = PAYCHECK_CREW -/datum/armament_entry/company_import/kahraman/mining_tool/super_resonator - item_type = /obj/item/resonator/upgraded - cost = PAYCHECK_COMMAND * 4 +/datum/armament_entry/company_import/kahraman/work_clothing/jacket_short + item_type = /obj/item/clothing/suit/jacket/frontier_colonist/short + cost = PAYCHECK_CREW -/datum/armament_entry/company_import/kahraman/mining_tool/jackhammer - item_type = /obj/item/pickaxe/drill/jackhammer - cost = PAYCHECK_COMMAND * 3 +/datum/armament_entry/company_import/kahraman/work_clothing/med_jacket + item_type = /obj/item/clothing/suit/jacket/frontier_colonist/medical + cost = PAYCHECK_CREW -/datum/armament_entry/company_import/kahraman/sensing - subcategory = "Sensing Equipment" +/datum/armament_entry/company_import/kahraman/work_clothing/ballcap + item_type = /obj/item/clothing/head/soft/frontier_colonist + cost = PAYCHECK_CREW -/datum/armament_entry/company_import/kahraman/sensing/mesons - item_type = /obj/item/clothing/glasses/meson +/datum/armament_entry/company_import/kahraman/work_clothing/med_ballcap + item_type = /obj/item/clothing/head/soft/frontier_colonist/medic cost = PAYCHECK_CREW -/datum/armament_entry/company_import/kahraman/sensing/autoscanner - item_type = /obj/item/t_scanner/adv_mining_scanner/lesser - cost = PAYCHECK_LOWER +/datum/armament_entry/company_import/kahraman/work_clothing/booties + item_type = /obj/item/clothing/shoes/jackboots/frontier_colonist + cost = PAYCHECK_CREW -/datum/armament_entry/company_import/kahraman/sensing/super_autoscanner - item_type = /obj/item/t_scanner/adv_mining_scanner - cost = PAYCHECK_COMMAND * 3 +/datum/armament_entry/company_import/kahraman/work_clothing/gloves + item_type = /obj/item/clothing/gloves/frontier_colonist + cost = PAYCHECK_CREW -/datum/armament_entry/company_import/kahraman/sensing/nvg_mesons - item_type = /obj/item/clothing/glasses/meson/night - cost = PAYCHECK_COMMAND * 3 +// "Equipment", so storage items and whatnot -/datum/armament_entry/company_import/kahraman/mecha_tools - subcategory = "Heavy Powered Mining Equipment" +/datum/armament_entry/company_import/kahraman/storage_equipment + subcategory = "Personal Equipment" -/datum/armament_entry/company_import/kahraman/mecha_tools/scanner - item_type = /obj/item/mecha_parts/mecha_equipment/mining_scanner +/datum/armament_entry/company_import/kahraman/storage_equipment/backpack + item_type = /obj/item/storage/backpack/industrial/frontier_colonist cost = PAYCHECK_CREW -/datum/armament_entry/company_import/kahraman/mecha_tools/drill - item_type = /obj/item/mecha_parts/mecha_equipment/drill +/datum/armament_entry/company_import/kahraman/storage_equipment/satchel + item_type = /obj/item/storage/backpack/industrial/frontier_colonist/satchel cost = PAYCHECK_CREW -/datum/armament_entry/company_import/kahraman/mecha_tools/pka - item_type = /obj/item/mecha_parts/mecha_equipment/weapon/energy/mecha_kineticgun - cost = PAYCHECK_CREW * 3 - -/datum/armament_entry/company_import/kahraman/mecha_tools/diamond_drill - item_type = /obj/item/mecha_parts/mecha_equipment/drill/diamonddrill - cost = PAYCHECK_CREW * 3 +/datum/armament_entry/company_import/kahraman/storage_equipment/messenger + item_type = /obj/item/storage/backpack/industrial/frontier_colonist/messenger + cost = PAYCHECK_CREW -/datum/armament_entry/company_import/kahraman/mecha_tools/cutter - item_type = /obj/item/mecha_parts/mecha_equipment/weapon/energy/plasma - cost = PAYCHECK_CREW * 3 +/datum/armament_entry/company_import/kahraman/storage_equipment/belt + item_type = /obj/item/storage/belt/utility/frontier_colonist + cost = PAYCHECK_CREW diff --git a/modular_nova/modules/cortical_borer/code/cortical_borer.dm b/modular_nova/modules/cortical_borer/code/cortical_borer.dm index 9d5b83fc24a..d77025e6853 100644 --- a/modular_nova/modules/cortical_borer/code/cortical_borer.dm +++ b/modular_nova/modules/cortical_borer/code/cortical_borer.dm @@ -32,7 +32,7 @@ GLOBAL_LIST_EMPTY(cortical_borers) return FALSE //so if a person is debrained, the borer is removed -/obj/item/organ/internal/brain/Remove(mob/living/carbon/target, special = 0, no_id_transfer = FALSE) +/obj/item/organ/internal/brain/Remove(mob/living/carbon/target, special = FALSE, movement_flags) . = ..() var/mob/living/basic/cortical_borer/cb_inside = target.has_borer() if(cb_inside) @@ -50,7 +50,7 @@ GLOBAL_LIST_EMPTY(cortical_borers) borer = null return ..() -/obj/item/organ/internal/borer_body/Insert(mob/living/carbon/carbon_target, special, drop_if_replaced) +/obj/item/organ/internal/borer_body/Insert(mob/living/carbon/carbon_target, special, movement_flags) . = ..() for(var/datum/borer_focus/body_focus as anything in borer.body_focuses) body_focus.on_add() diff --git a/modular_nova/modules/cortical_borer/code/evolution/evolution_things/empowered_egg.dm b/modular_nova/modules/cortical_borer/code/evolution/evolution_things/empowered_egg.dm index d04b31cce56..e1c12846835 100644 --- a/modular_nova/modules/cortical_borer/code/evolution/evolution_things/empowered_egg.dm +++ b/modular_nova/modules/cortical_borer/code/evolution/evolution_things/empowered_egg.dm @@ -19,7 +19,7 @@ if(iscarbon(loc)) Insert(loc) -/obj/item/organ/internal/empowered_borer_egg/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/empowered_borer_egg/Insert(mob/living/carbon/M, special = FALSE, movement_flags = DELETE_IF_REPLACED) ..() addtimer(CALLBACK(src, PROC_REF(try_burst)), burst_time) diff --git a/modular_nova/modules/customization/modules/client/augment/limbs.dm b/modular_nova/modules/customization/modules/client/augment/limbs.dm index 8ae5fed1f04..3d855176497 100644 --- a/modular_nova/modules/customization/modules/client/augment/limbs.dm +++ b/modular_nova/modules/customization/modules/client/augment/limbs.dm @@ -31,8 +31,6 @@ var/chosen_style = GLOB.robotic_styles_list[prefs.augment_limb_styles[slot]] new_limb.set_icon_static(chosen_style) new_limb.current_style = prefs.augment_limb_styles[slot] - for (var/obj/item/organ/external/external_organ as anything in old_limb.external_organs) - external_organ.transfer_to_limb(new_limb) new_limb.replace_limb(augmented) qdel(old_limb) diff --git a/modular_nova/modules/customization/modules/client/augment/organs.dm b/modular_nova/modules/customization/modules/client/augment/organs.dm index 091b0414456..0384c3668d9 100644 --- a/modular_nova/modules/customization/modules/client/augment/organs.dm +++ b/modular_nova/modules/customization/modules/client/augment/organs.dm @@ -8,7 +8,7 @@ var/obj/item/organ/organ_path = path // cast this to an organ so we can get the slot from it using initial() var/obj/item/organ/new_organ = new path() new_organ.copy_traits_from(human_holder.get_organ_slot(initial(organ_path.slot))) - new_organ.Insert(human_holder, special = TRUE, drop_if_replaced = FALSE) + new_organ.Insert(human_holder, special = TRUE, movement_flags = DELETE_IF_REPLACED) //HEARTS /datum/augment_item/organ/heart diff --git a/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm b/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm index 159d8c9a652..9eb7da1b4dd 100644 --- a/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm +++ b/modular_nova/modules/customization/modules/mob/dead/new_player/sprite_accessories/snout.dm @@ -30,7 +30,7 @@ return !sprite_datum.is_hidden(human) -/obj/item/organ/external/snout/Insert(mob/living/carbon/reciever, special, drop_if_replaced) +/obj/item/organ/external/snout/Insert(mob/living/carbon/reciever, special, movement_flags) if(sprite_accessory_flags & SPRITE_ACCESSORY_USE_MUZZLED_SPRITE) external_bodytypes |= BODYTYPE_SNOUTED if(sprite_accessory_flags & SPRITE_ACCESSORY_USE_ALT_FACEWEAR_LAYER) diff --git a/modular_nova/modules/customization/modules/mob/living/carbon/human/species.dm b/modular_nova/modules/customization/modules/mob/living/carbon/human/species.dm index 9568aec0bd0..31b0dd14e20 100644 --- a/modular_nova/modules/customization/modules/mob/living/carbon/human/species.dm +++ b/modular_nova/modules/customization/modules/mob/living/carbon/human/species.dm @@ -277,7 +277,7 @@ GLOBAL_LIST_EMPTY(customizable_races) replacement.build_from_dna(target.dna, key) // organ.Insert will qdel any current organs in that slot, so we don't need to. - replacement.Insert(target, special = TRUE, drop_if_replaced = FALSE) + replacement.Insert(target, special = TRUE, movement_flags = DELETE_IF_REPLACED) // var/obj/item/organ/path = new SA.organ_type // var/obj/item/organ/oldorgan = C.get_organ_slot(path.slot) diff --git a/modular_nova/modules/customization/modules/mob/living/carbon/human/species/ghoul.dm b/modular_nova/modules/customization/modules/mob/living/carbon/human/species/ghoul.dm index a1574f895a4..e71c3ed9e50 100644 --- a/modular_nova/modules/customization/modules/mob/living/carbon/human/species/ghoul.dm +++ b/modular_nova/modules/customization/modules/mob/living/carbon/human/species/ghoul.dm @@ -53,39 +53,39 @@ /mob/living/carbon/proc/ReassignForeignBodyparts() var/obj/item/bodypart/head = get_bodypart(BODY_ZONE_HEAD) if (head?.type != part_default_head) - qdel(head) var/obj/item/bodypart/limb = new part_default_head limb.replace_limb(src, TRUE) + qdel(head) var/obj/item/bodypart/chest = get_bodypart(BODY_ZONE_CHEST) if (chest?.type != part_default_chest) - qdel(chest) var/obj/item/bodypart/limb = new part_default_chest limb.replace_limb(src, TRUE) + qdel(chest) var/obj/item/bodypart/arm/left/left_arm = get_bodypart(BODY_ZONE_L_ARM) if (left_arm?.type != part_default_l_arm) - qdel(left_arm) var/obj/item/bodypart/limb = new part_default_l_arm limb.replace_limb(src, TRUE) + qdel(left_arm) var/obj/item/bodypart/arm/right/right_arm = get_bodypart(BODY_ZONE_R_ARM) if (right_arm?.type != part_default_r_arm) - qdel(right_arm) var/obj/item/bodypart/limb = new part_default_r_arm limb.replace_limb(src, TRUE) + qdel(right_arm) var/obj/item/bodypart/leg/left/left_leg = get_bodypart(BODY_ZONE_L_LEG) if (left_leg?.type != part_default_l_leg) - qdel(left_leg) var/obj/item/bodypart/limb = new part_default_l_leg limb.replace_limb(src, TRUE) + qdel(left_leg) var/obj/item/bodypart/leg/right/right_leg = get_bodypart(BODY_ZONE_R_LEG) if (right_leg?.type != part_default_r_leg) - qdel(right_leg) var/obj/item/bodypart/limb = new part_default_r_leg limb.replace_limb(src, TRUE) + qdel(right_leg) /datum/species/ghoul/on_species_gain(mob/living/carbon/new_ghoul, datum/species/old_species, pref_load) // Missing Defaults in DNA? Randomize! diff --git a/modular_nova/modules/customization/modules/mob/living/carbon/human/species/hemophage/hemophage_tumor.dm b/modular_nova/modules/customization/modules/mob/living/carbon/human/species/hemophage/hemophage_tumor.dm index 2f4ee0c3c52..e19afb9734f 100644 --- a/modular_nova/modules/customization/modules/mob/living/carbon/human/species/hemophage/hemophage_tumor.dm +++ b/modular_nova/modules/customization/modules/mob/living/carbon/human/species/hemophage/hemophage_tumor.dm @@ -25,7 +25,7 @@ var/bloodloss_rate = NORMAL_BLOOD_DRAIN -/obj/item/organ/internal/heart/hemophage/Insert(mob/living/carbon/tumorful, special, drop_if_replaced) +/obj/item/organ/internal/heart/hemophage/Insert(mob/living/carbon/tumorful, special, movement_flags) . = ..() if(!. || !owner) return diff --git a/modular_nova/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm b/modular_nova/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm index ad469037a85..33cd7ff1907 100644 --- a/modular_nova/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm +++ b/modular_nova/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm @@ -389,7 +389,7 @@ if(robot_organs) replacement_organ.organ_flags |= ORGAN_ROBOTIC replacement_organ.build_from_dna(alterer.dna, chosen_key) - replacement_organ.Insert(alterer, special = TRUE, drop_if_replaced = FALSE) + replacement_organ.Insert(alterer, special = TRUE, movement_flags = DELETE_IF_REPLACED) else var/list/new_acc_list = list() new_acc_list[MUTANT_INDEX_NAME] = selected_sprite_accessory.name diff --git a/modular_nova/modules/customization/modules/surgery/organs/genitals.dm b/modular_nova/modules/customization/modules/surgery/organs/genitals.dm index 4abce60d6e3..17a22786e29 100644 --- a/modular_nova/modules/customization/modules/surgery/organs/genitals.dm +++ b/modular_nova/modules/customization/modules/surgery/organs/genitals.dm @@ -50,7 +50,7 @@ return INITIALIZE_HINT_QDEL //Removes ERP organs depending on config -/obj/item/organ/external/genital/Insert(mob/living/carbon/M, special, drop_if_replaced) +/obj/item/organ/external/genital/Insert(mob/living/carbon/M, special, movement_flags) if(CONFIG_GET(flag/disable_erp_preferences)) return . = ..() diff --git a/modular_nova/modules/customization/modules/surgery/organs/organ.dm b/modular_nova/modules/customization/modules/surgery/organs/organ.dm index ac69342a036..e1892fc5543 100644 --- a/modular_nova/modules/customization/modules/surgery/organs/organ.dm +++ b/modular_nova/modules/customization/modules/surgery/organs/organ.dm @@ -14,21 +14,23 @@ if(mutantpart_key) color = mutantpart_info[MUTANT_INDEX_COLOR_LIST][1] -/obj/item/organ/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/Insert(mob/living/carbon/M, special = FALSE, movement_flags = DELETE_IF_REPLACED) var/mob/living/carbon/human/H = M if(mutantpart_key && istype(H)) H.dna.species.mutant_bodyparts[mutantpart_key] = mutantpart_info.Copy() - H.update_body() + if(!special) + H.update_body() . = ..() -/obj/item/organ/Remove(mob/living/carbon/M, special = FALSE) +/obj/item/organ/Remove(mob/living/carbon/M, special = FALSE, movement_flags) var/mob/living/carbon/human/H = M if(mutantpart_key && istype(H)) if(H.dna.species.mutant_bodyparts[mutantpart_key]) mutantpart_info = H.dna.species.mutant_bodyparts[mutantpart_key].Copy() //Update the info in case it was changed on the person color = mutantpart_info[MUTANT_INDEX_COLOR_LIST][1] H.dna.species.mutant_bodyparts -= mutantpart_key - H.update_body() + if(!special) + H.update_body() . = ..() /obj/item/organ/proc/build_from_dna(datum/dna/DNA, associated_key) diff --git a/modular_nova/modules/customization/modules/surgery/organs/tails.dm b/modular_nova/modules/customization/modules/surgery/organs/tails.dm index 007fcb16dfd..3cafd6852a0 100644 --- a/modular_nova/modules/customization/modules/surgery/organs/tails.dm +++ b/modular_nova/modules/customization/modules/surgery/organs/tails.dm @@ -41,7 +41,7 @@ return TRUE -/obj/item/organ/external/tail/Insert(mob/living/carbon/reciever, special, drop_if_replaced) +/obj/item/organ/external/tail/Insert(mob/living/carbon/reciever, special, movement_flags) if(sprite_accessory_flags & SPRITE_ACCESSORY_WAG_ABLE) wag_flags |= WAG_ABLE return ..() diff --git a/modular_nova/modules/customization/modules/surgery/organs/taur_body.dm b/modular_nova/modules/customization/modules/surgery/organs/taur_body.dm index 233b2290b7c..81b842a1af6 100644 --- a/modular_nova/modules/customization/modules/surgery/organs/taur_body.dm +++ b/modular_nova/modules/customization/modules/surgery/organs/taur_body.dm @@ -31,7 +31,7 @@ return GLOB.sprite_accessories["taur"] -/obj/item/organ/external/taur_body/Insert(mob/living/carbon/reciever, special, drop_if_replaced) +/obj/item/organ/external/taur_body/Insert(mob/living/carbon/reciever, special, movement_flags) if(sprite_accessory_flags & SPRITE_ACCESSORY_HIDE_SHOES) external_bodytypes |= BODYTYPE_HIDE_SHOES diff --git a/modular_nova/modules/deforest_medical_items/code/healing_stack_items.dm b/modular_nova/modules/deforest_medical_items/code/healing_stack_items.dm index 5c1563fd07b..e6bed70129f 100644 --- a/modular_nova/modules/deforest_medical_items/code/healing_stack_items.dm +++ b/modular_nova/modules/deforest_medical_items/code/healing_stack_items.dm @@ -30,7 +30,7 @@ var/treatment_sound = 'sound/items/duct_tape_rip.ogg' // This is only relevant for the types of wounds defined, we can't work if there are none -/obj/item/stack/medical/wound_recovery/try_heal(mob/living/patient, mob/user, silent) +/obj/item/stack/medical/wound_recovery/try_heal(mob/living/patient, mob/user, silent, looping) if(patient.has_status_effect(/datum/status_effect/vulnerable_to_damage)) patient.balloon_alert(user, "still recovering from last use!") diff --git a/modular_nova/modules/kahraman_equipment/code/clothing/armor_datums.dm b/modular_nova/modules/kahraman_equipment/code/clothing/armor_datums.dm new file mode 100644 index 00000000000..aa887a848c3 --- /dev/null +++ b/modular_nova/modules/kahraman_equipment/code/clothing/armor_datums.dm @@ -0,0 +1,30 @@ +/datum/armor/colonist_clothing + laser = ARMOR_LEVEL_TINY + energy = ARMOR_LEVEL_TINY + bomb = ARMOR_LEVEL_TINY + bio = ARMOR_LEVEL_TINY + fire = ARMOR_LEVEL_WEAK + acid = ARMOR_LEVEL_TINY + wound = WOUND_ARMOR_WEAK + +/datum/armor/colonist_armor + melee = ARMOR_LEVEL_WEAK + bullet = ARMOR_LEVEL_WEAK + laser = ARMOR_LEVEL_TINY + energy = ARMOR_LEVEL_TINY + bomb = ARMOR_LEVEL_TINY + bio = ARMOR_LEVEL_TINY + fire = ARMOR_LEVEL_WEAK + acid = ARMOR_LEVEL_TINY + wound = WOUND_ARMOR_STANDARD + +/datum/armor/colonist_hazard + melee = ARMOR_LEVEL_TINY + bullet = ARMOR_LEVEL_TINY + laser = ARMOR_LEVEL_WEAK + energy = ARMOR_LEVEL_WEAK + bomb = ARMOR_LEVEL_MID + bio = 100 + fire = 100 + acid = ARMOR_LEVEL_MID + wound = WOUND_ARMOR_WEAK diff --git a/modular_nova/modules/kahraman_equipment/code/clothing/clothing.dm b/modular_nova/modules/kahraman_equipment/code/clothing/clothing.dm new file mode 100644 index 00000000000..45649885402 --- /dev/null +++ b/modular_nova/modules/kahraman_equipment/code/clothing/clothing.dm @@ -0,0 +1,214 @@ +// Jumpsuit + +/obj/item/clothing/under/frontier_colonist + name = "frontier jumpsuit" + desc = "A heavy grey jumpsuit with extra padding around the joints. Two massive pockets included. \ + No matter what you do to adjust it, its always just slightly too large." + icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing.dmi' + icon_state = "jumpsuit" + worn_icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn.dmi' + worn_icon_digi = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_digi.dmi' + worn_icon_teshari = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi' + worn_icon_state = "jumpsuit" + has_sensor = SENSOR_COORDS + random_sensor = FALSE + +/obj/item/clothing/under/frontier_colonist/Initialize(mapload) + . = ..() + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) + +// Boots + +/obj/item/clothing/shoes/jackboots/frontier_colonist + name = "heavy frontier boots" + desc = "A well built pair of tall boots usually seen on the feet of explorers, first wave colonists, \ + and LARPers across the galaxy." + icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing.dmi' + icon_state = "boots" + worn_icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn.dmi' + worn_icon_digi = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_digi.dmi' + worn_icon_teshari = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi' + worn_icon_state = "boots" + armor_type = /datum/armor/colonist_clothing + resistance_flags = NONE + +/obj/item/clothing/shoes/jackboots/frontier_colonist/Initialize(mapload) + . = ..() + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) + +// Jackets + +/obj/item/clothing/suit/jacket/frontier_colonist + name = "frontier trenchcoat" + desc = "A knee length coat with a water-resistant exterior and relatively comfortable interior. \ + In between? Just enough protective material to stop the odd sharp thing getting through, \ + though don't expect miracles." + icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing.dmi' + icon_state = "jacket" + worn_icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn.dmi' + supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON + worn_icon_teshari = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi' + worn_icon_state = "jacket" + slot_flags = ITEM_SLOT_OCLOTHING|ITEM_SLOT_NECK + armor_type = /datum/armor/colonist_clothing + resistance_flags = NONE + allowed = null + +/obj/item/clothing/suit/jacket/frontier_colonist/Initialize(mapload) + . = ..() + allowed += GLOB.colonist_suit_allowed + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) + +/obj/item/clothing/suit/jacket/frontier_colonist/short + name = "frontier jacket" + desc = "A short coat with a water-resistant exterior and relatively comfortable interior. \ + In between? Just enough protective material to stop the odd sharp thing getting through, \ + though don't expect miracles." + icon_state = "jacket_short" + worn_icon_state = "jacket_short" + +/obj/item/clothing/suit/jacket/frontier_colonist/medical + name = "frontier medical jacket" + desc = "A short coat with a water-resistant exterior and relatively comfortable interior. \ + In between? Just enough protective material to stop the odd sharp thing getting through, \ + though don't expect miracles. This one is colored a bright red and covered in white \ + stripes to denote that someone wearing it might be able to provide medical assistance." + icon_state = "jacket_med" + worn_icon_state = "jacket_med" + +// Flak Jacket + +/obj/item/clothing/suit/frontier_colonist_flak + name = "frontier flak jacket" + desc = "A simple flak jacket with an exterior of water-resistant material. \ + Jackets like these are often found on first wave colonists that want some armor \ + due to the fact they can be made easily within a colony core type machine." + icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing.dmi' + icon_state = "flak" + worn_icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn.dmi' + supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON + worn_icon_teshari = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi' + worn_icon_state = "flak" + body_parts_covered = CHEST + cold_protection = CHEST|GROIN + min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT + heat_protection = CHEST|GROIN + max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT + armor_type = /datum/armor/colonist_armor + resistance_flags = NONE + allowed = null + +/obj/item/clothing/suit/frontier_colonist_flak/Initialize(mapload) + . = ..() + allowed += GLOB.colonist_suit_allowed + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) + +// Various softcaps + +/obj/item/clothing/head/soft/frontier_colonist + name = "frontier cap" + desc = "It's a robust baseball hat in a rugged green color." + icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing.dmi' + icon_state = "cap" + soft_type = "cap" + soft_suffix = null + worn_icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn.dmi' + supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON + worn_icon_teshari = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi' + worn_icon_state = "cap" + +/obj/item/clothing/head/soft/frontier_colonist/Initialize(mapload) + . = ..() + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) + +/obj/item/clothing/head/soft/frontier_colonist/medic + name = "frontier medical cap" + desc = "It's a robust baseball hat in a stylish red color. Has a white diamond to denote that its wearer might be able to provide medical assistance." + icon_state = "cap_medical" + soft_type = "cap_medical" + worn_icon_state = "cap_medical" + +// Helmet (Is it a helmet? Questionable? I'm not sure what to call this thing) + +/obj/item/clothing/head/frontier_colonist_helmet + name = "frontier soft helmet" + desc = "A unusual piece of headwear somewhere between a proper helmet and a normal cap." + icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing.dmi' + icon_state = "tanker" + worn_icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn.dmi' + supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON + worn_icon_teshari = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi' + worn_icon_state = "tanker" + armor_type = /datum/armor/colonist_armor + resistance_flags = NONE + flags_inv = 0 + clothing_flags = SNUG_FIT | STACKABLE_HELMET_EXEMPT + +/obj/item/clothing/head/frontier_colonist_helmet/Initialize(mapload) + . = ..() + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) + +// Headset + +/obj/item/radio/headset/headset_frontier_colonist + name = "frontier radio headset" + desc = "A bulky headset that should hopefully survive exposure to the elements better than station headsets might. \ + Has a built-in antenna allowing the headset to work independently of a communications network." + icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing.dmi' + icon_state = "radio" + worn_icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn.dmi' + supports_variations_flags = CLOTHING_SNOUTED_VARIATION_NO_NEW_ICON + worn_icon_teshari = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi' + worn_icon_state = "radio" + alternate_worn_layer = FACEMASK_LAYER + 0.5 + subspace_transmission = FALSE + radiosound = 'modular_nova/modules/kahraman_equipment/sound/morse_signal.wav' + +/obj/item/radio/headset/headset_frontier_colonist/Initialize(mapload) + . = ..() + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) + +// Gloves + +/obj/item/clothing/gloves/frontier_colonist + name = "frontier gloves" + desc = "A sturdy pair of black gloves that'll keep your precious fingers protected from the outside world. \ + They go a bit higher up the arm than most gloves should, and you aren't quite sure why." + icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing.dmi' + icon_state = "gloves" + worn_icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn.dmi' + supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON + worn_icon_teshari = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi' + worn_icon_state = "gloves" + greyscale_colors = "#3a373e" + siemens_coefficient = 0.25 // Doesn't insulate you entirely, but makes you a little more resistant + cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT + heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT + resistance_flags = NONE + clothing_traits = list(TRAIT_QUICK_CARRY) + +/obj/item/clothing/gloves/frontier_colonist/Initialize(mapload) + . = ..() + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) + +// Special mask + +/obj/item/clothing/mask/gas/atmos/frontier_colonist + name = "frontier gas mask" + desc = "An improved gas mask commonly seen in places where the atmosphere is less than breathable, \ + but otherwise more or less habitable. Its certified to protect against most biological hazards \ + to boot." + icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing.dmi' + icon_state = "mask" + worn_icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn.dmi' + worn_icon_digi = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_digi.dmi' + worn_icon_teshari = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi' + worn_icon_state = "mask" + flags_inv = HIDEEYES|HIDEFACE|HIDEFACIALHAIR|HIDESNOUT + armor_type = /datum/armor/colonist_hazard + +/obj/item/clothing/mask/gas/atmos/frontier_colonist/Initialize(mapload) + . = ..() + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) diff --git a/modular_nova/modules/kahraman_equipment/code/clothing/mod.dm b/modular_nova/modules/kahraman_equipment/code/clothing/mod.dm new file mode 100644 index 00000000000..f3ef68e8f66 --- /dev/null +++ b/modular_nova/modules/kahraman_equipment/code/clothing/mod.dm @@ -0,0 +1,105 @@ +// Its modsuiting time + +/datum/mod_theme/frontier_colonist + name = "frontier hazard protective" + desc = "An unusual design of suit, in reality being no more than a slim underlayer with a built in coat and sealed helmet." + extended_desc = "The pinnacle of frontier cheap technology. Suits like this are usually not unified in design \ + though are common in frontier settlements with less than optimal infrastructure. As with most unofficial \ + designs, there are flaws and no single one is perfect, but they achieve a singular goal and that is the \ + important part. Suits such as these are made specifically for the rare emergency that creates a hazard \ + environment that other equipment just can't quite handle. Often, these suits are able to protect their users \ + from not only electricity, but also radiation, biological hazards, other people, so on. This suit will not, \ + however, protect you from yourself." + + default_skin = "colonist" + armor_type = /datum/armor/colonist_hazard + resistance_flags = FIRE_PROOF + max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT + siemens_coefficient = 0 + complexity_max = DEFAULT_MAX_COMPLEXITY - 7 + charge_drain = DEFAULT_CHARGE_DRAIN * 2 + slowdown_inactive = 1.5 + slowdown_active = 1 + inbuilt_modules = list( + /obj/item/mod/module/plate_compression/permanent, + /obj/item/mod/module/joint_torsion/permanent + ) + allowed_suit_storage = list( + /obj/item/ammo_box, + /obj/item/ammo_casing, + /obj/item/flashlight, + /obj/item/gun, + /obj/item/melee, + /obj/item/tank/internals, + /obj/item/storage/belt/holster, + /obj/item/construction, + /obj/item/fireaxe, + /obj/item/pipe_dispenser, + /obj/item/storage/bag, + /obj/item/pickaxe, + /obj/item/resonator, + /obj/item/t_scanner, + /obj/item/analyzer, + /obj/item/storage/medkit, + ) + skins = list( + "colonist" = list( + MOD_ICON_OVERRIDE = 'modular_nova/modules/kahraman_equipment/icons/modsuits/mod.dmi', + MOD_WORN_ICON_OVERRIDE = 'modular_nova/modules/kahraman_equipment/icons/modsuits/mod_worn.dmi', + HELMET_FLAGS = list( + UNSEALED_LAYER = null, + UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT, + UNSEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF, + ), + CHESTPLATE_FLAGS = list( + UNSEALED_CLOTHING = THICKMATERIAL, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + SEALED_INVISIBILITY = HIDEJUMPSUIT, + ), + GAUNTLETS_FLAGS = list( + UNSEALED_CLOTHING = THICKMATERIAL, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + CAN_OVERSLOT = TRUE, + ), + BOOTS_FLAGS = list( + UNSEALED_CLOTHING = THICKMATERIAL, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + CAN_OVERSLOT = TRUE, + ), + ), + ) + +/obj/item/mod/control/pre_equipped/frontier_colonist + theme = /datum/mod_theme/frontier_colonist + applied_cell = /obj/item/stock_parts/cell/high + applied_modules = list( + /obj/item/mod/module/welding, + /obj/item/mod/module/magboot, + /obj/item/mod/module/flashlight, + /obj/item/mod/module/status_readout, + /obj/item/mod/module/thermal_regulator, + /obj/item/mod/module/rad_protection, + ) + default_pins = list( + /obj/item/mod/module/magboot, + /obj/item/mod/module/flashlight, + /obj/item/mod/module/thermal_regulator, + ) + +/obj/item/mod/control/pre_equipped/frontier_colonist/Initialize(mapload) + . = ..() + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) + +// Plate compression module that cannot be removed + +/obj/item/mod/module/plate_compression/permanent + removable = FALSE + complexity = 0 + +// Joint torsion module that can't be removed and has no complexity + +/obj/item/mod/module/joint_torsion/permanent + removable = FALSE + complexity = 0 diff --git a/modular_nova/modules/kahraman_equipment/code/clothing/storage.dm b/modular_nova/modules/kahraman_equipment/code/clothing/storage.dm new file mode 100644 index 00000000000..3bd57a9fa94 --- /dev/null +++ b/modular_nova/modules/kahraman_equipment/code/clothing/storage.dm @@ -0,0 +1,88 @@ +// Backpacks + +/obj/item/storage/backpack/industrial/frontier_colonist + name = "frontier backpack" + desc = "A rugged backpack often used by settlers and explorers. Holds all of your equipment and then some." + icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing.dmi' + icon_state = "backpack" + worn_icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn.dmi' + supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON + worn_icon_teshari = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi' + worn_icon_state = "backpack" + inhand_icon_state = "backpack" + +/obj/item/storage/backpack/industrial/frontier_colonist/Initialize(mapload) + . = ..() + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) + +/obj/item/storage/backpack/industrial/frontier_colonist/satchel + name = "frontier satchel" + desc = "A rugged satchel often used by settlers and explorers. Holds less of your equipment than a backpack will." + icon_state = "satchel" + worn_icon_state = "satchel" + +/obj/item/storage/backpack/industrial/frontier_colonist/messenger + name = "frontier messenger bag" + desc = "A rugged messenger bag often used by settlers and explorers. Holds less of your equipment than a backpack will." + icon_state = "messenger" + worn_icon_state = "messenger" + +// Belts + +/obj/item/storage/belt/utility/frontier_colonist + name = "frontier chest rig" + desc = "A versatile chest rig with pockets to store really whatever you could think of within. \ + That is, if whatever you could think of is within the realms of a utility belt. Fashion like this \ + comes at a price you know!" + icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing.dmi' + icon_state = "harness" + worn_icon = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn.dmi' + supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON + worn_icon_teshari = 'modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi' + worn_icon_state = "harness" + inhand_icon_state = null + +/obj/item/storage/belt/utility/frontier_colonist/Initialize(mapload) + . = ..() + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) + atom_storage.max_slots = 6 + atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL + // Can hold whatever a toolbelt can + some mining equipment for convenience + atom_storage.set_holdable(list( + /obj/item/airlock_painter, + /obj/item/analyzer, + /obj/item/assembly/signaler, + /obj/item/clothing/gloves, + /obj/item/construction, + /obj/item/crowbar, + /obj/item/extinguisher/mini, + /obj/item/flashlight, + /obj/item/forcefield_projector, + /obj/item/geiger_counter, + /obj/item/holosign_creator, + /obj/item/inducer, + /obj/item/lightreplacer, + /obj/item/multitool, + /obj/item/pipe_dispenser, + /obj/item/pipe_painter, + /obj/item/plunger, + /obj/item/radio, + /obj/item/screwdriver, + /obj/item/stack/cable_coil, + /obj/item/t_scanner, + /obj/item/weldingtool, + /obj/item/wirecutters, + /obj/item/wrench, + /obj/item/spess_knife, + /obj/item/gps, + /obj/item/knife, + /obj/item/mining_scanner, + /obj/item/pickaxe, + /obj/item/reagent_containers/hypospray, + /obj/item/shovel, + /obj/item/survivalcapsule, + /obj/item/storage/bag/ore, + /obj/item/storage/fancy/cigarettes, + /obj/item/wormhole_jaunter, + /obj/item/resonator, + )) diff --git a/modular_nova/modules/kahraman_equipment/code/gps_beacon.dm b/modular_nova/modules/kahraman_equipment/code/gps_beacon.dm new file mode 100644 index 00000000000..dc7411a3e17 --- /dev/null +++ b/modular_nova/modules/kahraman_equipment/code/gps_beacon.dm @@ -0,0 +1,23 @@ +/obj/item/gps/computer/beacon + name = "\improper GPS beacon" + desc = "A GPS beacon, anchored to the ground to prevent loss or accidental movement." + icon = 'modular_nova/modules/kahraman_equipment/icons/gps_beacon.dmi' + icon_state = "gps_beacon" + pixel_y = 0 + /// What this is undeployed back into + var/undeploy_type = /obj/item/flatpacked_machine/gps_beacon + +/obj/item/gps/computer/beacon/Initialize(mapload) + . = ..() + AddElement(/datum/element/repackable, undeploy_type, 2 SECONDS) + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) + +/obj/item/flatpacked_machine/gps_beacon + name = "packed GPS beacon" + icon = 'modular_nova/modules/kahraman_equipment/icons/gps_beacon.dmi' + icon_state = "beacon_folded" + w_class = WEIGHT_CLASS_SMALL + type_to_deploy = /obj/item/gps/computer/beacon + +/obj/item/flatpacked_machine/gps_beacon/give_manufacturer_examine() + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) diff --git a/modular_nova/modules/kahraman_equipment/code/looping_sounds.dm b/modular_nova/modules/kahraman_equipment/code/looping_sounds.dm new file mode 100644 index 00000000000..b7edf20ccb5 --- /dev/null +++ b/modular_nova/modules/kahraman_equipment/code/looping_sounds.dm @@ -0,0 +1,13 @@ +/datum/looping_sound/ore_thumper_fan + start_sound = 'modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_start.wav' + start_length = 3 + mid_sounds = list( + 'modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_mid_1.wav' = 1, + 'modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_mid_2.wav' = 1, + 'modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_mid_3.wav' = 1, + 'modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_mid_4.wav' = 1, + ) + mid_length = 3 SECONDS + end_sound = 'modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_end.wav' + volume = 100 + falloff_exponent = 3 diff --git a/modular_nova/modules/kahraman_equipment/code/ore_thumper.dm b/modular_nova/modules/kahraman_equipment/code/ore_thumper.dm new file mode 100644 index 00000000000..6f67a760deb --- /dev/null +++ b/modular_nova/modules/kahraman_equipment/code/ore_thumper.dm @@ -0,0 +1,271 @@ +#define SLAM_JAM_DELAY 15 SECONDS + +/obj/machinery/power/colony_ore_thumper + name = "ore thumper" + desc = "A frame with a heavy block of metal suspended atop a pipe. \ + Must be deployed outdoors and given a wired power connection. \ + Forces pressurized gas into the ground which brings up buried resources." + icon = 'modular_nova/modules/kahraman_equipment/icons/ore_thumper.dmi' + icon_state = "thumper_idle" + density = TRUE + max_integrity = 250 + idle_power_usage = 0 + active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 25 // Should be 25 kw or half of a SOFIE generator + anchored = TRUE + can_change_cable_layer = FALSE + circuit = null + layer = ABOVE_MOB_LAYER + /// Are we currently working? + var/thumping = FALSE + /// Our looping fan sound that we play when turned on + var/datum/looping_sound/ore_thumper_fan/soundloop + /// How many times we've slammed, counts up until the number is high enough to make a box of materials + var/slam_jams = 0 + /// How many times we need to slam in order to produce a box of materials + var/slam_jams_needed = 15 + /// List of the thumping sounds we can choose from + var/static/list/list_of_thumper_sounds = list( + 'modular_nova/modules/kahraman_equipment/sound/thumper_thump/punch_press_1.wav', + 'modular_nova/modules/kahraman_equipment/sound/thumper_thump/punch_press_2.wav', + ) + /// Keeps track of the callback timer to make sure we don't have more than one + var/callback_tracker + /// Weighted list of the ores we can spawn + var/static/list/ore_weight_list = list( + /obj/item/stack/ore/iron = 5, + /obj/item/stack/ore/glass/basalt = 5, + /obj/item/stack/ore/plasma = 4, + /obj/item/stack/ore/uranium = 3, + /obj/item/stack/ore/silver = 3, + /obj/item/stack/ore/gold = 3, + /obj/item/stack/ore/titanium = 3, + /obj/item/stack/ore/diamond = 2, + /obj/item/stack/ore/bluespace_crystal = 1, + ) + /// How much of the listed types of ores should we spawn when spawning ore + var/static/list/ore_spawn_values = list( + /obj/item/stack/ore/iron = 25, + /obj/item/stack/ore/glass/basalt = 25, + /obj/item/stack/ore/plasma = 15, + /obj/item/stack/ore/uranium = 10, + /obj/item/stack/ore/silver = 10, + /obj/item/stack/ore/gold = 10, + /obj/item/stack/ore/titanium = 10, + /obj/item/stack/ore/diamond = 5, + /obj/item/stack/ore/bluespace_crystal = 1, + ) + /// What's the limit for ore near us? Counts by stacks, not individual amounts of ore + var/nearby_ore_limit = 10 + /// How far away does ore spawn? + var/ore_spawn_range = 2 + /// What do we undeploy into + var/undeploy_type = /obj/item/flatpacked_machine/ore_thumper + +/obj/machinery/power/colony_ore_thumper/Initialize(mapload) + . = ..() + soundloop = new(src, FALSE) + AddElement(/datum/element/repackable, undeploy_type, 4 SECONDS) + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) + +/obj/machinery/power/colony_ore_thumper/add_context( + atom/source, + list/context, + obj/item/held_item, + mob/living/user, +) + + if(isnull(held_item)) + if(panel_open) + context[SCREENTIP_CONTEXT_LMB] = "Activate Thumper" + return CONTEXTUAL_SCREENTIP_SET + return NONE + + +/obj/machinery/power/colony_ore_thumper/examine(mob/user) + . = ..() + var/area/thumper_area = get_area(src) + if(!thumper_area.outdoors) + . += span_notice("Its must be constructed outdoors to function.") + if(!istype(get_turf(src), /turf/open/misc)) + . += span_notice("It must be constructed on suitable terrain, like ash, snow, or sand.") + . += span_notice("It must have a powered, wired connection running beneath it with 25 kW of excess power to function.") + . += span_notice("It will produce a box of materials after it has slammed [slam_jams_needed] times.") + . += span_notice("Currently, it has slammed [slam_jams] / [slam_jams_needed] times needed.") + . += span_notice("It will stop producing resources if there are too many piles of ore near it.") + + +/obj/machinery/power/colony_ore_thumper/process() + var/turf/our_turf = get_turf(src) + var/obj/structure/cable/cable_under_us = locate() in our_turf + if(!cable_under_us && powernet) + disconnect_from_network() + else if(cable_under_us && !powernet) + connect_to_network() + if(thumping) + if(!see_if_we_can_work(our_turf)) + balloon_alert_to_viewers("invalid location!") + cut_that_out() + return + if(avail(active_power_usage)) + add_load(active_power_usage) + else + balloon_alert_to_viewers("not enough power!") + cut_that_out() + else if(avail(idle_power_usage)) + add_load(idle_power_usage) + + +/// Checks the turf we are on to make sure we are outdoors and on a misc turf +/obj/machinery/power/colony_ore_thumper/proc/see_if_we_can_work(turf/our_turf) + var/area/our_current_area = get_area(src) + if(!our_current_area.outdoors) + return FALSE + if(!istype(get_turf(src), /turf/open/misc)) + return FALSE + return TRUE + + +/obj/machinery/power/colony_ore_thumper/attack_hand(mob/user, list/modifiers) + . = ..() + if(.) + return + + to_chat(user, span_notice("You toggle [src]'s power button.")) + + if(thumping) + cut_that_out(user) + return + start_her_up(user) + + +/obj/machinery/power/colony_ore_thumper/attack_ai(mob/user) + return attack_hand(user) + + +/obj/machinery/power/colony_ore_thumper/attack_robot(mob/user) + return attack_hand(user) + + +/// Attempts turning the thumper on, failing if any of the conditions aren't met +/obj/machinery/power/colony_ore_thumper/proc/start_her_up(mob/user) + var/turf/our_turf = get_turf(src) + var/obj/structure/cable/cable_under_us = locate() in our_turf + if(!cable_under_us && powernet) + balloon_alert(user, "not connected to wire") + return + if(!avail(active_power_usage)) + balloon_alert(user, "not enough power") + return + + thumping = TRUE + soundloop.start() + + if(callback_tracker) + deltimer(callback_tracker) + + balloon_alert(user, "thumper started") + + callback_tracker = addtimer(CALLBACK(src, PROC_REF(slam_it_down)), SLAM_JAM_DELAY, TIMER_DELETE_ME | TIMER_STOPPABLE) + + +/// Attempts to shut the thumper down +/obj/machinery/power/colony_ore_thumper/proc/cut_that_out(mob/user) + thumping = FALSE + soundloop.stop() + if(user) + balloon_alert(user, "thumper stopped") + + +/// Makes the machine slam down, producing a box of ore if it has been slamming long enough +/obj/machinery/power/colony_ore_thumper/proc/slam_it_down() + if(!thumping) + return + var/turf/our_turf = get_turf(src) + if(!see_if_we_can_work(our_turf)) + balloon_alert_to_viewers("invalid location!") + cut_that_out() + return + // Down we go + flick("thumper_slam", src) + playsound(src, pick(list_of_thumper_sounds), 80, TRUE) + if(slam_jams < (slam_jams_needed + 1)) + slam_jams += 1 + + if(callback_tracker) + deltimer(callback_tracker) + + callback_tracker = addtimer(CALLBACK(src, PROC_REF(slam_it_down)), SLAM_JAM_DELAY, TIMER_DELETE_ME | TIMER_STOPPABLE,) + + // If the number of slams is less than that of what we need, then we can stop here + if(!(slam_jams >= slam_jams_needed)) + return + + var/nearby_ore = 0 + var/is_there_a_thumper_too = FALSE + for(var/turf/nearby_turf in orange(ore_spawn_range, src)) + for(var/ore as anything in nearby_turf.contents) + if(istype(ore, /obj/item/stack/ore)) + nearby_ore += 1 + continue + if(istype(ore, /obj/machinery/power/colony_ore_thumper)) + if(ore == src) + continue + is_there_a_thumper_too = TRUE + break + + if(nearby_ore > nearby_ore_limit) + balloon_alert_to_viewers("nearby ore too saturated") + return + + if(is_there_a_thumper_too) + balloon_alert_to_viewers("too close to another thumper") + return + + addtimer(CALLBACK(src, PROC_REF(make_some_ore)), 3 SECONDS, TIMER_DELETE_ME) + + +/// Spawns an ore box on top of the thumper +/obj/machinery/power/colony_ore_thumper/proc/make_some_ore() + var/list/nearby_valid_turfs = list() + for(var/turf/nearby_turf in orange(ore_spawn_range, src)) + if(nearby_turf.is_blocked_turf(TRUE)) + continue + if(!ismiscturf(nearby_turf)) + continue + nearby_valid_turfs.Add(nearby_turf) + // Fallback in case somehow there are no valid nearby turfs + if(!length(nearby_valid_turfs)) + nearby_valid_turfs.Add(get_turf(src)) + + for(var/iteration in 1 to rand(2, 4)) + var/turf/target_turf = pick(nearby_valid_turfs) + var/obj/item/stack/new_ore = pick_weight(ore_weight_list) + var/obj/new_ore_pile = new new_ore(target_turf, ore_spawn_values[new_ore.type]) + new /obj/effect/temp_visual/mook_dust/robot(target_turf) + playsound(new_ore_pile, 'modular_nova/master_files/sound/effects/robot_sit.ogg', 25, TRUE) + + slam_jams -= slam_jams_needed + + +// Item for deploying ore thumpers +/obj/item/flatpacked_machine/ore_thumper + name = "flat-packed ore thumper" + icon = 'modular_nova/modules/kahraman_equipment/icons/ore_thumper_item.dmi' + icon_state = "thumper_packed" + type_to_deploy = /obj/machinery/power/colony_ore_thumper + custom_materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 15, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 5, + /datum/material/titanium = SHEET_MATERIAL_AMOUNT * 5, + /datum/material/silver = SHEET_MATERIAL_AMOUNT, + /datum/material/gold = HALF_SHEET_MATERIAL_AMOUNT, + ) + +/obj/item/flatpacked_machine/ore_thumper/examine(mob/user) + . = ..() + . += span_notice("Its must be constructed outdoors to function.") + . += span_notice("It must be constructed on suitable terrain, like ash, snow, or sand.") + . += span_notice("It must have a powered, wired connection running beneath it to function.") + +/obj/item/flatpacked_machine/ore_thumper/give_manufacturer_examine() + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) diff --git a/modular_nova/modules/kahraman_equipment/code/organic_printer.dm b/modular_nova/modules/kahraman_equipment/code/organic_printer.dm new file mode 100644 index 00000000000..a548317c2e7 --- /dev/null +++ b/modular_nova/modules/kahraman_equipment/code/organic_printer.dm @@ -0,0 +1,40 @@ +/obj/machinery/biogenerator/organic_printer + name = "organic materials printer" + desc = "An advanced machine seen in frontier outposts and colonies capable of turning organic plant matter into \ + reagents and items of use that a fabricator can't typically make. While the exact designs these machines have differs from \ + location to location, and upon who designed them, this one should be able to at the very least provide you with \ + some clothing, basic food supplies, and whatever else you may require." + icon = 'modular_nova/modules/kahraman_equipment/icons/biogenerator.dmi' + circuit = null + anchored = FALSE + efficiency = 1 + productivity = 2 + max_items = 35 + show_categories = list( + RND_CATEGORY_AKHTER_CLOTHING, + RND_CATEGORY_AKHTER_EQUIPMENT, + RND_CATEGORY_AKHTER_RESOURCES, + ) + +/obj/machinery/biogenerator/organic_printer/Initialize(mapload) + . = ..() + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) + +/obj/machinery/biogenerator/organic_printer/RefreshParts() + . = ..() + efficiency = 1 + productivity = 2 + max_items = 35 + +/obj/machinery/biogenerator/organic_printer/default_deconstruction_crowbar() + return + +// Deployable item for cargo for the organics printer +/obj/item/flatpacked_machine/organics_printer + name = "organic materials printer parts kit" + icon = 'modular_nova/modules/kahraman_equipment/icons/biogenerator.dmi' + icon_state = "biogenerator_parts" + type_to_deploy = /obj/machinery/biogenerator/organic_printer + +/obj/item/flatpacked_machine/organics_printer/give_manufacturer_examine() + AddElement(/datum/element/manufacturer_examine, COMPANY_KAHRAMAN) diff --git a/modular_nova/modules/kahraman_equipment/code/organic_printer_designs/clothing.dm b/modular_nova/modules/kahraman_equipment/code/organic_printer_designs/clothing.dm new file mode 100644 index 00000000000..478dd89beb5 --- /dev/null +++ b/modular_nova/modules/kahraman_equipment/code/organic_printer_designs/clothing.dm @@ -0,0 +1,132 @@ +// Jumpsuit + +/datum/design/frontier_jumpsuit + name = "Frontier Jumpsuit" + id = "frontier_jumpsuit" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 75) + build_path = /obj/item/clothing/under/frontier_colonist + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_CLOTHING, + ) + +// Boots + +/datum/design/frontier_boots + name = "Heavy Frontier Boots" + id = "frontier_boots" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 50) + build_path = /obj/item/clothing/shoes/jackboots/frontier_colonist + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_CLOTHING, + ) + +// Gloves + +/datum/design/frontier_gloves + name = "Frontier Gloves" + id = "frontier_gloves" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 50) + build_path = /obj/item/clothing/gloves/frontier_colonist + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_CLOTHING, + ) + +// Suit items + +/datum/design/frontier_trench + name = "Frontier Trenchcoat" + id = "frontier_trench" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 100) + build_path = /obj/item/clothing/suit/jacket/frontier_colonist + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_CLOTHING, + ) + +/datum/design/frontier_jacket + name = "Frontier Jacket" + id = "frontier_jacket" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 100) + build_path = /obj/item/clothing/suit/jacket/frontier_colonist/short + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_CLOTHING, + ) + +/datum/design/frontier_med_jacket + name = "Frontier Medical Jacket" + id = "frontier_med_jacket" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 125) + build_path = /obj/item/clothing/suit/jacket/frontier_colonist/medical + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_CLOTHING, + ) + +/datum/design/frontier_flak + name = "Frontier Flak Jacket" + id = "frontier_flak_jacket" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 150) + build_path = /obj/item/clothing/suit/frontier_colonist_flak + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_CLOTHING, + ) + +/datum/design/frontier_tanker_helmet + name = "Frontier Soft Helmet" + id = "frontier_tanker_helmet" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 150) + build_path = /obj/item/clothing/head/frontier_colonist_helmet + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_CLOTHING, + ) + +// Hats + +/datum/design/frontier_cap + name = "Frontier Soft Cap" + id = "frontier_cap" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 75) + build_path = /obj/item/clothing/head/soft/frontier_colonist + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_CLOTHING, + ) + +/datum/design/frontier_cap_med + name = "Frontier Medical Cap" + id = "frontier_cap_med" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 100) + build_path = /obj/item/clothing/head/soft/frontier_colonist/medic + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_CLOTHING, + ) + +// That one gas mask + +/datum/design/frontier_mask + name = "Frontier Gas Mask" + id = "frontier_mask" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 100) + build_path = /obj/item/clothing/mask/gas/atmos/frontier_colonist + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_CLOTHING, + ) diff --git a/modular_nova/modules/kahraman_equipment/code/organic_printer_designs/equipment.dm b/modular_nova/modules/kahraman_equipment/code/organic_printer_designs/equipment.dm new file mode 100644 index 00000000000..cc019598dc9 --- /dev/null +++ b/modular_nova/modules/kahraman_equipment/code/organic_printer_designs/equipment.dm @@ -0,0 +1,69 @@ +// Belts + +/datum/design/frontier_chest_rig + name = "Frontier Chest Rig" + id = "frontier_chest_rig" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 150) + build_path = /obj/item/storage/belt/utility/frontier_colonist + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_EQUIPMENT, + ) + +/datum/design/frontier_med_belt + name = "Satchel Medical Kit" + id = "frontier_med_belt" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 200) + build_path = /obj/item/storage/backpack/duffelbag/deforest_medkit + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_EQUIPMENT, + ) + +/datum/design/frontier_medkit + name = "Frontier Medical Kit" + id = "frontier_medkit" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 100) + build_path = /obj/item/storage/medkit/frontier + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_EQUIPMENT, + ) + +// Backpacks + +/datum/design/frontier_backpack + name = "Frontier Backpack" + id = "frontier_backpack" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 100) + build_path = /obj/item/storage/backpack/industrial/frontier_colonist + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_EQUIPMENT, + ) + +/datum/design/frontier_satchel + name = "Frontier Satchel" + id = "frontier_satchel" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 100) + build_path = /obj/item/storage/backpack/industrial/frontier_colonist/satchel + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_EQUIPMENT, + ) + +/datum/design/frontier_messenger + name = "Frontier Messenger Bag" + id = "frontier_messenger" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 100) + build_path = /obj/item/storage/backpack/industrial/frontier_colonist/messenger + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_EQUIPMENT, + ) diff --git a/modular_nova/modules/kahraman_equipment/code/organic_printer_designs/resources.dm b/modular_nova/modules/kahraman_equipment/code/organic_printer_designs/resources.dm new file mode 100644 index 00000000000..9fb685140db --- /dev/null +++ b/modular_nova/modules/kahraman_equipment/code/organic_printer_designs/resources.dm @@ -0,0 +1,21 @@ +/datum/design/organic_plastic + name = "Plastic Sheet" + id = "oganic_plastic" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 25) + build_path = /obj/item/stack/sheet/plastic + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_RESOURCES, + ) + +/datum/design/organic_cloth + name = "Cloth" + id = "oganic_cloth" + build_type = BIOGENERATOR + materials = list(/datum/material/biomass = 10) + build_path = /obj/item/stack/sheet/cloth + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_AKHTER_RESOURCES, + ) diff --git a/modular_nova/modules/kahraman_equipment/icons/biogenerator.dmi b/modular_nova/modules/kahraman_equipment/icons/biogenerator.dmi new file mode 100644 index 00000000000..5fd87ee0ace Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/icons/biogenerator.dmi differ diff --git a/modular_nova/modules/kahraman_equipment/icons/clothes/clothing.dmi b/modular_nova/modules/kahraman_equipment/icons/clothes/clothing.dmi new file mode 100644 index 00000000000..bb4d9cec962 Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/icons/clothes/clothing.dmi differ diff --git a/modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn.dmi b/modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn.dmi new file mode 100644 index 00000000000..fa232094446 Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn.dmi differ diff --git a/modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_digi.dmi b/modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_digi.dmi new file mode 100644 index 00000000000..cb954472b24 Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_digi.dmi differ diff --git a/modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi b/modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi new file mode 100644 index 00000000000..da167942a77 Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/icons/clothes/clothing_worn_teshari.dmi differ diff --git a/modular_nova/modules/kahraman_equipment/icons/gps_beacon.dmi b/modular_nova/modules/kahraman_equipment/icons/gps_beacon.dmi new file mode 100644 index 00000000000..62c9cc11fa4 Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/icons/gps_beacon.dmi differ diff --git a/modular_nova/modules/kahraman_equipment/icons/modsuits/mod.dmi b/modular_nova/modules/kahraman_equipment/icons/modsuits/mod.dmi new file mode 100644 index 00000000000..a2e6c642b18 Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/icons/modsuits/mod.dmi differ diff --git a/modular_nova/modules/kahraman_equipment/icons/modsuits/mod_worn.dmi b/modular_nova/modules/kahraman_equipment/icons/modsuits/mod_worn.dmi new file mode 100644 index 00000000000..99254f654a4 Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/icons/modsuits/mod_worn.dmi differ diff --git a/modular_nova/modules/kahraman_equipment/icons/ore_thumper.dmi b/modular_nova/modules/kahraman_equipment/icons/ore_thumper.dmi new file mode 100644 index 00000000000..a99b196ae67 Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/icons/ore_thumper.dmi differ diff --git a/modular_nova/modules/kahraman_equipment/icons/ore_thumper_item.dmi b/modular_nova/modules/kahraman_equipment/icons/ore_thumper_item.dmi new file mode 100644 index 00000000000..7c53ff0f06a Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/icons/ore_thumper_item.dmi differ diff --git a/modular_nova/modules/kahraman_equipment/sound/attributions.txt b/modular_nova/modules/kahraman_equipment/sound/attributions.txt new file mode 100644 index 00000000000..19b7ff0e57e --- /dev/null +++ b/modular_nova/modules/kahraman_equipment/sound/attributions.txt @@ -0,0 +1,7 @@ +The sounds at modular_skyrat/modules/colony_fabriactor_event_code/sound/thumper_fan are from https://pixabay.com/sound-effects/fan-1-6360/ + +The sounds at modular_skyrat/modules/colony_fabriactor_event_code/sound/thumper_thump are from https://pixabay.com/sound-effects/punch-press-10-ton-clip1-104921/ + +The following sounds are from https://pixabay.com/sound-effects/sos-signal-137144/ + +modular_skyrat/modules/colony_fabricator/sound/morse_signal.wav diff --git a/modular_nova/modules/kahraman_equipment/sound/morse_signal.wav b/modular_nova/modules/kahraman_equipment/sound/morse_signal.wav new file mode 100644 index 00000000000..2f0dd568209 Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/sound/morse_signal.wav differ diff --git a/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_end.wav b/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_end.wav new file mode 100644 index 00000000000..f89e8d20ff9 Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_end.wav differ diff --git a/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_mid_1.wav b/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_mid_1.wav new file mode 100644 index 00000000000..96582d0ce32 Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_mid_1.wav differ diff --git a/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_mid_2.wav b/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_mid_2.wav new file mode 100644 index 00000000000..e1656ec08ef Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_mid_2.wav differ diff --git a/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_mid_3.wav b/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_mid_3.wav new file mode 100644 index 00000000000..7d7275b5bea Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_mid_3.wav differ diff --git a/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_mid_4.wav b/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_mid_4.wav new file mode 100644 index 00000000000..7298e4eddca Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_mid_4.wav differ diff --git a/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_start.wav b/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_start.wav new file mode 100644 index 00000000000..c3e95ad1e8b Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/sound/thumper_fan/fan_start.wav differ diff --git a/modular_nova/modules/kahraman_equipment/sound/thumper_thump/punch_press_1.wav b/modular_nova/modules/kahraman_equipment/sound/thumper_thump/punch_press_1.wav new file mode 100644 index 00000000000..513bb1f8f19 Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/sound/thumper_thump/punch_press_1.wav differ diff --git a/modular_nova/modules/kahraman_equipment/sound/thumper_thump/punch_press_2.wav b/modular_nova/modules/kahraman_equipment/sound/thumper_thump/punch_press_2.wav new file mode 100644 index 00000000000..c4d259839b3 Binary files /dev/null and b/modular_nova/modules/kahraman_equipment/sound/thumper_thump/punch_press_2.wav differ diff --git a/modular_nova/modules/modular_implants/code/nifs.dm b/modular_nova/modules/modular_implants/code/nifs.dm index 5ec2b9b17fa..35177c8c0cf 100644 --- a/modular_nova/modules/modular_implants/code/nifs.dm +++ b/modular_nova/modules/modular_implants/code/nifs.dm @@ -126,7 +126,7 @@ QDEL_LIST(loaded_nifsofts) return ..() -/obj/item/organ/internal/cyberimp/brain/nif/Insert(mob/living/carbon/human/insertee, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/cyberimp/brain/nif/Insert(mob/living/carbon/human/insertee, special = FALSE, movement_flags = DELETE_IF_REPLACED) . = ..() if(linked_mob && stored_ckey != insertee.ckey && theft_protection) diff --git a/modular_nova/modules/organs/code/heart.dm b/modular_nova/modules/organs/code/heart.dm index 857e1f05749..bc2f8ebc59b 100644 --- a/modular_nova/modules/organs/code/heart.dm +++ b/modular_nova/modules/organs/code/heart.dm @@ -9,7 +9,7 @@ COOLDOWN_DECLARE(shell_effect_cd) -/obj/item/organ/internal/heart/snail/on_insert(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/heart/snail/on_mob_insert(mob/living/carbon/organ_owner, special) . = ..() if(!ishuman(organ_owner)) return @@ -22,7 +22,7 @@ RegisterSignal(human_owner, COMSIG_MOB_APPLY_DAMAGE_MODIFIERS, PROC_REF(modify_damage)) RegisterSignal(human_owner, COMSIG_MOB_AFTER_APPLY_DAMAGE, PROC_REF(do_block_effect)) -/obj/item/organ/internal/heart/snail/on_remove(mob/living/carbon/organ_owner, special) +/obj/item/organ/internal/heart/snail/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() if(!ishuman(organ_owner) || QDELETED(organ_owner)) return diff --git a/modular_nova/modules/organs/code/tongue.dm b/modular_nova/modules/organs/code/tongue.dm index 957ee29fcda..c803bfc90c9 100644 --- a/modular_nova/modules/organs/code/tongue.dm +++ b/modular_nova/modules/organs/code/tongue.dm @@ -12,7 +12,7 @@ icon_state = "tongue" modifies_speech = TRUE -/obj/item/organ/internal/tongue/dog/Insert(mob/living/carbon/signer, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/tongue/dog/Insert(mob/living/carbon/signer, special = FALSE, movement_flags = DELETE_IF_REPLACED) . = ..() signer.verb_ask = "arfs" signer.verb_exclaim = "wans" @@ -34,7 +34,7 @@ icon_state = "tongue" modifies_speech = TRUE -/obj/item/organ/internal/tongue/avian/Insert(mob/living/carbon/signer, special = FALSE, drop_if_replaced = TRUE) +/obj/item/organ/internal/tongue/avian/Insert(mob/living/carbon/signer, special = FALSE, movement_flags = DELETE_IF_REPLACED) . = ..() signer.verb_ask = "peeps" signer.verb_exclaim = "squawks" diff --git a/modular_nova/modules/primitive_structures/code/storage_structures.dm b/modular_nova/modules/primitive_structures/code/storage_structures.dm index 1fa28126a47..ea4d9616108 100644 --- a/modular_nova/modules/primitive_structures/code/storage_structures.dm +++ b/modular_nova/modules/primitive_structures/code/storage_structures.dm @@ -58,7 +58,7 @@ icon = 'modular_nova/modules/primitive_structures/icons/storage.dmi' resistance_flags = FLAMMABLE base_build_path = /obj/machinery/smartfridge/producebin - contents_icon_state = "produce" + base_icon_state = "produce" use_power = NO_POWER_USE light_power = 0 idle_power_usage = 0 @@ -89,7 +89,7 @@ icon = 'modular_nova/modules/primitive_structures/icons/storage.dmi' resistance_flags = FLAMMABLE base_build_path = /obj/machinery/smartfridge/seedshelf - contents_icon_state = "seed" + base_icon_state = "seed" use_power = NO_POWER_USE light_power = 0 idle_power_usage = 0 @@ -119,7 +119,7 @@ icon = 'modular_nova/modules/primitive_structures/icons/storage.dmi' resistance_flags = FLAMMABLE base_build_path = /obj/machinery/smartfridge/rationshelf - contents_icon_state = "ration" + base_icon_state = "ration" use_power = NO_POWER_USE light_power = 0 idle_power_usage = 0 @@ -149,7 +149,7 @@ icon = 'modular_nova/modules/primitive_structures/icons/storage.dmi' resistance_flags = FLAMMABLE base_build_path = /obj/machinery/smartfridge/producedisplay - contents_icon_state = "nonfood" + base_icon_state = "nonfood" use_power = NO_POWER_USE light_power = 0 idle_power_usage = 0 diff --git a/modular_nova/modules/synths/code/bodyparts/brain.dm b/modular_nova/modules/synths/code/bodyparts/brain.dm index 5638c39269f..bd4564c0886 100644 --- a/modular_nova/modules/synths/code/bodyparts/brain.dm +++ b/modular_nova/modules/synths/code/bodyparts/brain.dm @@ -10,15 +10,15 @@ /// The last time (in ticks) a message about brain damage was sent. Don't touch. var/last_message_time = 0 -/obj/item/organ/internal/brain/synth/Insert(mob/living/carbon/user, special = FALSE, drop_if_replaced = TRUE, no_id_transfer = FALSE) +/obj/item/organ/internal/brain/synth/mob_insert(mob/living/carbon/brain_owner, special = FALSE, movement_flags) . = ..() - if(user.stat != DEAD || !ishuman(user)) + if(brain_owner.stat != DEAD || !ishuman(brain_owner)) return - var/mob/living/carbon/human/user_human = user - if(HAS_TRAIT(user_human, TRAIT_REVIVES_BY_HEALING) && user_human.health > SYNTH_BRAIN_WAKE_THRESHOLD) - user_human.revive(FALSE) + var/mob/living/carbon/human/human_brain_owner = brain_owner + if(HAS_TRAIT(human_brain_owner, TRAIT_REVIVES_BY_HEALING) && human_brain_owner.health > SYNTH_BRAIN_WAKE_THRESHOLD) + human_brain_owner.revive(FALSE) /obj/item/organ/internal/brain/synth/emp_act(severity) // EMP act against the posi, keep the cap far below the organ health . = ..() diff --git a/modular_nova/modules/synths/code/bodyparts/stomach.dm b/modular_nova/modules/synths/code/bodyparts/stomach.dm index 437d9eacff2..686774162ec 100644 --- a/modular_nova/modules/synths/code/bodyparts/stomach.dm +++ b/modular_nova/modules/synths/code/bodyparts/stomach.dm @@ -47,7 +47,7 @@ ) departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SCIENCE -/obj/item/organ/internal/stomach/synth/Insert(mob/living/carbon/receiver, special, drop_if_replaced) +/obj/item/organ/internal/stomach/synth/Insert(mob/living/carbon/receiver, special, movement_flags) . = ..() RegisterSignal(receiver, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, PROC_REF(on_borg_charge)) diff --git a/modular_nova/tools/merge-upstream-pull-request.sh b/modular_nova/tools/merge-upstream-pull-request.sh old mode 100644 new mode 100755 diff --git a/modular_nova/tools/nova_check_grep.sh b/modular_nova/tools/nova_check_grep.sh old mode 100644 new mode 100755 diff --git a/tff_modular/modules/nabbers/code/nabber_organs.dm b/tff_modular/modules/nabbers/code/nabber_organs.dm index f15456dbedf..7bb98527030 100644 --- a/tff_modular/modules/nabbers/code/nabber_organs.dm +++ b/tff_modular/modules/nabbers/code/nabber_organs.dm @@ -45,7 +45,7 @@ var/datum/action/toggle_welding/shield var/active = FALSE -/obj/item/organ/internal/eyes/robotic/nabber/Insert(mob/living/carbon/eye_recipient, special, drop_if_replaced) +/obj/item/organ/internal/eyes/robotic/nabber/Insert(mob/living/carbon/eye_recipient, special, movement_flags) . = ..() shield = new(eye_recipient) shield.button_icon = ORGGAN_ICON_NABBER diff --git a/tgstation.dme b/tgstation.dme index 2e12830c4c8..a06164488ef 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -159,6 +159,7 @@ #include "code\__DEFINES\nuclear_bomb.dm" #include "code\__DEFINES\obj_flags.dm" #include "code\__DEFINES\observers.dm" +#include "code\__DEFINES\organ_movement.dm" #include "code\__DEFINES\overlays.dm" #include "code\__DEFINES\pai.dm" #include "code\__DEFINES\paintings.dm" @@ -4256,8 +4257,6 @@ #include "code\modules\jobs\job_types\medical_doctor.dm" #include "code\modules\jobs\job_types\mime.dm" #include "code\modules\jobs\job_types\paramedic.dm" -#include "code\modules\jobs\job_types\personal_ai.dm" -#include "code\modules\jobs\job_types\positronic_brain.dm" #include "code\modules\jobs\job_types\prisoner.dm" #include "code\modules\jobs\job_types\psychologist.dm" #include "code\modules\jobs\job_types\quartermaster.dm" @@ -4265,7 +4264,6 @@ #include "code\modules\jobs\job_types\roboticist.dm" #include "code\modules\jobs\job_types\scientist.dm" #include "code\modules\jobs\job_types\security_officer.dm" -#include "code\modules\jobs\job_types\servant_golem.dm" #include "code\modules\jobs\job_types\shaft_miner.dm" #include "code\modules\jobs\job_types\station_engineer.dm" #include "code\modules\jobs\job_types\unassigned.dm" @@ -4311,6 +4309,9 @@ #include "code\modules\jobs\job_types\spawner\lavaland_syndicate.dm" #include "code\modules\jobs\job_types\spawner\lifebringer.dm" #include "code\modules\jobs\job_types\spawner\maintenance_drone.dm" +#include "code\modules\jobs\job_types\spawner\personal_ai.dm" +#include "code\modules\jobs\job_types\spawner\positronic_brain.dm" +#include "code\modules\jobs\job_types\spawner\servant_golem.dm" #include "code\modules\jobs\job_types\spawner\skeleton.dm" #include "code\modules\jobs\job_types\spawner\space_bar_patron.dm" #include "code\modules\jobs\job_types\spawner\space_bartender.dm" @@ -5802,6 +5803,7 @@ #include "code\modules\surgery\organs\_organ.dm" #include "code\modules\surgery\organs\autosurgeon.dm" #include "code\modules\surgery\organs\helpers.dm" +#include "code\modules\surgery\organs\organ_movement.dm" #include "code\modules\surgery\organs\external\_external_organ.dm" #include "code\modules\surgery\organs\external\restyling.dm" #include "code\modules\surgery\organs\external\spines.dm" @@ -7319,6 +7321,17 @@ #include "modular_nova\modules\jukebox\code\dance_machine.dm" #include "modular_nova\modules\jukebox\code\jukebox_subsystem.dm" #include "modular_nova\modules\jungle\code\flora.dm" +#include "modular_nova\modules\kahraman_equipment\code\gps_beacon.dm" +#include "modular_nova\modules\kahraman_equipment\code\looping_sounds.dm" +#include "modular_nova\modules\kahraman_equipment\code\ore_thumper.dm" +#include "modular_nova\modules\kahraman_equipment\code\organic_printer.dm" +#include "modular_nova\modules\kahraman_equipment\code\clothing\armor_datums.dm" +#include "modular_nova\modules\kahraman_equipment\code\clothing\clothing.dm" +#include "modular_nova\modules\kahraman_equipment\code\clothing\mod.dm" +#include "modular_nova\modules\kahraman_equipment\code\clothing\storage.dm" +#include "modular_nova\modules\kahraman_equipment\code\organic_printer_designs\clothing.dm" +#include "modular_nova\modules\kahraman_equipment\code\organic_printer_designs\equipment.dm" +#include "modular_nova\modules\kahraman_equipment\code\organic_printer_designs\resources.dm" #include "modular_nova\modules\knives\knives.dm" #include "modular_nova\modules\layer_shift\code\mob_movement.dm" #include "modular_nova\modules\liquids\code\drains.dm" diff --git a/tgui/packages/tgui/interfaces/CentcomPodLauncher.jsx b/tgui/packages/tgui/interfaces/CentcomPodLauncher.jsx index 34dd4b36261..9b53499f046 100644 --- a/tgui/packages/tgui/interfaces/CentcomPodLauncher.jsx +++ b/tgui/packages/tgui/interfaces/CentcomPodLauncher.jsx @@ -3,7 +3,7 @@ import { classes } from 'common/react'; import { storage } from 'common/storage'; import { multiline } from 'common/string'; import { createUuid } from 'common/uuid'; -import { Component, Fragment, useState } from 'react'; +import { Component, Fragment } from 'react'; import { useBackend, useLocalState } from '../backend'; import { @@ -25,7 +25,7 @@ const pod_grey = { }; const useCompact = () => { - const [compact, setCompact] = useState(false); + const [compact, setCompact] = useLocalState('compact', false); const toggleCompact = () => setCompact(!compact); return [compact, toggleCompact]; }; @@ -830,10 +830,10 @@ class PresetsPage extends Component { render() { const { presets } = this.state; const { act, data } = useBackend(); - const [presetIndex, setSelectedPreset] = useState(0); - const [settingName, setEditingNameStatus] = useState(0); - const [newNameText, setText] = useState(''); - const [hue, setHue] = useState(0); + const [presetIndex, setSelectedPreset] = useLocalState('presetIdx', 0); + const [settingName, setEditingNameStatus] = useLocalState('settingName', 0); + const [newNameText, setText] = useLocalState('nameText', ''); + const [hue, setHue] = useLocalState('hue', 0); return (
{ /** Individual crew tab */ const CrewTab = (props: { record: MedicalRecord }) => { - const [selectedRecord, setSelectedRecord] = useState< + const [selectedRecord, setSelectedRecord] = useLocalState< MedicalRecord | undefined - >(); + >('medicalRecord', undefined); const { act, data } = useBackend(); const { assigned_view } = data; diff --git a/tgui/packages/tgui/interfaces/SecurityRecords/RecordTabs.tsx b/tgui/packages/tgui/interfaces/SecurityRecords/RecordTabs.tsx index 70e68963705..4670d9b06b1 100644 --- a/tgui/packages/tgui/interfaces/SecurityRecords/RecordTabs.tsx +++ b/tgui/packages/tgui/interfaces/SecurityRecords/RecordTabs.tsx @@ -1,5 +1,6 @@ import { filter, sortBy } from 'common/collections'; import { flow } from 'common/fp'; +import { useState } from 'react'; import { useBackend, useLocalState } from 'tgui/backend'; import { Box, @@ -26,7 +27,7 @@ export const SecurityRecordTabs = (props) => { ? 'No records found.' : 'No match. Refine your search.'; - const [search, setSearch] = useLocalState('search', ''); + const [search, setSearch] = useState(''); const sorted: SecurityRecord[] = flow([ filter((record: SecurityRecord) => isRecordMatch(record, search)), diff --git a/tools/build/build.js b/tools/build/build.js index 2eda2ebed01..386d648c029 100644 --- a/tools/build/build.js +++ b/tools/build/build.js @@ -188,6 +188,7 @@ export const DmTarget = new Juke.Target({ ], inputs: [ '_maps/map_files/generic/**', + 'maps/**/*.dm', 'code/**', 'html/**', 'icons/**', diff --git a/tools/pull_request_hooks/rerunFlakyTests.js b/tools/pull_request_hooks/rerunFlakyTests.js index a0d96ebcad5..6625d9caa8c 100644 --- a/tools/pull_request_hooks/rerunFlakyTests.js +++ b/tools/pull_request_hooks/rerunFlakyTests.js @@ -4,203 +4,221 @@ const TITLE_BOT_HEADER = "title: "; // Only check jobs that start with these. // Helps make sure we don't restart something like screenshot tests or linters, which are not known to be flaky. const CONSIDERED_JOBS = [ - "Integration Tests", + "Integration Tests", ]; async function getFailedJobsForRun(github, context, workflowRunId, runAttempt) { - const { - data: { jobs }, - } = await github.rest.actions.listJobsForWorkflowRunAttempt({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: workflowRunId, - attempt_number: runAttempt, - }); - - return jobs - .filter((job) => job.conclusion === "failure") - .filter((job) => - CONSIDERED_JOBS.some((title) => job.name.startsWith(title)) - ); + const { + data: { jobs }, + } = await github.rest.actions.listJobsForWorkflowRunAttempt({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: workflowRunId, + attempt_number: runAttempt, + }); + + return jobs + .filter((job) => job.conclusion === "failure") + .filter((job) => + CONSIDERED_JOBS.some((title) => job.name.startsWith(title)) + ); } export async function rerunFlakyTests({ github, context }) { - const failingJobs = await getFailedJobsForRun( - github, - context, - context.payload.workflow_run.id, - context.payload.workflow_run.run_attempt - ); - - if (failingJobs.length > 1) { - console.log("Multiple jobs failing. PROBABLY not flaky, not rerunning."); - return; - } - - if (failingJobs.length === 0) { - throw new Error( - "rerunFlakyTests should not have run on a run with no failing jobs" - ); - } - - github.rest.actions.reRunWorkflowFailedJobs({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: context.payload.workflow_run.id, - }); + const failingJobs = await getFailedJobsForRun( + github, + context, + context.payload.workflow_run.id, + context.payload.workflow_run.run_attempt + ); + + if (failingJobs.length > 1) { + console.log("Multiple jobs failing. PROBABLY not flaky, not rerunning."); + return; + } + + if (failingJobs.length === 0) { + throw new Error( + "rerunFlakyTests should not have run on a run with no failing jobs" + ); + } + + github.rest.actions.reRunWorkflowFailedJobs({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id, + }); } // Tries its best to extract a useful error title and message for the given log export function extractDetails(log) { - // Strip off timestamp - const lines = log.split(/^[0-9.:T\-]*?Z /gm); - - const failureRegex = /^\t?FAILURE #(?[0-9]+): (?.+)/; - const groupRegex = /^##\[group\](?.+)/; - - const failures = []; - let lastGroup = "root"; - let loggingFailure; - - const newFailure = (failureMatch) => { - const { headline } = failureMatch.groups; - - loggingFailure = { - headline, - group: lastGroup.replace("/datum/unit_test/", ""), - details: [], - }; - }; - - for (const line of lines) { - const groupMatch = line.match(groupRegex); - if (groupMatch) { - lastGroup = groupMatch.groups.group.trim(); - continue; - } - - const failureMatch = line.match(failureRegex); - - if (loggingFailure === undefined) { - if (!failureMatch) { - continue; - } - - newFailure(failureMatch); - } else if (failureMatch || line.startsWith("##")) { - failures.push(loggingFailure); - loggingFailure = undefined; - - if (failureMatch) { - newFailure(failureMatch); - } - } else { - loggingFailure.details.push(line.trim()); - } - } - - // We had no logged failures, there's not really anything we can do here - if (failures.length === 0) { - return { - title: "Flaky test failure with no obvious source", - failures, - }; - } - - // We *could* create multiple failures for multiple groups. - // This would be important if we had multiple flaky tests at the same time. - // I'm choosing not to because it complicates this logic a bit, has the ability to go terribly wrong, - // and also because there's something funny to me about that increasing the urgency of fixing - // flaky tests. If it becomes a serious issue though, I would not mind this being fixed. - const uniqueGroups = new Set(failures.map((failure) => failure.group)); - - if (uniqueGroups.size > 1) { - return { - title: `Multiple flaky test failures in ${Array.from(uniqueGroups) - .sort() - .join(", ")}`, - failures, - }; - } - - const failGroup = failures[0].group; - - if (failures.length > 1) { - return { - title: `Multiple errors in flaky test ${failGroup}`, - failures, - }; - } - - const failure = failures[0]; - - // Common patterns where we can always get a detailed title - const runtimeMatch = failure.headline.match(/Runtime in .+?: (?.+)/); - if (runtimeMatch) { - return { - title: `Flaky test ${failGroup}: ${runtimeMatch.groups.error.trim()}`, - failures, - }; - } - - // Try to normalize the title and remove anything that might be variable - const normalizedError = failure.headline.replace(/\s*at .+?:[0-9]+.*/g, ""); // " at code.dm:123" - - return { - title: `Flaky test ${failGroup}: ${normalizedError}`, - failures, - }; + // Strip off timestamp + const lines = log.split(/^[0-9.:T\-]*?Z /gm); + + const failureRegex = /^\t?FAILURE #(?[0-9]+): (?.+)/; + const groupRegex = /^##\[group\](?.+)/; + + const failures = []; + let lastGroup = "root"; + let loggingFailure; + + const newFailure = (failureMatch) => { + const { headline } = failureMatch.groups; + + loggingFailure = { + headline, + group: lastGroup.replace("/datum/unit_test/", ""), + details: [], + }; + }; + + for (const line of lines) { + const groupMatch = line.match(groupRegex); + if (groupMatch) { + lastGroup = groupMatch.groups.group.trim(); + continue; + } + + const failureMatch = line.match(failureRegex); + + if (loggingFailure === undefined) { + if (!failureMatch) { + continue; + } + + newFailure(failureMatch); + } else if (failureMatch || line.startsWith("##")) { + failures.push(loggingFailure); + loggingFailure = undefined; + + if (failureMatch) { + newFailure(failureMatch); + } + } else { + loggingFailure.details.push(line.trim()); + } + } + + // We had no logged failures, there's not really anything we can do here + if (failures.length === 0) { + return { + title: "Flaky test failure with no obvious source", + failures, + }; + } + + // We *could* create multiple failures for multiple groups. + // This would be important if we had multiple flaky tests at the same time. + // I'm choosing not to because it complicates this logic a bit, has the ability to go terribly wrong, + // and also because there's something funny to me about that increasing the urgency of fixing + // flaky tests. If it becomes a serious issue though, I would not mind this being fixed. + const uniqueGroups = new Set(failures.map((failure) => failure.group)); + + if (uniqueGroups.size > 1) { + return { + title: `Multiple flaky test failures in ${Array.from(uniqueGroups) + .sort() + .join(", ")}`, + failures, + }; + } + + const failGroup = failures[0].group; + + if (failures.length > 1) { + return { + title: `Multiple errors in flaky test ${failGroup}`, + failures, + }; + } + + const failure = failures[0]; + + // Common patterns where we can always get a detailed title + const runtimeMatch = failure.headline.match(/Runtime in .+?: (?.+)/); + if (runtimeMatch) { + const runtime = runtimeMatch.groups.error.trim(); + + const invalidTimerMatch = runtime.match(/^Invalid timer:.+object:(?[^[]+).*delegate:(?.+?), source:/); + if (invalidTimerMatch) { + return { + title: `Flaky test ${failGroup}: Invalid timer: ${invalidTimerMatch.groups.proc.trim()} on ${invalidTimerMatch.groups.object.trim()}`, + failures, + }; + } + + return { + title: `Flaky test ${failGroup}: ${runtime}`, + failures, + }; + } + + const hardDelMatch = failure.headline.match(/^(?\/[\w/]+) hard deleted .* times out of a total del count of/); + if (hardDelMatch) { + return { + title: `Flaky hard delete: ${hardDelMatch.groups.object}`, + failures, + }; + } + + // Try to normalize the title and remove anything that might be variable + const normalizedError = failure.headline.replace(/\s*at .+?:[0-9]+.*/g, ""); // " at code.dm:123" + + return { + title: `Flaky test ${failGroup}: ${normalizedError}`, + failures, + }; } async function getExistingIssueId(graphql, context, title) { - // Hope you never have more than 100 of these open! - const { - repository: { - issues: { nodes: openFlakyTestIssues }, - }, - } = await graphql( - ` - query ($owner: String!, $repo: String!, $label: String!) { - repository(owner: $owner, name: $repo) { - issues( - labels: [$label] - first: 100 - orderBy: { field: CREATED_AT, direction: DESC } - states: [OPEN] - ) { - nodes { - number - title - body - } - } - } - } - `, - { - owner: context.repo.owner, - repo: context.repo.repo, - label: LABEL, - } - ); - - const exactTitle = openFlakyTestIssues.find((issue) => issue.title === title); - if (exactTitle !== undefined) { - return exactTitle.number; - } - - const foundInBody = openFlakyTestIssues.find((issue) => - issue.body.includes(``) - ); - if (foundInBody !== undefined) { - return foundInBody.number; - } - - return undefined; + // Hope you never have more than 100 of these open! + const { + repository: { + issues: { nodes: openFlakyTestIssues }, + }, + } = await graphql( + ` + query ($owner: String!, $repo: String!, $label: String!) { + repository(owner: $owner, name: $repo) { + issues( + labels: [$label] + first: 100 + orderBy: { field: CREATED_AT, direction: DESC } + states: [OPEN] + ) { + nodes { + number + title + body + } + } + } + } + `, + { + owner: context.repo.owner, + repo: context.repo.repo, + label: LABEL, + } + ); + + const exactTitle = openFlakyTestIssues.find((issue) => issue.title === title); + if (exactTitle !== undefined) { + return exactTitle.number; + } + + const foundInBody = openFlakyTestIssues.find((issue) => + issue.body.includes(``) + ); + if (foundInBody !== undefined) { + return foundInBody.number; + } + + return undefined; } function createBody({ title, failures }, runUrl) { - return ` + return ` @@ -209,67 +227,67 @@ function createBody({ title, failures }, runUrl) { Failures: \`\`\` ${failures - .map( - (failure) => - `${failure.group}: ${failure.headline}\n\t${failure.details.join("\n")}` - ) - .join("\n")} + .map( + (failure) => + `${failure.group}: ${failure.headline}\n\t${failure.details.join("\n")}` + ) + .join("\n")} \`\`\` `.replace(/^\s*/gm, ""); } export async function reportFlakyTests({ github, context }) { - const failedJobsFromLastRun = await getFailedJobsForRun( - github, - context, - context.payload.workflow_run.id, - context.payload.workflow_run.run_attempt - 1 - ); - - // This could one day be relaxed if we face serious enough flaky test problems, so we're going to loop anyway - if (failedJobsFromLastRun.length !== 1) { - console.log( - "Multiple jobs failing after retry, assuming maintainer rerun." - ); - - return; - } - - for (const job of failedJobsFromLastRun) { - const { data: log } = - await github.rest.actions.downloadJobLogsForWorkflowRun({ - owner: context.repo.owner, - repo: context.repo.repo, - job_id: job.id, - }); - - const details = extractDetails(log); - - const existingIssueId = await getExistingIssueId( - github.graphql, - context, - details.title - ); - - if (existingIssueId !== undefined) { - // Maybe in the future, if it's helpful, update the existing issue with new links - console.log(`Existing issue found: #${existingIssueId}`); - return; - } - - await github.rest.issues.create({ - owner: context.repo.owner, - repo: context.repo.repo, - title: details.title, - labels: [LABEL], - body: createBody( - details, - `https://github.com/${context.repo.owner}/${ - context.repo.repo - }/actions/runs/${context.payload.workflow_run.id}/attempts/${ - context.payload.workflow_run.run_attempt - 1 - }` - ), - }); - } + const failedJobsFromLastRun = await getFailedJobsForRun( + github, + context, + context.payload.workflow_run.id, + context.payload.workflow_run.run_attempt - 1 + ); + + // This could one day be relaxed if we face serious enough flaky test problems, so we're going to loop anyway + if (failedJobsFromLastRun.length !== 1) { + console.log( + "Multiple jobs failing after retry, assuming maintainer rerun." + ); + + return; + } + + for (const job of failedJobsFromLastRun) { + const { data: log } = + await github.rest.actions.downloadJobLogsForWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + job_id: job.id, + }); + + const details = extractDetails(log); + + const existingIssueId = await getExistingIssueId( + github.graphql, + context, + details.title + ); + + if (existingIssueId !== undefined) { + // Maybe in the future, if it's helpful, update the existing issue with new links + console.log(`Existing issue found: #${existingIssueId}`); + return; + } + + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: details.title, + labels: [LABEL], + body: createBody( + details, + `https://github.com/${context.repo.owner}/${ + context.repo.repo + }/actions/runs/${context.payload.workflow_run.id}/attempts/${ + context.payload.workflow_run.run_attempt - 1 + }` + ), + }); + } } diff --git a/tools/pull_request_hooks/rerunFlakyTests.test.js b/tools/pull_request_hooks/rerunFlakyTests.test.js index eed126df7f2..6a3300ff59b 100644 --- a/tools/pull_request_hooks/rerunFlakyTests.test.js +++ b/tools/pull_request_hooks/rerunFlakyTests.test.js @@ -3,37 +3,43 @@ import fs from "node:fs"; import { extractDetails } from "./rerunFlakyTests.js"; function extractDetailsFromPayload(filename) { - return extractDetails( - fs.readFileSync(`tests/flakyTestPayloads/${filename}.txt`, { - encoding: "utf8", - }) - ); + return extractDetails( + fs.readFileSync(`tests/flakyTestPayloads/${filename}.txt`, { + encoding: "utf8", + }) + ); } const chatClient = extractDetailsFromPayload("chat_client"); assert.equal( - chatClient.title, - "Flaky test create_and_destroy: /datum/computer_file/program/chatclient hard deleted 1 times out of a total del count of 13" + chatClient.title, + "Flaky hard delete: /datum/computer_file/program/chatclient" ); assert.equal(chatClient.failures.length, 1); const monkeyBusiness = extractDetailsFromPayload("monkey_business"); assert.equal( - monkeyBusiness.title, - "Flaky test monkey_business: Cannot execute null.resolve()." + monkeyBusiness.title, + "Flaky test monkey_business: Cannot execute null.resolve()." ); assert.equal(monkeyBusiness.failures.length, 1); const shapeshift = extractDetailsFromPayload("shapeshift"); assert.equal( - shapeshift.title, - "Multiple errors in flaky test shapeshift_spell" + shapeshift.title, + "Multiple errors in flaky test shapeshift_spell" ); assert.equal(shapeshift.failures.length, 16); const multipleFailures = extractDetailsFromPayload("multiple_failures"); assert.equal( - multipleFailures.title, - "Multiple flaky test failures in more_shapeshift_spell, shapeshift_spell" + multipleFailures.title, + "Multiple flaky test failures in more_shapeshift_spell, shapeshift_spell" ); assert.equal(multipleFailures.failures.length, 2); + +const invalidTimer = extractDetailsFromPayload("invalid_timer"); +assert.equal( + invalidTimer.title, + "Flaky test monkey_business: Invalid timer: /datum/looping_sound/proc/start_sound_loop() on /datum/looping_sound/showering" +); diff --git a/tools/pull_request_hooks/tests/flakyTestPayloads/invalid_timer.txt b/tools/pull_request_hooks/tests/flakyTestPayloads/invalid_timer.txt new file mode 100644 index 00000000000..eea9b3774ca --- /dev/null +++ b/tools/pull_request_hooks/tests/flakyTestPayloads/invalid_timer.txt @@ -0,0 +1,2389 @@ +2023-11-12T08:57:50.1971985Z Requested labels: ubuntu-latest +2023-11-12T08:57:50.1972288Z Job defined at: tgstation/tgstation/.github/workflows/run_integration_tests.yml@refs/pull/79384/merge +2023-11-12T08:57:50.1972523Z Reusable workflow chain: +2023-11-12T08:57:50.1972632Z tgstation/tgstation/.github/workflows/ci_suite.yml@refs/pull/79384/merge (0f52a54577af8e336ee4407c83bc6d3bfedd1d11) +2023-11-12T08:57:50.1972727Z -> tgstation/tgstation/.github/workflows/run_integration_tests.yml@refs/pull/79384/merge (0f52a54577af8e336ee4407c83bc6d3bfedd1d11) +2023-11-12T08:57:50.1972819Z Waiting for a runner to pick up this job... +2023-11-12T08:59:41.2590058Z Job is waiting for a hosted runner to come online. +2023-11-12T08:59:44.1017042Z Job is about to start running on the hosted runner: GitHub Actions 11 (hosted) +2023-11-12T08:59:46.1455792Z Current runner version: '2.311.0' +2023-11-12T08:59:46.1479790Z ##[group]Operating System +2023-11-12T08:59:46.1480441Z Ubuntu +2023-11-12T08:59:46.1480899Z 22.04.3 +2023-11-12T08:59:46.1481734Z LTS +2023-11-12T08:59:46.1482077Z ##[endgroup] +2023-11-12T08:59:46.1482560Z ##[group]Runner Image +2023-11-12T08:59:46.1482961Z Image: ubuntu-22.04 +2023-11-12T08:59:46.1483353Z Version: 20231030.2.0 +2023-11-12T08:59:46.1484421Z Included Software: https://github.com/actions/runner-images/blob/ubuntu22/20231030.2/images/linux/Ubuntu2204-Readme.md +2023-11-12T08:59:46.1485799Z Image Release: https://github.com/actions/runner-images/releases/tag/ubuntu22%2F20231030.2 +2023-11-12T08:59:46.1486650Z ##[endgroup] +2023-11-12T08:59:46.1487161Z ##[group]Runner Image Provisioner +2023-11-12T08:59:46.1487606Z 2.0.312.1 +2023-11-12T08:59:46.1487945Z ##[endgroup] +2023-11-12T08:59:46.1490099Z ##[group]GITHUB_TOKEN Permissions +2023-11-12T08:59:46.1491698Z Actions: read +2023-11-12T08:59:46.1492248Z Checks: read +2023-11-12T08:59:46.1492761Z Contents: read +2023-11-12T08:59:46.1493311Z Deployments: read +2023-11-12T08:59:46.1493676Z Discussions: read +2023-11-12T08:59:46.1494123Z Issues: read +2023-11-12T08:59:46.1494582Z Metadata: read +2023-11-12T08:59:46.1494935Z Packages: read +2023-11-12T08:59:46.1495330Z Pages: read +2023-11-12T08:59:46.1495763Z PullRequests: read +2023-11-12T08:59:46.1496142Z RepositoryProjects: read +2023-11-12T08:59:46.1496603Z SecurityEvents: read +2023-11-12T08:59:46.1497060Z Statuses: read +2023-11-12T08:59:46.1497394Z ##[endgroup] +2023-11-12T08:59:46.1500314Z Secret source: None +2023-11-12T08:59:46.1501009Z Prepare workflow directory +2023-11-12T08:59:46.2366322Z Prepare all required actions +2023-11-12T08:59:46.2521312Z Getting action download info +2023-11-12T08:59:46.4989409Z Download action repository 'actions/checkout@v3' (SHA:f43a0e5ff2bd294095638e18286ca9a3d1956744) +2023-11-12T08:59:46.6372596Z Download action repository 'actions/cache@v3' (SHA:704facf57e6136b1bc63b828d79edcd491f0ee84) +2023-11-12T08:59:46.7365405Z Download action repository 'actions/upload-artifact@v3' (SHA:a8a3f3ad30e3422c9c7b888a15615d19a852ae32) +2023-11-12T08:59:46.7793243Z Download action repository 'tgstation/byond-client-compatibility-check@v3' (SHA:d9fac1c9713569fa6681906325ddce115bb53365) +2023-11-12T08:59:47.0659791Z Uses: tgstation/tgstation/.github/workflows/run_integration_tests.yml@refs/pull/79384/merge (0f52a54577af8e336ee4407c83bc6d3bfedd1d11) +2023-11-12T08:59:47.0662504Z ##[group] Inputs +2023-11-12T08:59:47.0663016Z map: tramstation +2023-11-12T08:59:47.0663530Z major: +2023-11-12T08:59:47.0663853Z minor: +2023-11-12T08:59:47.0664217Z max_required_byond_client: 514 +2023-11-12T08:59:47.0664786Z ##[endgroup] +2023-11-12T08:59:47.0665727Z Complete job name: Integration Tests (tramstation) / run_integration_tests +2023-11-12T08:59:47.1316890Z ##[group]Checking docker version +2023-11-12T08:59:47.1331488Z ##[command]/usr/bin/docker version --format '{{.Server.APIVersion}}' +2023-11-12T08:59:47.2035568Z '1.43' +2023-11-12T08:59:47.2048856Z Docker daemon API version: '1.43' +2023-11-12T08:59:47.2049704Z ##[command]/usr/bin/docker version --format '{{.Client.APIVersion}}' +2023-11-12T08:59:47.2209793Z '1.43' +2023-11-12T08:59:47.2229627Z Docker client API version: '1.43' +2023-11-12T08:59:47.2235325Z ##[endgroup] +2023-11-12T08:59:47.2239282Z ##[group]Clean up resources from previous jobs +2023-11-12T08:59:47.2245596Z ##[command]/usr/bin/docker ps --all --quiet --no-trunc --filter "label=bae3f2" +2023-11-12T08:59:47.2382764Z ##[command]/usr/bin/docker network prune --force --filter "label=bae3f2" +2023-11-12T08:59:47.2513406Z ##[endgroup] +2023-11-12T08:59:47.2513906Z ##[group]Create local container network +2023-11-12T08:59:47.2524774Z ##[command]/usr/bin/docker network create --label bae3f2 github_network_bc2270e2d9644957ba98982ec5cf35f2 +2023-11-12T08:59:47.3421425Z 7e144ec3bd040fce7400908b83369d64424efaa98e355fff9ec0d703a41602b1 +2023-11-12T08:59:47.3441937Z ##[endgroup] +2023-11-12T08:59:47.3517647Z ##[group]Starting mysql service container +2023-11-12T08:59:47.3536963Z ##[command]/usr/bin/docker pull mysql:latest +2023-11-12T08:59:47.5471538Z latest: Pulling from library/mysql +2023-11-12T08:59:47.5925068Z 8e0176adc18c: Pulling fs layer +2023-11-12T08:59:47.5926146Z 2d2c52718f65: Pulling fs layer +2023-11-12T08:59:47.5926867Z d88d03ce139b: Pulling fs layer +2023-11-12T08:59:47.5927652Z 4a7d7f11aa1e: Pulling fs layer +2023-11-12T08:59:47.5928644Z ce5949193e4c: Pulling fs layer +2023-11-12T08:59:47.5929143Z f7f024dfb329: Pulling fs layer +2023-11-12T08:59:47.5929598Z 5fc3c840facc: Pulling fs layer +2023-11-12T08:59:47.5930195Z 509068e49488: Pulling fs layer +2023-11-12T08:59:47.5930586Z cbc847bab598: Pulling fs layer +2023-11-12T08:59:47.5930994Z 942bef62a146: Pulling fs layer +2023-11-12T08:59:47.5931450Z f7f024dfb329: Waiting +2023-11-12T08:59:47.5931833Z 5fc3c840facc: Waiting +2023-11-12T08:59:47.5932180Z 509068e49488: Waiting +2023-11-12T08:59:47.5932601Z cbc847bab598: Waiting +2023-11-12T08:59:47.5932952Z 942bef62a146: Waiting +2023-11-12T08:59:47.5933295Z 4a7d7f11aa1e: Waiting +2023-11-12T08:59:47.5933717Z ce5949193e4c: Waiting +2023-11-12T08:59:47.6370843Z 2d2c52718f65: Verifying Checksum +2023-11-12T08:59:47.6371886Z 2d2c52718f65: Download complete +2023-11-12T08:59:47.6628390Z d88d03ce139b: Verifying Checksum +2023-11-12T08:59:47.6630340Z d88d03ce139b: Download complete +2023-11-12T08:59:47.7021669Z ce5949193e4c: Verifying Checksum +2023-11-12T08:59:47.7022614Z ce5949193e4c: Download complete +2023-11-12T08:59:47.7184829Z 4a7d7f11aa1e: Verifying Checksum +2023-11-12T08:59:47.7185700Z 4a7d7f11aa1e: Download complete +2023-11-12T08:59:47.7547210Z f7f024dfb329: Download complete +2023-11-12T08:59:47.8055625Z 509068e49488: Verifying Checksum +2023-11-12T08:59:47.8057291Z 509068e49488: Download complete +2023-11-12T08:59:48.0054531Z 8e0176adc18c: Verifying Checksum +2023-11-12T08:59:48.0055844Z 8e0176adc18c: Download complete +2023-11-12T08:59:48.0721310Z 942bef62a146: Verifying Checksum +2023-11-12T08:59:48.0723241Z 942bef62a146: Download complete +2023-11-12T08:59:48.2055324Z 5fc3c840facc: Verifying Checksum +2023-11-12T08:59:48.2056029Z 5fc3c840facc: Download complete +2023-11-12T08:59:48.2822740Z cbc847bab598: Verifying Checksum +2023-11-12T08:59:48.2824083Z cbc847bab598: Download complete +2023-11-12T08:59:49.3079176Z 8e0176adc18c: Pull complete +2023-11-12T08:59:49.6617199Z 2d2c52718f65: Pull complete +2023-11-12T08:59:49.6872468Z d88d03ce139b: Pull complete +2023-11-12T08:59:49.8872416Z 4a7d7f11aa1e: Pull complete +2023-11-12T08:59:49.9014484Z ce5949193e4c: Pull complete +2023-11-12T08:59:49.9174666Z f7f024dfb329: Pull complete +2023-11-12T08:59:51.3130074Z 5fc3c840facc: Pull complete +2023-11-12T08:59:51.3233267Z 509068e49488: Pull complete +2023-11-12T08:59:56.1487617Z cbc847bab598: Pull complete +2023-11-12T08:59:56.6779169Z 942bef62a146: Pull complete +2023-11-12T08:59:56.6823169Z Digest: sha256:1773f3c7aa9522f0014d0ad2bbdaf597ea3b1643c64c8ccc2123c64afd8b82b1 +2023-11-12T08:59:56.6835281Z Status: Downloaded newer image for mysql:latest +2023-11-12T08:59:56.6843575Z docker.io/library/mysql:latest +2023-11-12T08:59:56.6952276Z ##[command]/usr/bin/docker create --name c43e2a4f7a0044eda3c3640d7583be1f_mysqllatest_210664 --label bae3f2 --network github_network_bc2270e2d9644957ba98982ec5cf35f2 --network-alias mysql -p 3306 --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 -e "MYSQL_ROOT_PASSWORD=root" -e GITHUB_ACTIONS=true -e CI=true mysql:latest +2023-11-12T08:59:56.7205373Z 37a3cfd21d3298b61164877b4eaf9717ee52eda64115ae9cd1aef5206d293ded +2023-11-12T08:59:56.7226574Z ##[command]/usr/bin/docker start 37a3cfd21d3298b61164877b4eaf9717ee52eda64115ae9cd1aef5206d293ded +2023-11-12T08:59:57.0122389Z 37a3cfd21d3298b61164877b4eaf9717ee52eda64115ae9cd1aef5206d293ded +2023-11-12T08:59:57.0147762Z ##[command]/usr/bin/docker ps --all --filter id=37a3cfd21d3298b61164877b4eaf9717ee52eda64115ae9cd1aef5206d293ded --filter status=running --no-trunc --format "{{.ID}} {{.Status}}" +2023-11-12T08:59:57.0270403Z 37a3cfd21d3298b61164877b4eaf9717ee52eda64115ae9cd1aef5206d293ded Up Less than a second (health: starting) +2023-11-12T08:59:57.0292510Z ##[command]/usr/bin/docker port 37a3cfd21d3298b61164877b4eaf9717ee52eda64115ae9cd1aef5206d293ded +2023-11-12T08:59:57.0413612Z 3306/tcp -> 0.0.0.0:32768 +2023-11-12T08:59:57.0414454Z 3306/tcp -> [::]:32768 +2023-11-12T08:59:57.0511341Z ##[endgroup] +2023-11-12T08:59:57.0545971Z ##[group]Waiting for all services to be ready +2023-11-12T08:59:57.0594766Z ##[command]/usr/bin/docker inspect --format="{{if .Config.Healthcheck}}{{print .State.Health.Status}}{{end}}" 37a3cfd21d3298b61164877b4eaf9717ee52eda64115ae9cd1aef5206d293ded +2023-11-12T08:59:57.0736995Z starting +2023-11-12T08:59:57.0767183Z mysql service is starting, waiting 2 seconds before checking again. +2023-11-12T08:59:59.0767458Z ##[command]/usr/bin/docker inspect --format="{{if .Config.Healthcheck}}{{print .State.Health.Status}}{{end}}" 37a3cfd21d3298b61164877b4eaf9717ee52eda64115ae9cd1aef5206d293ded +2023-11-12T08:59:59.0896661Z starting +2023-11-12T08:59:59.0908862Z mysql service is starting, waiting 4 seconds before checking again. +2023-11-12T09:00:03.1488036Z ##[command]/usr/bin/docker inspect --format="{{if .Config.Healthcheck}}{{print .State.Health.Status}}{{end}}" 37a3cfd21d3298b61164877b4eaf9717ee52eda64115ae9cd1aef5206d293ded +2023-11-12T09:00:03.1606151Z starting +2023-11-12T09:00:03.1617891Z mysql service is starting, waiting 8 seconds before checking again. +2023-11-12T09:00:11.5749953Z ##[command]/usr/bin/docker inspect --format="{{if .Config.Healthcheck}}{{print .State.Health.Status}}{{end}}" 37a3cfd21d3298b61164877b4eaf9717ee52eda64115ae9cd1aef5206d293ded +2023-11-12T09:00:11.5876640Z healthy +2023-11-12T09:00:11.5893980Z mysql service is healthy. +2023-11-12T09:00:11.5894520Z ##[endgroup] +2023-11-12T09:00:11.6253438Z ##[group]Run actions/checkout@v3 +2023-11-12T09:00:11.6253862Z with: +2023-11-12T09:00:11.6254192Z repository: tgstation/tgstation +2023-11-12T09:00:11.6254857Z token: *** +2023-11-12T09:00:11.6255173Z ssh-strict: true +2023-11-12T09:00:11.6255558Z persist-credentials: true +2023-11-12T09:00:11.6256022Z clean: true +2023-11-12T09:00:11.6256343Z sparse-checkout-cone-mode: true +2023-11-12T09:00:11.6256740Z fetch-depth: 1 +2023-11-12T09:00:11.6257139Z fetch-tags: false +2023-11-12T09:00:11.6257424Z lfs: false +2023-11-12T09:00:11.6257739Z submodules: false +2023-11-12T09:00:11.6258160Z set-safe-directory: true +2023-11-12T09:00:11.6258498Z ##[endgroup] +2023-11-12T09:00:11.7905131Z Syncing repository: tgstation/tgstation +2023-11-12T09:00:11.7906924Z ##[group]Getting Git version info +2023-11-12T09:00:11.7907608Z Working directory is '/home/runner/work/tgstation/tgstation' +2023-11-12T09:00:11.7908545Z [command]/usr/bin/git version +2023-11-12T09:00:11.7926430Z git version 2.42.0 +2023-11-12T09:00:11.7950009Z ##[endgroup] +2023-11-12T09:00:11.7969428Z Temporarily overriding HOME='/home/runner/work/_temp/36501371-137a-461b-978e-be8cc4242865' before making global git config changes +2023-11-12T09:00:11.7971339Z Adding repository directory to the temporary git global config as a safe directory +2023-11-12T09:00:11.7973813Z [command]/usr/bin/git config --global --add safe.directory /home/runner/work/tgstation/tgstation +2023-11-12T09:00:11.8018133Z Deleting the contents of '/home/runner/work/tgstation/tgstation' +2023-11-12T09:00:11.8021715Z ##[group]Initializing the repository +2023-11-12T09:00:11.8024938Z [command]/usr/bin/git init /home/runner/work/tgstation/tgstation +2023-11-12T09:00:11.8167504Z hint: Using 'master' as the name for the initial branch. This default branch name +2023-11-12T09:00:11.8168867Z hint: is subject to change. To configure the initial branch name to use in all +2023-11-12T09:00:11.8170077Z hint: of your new repositories, which will suppress this warning, call: +2023-11-12T09:00:11.8170644Z hint: +2023-11-12T09:00:11.8171097Z hint: git config --global init.defaultBranch +2023-11-12T09:00:11.8171661Z hint: +2023-11-12T09:00:11.8172234Z hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and +2023-11-12T09:00:11.8173070Z hint: 'development'. The just-created branch can be renamed via this command: +2023-11-12T09:00:11.8173978Z hint: +2023-11-12T09:00:11.8174325Z hint: git branch -m +2023-11-12T09:00:11.8177381Z Initialized empty Git repository in /home/runner/work/tgstation/tgstation/.git/ +2023-11-12T09:00:11.8185891Z [command]/usr/bin/git remote add origin https://github.com/tgstation/tgstation +2023-11-12T09:00:11.8237650Z ##[endgroup] +2023-11-12T09:00:11.8238368Z ##[group]Disabling automatic garbage collection +2023-11-12T09:00:11.8241714Z [command]/usr/bin/git config --local gc.auto 0 +2023-11-12T09:00:11.8277184Z ##[endgroup] +2023-11-12T09:00:11.8277752Z ##[group]Setting up auth +2023-11-12T09:00:11.8283624Z [command]/usr/bin/git config --local --name-only --get-regexp core\.sshCommand +2023-11-12T09:00:11.8319856Z [command]/usr/bin/git submodule foreach --recursive sh -c "git config --local --name-only --get-regexp 'core\.sshCommand' && git config --local --unset-all 'core.sshCommand' || :" +2023-11-12T09:00:11.8657173Z [command]/usr/bin/git config --local --name-only --get-regexp http\.https\:\/\/github\.com\/\.extraheader +2023-11-12T09:00:11.8696672Z [command]/usr/bin/git submodule foreach --recursive sh -c "git config --local --name-only --get-regexp 'http\.https\:\/\/github\.com\/\.extraheader' && git config --local --unset-all 'http.https://github.com/.extraheader' || :" +2023-11-12T09:00:11.8934506Z [command]/usr/bin/git config --local http.https://github.com/.extraheader AUTHORIZATION: basic *** +2023-11-12T09:00:11.8975797Z ##[endgroup] +2023-11-12T09:00:11.8976409Z ##[group]Fetching the repository +2023-11-12T09:00:11.8984535Z [command]/usr/bin/git -c protocol.version=2 fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 origin +0f52a54577af8e336ee4407c83bc6d3bfedd1d11:refs/remotes/pull/79384/merge +2023-11-12T09:00:12.3422502Z remote: Enumerating objects: 14728, done. +2023-11-12T09:00:12.3435399Z remote: Counting objects: 0% (1/14728) +2023-11-12T09:00:12.3437322Z remote: Counting objects: 1% (148/14728) +2023-11-12T09:00:12.3438041Z remote: Counting objects: 2% (295/14728) +2023-11-12T09:00:12.3438941Z remote: Counting objects: 3% (442/14728) +2023-11-12T09:00:12.3440148Z remote: Counting objects: 4% (590/14728) +2023-11-12T09:00:12.3442925Z remote: Counting objects: 5% (737/14728) +2023-11-12T09:00:12.3445483Z remote: Counting objects: 6% (884/14728) +2023-11-12T09:00:12.3447273Z remote: Counting objects: 7% (1031/14728) +2023-11-12T09:00:12.3460133Z remote: Counting objects: 8% (1179/14728) +2023-11-12T09:00:12.3461187Z remote: Counting objects: 9% (1326/14728) +2023-11-12T09:00:12.3461949Z remote: Counting objects: 10% (1473/14728) +2023-11-12T09:00:12.3462472Z remote: Counting objects: 11% (1621/14728) +2023-11-12T09:00:12.3463038Z remote: Counting objects: 12% (1768/14728) +2023-11-12T09:00:12.3463556Z remote: Counting objects: 13% (1915/14728) +2023-11-12T09:00:12.3467828Z remote: Counting objects: 14% (2062/14728) +2023-11-12T09:00:12.3483848Z remote: Counting objects: 15% (2210/14728) +2023-11-12T09:00:12.3489421Z remote: Counting objects: 16% (2357/14728) +2023-11-12T09:00:12.3489959Z remote: Counting objects: 17% (2504/14728) +2023-11-12T09:00:12.3490601Z remote: Counting objects: 18% (2652/14728) +2023-11-12T09:00:12.3491065Z remote: Counting objects: 19% (2799/14728) +2023-11-12T09:00:12.3491549Z remote: Counting objects: 20% (2946/14728) +2023-11-12T09:00:12.3492150Z remote: Counting objects: 21% (3093/14728) +2023-11-12T09:00:12.3492599Z remote: Counting objects: 22% (3241/14728) +2023-11-12T09:00:12.3497394Z remote: Counting objects: 23% (3388/14728) +2023-11-12T09:00:12.3498533Z remote: Counting objects: 24% (3535/14728) +2023-11-12T09:00:12.3499302Z remote: Counting objects: 25% (3682/14728) +2023-11-12T09:00:12.3500231Z remote: Counting objects: 26% (3830/14728) +2023-11-12T09:00:12.3500908Z remote: Counting objects: 27% (3977/14728) +2023-11-12T09:00:12.3501885Z remote: Counting objects: 28% (4124/14728) +2023-11-12T09:00:12.3502758Z remote: Counting objects: 29% (4272/14728) +2023-11-12T09:00:12.3504000Z remote: Counting objects: 30% (4419/14728) +2023-11-12T09:00:12.3508426Z remote: Counting objects: 31% (4566/14728) +2023-11-12T09:00:12.3510860Z remote: Counting objects: 32% (4713/14728) +2023-11-12T09:00:12.3513541Z remote: Counting objects: 33% (4861/14728) +2023-11-12T09:00:12.3517241Z remote: Counting objects: 34% (5008/14728) +2023-11-12T09:00:12.3518978Z remote: Counting objects: 35% (5155/14728) +2023-11-12T09:00:12.3522056Z remote: Counting objects: 36% (5303/14728) +2023-11-12T09:00:12.3522867Z remote: Counting objects: 37% (5450/14728) +2023-11-12T09:00:12.3524352Z remote: Counting objects: 38% (5597/14728) +2023-11-12T09:00:12.3525521Z remote: Counting objects: 39% (5744/14728) +2023-11-12T09:00:12.3526808Z remote: Counting objects: 40% (5892/14728) +2023-11-12T09:00:12.3528838Z remote: Counting objects: 41% (6039/14728) +2023-11-12T09:00:12.3529652Z remote: Counting objects: 42% (6186/14728) +2023-11-12T09:00:12.3531108Z remote: Counting objects: 43% (6334/14728) +2023-11-12T09:00:12.3531942Z remote: Counting objects: 44% (6481/14728) +2023-11-12T09:00:12.3535178Z remote: Counting objects: 45% (6628/14728) +2023-11-12T09:00:12.3536185Z remote: Counting objects: 46% (6775/14728) +2023-11-12T09:00:12.3537509Z remote: Counting objects: 47% (6923/14728) +2023-11-12T09:00:12.3538838Z remote: Counting objects: 48% (7070/14728) +2023-11-12T09:00:12.3539490Z remote: Counting objects: 49% (7217/14728) +2023-11-12T09:00:12.3540416Z remote: Counting objects: 50% (7364/14728) +2023-11-12T09:00:12.3542997Z remote: Counting objects: 51% (7512/14728) +2023-11-12T09:00:12.3546735Z remote: Counting objects: 52% (7659/14728) +2023-11-12T09:00:12.3547627Z remote: Counting objects: 53% (7806/14728) +2023-11-12T09:00:12.3549945Z remote: Counting objects: 54% (7954/14728) +2023-11-12T09:00:12.3551486Z remote: Counting objects: 55% (8101/14728) +2023-11-12T09:00:12.3554841Z remote: Counting objects: 56% (8248/14728) +2023-11-12T09:00:12.3558919Z remote: Counting objects: 57% (8395/14728) +2023-11-12T09:00:12.3559895Z remote: Counting objects: 58% (8543/14728) +2023-11-12T09:00:12.3561635Z remote: Counting objects: 59% (8690/14728) +2023-11-12T09:00:12.3562509Z remote: Counting objects: 60% (8837/14728) +2023-11-12T09:00:12.3565221Z remote: Counting objects: 61% (8985/14728) +2023-11-12T09:00:12.3566377Z remote: Counting objects: 62% (9132/14728) +2023-11-12T09:00:12.3567330Z remote: Counting objects: 63% (9279/14728) +2023-11-12T09:00:12.3568404Z remote: Counting objects: 64% (9426/14728) +2023-11-12T09:00:12.3569399Z remote: Counting objects: 65% (9574/14728) +2023-11-12T09:00:12.3570508Z remote: Counting objects: 66% (9721/14728) +2023-11-12T09:00:12.3573805Z remote: Counting objects: 67% (9868/14728) +2023-11-12T09:00:12.3574713Z remote: Counting objects: 68% (10016/14728) +2023-11-12T09:00:12.3575852Z remote: Counting objects: 69% (10163/14728) +2023-11-12T09:00:12.3576870Z remote: Counting objects: 70% (10310/14728) +2023-11-12T09:00:12.3577724Z remote: Counting objects: 71% (10457/14728) +2023-11-12T09:00:12.3578357Z remote: Counting objects: 72% (10605/14728) +2023-11-12T09:00:12.3578886Z remote: Counting objects: 73% (10752/14728) +2023-11-12T09:00:12.3579497Z remote: Counting objects: 74% (10899/14728) +2023-11-12T09:00:12.3580417Z remote: Counting objects: 75% (11046/14728) +2023-11-12T09:00:12.3581097Z remote: Counting objects: 76% (11194/14728) +2023-11-12T09:00:12.3581574Z remote: Counting objects: 77% (11341/14728) +2023-11-12T09:00:12.3582409Z remote: Counting objects: 78% (11488/14728) +2023-11-12T09:00:12.3582915Z remote: Counting objects: 79% (11636/14728) +2023-11-12T09:00:12.3583405Z remote: Counting objects: 80% (11783/14728) +2023-11-12T09:00:12.3583954Z remote: Counting objects: 81% (11930/14728) +2023-11-12T09:00:12.3586461Z remote: Counting objects: 82% (12077/14728) +2023-11-12T09:00:12.3587052Z remote: Counting objects: 83% (12225/14728) +2023-11-12T09:00:12.3587941Z remote: Counting objects: 84% (12372/14728) +2023-11-12T09:00:12.3588988Z remote: Counting objects: 85% (12519/14728) +2023-11-12T09:00:12.3591543Z remote: Counting objects: 86% (12667/14728) +2023-11-12T09:00:12.3594301Z remote: Counting objects: 87% (12814/14728) +2023-11-12T09:00:12.3597908Z remote: Counting objects: 88% (12961/14728) +2023-11-12T09:00:12.3601958Z remote: Counting objects: 89% (13108/14728) +2023-11-12T09:00:12.3605574Z remote: Counting objects: 90% (13256/14728) +2023-11-12T09:00:12.3610280Z remote: Counting objects: 91% (13403/14728) +2023-11-12T09:00:12.3612894Z remote: Counting objects: 92% (13550/14728) +2023-11-12T09:00:12.3615660Z remote: Counting objects: 93% (13698/14728) +2023-11-12T09:00:12.3619462Z remote: Counting objects: 94% (13845/14728) +2023-11-12T09:00:12.3623758Z remote: Counting objects: 95% (13992/14728) +2023-11-12T09:00:12.3628748Z remote: Counting objects: 96% (14139/14728) +2023-11-12T09:00:12.3636487Z remote: Counting objects: 97% (14287/14728) +2023-11-12T09:00:12.3641426Z remote: Counting objects: 98% (14434/14728) +2023-11-12T09:00:12.3646422Z remote: Counting objects: 99% (14581/14728) +2023-11-12T09:00:12.3649144Z remote: Counting objects: 100% (14728/14728) +2023-11-12T09:00:12.3649919Z remote: Counting objects: 100% (14728/14728), done. +2023-11-12T09:00:12.3825128Z remote: Compressing objects: 0% (1/13137) +2023-11-12T09:00:12.3961841Z remote: Compressing objects: 1% (132/13137) +2023-11-12T09:00:12.4112502Z remote: Compressing objects: 2% (263/13137) +2023-11-12T09:00:12.4227069Z remote: Compressing objects: 3% (395/13137) +2023-11-12T09:00:12.4228313Z remote: Compressing objects: 4% (526/13137) +2023-11-12T09:00:12.4228983Z remote: Compressing objects: 5% (657/13137) +2023-11-12T09:00:12.4229643Z remote: Compressing objects: 6% (789/13137) +2023-11-12T09:00:12.4271804Z remote: Compressing objects: 7% (920/13137) +2023-11-12T09:00:12.4360389Z remote: Compressing objects: 8% (1051/13137) +2023-11-12T09:00:12.4466461Z remote: Compressing objects: 9% (1183/13137) +2023-11-12T09:00:12.4646998Z remote: Compressing objects: 10% (1314/13137) +2023-11-12T09:00:12.5428669Z remote: Compressing objects: 11% (1446/13137) +2023-11-12T09:00:12.8296153Z remote: Compressing objects: 12% (1577/13137) +2023-11-12T09:00:12.9213149Z remote: Compressing objects: 13% (1708/13137) +2023-11-12T09:00:13.0041408Z remote: Compressing objects: 14% (1840/13137) +2023-11-12T09:00:13.1340856Z remote: Compressing objects: 15% (1971/13137) +2023-11-12T09:00:13.1645036Z remote: Compressing objects: 16% (2102/13137) +2023-11-12T09:00:13.1904768Z remote: Compressing objects: 17% (2234/13137) +2023-11-12T09:00:13.2018494Z remote: Compressing objects: 18% (2365/13137) +2023-11-12T09:00:13.2019779Z remote: Compressing objects: 19% (2497/13137) +2023-11-12T09:00:13.2134073Z remote: Compressing objects: 20% (2628/13137) +2023-11-12T09:00:13.2199911Z remote: Compressing objects: 21% (2759/13137) +2023-11-12T09:00:13.2260920Z remote: Compressing objects: 22% (2891/13137) +2023-11-12T09:00:13.2343043Z remote: Compressing objects: 23% (3022/13137) +2023-11-12T09:00:13.2821833Z remote: Compressing objects: 24% (3153/13137) +2023-11-12T09:00:13.3039708Z remote: Compressing objects: 25% (3285/13137) +2023-11-12T09:00:13.3255129Z remote: Compressing objects: 26% (3416/13137) +2023-11-12T09:00:13.3405305Z remote: Compressing objects: 27% (3547/13137) +2023-11-12T09:00:13.3571381Z remote: Compressing objects: 28% (3679/13137) +2023-11-12T09:00:13.3670018Z remote: Compressing objects: 29% (3810/13137) +2023-11-12T09:00:13.4040877Z remote: Compressing objects: 29% (3868/13137) +2023-11-12T09:00:13.4251871Z remote: Compressing objects: 30% (3942/13137) +2023-11-12T09:00:13.4457155Z remote: Compressing objects: 31% (4073/13137) +2023-11-12T09:00:13.4780533Z remote: Compressing objects: 32% (4204/13137) +2023-11-12T09:00:13.4983464Z remote: Compressing objects: 33% (4336/13137) +2023-11-12T09:00:13.5295246Z remote: Compressing objects: 34% (4467/13137) +2023-11-12T09:00:13.5719629Z remote: Compressing objects: 35% (4598/13137) +2023-11-12T09:00:13.6054442Z remote: Compressing objects: 36% (4730/13137) +2023-11-12T09:00:13.6350098Z remote: Compressing objects: 37% (4861/13137) +2023-11-12T09:00:13.6626461Z remote: Compressing objects: 38% (4993/13137) +2023-11-12T09:00:13.6916464Z remote: Compressing objects: 39% (5124/13137) +2023-11-12T09:00:13.7302124Z remote: Compressing objects: 40% (5255/13137) +2023-11-12T09:00:13.7576240Z remote: Compressing objects: 41% (5387/13137) +2023-11-12T09:00:13.7850663Z remote: Compressing objects: 42% (5518/13137) +2023-11-12T09:00:13.8125191Z remote: Compressing objects: 43% (5649/13137) +2023-11-12T09:00:13.8344430Z remote: Compressing objects: 44% (5781/13137) +2023-11-12T09:00:13.8648361Z remote: Compressing objects: 45% (5912/13137) +2023-11-12T09:00:13.8890504Z remote: Compressing objects: 46% (6044/13137) +2023-11-12T09:00:13.9134975Z remote: Compressing objects: 47% (6175/13137) +2023-11-12T09:00:13.9382739Z remote: Compressing objects: 48% (6306/13137) +2023-11-12T09:00:13.9574317Z remote: Compressing objects: 49% (6438/13137) +2023-11-12T09:00:13.9764171Z remote: Compressing objects: 50% (6569/13137) +2023-11-12T09:00:13.9965671Z remote: Compressing objects: 51% (6700/13137) +2023-11-12T09:00:14.0240257Z remote: Compressing objects: 52% (6832/13137) +2023-11-12T09:00:14.0468725Z remote: Compressing objects: 53% (6963/13137) +2023-11-12T09:00:14.0669881Z remote: Compressing objects: 54% (7094/13137) +2023-11-12T09:00:14.0895124Z remote: Compressing objects: 55% (7226/13137) +2023-11-12T09:00:14.1141069Z remote: Compressing objects: 56% (7357/13137) +2023-11-12T09:00:14.1354395Z remote: Compressing objects: 57% (7489/13137) +2023-11-12T09:00:14.1570266Z remote: Compressing objects: 58% (7620/13137) +2023-11-12T09:00:14.1754980Z remote: Compressing objects: 59% (7751/13137) +2023-11-12T09:00:14.2084676Z remote: Compressing objects: 60% (7883/13137) +2023-11-12T09:00:14.2310657Z remote: Compressing objects: 61% (8014/13137) +2023-11-12T09:00:14.2625166Z remote: Compressing objects: 62% (8145/13137) +2023-11-12T09:00:14.2909864Z remote: Compressing objects: 63% (8277/13137) +2023-11-12T09:00:14.3192565Z remote: Compressing objects: 64% (8408/13137) +2023-11-12T09:00:14.3424597Z remote: Compressing objects: 65% (8540/13137) +2023-11-12T09:00:14.3648230Z remote: Compressing objects: 66% (8671/13137) +2023-11-12T09:00:14.3654208Z remote: Compressing objects: 67% (8802/13137) +2023-11-12T09:00:14.3852572Z remote: Compressing objects: 67% (8803/13137) +2023-11-12T09:00:14.4083890Z remote: Compressing objects: 68% (8934/13137) +2023-11-12T09:00:14.4346236Z remote: Compressing objects: 69% (9065/13137) +2023-11-12T09:00:14.4412610Z remote: Compressing objects: 70% (9196/13137) +2023-11-12T09:00:14.4438826Z remote: Compressing objects: 71% (9328/13137) +2023-11-12T09:00:14.4557338Z remote: Compressing objects: 72% (9459/13137) +2023-11-12T09:00:14.4560053Z remote: Compressing objects: 73% (9591/13137) +2023-11-12T09:00:14.4561406Z remote: Compressing objects: 74% (9722/13137) +2023-11-12T09:00:14.4562102Z remote: Compressing objects: 75% (9853/13137) +2023-11-12T09:00:14.4598003Z remote: Compressing objects: 76% (9985/13137) +2023-11-12T09:00:14.4599196Z remote: Compressing objects: 77% (10116/13137) +2023-11-12T09:00:14.4600027Z remote: Compressing objects: 78% (10247/13137) +2023-11-12T09:00:14.4610318Z remote: Compressing objects: 79% (10379/13137) +2023-11-12T09:00:14.4610882Z remote: Compressing objects: 80% (10510/13137) +2023-11-12T09:00:14.4625739Z remote: Compressing objects: 81% (10641/13137) +2023-11-12T09:00:14.4627218Z remote: Compressing objects: 82% (10773/13137) +2023-11-12T09:00:14.4628087Z remote: Compressing objects: 83% (10904/13137) +2023-11-12T09:00:14.4628755Z remote: Compressing objects: 84% (11036/13137) +2023-11-12T09:00:14.4641964Z remote: Compressing objects: 85% (11167/13137) +2023-11-12T09:00:14.4643000Z remote: Compressing objects: 86% (11298/13137) +2023-11-12T09:00:14.4643588Z remote: Compressing objects: 87% (11430/13137) +2023-11-12T09:00:14.4644263Z remote: Compressing objects: 88% (11561/13137) +2023-11-12T09:00:14.4644780Z remote: Compressing objects: 89% (11692/13137) +2023-11-12T09:00:14.4667702Z remote: Compressing objects: 90% (11824/13137) +2023-11-12T09:00:14.4763174Z remote: Compressing objects: 91% (11955/13137) +2023-11-12T09:00:14.4790967Z remote: Compressing objects: 92% (12087/13137) +2023-11-12T09:00:14.4805225Z remote: Compressing objects: 93% (12218/13137) +2023-11-12T09:00:14.4826093Z remote: Compressing objects: 94% (12349/13137) +2023-11-12T09:00:14.4845748Z remote: Compressing objects: 95% (12481/13137) +2023-11-12T09:00:14.4852480Z remote: Compressing objects: 96% (12612/13137) +2023-11-12T09:00:14.4863608Z remote: Compressing objects: 97% (12743/13137) +2023-11-12T09:00:14.4890566Z remote: Compressing objects: 98% (12875/13137) +2023-11-12T09:00:14.4901499Z remote: Compressing objects: 99% (13006/13137) +2023-11-12T09:00:14.4905499Z remote: Compressing objects: 100% (13137/13137) +2023-11-12T09:00:14.4906263Z remote: Compressing objects: 100% (13137/13137), done. +2023-11-12T09:00:14.5298519Z Receiving objects: 0% (1/14728) +2023-11-12T09:00:14.7511556Z Receiving objects: 1% (148/14728) +2023-11-12T09:00:15.0383718Z Receiving objects: 2% (295/14728) +2023-11-12T09:00:15.0790920Z Receiving objects: 3% (442/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.1841924Z Receiving objects: 4% (590/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.1886539Z Receiving objects: 5% (737/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.1946135Z Receiving objects: 6% (884/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.2129478Z Receiving objects: 7% (1031/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.2298890Z Receiving objects: 8% (1179/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.2441190Z Receiving objects: 9% (1326/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.2535883Z Receiving objects: 10% (1473/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.2682741Z Receiving objects: 11% (1621/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.2854458Z Receiving objects: 12% (1768/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.2953047Z Receiving objects: 13% (1915/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.2998284Z Receiving objects: 14% (2062/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.3017511Z Receiving objects: 15% (2210/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.3161978Z Receiving objects: 16% (2357/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.3233106Z Receiving objects: 17% (2504/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.3483968Z Receiving objects: 18% (2652/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.3784019Z Receiving objects: 19% (2799/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.3954481Z Receiving objects: 20% (2946/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.4245221Z Receiving objects: 21% (3093/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.4470709Z Receiving objects: 22% (3241/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.4723098Z Receiving objects: 23% (3388/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.4937347Z Receiving objects: 24% (3535/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.4944940Z Receiving objects: 24% (3669/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.5175139Z Receiving objects: 25% (3682/14728), 2.91 MiB | 5.72 MiB/s +2023-11-12T09:00:15.5292638Z Receiving objects: 26% (3830/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.5497254Z Receiving objects: 27% (3977/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.5672343Z Receiving objects: 28% (4124/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.5843576Z Receiving objects: 29% (4272/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.5937090Z Receiving objects: 30% (4419/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.6094771Z Receiving objects: 31% (4566/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.6238194Z Receiving objects: 32% (4713/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.6342923Z Receiving objects: 33% (4861/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.6565056Z Receiving objects: 34% (5008/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.6729745Z Receiving objects: 35% (5155/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.6807225Z Receiving objects: 36% (5303/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.6932642Z Receiving objects: 37% (5450/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.7116778Z Receiving objects: 38% (5597/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.7226855Z Receiving objects: 39% (5744/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.7368698Z Receiving objects: 40% (5892/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.7722704Z Receiving objects: 41% (6039/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.8013149Z Receiving objects: 42% (6186/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.8245559Z Receiving objects: 43% (6334/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.8412984Z Receiving objects: 44% (6481/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.8809019Z Receiving objects: 45% (6628/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.9077444Z Receiving objects: 46% (6775/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.9198076Z Receiving objects: 47% (6923/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.9335440Z Receiving objects: 48% (7070/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.9409235Z Receiving objects: 49% (7217/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.9475966Z Receiving objects: 50% (7364/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.9632751Z Receiving objects: 51% (7512/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.9710761Z Receiving objects: 52% (7659/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:15.9997665Z Receiving objects: 53% (7806/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:16.1754062Z Receiving objects: 54% (7954/14728), 8.94 MiB | 8.86 MiB/s +2023-11-12T09:00:16.4937069Z Receiving objects: 55% (8101/14728), 16.55 MiB | 10.97 MiB/s +2023-11-12T09:00:16.4977595Z Receiving objects: 55% (8228/14728), 16.55 MiB | 10.97 MiB/s +2023-11-12T09:00:16.5335682Z Receiving objects: 56% (8248/14728), 16.55 MiB | 10.97 MiB/s +2023-11-12T09:00:16.5529510Z Receiving objects: 57% (8395/14728), 40.02 MiB | 19.93 MiB/s +2023-11-12T09:00:16.6298834Z Receiving objects: 58% (8543/14728), 40.02 MiB | 19.93 MiB/s +2023-11-12T09:00:16.6477417Z Receiving objects: 59% (8690/14728), 40.02 MiB | 19.93 MiB/s +2023-11-12T09:00:16.6877035Z Receiving objects: 60% (8837/14728), 40.02 MiB | 19.93 MiB/s +2023-11-12T09:00:16.7190945Z Receiving objects: 61% (8985/14728), 40.02 MiB | 19.93 MiB/s +2023-11-12T09:00:16.7421126Z Receiving objects: 62% (9132/14728), 40.02 MiB | 19.93 MiB/s +2023-11-12T09:00:16.7678021Z Receiving objects: 63% (9279/14728), 40.02 MiB | 19.93 MiB/s +2023-11-12T09:00:16.8523998Z Receiving objects: 64% (9426/14728), 40.02 MiB | 19.93 MiB/s +2023-11-12T09:00:17.1043001Z Receiving objects: 65% (9574/14728), 40.02 MiB | 19.93 MiB/s +2023-11-12T09:00:17.3854775Z Receiving objects: 66% (9721/14728), 71.27 MiB | 28.42 MiB/s +2023-11-12T09:00:17.4325550Z Receiving objects: 67% (9868/14728), 71.27 MiB | 28.42 MiB/s +2023-11-12T09:00:17.4843860Z Receiving objects: 68% (10016/14728), 71.27 MiB | 28.42 MiB/s +2023-11-12T09:00:17.4974216Z Receiving objects: 69% (10163/14728), 71.27 MiB | 28.42 MiB/s +2023-11-12T09:00:17.5355293Z Receiving objects: 69% (10174/14728), 71.27 MiB | 28.42 MiB/s +2023-11-12T09:00:17.6035052Z Receiving objects: 70% (10310/14728), 104.98 MiB | 34.90 MiB/s +2023-11-12T09:00:17.6662170Z Receiving objects: 71% (10457/14728), 104.98 MiB | 34.90 MiB/s +2023-11-12T09:00:17.7426342Z Receiving objects: 72% (10605/14728), 104.98 MiB | 34.90 MiB/s +2023-11-12T09:00:17.7732421Z Receiving objects: 73% (10752/14728), 104.98 MiB | 34.90 MiB/s +2023-11-12T09:00:17.7890371Z Receiving objects: 74% (10899/14728), 104.98 MiB | 34.90 MiB/s +2023-11-12T09:00:17.8003342Z Receiving objects: 75% (11046/14728), 104.98 MiB | 34.90 MiB/s +2023-11-12T09:00:17.8123812Z Receiving objects: 76% (11194/14728), 104.98 MiB | 34.90 MiB/s +2023-11-12T09:00:17.8868154Z Receiving objects: 77% (11341/14728), 104.98 MiB | 34.90 MiB/s +2023-11-12T09:00:17.9248750Z Receiving objects: 78% (11488/14728), 104.98 MiB | 34.90 MiB/s +2023-11-12T09:00:17.9430493Z Receiving objects: 79% (11636/14728), 104.98 MiB | 34.90 MiB/s +2023-11-12T09:00:17.9815619Z Receiving objects: 80% (11783/14728), 104.98 MiB | 34.90 MiB/s +2023-11-12T09:00:17.9897797Z Receiving objects: 81% (11930/14728), 104.98 MiB | 34.90 MiB/s +2023-11-12T09:00:18.0004021Z Receiving objects: 82% (12077/14728), 104.98 MiB | 34.90 MiB/s +2023-11-12T09:00:18.0065635Z Receiving objects: 83% (12225/14728), 104.98 MiB | 34.90 MiB/s +2023-11-12T09:00:18.0133099Z Receiving objects: 84% (12372/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.0212448Z Receiving objects: 85% (12519/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.0292270Z Receiving objects: 86% (12667/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.0477194Z Receiving objects: 87% (12814/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.1050651Z Receiving objects: 88% (12961/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.1401134Z Receiving objects: 89% (13108/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.1440829Z Receiving objects: 90% (13256/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.1503769Z Receiving objects: 91% (13403/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.1562677Z Receiving objects: 92% (13550/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.1618314Z Receiving objects: 93% (13698/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.1655496Z Receiving objects: 94% (13845/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.1708799Z Receiving objects: 95% (13992/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.1779590Z Receiving objects: 96% (14139/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.1850924Z Receiving objects: 97% (14287/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.1887710Z Receiving objects: 98% (14434/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.1982209Z Receiving objects: 99% (14581/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.1983900Z remote: Total 14728 (delta 1648), reused 9457 (delta 1437), pack-reused 0 +2023-11-12T09:00:18.1993200Z Receiving objects: 100% (14728/14728), 137.62 MiB | 39.23 MiB/s +2023-11-12T09:00:18.1994500Z Receiving objects: 100% (14728/14728), 147.84 MiB | 39.90 MiB/s, done. +2023-11-12T09:00:18.2019068Z Resolving deltas: 0% (0/1648) +2023-11-12T09:00:18.2023348Z Resolving deltas: 1% (17/1648) +2023-11-12T09:00:18.2032679Z Resolving deltas: 2% (33/1648) +2023-11-12T09:00:18.2057515Z Resolving deltas: 3% (50/1648) +2023-11-12T09:00:18.2067595Z Resolving deltas: 4% (66/1648) +2023-11-12T09:00:18.2311083Z Resolving deltas: 5% (83/1648) +2023-11-12T09:00:18.2318508Z Resolving deltas: 6% (99/1648) +2023-11-12T09:00:18.2326847Z Resolving deltas: 7% (116/1648) +2023-11-12T09:00:18.2335304Z Resolving deltas: 8% (132/1648) +2023-11-12T09:00:18.2348077Z Resolving deltas: 9% (149/1648) +2023-11-12T09:00:18.2360740Z Resolving deltas: 10% (165/1648) +2023-11-12T09:00:18.2369574Z Resolving deltas: 11% (182/1648) +2023-11-12T09:00:18.2383691Z Resolving deltas: 12% (198/1648) +2023-11-12T09:00:18.2394926Z Resolving deltas: 13% (215/1648) +2023-11-12T09:00:18.2398748Z Resolving deltas: 14% (231/1648) +2023-11-12T09:00:18.2404491Z Resolving deltas: 15% (248/1648) +2023-11-12T09:00:18.2406714Z Resolving deltas: 16% (264/1648) +2023-11-12T09:00:18.2407998Z Resolving deltas: 17% (281/1648) +2023-11-12T09:00:18.2409292Z Resolving deltas: 18% (297/1648) +2023-11-12T09:00:18.2411513Z Resolving deltas: 19% (315/1648) +2023-11-12T09:00:18.2413614Z Resolving deltas: 20% (330/1648) +2023-11-12T09:00:18.2414462Z Resolving deltas: 21% (347/1648) +2023-11-12T09:00:18.2418247Z Resolving deltas: 22% (363/1648) +2023-11-12T09:00:18.2418936Z Resolving deltas: 23% (380/1648) +2023-11-12T09:00:18.2419539Z Resolving deltas: 24% (396/1648) +2023-11-12T09:00:18.2427604Z Resolving deltas: 25% (412/1648) +2023-11-12T09:00:18.2432866Z Resolving deltas: 26% (429/1648) +2023-11-12T09:00:18.2441981Z Resolving deltas: 27% (445/1648) +2023-11-12T09:00:18.2447582Z Resolving deltas: 28% (462/1648) +2023-11-12T09:00:18.2466027Z Resolving deltas: 29% (478/1648) +2023-11-12T09:00:18.2471796Z Resolving deltas: 30% (495/1648) +2023-11-12T09:00:18.2480036Z Resolving deltas: 31% (511/1648) +2023-11-12T09:00:18.2490887Z Resolving deltas: 32% (528/1648) +2023-11-12T09:00:18.2494739Z Resolving deltas: 33% (544/1648) +2023-11-12T09:00:18.2502376Z Resolving deltas: 34% (561/1648) +2023-11-12T09:00:18.2508410Z Resolving deltas: 35% (577/1648) +2023-11-12T09:00:18.2513823Z Resolving deltas: 36% (594/1648) +2023-11-12T09:00:18.2527222Z Resolving deltas: 37% (610/1648) +2023-11-12T09:00:18.2537398Z Resolving deltas: 38% (627/1648) +2023-11-12T09:00:18.2549132Z Resolving deltas: 39% (643/1648) +2023-11-12T09:00:18.2554784Z Resolving deltas: 40% (660/1648) +2023-11-12T09:00:18.2556656Z Resolving deltas: 41% (676/1648) +2023-11-12T09:00:18.2557507Z Resolving deltas: 42% (693/1648) +2023-11-12T09:00:18.2558588Z Resolving deltas: 43% (709/1648) +2023-11-12T09:00:18.2559455Z Resolving deltas: 44% (727/1648) +2023-11-12T09:00:18.2561210Z Resolving deltas: 45% (742/1648) +2023-11-12T09:00:18.2562565Z Resolving deltas: 46% (760/1648) +2023-11-12T09:00:18.2563347Z Resolving deltas: 47% (775/1648) +2023-11-12T09:00:18.2564389Z Resolving deltas: 48% (792/1648) +2023-11-12T09:00:18.2565291Z Resolving deltas: 49% (808/1648) +2023-11-12T09:00:18.2566382Z Resolving deltas: 50% (824/1648) +2023-11-12T09:00:18.2567240Z Resolving deltas: 51% (841/1648) +2023-11-12T09:00:18.2568283Z Resolving deltas: 52% (857/1648) +2023-11-12T09:00:18.2573986Z Resolving deltas: 53% (874/1648) +2023-11-12T09:00:18.2578038Z Resolving deltas: 54% (890/1648) +2023-11-12T09:00:18.2579766Z Resolving deltas: 55% (907/1648) +2023-11-12T09:00:18.2583389Z Resolving deltas: 56% (923/1648) +2023-11-12T09:00:18.2587856Z Resolving deltas: 57% (940/1648) +2023-11-12T09:00:18.2589664Z Resolving deltas: 58% (956/1648) +2023-11-12T09:00:18.2591411Z Resolving deltas: 59% (973/1648) +2023-11-12T09:00:18.2594574Z Resolving deltas: 60% (989/1648) +2023-11-12T09:00:18.2597339Z Resolving deltas: 61% (1006/1648) +2023-11-12T09:00:18.2599661Z Resolving deltas: 62% (1022/1648) +2023-11-12T09:00:18.2605805Z Resolving deltas: 63% (1039/1648) +2023-11-12T09:00:18.2606445Z Resolving deltas: 64% (1055/1648) +2023-11-12T09:00:18.2608833Z Resolving deltas: 65% (1072/1648) +2023-11-12T09:00:18.2612033Z Resolving deltas: 66% (1088/1648) +2023-11-12T09:00:18.2614253Z Resolving deltas: 67% (1105/1648) +2023-11-12T09:00:18.2618118Z Resolving deltas: 68% (1121/1648) +2023-11-12T09:00:18.2619827Z Resolving deltas: 69% (1138/1648) +2023-11-12T09:00:18.2621203Z Resolving deltas: 70% (1154/1648) +2023-11-12T09:00:18.2624401Z Resolving deltas: 71% (1171/1648) +2023-11-12T09:00:18.2627592Z Resolving deltas: 72% (1187/1648) +2023-11-12T09:00:18.2630703Z Resolving deltas: 73% (1204/1648) +2023-11-12T09:00:18.2633542Z Resolving deltas: 74% (1220/1648) +2023-11-12T09:00:18.2636165Z Resolving deltas: 75% (1236/1648) +2023-11-12T09:00:18.2638056Z Resolving deltas: 76% (1253/1648) +2023-11-12T09:00:18.2642611Z Resolving deltas: 77% (1269/1648) +2023-11-12T09:00:18.2645574Z Resolving deltas: 78% (1286/1648) +2023-11-12T09:00:18.2650111Z Resolving deltas: 79% (1302/1648) +2023-11-12T09:00:18.2653615Z Resolving deltas: 80% (1319/1648) +2023-11-12T09:00:18.2657080Z Resolving deltas: 81% (1335/1648) +2023-11-12T09:00:18.2661192Z Resolving deltas: 82% (1352/1648) +2023-11-12T09:00:18.2666443Z Resolving deltas: 83% (1368/1648) +2023-11-12T09:00:18.2671066Z Resolving deltas: 84% (1385/1648) +2023-11-12T09:00:18.2675875Z Resolving deltas: 85% (1401/1648) +2023-11-12T09:00:18.2680749Z Resolving deltas: 86% (1418/1648) +2023-11-12T09:00:18.2685418Z Resolving deltas: 87% (1434/1648) +2023-11-12T09:00:18.2691672Z Resolving deltas: 88% (1451/1648) +2023-11-12T09:00:18.2696947Z Resolving deltas: 89% (1467/1648) +2023-11-12T09:00:18.2704268Z Resolving deltas: 90% (1484/1648) +2023-11-12T09:00:18.2714966Z Resolving deltas: 91% (1500/1648) +2023-11-12T09:00:18.2724238Z Resolving deltas: 92% (1518/1648) +2023-11-12T09:00:18.2727054Z Resolving deltas: 93% (1533/1648) +2023-11-12T09:00:18.2732989Z Resolving deltas: 94% (1550/1648) +2023-11-12T09:00:18.2738406Z Resolving deltas: 95% (1567/1648) +2023-11-12T09:00:18.2743401Z Resolving deltas: 96% (1583/1648) +2023-11-12T09:00:18.2748306Z Resolving deltas: 97% (1599/1648) +2023-11-12T09:00:18.2752079Z Resolving deltas: 98% (1616/1648) +2023-11-12T09:00:18.2774732Z Resolving deltas: 99% (1632/1648) +2023-11-12T09:00:18.2776965Z Resolving deltas: 100% (1648/1648) +2023-11-12T09:00:18.2777617Z Resolving deltas: 100% (1648/1648), done. +2023-11-12T09:00:18.4151233Z From https://github.com/tgstation/tgstation +2023-11-12T09:00:18.4152324Z * [new ref] 0f52a54577af8e336ee4407c83bc6d3bfedd1d11 -> pull/79384/merge +2023-11-12T09:00:18.4174692Z ##[endgroup] +2023-11-12T09:00:18.4175546Z ##[group]Determining the checkout info +2023-11-12T09:00:18.4177292Z ##[endgroup] +2023-11-12T09:00:18.4178077Z ##[group]Checking out the ref +2023-11-12T09:00:18.4182006Z [command]/usr/bin/git checkout --progress --force refs/remotes/pull/79384/merge +2023-11-12T09:00:19.4499153Z Updating files: 65% (8853/13535) +2023-11-12T09:00:19.4677754Z Updating files: 66% (8934/13535) +2023-11-12T09:00:19.4881367Z Updating files: 67% (9069/13535) +2023-11-12T09:00:19.5117589Z Updating files: 68% (9204/13535) +2023-11-12T09:00:19.5393100Z Updating files: 69% (9340/13535) +2023-11-12T09:00:19.5649915Z Updating files: 70% (9475/13535) +2023-11-12T09:00:19.5885545Z Updating files: 71% (9610/13535) +2023-11-12T09:00:19.6092470Z Updating files: 72% (9746/13535) +2023-11-12T09:00:19.6193070Z Updating files: 73% (9881/13535) +2023-11-12T09:00:19.6275200Z Updating files: 74% (10016/13535) +2023-11-12T09:00:19.6366161Z Updating files: 75% (10152/13535) +2023-11-12T09:00:19.6497650Z Updating files: 76% (10287/13535) +2023-11-12T09:00:19.6864064Z Updating files: 77% (10422/13535) +2023-11-12T09:00:19.6905958Z Updating files: 78% (10558/13535) +2023-11-12T09:00:19.7095469Z Updating files: 79% (10693/13535) +2023-11-12T09:00:19.7217904Z Updating files: 80% (10828/13535) +2023-11-12T09:00:19.7299066Z Updating files: 81% (10964/13535) +2023-11-12T09:00:19.7371348Z Updating files: 82% (11099/13535) +2023-11-12T09:00:19.7439098Z Updating files: 83% (11235/13535) +2023-11-12T09:00:19.7509681Z Updating files: 84% (11370/13535) +2023-11-12T09:00:19.7583669Z Updating files: 85% (11505/13535) +2023-11-12T09:00:19.7654399Z Updating files: 86% (11641/13535) +2023-11-12T09:00:19.7761508Z Updating files: 87% (11776/13535) +2023-11-12T09:00:19.7996111Z Updating files: 88% (11911/13535) +2023-11-12T09:00:19.8212241Z Updating files: 89% (12047/13535) +2023-11-12T09:00:19.8280038Z Updating files: 90% (12182/13535) +2023-11-12T09:00:19.8351398Z Updating files: 91% (12317/13535) +2023-11-12T09:00:19.8428752Z Updating files: 92% (12453/13535) +2023-11-12T09:00:19.8508292Z Updating files: 93% (12588/13535) +2023-11-12T09:00:19.8572225Z Updating files: 94% (12723/13535) +2023-11-12T09:00:19.8650650Z Updating files: 95% (12859/13535) +2023-11-12T09:00:19.8729362Z Updating files: 96% (12994/13535) +2023-11-12T09:00:19.8829435Z Updating files: 97% (13129/13535) +2023-11-12T09:00:19.8894699Z Updating files: 98% (13265/13535) +2023-11-12T09:00:19.8994866Z Updating files: 99% (13400/13535) +2023-11-12T09:00:19.8995690Z Updating files: 100% (13535/13535) +2023-11-12T09:00:19.8996705Z Updating files: 100% (13535/13535), done. +2023-11-12T09:00:19.9124545Z Note: switching to 'refs/remotes/pull/79384/merge'. +2023-11-12T09:00:19.9125161Z +2023-11-12T09:00:19.9125767Z You are in 'detached HEAD' state. You can look around, make experimental +2023-11-12T09:00:19.9127145Z changes and commit them, and you can discard any commits you make in this +2023-11-12T09:00:19.9128712Z state without impacting any branches by switching back to a branch. +2023-11-12T09:00:19.9129440Z +2023-11-12T09:00:19.9129888Z If you want to create a new branch to retain commits you create, you may +2023-11-12T09:00:19.9131250Z do so (now or later) by using -c with the switch command. Example: +2023-11-12T09:00:19.9131887Z +2023-11-12T09:00:19.9132223Z git switch -c +2023-11-12T09:00:19.9132633Z +2023-11-12T09:00:19.9133095Z Or undo this operation with: +2023-11-12T09:00:19.9133655Z +2023-11-12T09:00:19.9133848Z git switch - +2023-11-12T09:00:19.9134127Z +2023-11-12T09:00:19.9134677Z Turn off this advice by setting config variable advice.detachedHead to false +2023-11-12T09:00:19.9135426Z +2023-11-12T09:00:19.9136195Z HEAD is now at 0f52a54 Merge 2104248ba951649225e5c5cb8168346f0220bdb7 into 1eb94ba2286812853f5c65b2557bf2f8f5e46d4f +2023-11-12T09:00:19.9215939Z ##[endgroup] +2023-11-12T09:00:19.9261644Z [command]/usr/bin/git log -1 --format='%H' +2023-11-12T09:00:19.9293509Z '0f52a54577af8e336ee4407c83bc6d3bfedd1d11' +2023-11-12T09:00:19.9616124Z ##[group]Run actions/cache@v3 +2023-11-12T09:00:19.9616601Z with: +2023-11-12T09:00:19.9616946Z path: ~/BYOND +2023-11-12T09:00:19.9617286Z key: Linux-byond- +2023-11-12T09:00:19.9617686Z enableCrossOsArchive: false +2023-11-12T09:00:19.9618092Z fail-on-cache-miss: false +2023-11-12T09:00:19.9618460Z lookup-only: false +2023-11-12T09:00:19.9618822Z ##[endgroup] +2023-11-12T09:00:20.2859595Z Cache Size: ~4 MB (4090426 B) +2023-11-12T09:00:20.2888527Z [command]/usr/bin/tar -xf /home/runner/work/_temp/edb2b23d-361f-4c19-b676-33998159e0b8/cache.tzst -P -C /home/runner/work/tgstation/tgstation --use-compress-program unzstd +2023-11-12T09:00:20.3193378Z Cache restored successfully +2023-11-12T09:00:20.3317264Z Cache restored from key: Linux-byond- +2023-11-12T09:00:20.3451434Z ##[group]Run sudo systemctl start mysql +2023-11-12T09:00:20.3452154Z sudo systemctl start mysql +2023-11-12T09:00:20.3452715Z mysql -u root -proot -e 'CREATE DATABASE tg_ci;' +2023-11-12T09:00:20.3453355Z mysql -u root -proot tg_ci < SQL/tgstation_schema.sql +2023-11-12T09:00:20.3454118Z mysql -u root -proot -e 'CREATE DATABASE tg_ci_prefixed;' +2023-11-12T09:00:20.3454828Z mysql -u root -proot tg_ci_prefixed < SQL/tgstation_schema_prefixed.sql +2023-11-12T09:00:20.3513329Z shell: /usr/bin/bash -e {0} +2023-11-12T09:00:20.3513775Z ##[endgroup] +2023-11-12T09:00:23.5982676Z mysql: [Warning] Using a password on the command line interface can be insecure. +2023-11-12T09:00:23.6362129Z mysql: [Warning] Using a password on the command line interface can be insecure. +2023-11-12T09:00:24.0220158Z mysql: [Warning] Using a password on the command line interface can be insecure. +2023-11-12T09:00:24.0302175Z mysql: [Warning] Using a password on the command line interface can be insecure. +2023-11-12T09:00:24.3266576Z ##[group]Run bash tools/ci/install_rust_g.sh +2023-11-12T09:00:24.3267216Z bash tools/ci/install_rust_g.sh +2023-11-12T09:00:24.3311615Z shell: /usr/bin/bash -e {0} +2023-11-12T09:00:24.3311996Z ##[endgroup] +2023-11-12T09:00:24.6018389Z 2023-11-12 09:00:24 URL:https://objects.githubusercontent.com/github-production-release-asset-2e65be/127494547/aea9a209-14bc-4b8b-b98c-1ba32c0aaf86?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20231112%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20231112T085850Z&X-Amz-Expires=300&X-Amz-Signature=c3e69a55ec6f839925bb9729c6b2e6b4d5b76b4855bfd64b96933c73f95a6734&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=127494547&response-content-disposition=attachment%3B%20filename%3Dlibrust_g.so&response-content-type=application%2Foctet-stream [66491316/66491316] -> "/home/runner/.byond/bin/librust_g.so" [1] +2023-11-12T09:00:24.6320307Z linux-gate.so.1 (0xf7f74000) +2023-11-12T09:00:24.6321993Z libz.so.1 => /lib32/libz.so.1 (0xf7f45000) +2023-11-12T09:00:24.6322879Z libgcc_s.so.1 => /lib32/libgcc_s.so.1 (0xf7f1e000) +2023-11-12T09:00:24.6323651Z libm.so.6 => /lib32/libm.so.6 (0xf7e16000) +2023-11-12T09:00:24.6324533Z libc.so.6 => /lib32/libc.so.6 (0xf7400000) +2023-11-12T09:00:24.6326012Z /lib/ld-linux.so.2 (0xf7f76000) +2023-11-12T09:00:24.6368501Z ##[group]Run bash tools/ci/install_auxlua.sh +2023-11-12T09:00:24.6369036Z bash tools/ci/install_auxlua.sh +2023-11-12T09:00:24.6417060Z shell: /usr/bin/bash -e {0} +2023-11-12T09:00:24.6417480Z ##[endgroup] +2023-11-12T09:00:24.7086755Z 2023-11-12 09:00:24 URL:https://objects.githubusercontent.com/github-production-release-asset-2e65be/473295481/ec517e6d-2695-477e-ae92-7645fee5b7ce?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20231112%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20231112T085916Z&X-Amz-Expires=300&X-Amz-Signature=e13d49b79e73a573dc4a351e5e9575d601b7f51fc16f9d3f03f959884cdf8941&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=473295481&response-content-disposition=attachment%3B%20filename%3Dlibauxlua.so&response-content-type=application%2Foctet-stream [6045340/6045340] -> "/home/runner/.byond/bin/libauxlua.so" [1] +2023-11-12T09:00:24.7172511Z linux-gate.so.1 (0xf7f77000) +2023-11-12T09:00:24.7173643Z libstdc++.so.6 => /lib32/libstdc++.so.6 (0xf7800000) +2023-11-12T09:00:24.7174378Z libgcc_s.so.1 => /lib32/libgcc_s.so.1 (0xf7f3e000) +2023-11-12T09:00:24.7175045Z libpthread.so.0 => /lib32/libpthread.so.0 (0xf7f39000) +2023-11-12T09:00:24.7176413Z libm.so.6 => /lib32/libm.so.6 (0xf7e31000) +2023-11-12T09:00:24.7177209Z libdl.so.2 => /lib32/libdl.so.2 (0xf7e2c000) +2023-11-12T09:00:24.7177918Z libc.so.6 => /lib32/libc.so.6 (0xf7400000) +2023-11-12T09:00:24.7178575Z /lib/ld-linux.so.2 (0xf7f79000) +2023-11-12T09:00:24.7231003Z ##[group]Run bash tools/ci/install_byond.sh +2023-11-12T09:00:24.7231555Z bash tools/ci/install_byond.sh +2023-11-12T09:00:24.7232077Z source $HOME/BYOND/byond/bin/byondsetup +2023-11-12T09:00:24.7232805Z tools/build/build --ci dm -DCIBUILDING -DANSICOLORS -WError -NWTG0001 +2023-11-12T09:00:24.7274898Z shell: /usr/bin/bash -e {0} +2023-11-12T09:00:24.7275297Z ##[endgroup] +2023-11-12T09:00:24.7365575Z Setting up BYOND. +2023-11-12T09:00:24.7497243Z % Total % Received % Xferd Average Speed Time Time Time Current +2023-11-12T09:00:24.7498339Z Dload Upload Total Spent Left Speed +2023-11-12T09:00:24.7499103Z +2023-11-12T09:00:24.7733411Z 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 +2023-11-12T09:00:24.7884475Z 0 4021k 0 4979 0 0 203k 0 0:00:19 --:--:-- 0:00:19 202k +2023-11-12T09:00:24.7885997Z 100 4021k 100 4021k 0 0 100M 0 --:--:-- --:--:-- --:--:-- 100M +2023-11-12T09:00:24.8068033Z Archive: byond.zip +2023-11-12T09:00:24.8069055Z creating: byond/ +2023-11-12T09:00:24.8069884Z creating: byond/key/ +2023-11-12T09:00:24.8071025Z creating: byond/web/ +2023-11-12T09:00:24.8073333Z inflating: byond/web/child.dms +2023-11-12T09:00:24.8074283Z inflating: byond/web/button.dms +2023-11-12T09:00:24.8076478Z inflating: byond/web/input.dms +2023-11-12T09:00:24.8077391Z inflating: byond/web/text.dms +2023-11-12T09:00:24.8176215Z inflating: byond/web/webclient.dart.js +2023-11-12T09:00:24.8177154Z inflating: byond/web/verbmenu.dms +2023-11-12T09:00:24.8178296Z inflating: byond/web/defaultSkin.dms +2023-11-12T09:00:24.8179798Z inflating: byond/web/hotbar.dms +2023-11-12T09:00:24.8180913Z inflating: byond/web/label.dms +2023-11-12T09:00:24.8181973Z inflating: byond/web/alert.dms +2023-11-12T09:00:24.8182843Z inflating: byond/web/message.dms +2023-11-12T09:00:24.8183665Z inflating: byond/web/drag.png +2023-11-12T09:00:24.8185004Z inflating: byond/web/map.dms +2023-11-12T09:00:24.8186150Z inflating: byond/web/splashlogo.png +2023-11-12T09:00:24.8186893Z inflating: byond/web/drop.png +2023-11-12T09:00:24.8282279Z inflating: byond/web/ext.js +2023-11-12T09:00:24.8283075Z inflating: byond/web/file.dms +2023-11-12T09:00:24.8284575Z inflating: byond/web/grid.dms +2023-11-12T09:00:24.8286207Z inflating: byond/web/bar.dms +2023-11-12T09:00:24.8288946Z inflating: byond/web/dpad.dms +2023-11-12T09:00:24.8289936Z inflating: byond/web/output.dms +2023-11-12T09:00:24.8291365Z inflating: byond/web/tab.dms +2023-11-12T09:00:24.8293155Z inflating: byond/web/info.dms +2023-11-12T09:00:24.8294881Z inflating: byond/web/color.dms +2023-11-12T09:00:24.8296103Z inflating: byond/web/gamepad.dms +2023-11-12T09:00:24.8297532Z inflating: byond/web/browser.dms +2023-11-12T09:00:24.8298158Z inflating: byond/web/status.dms +2023-11-12T09:00:24.8299313Z inflating: byond/web/any.dms +2023-11-12T09:00:24.8300438Z inflating: byond/web/pane.dms +2023-11-12T09:00:24.8302172Z inflating: byond/web/pop.dms +2023-11-12T09:00:24.8303255Z inflating: byond/license.txt +2023-11-12T09:00:24.8303882Z inflating: byond/legal.txt +2023-11-12T09:00:24.8305048Z inflating: byond/Makefile +2023-11-12T09:00:24.8305748Z creating: byond/man/ +2023-11-12T09:00:24.8306319Z creating: byond/man/man6/ +2023-11-12T09:00:24.8307604Z inflating: byond/man/man6/DreamDaemon.6 +2023-11-12T09:00:24.8308434Z inflating: byond/man/man6/DreamMaker.6 +2023-11-12T09:00:24.8309437Z creating: byond/lib/ +2023-11-12T09:00:24.8310004Z creating: byond/host/ +2023-11-12T09:00:24.8311286Z inflating: byond/host/readme.html +2023-11-12T09:00:24.8312492Z inflating: byond/host/readme-unix.txt +2023-11-12T09:00:24.8313289Z creating: byond/host/home/ +2023-11-12T09:00:24.8314244Z creating: byond/host/home/root/ +2023-11-12T09:00:24.8315083Z creating: byond/host/home/root/byond/ +2023-11-12T09:00:24.8315883Z creating: byond/host/home/root/byond/tools/ +2023-11-12T09:00:24.8316724Z creating: byond/host/home/root/byond/tools/root/ +2023-11-12T09:00:24.8321401Z inflating: byond/host/home/root/byond/tools/root/root.dmb +2023-11-12T09:00:24.8322363Z creating: byond/host/shared/ +2023-11-12T09:00:24.8323118Z creating: byond/host/shared/byond/ +2023-11-12T09:00:24.8323939Z creating: byond/host/shared/byond/tools/ +2023-11-12T09:00:24.8324697Z creating: byond/host/shared/byond/tools/ftp/ +2023-11-12T09:00:24.8326100Z inflating: byond/host/shared/byond/tools/ftp/ftp.dmb +2023-11-12T09:00:24.8327214Z creating: byond/host/shared/byond/tools/admin/ +2023-11-12T09:00:24.8332506Z inflating: byond/host/shared/byond/tools/admin/admin.dmb +2023-11-12T09:00:24.8333692Z creating: byond/host/shared-web/ +2023-11-12T09:00:24.8334536Z creating: byond/host/shared-web/web/ +2023-11-12T09:00:24.8335395Z creating: byond/host/shared-web/web/tools/ +2023-11-12T09:00:24.8336389Z creating: byond/host/shared-web/web/tools/admin/ +2023-11-12T09:00:24.8340610Z inflating: byond/host/shared-web/web/tools/admin/index.dmb +2023-11-12T09:00:24.8347816Z inflating: byond/host/host.dmb +2023-11-12T09:00:24.8348686Z inflating: byond/host/host.start +2023-11-12T09:00:24.8349570Z inflating: byond/host/hostconf.orig +2023-11-12T09:00:24.8350612Z inflating: byond/host/hostconf.txt +2023-11-12T09:00:24.8351646Z inflating: byond/readme.txt +2023-11-12T09:00:24.8352393Z creating: byond/bin/ +2023-11-12T09:00:24.8353203Z inflating: byond/bin/byondexec +2023-11-12T09:00:24.8355525Z inflating: byond/bin/DreamDownload +2023-11-12T09:00:24.8915164Z inflating: byond/bin/libbyond.so +2023-11-12T09:00:24.9052390Z inflating: byond/bin/libext.so +2023-11-12T09:00:24.9056691Z inflating: byond/bin/DreamDaemon +2023-11-12T09:00:24.9060064Z inflating: byond/bin/DreamMaker +2023-11-12T09:00:24.9060916Z creating: byond/cfg/ +2023-11-12T09:00:24.9061543Z inflating: byond/cfg/release.txt +2023-11-12T09:00:24.9218525Z *************************** +2023-11-12T09:00:24.9225188Z Now run the following command: +2023-11-12T09:00:24.9233824Z +2023-11-12T09:00:24.9243155Z source /home/runner/BYOND/byond/bin/byondsetup +2023-11-12T09:00:24.9251769Z +2023-11-12T09:00:24.9259232Z If it generates errors, your shell is not compatible with 'sh', so you will +2023-11-12T09:00:24.9265751Z have to edit byondsetup and make it work with your shell. If the script works, you should be able to run DreamDaemon. +2023-11-12T09:00:24.9273703Z +2023-11-12T09:00:24.9280708Z IMPORTANT: once you have the script working, you must add the above line +2023-11-12T09:00:24.9287739Z to your startup script. The name of your startup script depends on the +2023-11-12T09:00:24.9294443Z shell you use. Typical ones are .profile or .bash_profile. +2023-11-12T09:00:24.9302682Z +2023-11-12T09:00:24.9309851Z Once everything is working, you can find out more about the software +2023-11-12T09:00:24.9316763Z by doing 'man DreamDaemon'. A host server has also been included +2023-11-12T09:00:24.9323620Z so edit host/hostconf.txt and boot up your world server! +2023-11-12T09:00:24.9330177Z *************************** +2023-11-12T09:00:24.9736645Z Using system-wide Node v18.18.2 +2023-11-12T09:00:25.1112864Z :: Juke Build version 0.8.1 +2023-11-12T09:00:25.3377241Z => Starting 'dm' +2023-11-12T09:00:25.3385788Z :: Using defines: CBT, CIBUILDING, ANSICOLORS +2023-11-12T09:00:25.6662719Z DM compiler version 514.1588 +2023-11-12T09:00:25.6663169Z loading tgstation.m.dme +2023-11-12T09:00:25.9197564Z code/__DEFINES/qdel.dm:22:warning: #warn TG0001 qdel REFERENCE_TRACKING enabled +2023-11-12T09:00:36.5749452Z loading interface/skin.dmf +2023-11-12T09:01:29.5751892Z loading map_files/generic/CentCom.dmm +2023-11-12T09:01:29.9653644Z saving tgstation.m.dmb (DEBUG mode) +2023-11-12T09:01:30.6467137Z tgstation.m.dmb - 0 errors, 1 warning (11/12/23 9:01 am) +2023-11-12T09:01:30.6468251Z Total time: 1:05 +2023-11-12T09:01:31.6898602Z => Finished 'dm' in 66.352s +2023-11-12T09:01:31.6901009Z => Done in 66.578s +2023-11-12T09:01:31.7007243Z ##[group]Run source $HOME/BYOND/byond/bin/byondsetup +2023-11-12T09:01:31.7007981Z source $HOME/BYOND/byond/bin/byondsetup +2023-11-12T09:01:31.7008503Z bash tools/ci/run_server.sh tramstation +2023-11-12T09:01:31.7058146Z shell: /usr/bin/bash -e {0} +2023-11-12T09:01:31.7058547Z ##[endgroup] +2023-11-12T09:01:31.7139001Z Testing tramstation +2023-11-12T09:01:32.0865721Z cp: cannot stat 'tgui/packages/tgfont/dist/*': No such file or directory +2023-11-12T09:01:32.1025274Z Sun Nov 12 09:01:32 2023 +2023-11-12T09:01:32.1026062Z World opened on network port 34125. +2023-11-12T09:01:32.1026759Z Welcome BYOND! (5.0 Public Version 514.1588) +2023-11-12T09:01:54.2375415Z World loaded at 09:01:54! +2023-11-12T09:01:54.2376123Z Running /tg/ revision: +2023-11-12T09:01:54.2376721Z No commit information +2023-11-12T09:01:54.2377340Z Running rust-g version 3.0.0 +2023-11-12T09:01:54.2445249Z Loading config file config.txt... +2023-11-12T09:01:54.2449139Z Loading config file maps.txt... +2023-11-12T09:01:54.2703464Z Unable to locate admins backup file. +2023-11-12T09:01:55.2792475Z Initialized Title Screen subsystem within 0 seconds! +2023-11-12T09:01:55.2793681Z Initialized Server Tasks subsystem within 0 seconds! +2023-11-12T09:01:55.2795047Z Initialized Input subsystem within 0 seconds! +2023-11-12T09:01:55.2858203Z Initialized Profiler subsystem within 0 seconds! +2023-11-12T09:01:55.2859689Z Initialized Database subsystem within 0 seconds! +2023-11-12T09:01:55.2862218Z Initialized Blackbox subsystem within 0 seconds! +2023-11-12T09:01:55.2938165Z Initialized Sounds subsystem within 0.01 seconds! +2023-11-12T09:01:55.3061210Z Initialized Instruments subsystem within 0.01 seconds! +2023-11-12T09:01:55.8390630Z Initialized Greyscale subsystem within 0.53 seconds! +2023-11-12T09:01:55.8391416Z Initialized Vis contents overlays subsystem within 0 seconds! +2023-11-12T09:01:55.8392841Z Initialized Security Level subsystem within 0 seconds! +2023-11-12T09:01:55.8412303Z Initialized Station subsystem within 0 seconds! +2023-11-12T09:01:55.8426733Z Initialized Quirks subsystem within 0 seconds! +2023-11-12T09:01:55.8553936Z Initialized Reagents subsystem within 0.01 seconds! +2023-11-12T09:01:55.8563912Z Initialized Events subsystem within 0 seconds! +2023-11-12T09:01:55.8612984Z Initialized IDs and Access subsystem within 0 seconds! +2023-11-12T09:01:55.8616522Z Initialized Jobs subsystem within 0 seconds! +2023-11-12T09:01:55.8618600Z Initialized AI movement subsystem within 0 seconds! +2023-11-12T09:01:55.8637284Z Initialized Ticker subsystem within 0 seconds! +2023-11-12T09:01:55.8693586Z Initialized AI Controller Ticker subsystem within 0.01 seconds! +2023-11-12T09:01:55.8697702Z Initialized AI Behavior Ticker subsystem within 0 seconds! +2023-11-12T09:01:55.8821358Z Initialized Trading Card Game subsystem within 0.01 seconds! +2023-11-12T09:01:55.8968123Z Loading Tramstation... +2023-11-12T09:01:57.4366548Z Loaded Station in 1.6s! +2023-11-12T09:01:58.7018385Z Loaded Lavaland in 1.3s! +2023-11-12T09:01:59.6958478Z All ruins being loaded for map testing. +2023-11-12T09:01:59.6960551Z Ruin loader finished with 0 left to spend. +2023-11-12T09:01:59.6963383Z All ruins being loaded for map testing. +2023-11-12T09:01:59.6966951Z Ruin loader finished with 0 left to spend. +2023-11-12T09:01:59.8030218Z Cave Generator terrain generation finished in 0.1s! +2023-11-12T09:01:59.8242156Z Cave Generator terrain generation finished in 0s! +2023-11-12T09:02:00.0123579Z Cave Generator terrain population finished in 0.1s! +2023-11-12T09:02:00.0174657Z Cave Generator terrain population finished in 0s! +2023-11-12T09:02:00.4204586Z Initialized Mapping subsystem within 4.54 seconds! +2023-11-12T09:02:18.7137331Z Initialized Early Assets subsystem within 18.29 seconds! +2023-11-12T09:02:18.7960177Z Initialized Research subsystem within 0.08 seconds! +2023-11-12T09:02:18.7964943Z Initialized Time Tracking subsystem within 0 seconds! +2023-11-12T09:02:18.8516125Z Initialized Spatial Grid subsystem within 0.05 seconds! +2023-11-12T09:02:18.8519915Z Initialized Economy subsystem within 0 seconds! +2023-11-12T09:02:18.8529046Z Initialized Restaurant subsystem within 0 seconds! +2023-11-12T09:02:24.3564078Z The BYOND hub reports that port 34125 is not reachable. +2023-11-12T09:03:00.5242715Z ## NOTICE: morgue_cadaver_disable_nonhumans. There are no valid roundstart nonhuman races enabled. Defaulting to humans only! +2023-11-12T09:03:08.8938364Z Initialized Atoms subsystem within 50.04 seconds! +2023-11-12T09:03:08.9459509Z Initialized Language subsystem within 0.01 seconds! +2023-11-12T09:03:09.0602930Z Initialized Machines subsystem within 0.11 seconds! +2023-11-12T09:03:09.0612163Z Initialized Skills subsystem within 0 seconds! +2023-11-12T09:03:09.0615253Z Initialized Queue Links subsystem within 0 seconds! +2023-11-12T09:03:09.0619204Z Initialized Addiction subsystem within 0 seconds! +2023-11-12T09:03:09.0639408Z Initialized Blackmarket subsystem within 0 seconds! +2023-11-12T09:03:09.0647224Z Initialized Disease subsystem within 0 seconds! +2023-11-12T09:03:09.0650704Z Initialized Fluid subsystem within 0 seconds! +2023-11-12T09:03:09.0654199Z Initialized Smoke subsystem within 0 seconds! +2023-11-12T09:03:09.0657541Z Initialized Foam subsystem within 0 seconds! +2023-11-12T09:03:09.0660882Z Initialized Lag Switch subsystem within 0 seconds! +2023-11-12T09:03:09.0888582Z Initialized Library Loading subsystem within 0.02 seconds! +2023-11-12T09:03:09.2645071Z Initialized Lua Scripting subsystem within 0.18 seconds! +2023-11-12T09:03:09.2735036Z Initialized Modular Computers subsystem within 0.01 seconds! +2023-11-12T09:03:09.2737635Z Initialized Night Shift subsystem within 0 seconds! +2023-11-12T09:03:09.2741231Z Initialized Stock Market subsystem within 0 seconds! +2023-11-12T09:03:09.2743761Z Initialized Sun subsystem within 0 seconds! +2023-11-12T09:03:09.2792256Z Initialized Traitor subsystem within 0 seconds! +2023-11-12T09:03:09.2795417Z Initialized Tutorials subsystem within 0 seconds! +2023-11-12T09:03:09.3133961Z Initialized Wardrobe subsystem within 0.03 seconds! +2023-11-12T09:03:09.3136967Z Initialized Weather subsystem within 0 seconds! +2023-11-12T09:03:09.3140470Z Initialized Wiremod Composite Templates subsystem within 0 seconds! +2023-11-12T09:03:14.7053894Z Initialized Atmospherics subsystem within 5.39 seconds! +2023-11-12T09:03:14.7127034Z Initialized Persistence subsystem within 0.01 seconds! +2023-11-12T09:03:14.7131026Z Initialized Persistent Paintings subsystem within 0 seconds! +2023-11-12T09:03:14.7134716Z Initialized Vote subsystem within 0 seconds! +2023-11-12T09:03:25.6600909Z Initialized Assets subsystem within 10.95 seconds! +2023-11-12T09:03:29.1318017Z Initialized Icon Smoothing subsystem within 3.42 seconds! +2023-11-12T09:03:29.1329352Z Initialized XKeyScore subsystem within 0 seconds! +2023-11-12T09:03:29.1349808Z Initialized PRISM subsystem within 0 seconds! +2023-11-12T09:03:39.5066635Z Initialized Lighting subsystem within 10.37 seconds! +2023-11-12T09:03:42.0097538Z Initialized Shuttle subsystem within 2.5 seconds! +2023-11-12T09:03:42.0100528Z Initialized Pathfinder subsystem within 0 seconds! +2023-11-12T09:03:42.0112119Z Initialized Ban Cache subsystem within 0 seconds! +2023-11-12T09:03:42.0114877Z Initialized Init Profiler subsystem within 0 seconds! +2023-11-12T09:03:42.0117470Z Initialized Chat subsystem within 0 seconds! +2023-11-12T09:03:42.0119918Z Initializations complete within 106.8 seconds! +2023-11-12T09:03:42.0699329Z Game start took 0s +2023-11-12T09:03:53.5395990Z ##[group]/datum/unit_test/log_mapping +2023-11-12T09:03:53.5399338Z PASS /datum/unit_test/log_mapping 0s +2023-11-12T09:03:53.5400530Z ##[endgroup] +2023-11-12T09:03:53.5529741Z ##[group]/datum/unit_test/abductor_baton_spell +2023-11-12T09:03:53.6248315Z PASS /datum/unit_test/abductor_baton_spell 0.1s +2023-11-12T09:03:53.6250017Z ##[endgroup] +2023-11-12T09:03:53.7293652Z ##[group]/datum/unit_test/ablative_hood_hud +2023-11-12T09:03:53.7538980Z PASS /datum/unit_test/ablative_hood_hud 0s +2023-11-12T09:03:53.7540945Z ##[endgroup] +2023-11-12T09:03:53.8177940Z ##[group]/datum/unit_test/ablative_hood_hud_with_helmet +2023-11-12T09:03:53.8373528Z PASS /datum/unit_test/ablative_hood_hud_with_helmet 0s +2023-11-12T09:03:53.8375040Z ##[endgroup] +2023-11-12T09:03:53.9037089Z ##[group]/datum/unit_test/achievements +2023-11-12T09:03:53.9146939Z PASS /datum/unit_test/achievements 0s +2023-11-12T09:03:53.9148600Z ##[endgroup] +2023-11-12T09:03:53.9709749Z ##[group]/datum/unit_test/anchored_mobs +2023-11-12T09:03:53.9714871Z PASS /datum/unit_test/anchored_mobs 0s +2023-11-12T09:03:53.9717149Z ##[endgroup] +2023-11-12T09:03:54.0290915Z ##[group]/datum/unit_test/anonymous_themes +2023-11-12T09:03:54.1282674Z PASS /datum/unit_test/anonymous_themes 0.1s +2023-11-12T09:03:54.1284602Z ##[endgroup] +2023-11-12T09:03:54.2369870Z ##[group]/datum/unit_test/revolution_conversion +2023-11-12T09:03:54.2811074Z PASS /datum/unit_test/revolution_conversion 0s +2023-11-12T09:03:54.2812989Z ##[endgroup] +2023-11-12T09:03:54.3619950Z ##[group]/datum/unit_test/cult_conversion +2023-11-12T09:03:54.4185381Z PASS /datum/unit_test/cult_conversion 0.1s +2023-11-12T09:03:54.4187014Z ##[endgroup] +2023-11-12T09:03:54.5109339Z ##[group]/datum/unit_test/antag_moodlets +2023-11-12T09:03:54.5391588Z PASS /datum/unit_test/antag_moodlets 0s +2023-11-12T09:03:54.5393248Z ##[endgroup] +2023-11-12T09:03:54.6099817Z ##[group]/datum/unit_test/armor_verification +2023-11-12T09:03:54.6105398Z PASS /datum/unit_test/armor_verification 0s +2023-11-12T09:03:54.6107086Z ##[endgroup] +2023-11-12T09:03:54.6711998Z ##[group]/datum/unit_test/autowiki +2023-11-12T09:03:56.4795605Z PASS /datum/unit_test/autowiki 1.8s +2023-11-12T09:03:56.4797118Z ##[endgroup] +2023-11-12T09:03:56.5376207Z ##[group]/datum/unit_test/autowiki_include_template +2023-11-12T09:03:56.5378371Z PASS /datum/unit_test/autowiki_include_template 0s +2023-11-12T09:03:56.5380504Z ##[endgroup] +2023-11-12T09:03:56.6003986Z ##[group]/datum/unit_test/barsigns_icon +2023-11-12T09:03:56.6303581Z PASS /datum/unit_test/barsigns_icon 0.1s +2023-11-12T09:03:56.6305267Z ##[endgroup] +2023-11-12T09:03:56.6912219Z ##[group]/datum/unit_test/barsigns_name +2023-11-12T09:03:56.6914950Z PASS /datum/unit_test/barsigns_name 0s +2023-11-12T09:03:56.6917244Z ##[endgroup] +2023-11-12T09:03:56.7530053Z ##[group]/datum/unit_test/baseturfs_unmodified_scrape +2023-11-12T09:03:56.7541656Z PASS /datum/unit_test/baseturfs_unmodified_scrape 0s +2023-11-12T09:03:56.7543322Z ##[endgroup] +2023-11-12T09:03:56.8163460Z ##[group]/datum/unit_test/baseturfs_placed_on_top +2023-11-12T09:03:56.8173471Z PASS /datum/unit_test/baseturfs_placed_on_top 0s +2023-11-12T09:03:56.8175579Z ##[endgroup] +2023-11-12T09:03:56.8789484Z ##[group]/datum/unit_test/baseturfs_placed_on_bottom +2023-11-12T09:03:56.8806366Z PASS /datum/unit_test/baseturfs_placed_on_bottom 0s +2023-11-12T09:03:56.8808190Z ##[endgroup] +2023-11-12T09:03:56.9420497Z ##[group]/datum/unit_test/bespoke_id +2023-11-12T09:03:56.9422999Z PASS /datum/unit_test/bespoke_id 0s +2023-11-12T09:03:56.9425227Z ##[endgroup] +2023-11-12T09:03:57.1727331Z ##[group]/datum/unit_test/binary_insert +2023-11-12T09:03:57.1728436Z PASS /datum/unit_test/binary_insert 0s +2023-11-12T09:03:57.1730597Z ##[endgroup] +2023-11-12T09:03:57.2270246Z ##[group]/datum/unit_test/bitrunner_vdom_settings +2023-11-12T09:03:57.2368664Z PASS /datum/unit_test/bitrunner_vdom_settings 0s +2023-11-12T09:03:57.2370507Z ##[endgroup] +2023-11-12T09:03:57.2860471Z ##[group]/datum/unit_test/blindness +2023-11-12T09:03:57.3060031Z PASS /datum/unit_test/blindness 0.1s +2023-11-12T09:03:57.3061453Z ##[endgroup] +2023-11-12T09:03:57.3685247Z ##[group]/datum/unit_test/nearsightedness +2023-11-12T09:03:57.3856666Z PASS /datum/unit_test/nearsightedness 0s +2023-11-12T09:03:57.3857831Z ##[endgroup] +2023-11-12T09:03:57.4094606Z ##[group]/datum/unit_test/eye_damage +2023-11-12T09:03:57.4266705Z PASS /datum/unit_test/eye_damage 0s +2023-11-12T09:03:57.4268768Z ##[endgroup] +2023-11-12T09:03:57.4514012Z ##[group]/datum/unit_test/bloody_footprints +2023-11-12T09:03:57.4771474Z PASS /datum/unit_test/bloody_footprints 0s +2023-11-12T09:03:57.4773523Z ##[endgroup] +2023-11-12T09:03:57.5095312Z ##[group]/datum/unit_test/breath/breath_sanity +2023-11-12T09:03:57.5793797Z PASS /datum/unit_test/breath/breath_sanity 0s +2023-11-12T09:03:57.5795766Z ##[endgroup] +2023-11-12T09:03:57.6356372Z ##[group]/datum/unit_test/breath/breath_sanity_plasmamen +2023-11-12T09:03:57.6920259Z PASS /datum/unit_test/breath/breath_sanity_plasmamen 0s +2023-11-12T09:03:57.6922126Z ##[endgroup] +2023-11-12T09:03:57.7478880Z ##[group]/datum/unit_test/breath/breath_sanity_ashwalker +2023-11-12T09:03:57.7793279Z PASS /datum/unit_test/breath/breath_sanity_ashwalker 0s +2023-11-12T09:03:57.7794768Z ##[endgroup] +2023-11-12T09:03:57.8063286Z ##[group]/datum/unit_test/burning +2023-11-12T09:03:57.8235820Z PASS /datum/unit_test/burning 0s +2023-11-12T09:03:57.8237580Z ##[endgroup] +2023-11-12T09:03:57.8463809Z ##[group]/datum/unit_test/cable_powernets +2023-11-12T09:03:57.8467369Z PASS /datum/unit_test/cable_powernets 0s +2023-11-12T09:03:57.8468842Z ##[endgroup] +2023-11-12T09:03:57.8681387Z ##[group]/datum/unit_test/card_mismatch +2023-11-12T09:03:57.8715332Z PASS /datum/unit_test/card_mismatch 0s +2023-11-12T09:03:57.8717822Z ##[endgroup] +2023-11-12T09:03:57.8839316Z ##[group]/datum/unit_test/cardboard_cutouts +2023-11-12T09:03:57.8847499Z cardboard_cutouts_normal_cutout was put in data/screenshots_new +2023-11-12T09:03:58.1374772Z cardboard_cutouts_nukie_cutout was put in data/screenshots_new +2023-11-12T09:03:58.1378574Z cardboard_cutouts_nukie_cutout_pushed was put in data/screenshots_new +2023-11-12T09:03:58.1547388Z cardboard_cutouts_xenomorph_cutout was put in data/screenshots_new +2023-11-12T09:03:58.1550933Z PASS /datum/unit_test/cardboard_cutouts 0.3s +2023-11-12T09:03:58.1553499Z ##[endgroup] +2023-11-12T09:03:58.2402466Z ##[group]/datum/unit_test/chain_pull_through_space +2023-11-12T09:03:58.2453035Z PASS /datum/unit_test/chain_pull_through_space 0s +2023-11-12T09:03:58.2454853Z ##[endgroup] +2023-11-12T09:03:58.3033483Z ##[group]/datum/unit_test/transformation_sting +2023-11-12T09:03:59.7549687Z transformation_sting_appearances was put in data/screenshots_new +2023-11-12T09:03:59.7551965Z PASS /datum/unit_test/transformation_sting 1.4s +2023-11-12T09:03:59.7553272Z ##[endgroup] +2023-11-12T09:03:59.7969350Z ##[group]/datum/unit_test/chat_filter_sanity +2023-11-12T09:03:59.7976589Z PASS /datum/unit_test/chat_filter_sanity 0s +2023-11-12T09:03:59.7978237Z ##[endgroup] +2023-11-12T09:03:59.8105892Z ##[group]/datum/unit_test/circuit_component_category +2023-11-12T09:03:59.8107746Z PASS /datum/unit_test/circuit_component_category 0s +2023-11-12T09:03:59.8109947Z ##[endgroup] +2023-11-12T09:03:59.8879728Z ##[group]/datum/unit_test/client_colours +2023-11-12T09:03:59.8889068Z PASS /datum/unit_test/client_colours 0s +2023-11-12T09:03:59.8891665Z ##[endgroup] +2023-11-12T09:03:59.9525316Z ##[group]/datum/unit_test/closets +2023-11-12T09:04:01.8031965Z PASS /datum/unit_test/closets 1.9s +2023-11-12T09:04:01.8033340Z ##[endgroup] +2023-11-12T09:04:02.6399153Z ##[group]/datum/unit_test/clothing_under_armor_subtype_check +2023-11-12T09:04:02.6403381Z PASS /datum/unit_test/clothing_under_armor_subtype_check 0s +2023-11-12T09:04:02.6405014Z ##[endgroup] +2023-11-12T09:04:02.7020573Z ##[group]/datum/unit_test/harm_punch +2023-11-12T09:04:02.7364226Z PASS /datum/unit_test/harm_punch 0s +2023-11-12T09:04:02.7366615Z ##[endgroup] +2023-11-12T09:04:02.7919290Z ##[group]/datum/unit_test/harm_melee +2023-11-12T09:04:02.8266028Z PASS /datum/unit_test/harm_melee 0.1s +2023-11-12T09:04:02.8268574Z ##[endgroup] +2023-11-12T09:04:02.8738136Z ##[group]/datum/unit_test/harm_different_damage +2023-11-12T09:04:02.9125671Z PASS /datum/unit_test/harm_different_damage 0.1s +2023-11-12T09:04:02.9127697Z ##[endgroup] +2023-11-12T09:04:02.9510991Z ##[group]/datum/unit_test/attack_chain +2023-11-12T09:04:02.9859497Z PASS /datum/unit_test/attack_chain 0s +2023-11-12T09:04:02.9861383Z ##[endgroup] +2023-11-12T09:04:03.0312671Z ##[group]/datum/unit_test/disarm +2023-11-12T09:04:03.0675162Z PASS /datum/unit_test/disarm 0s +2023-11-12T09:04:03.0677029Z ##[endgroup] +2023-11-12T09:04:03.1122424Z ##[group]/datum/unit_test/self_punch +2023-11-12T09:04:03.1297149Z PASS /datum/unit_test/self_punch 0s +2023-11-12T09:04:03.1299012Z ##[endgroup] +2023-11-12T09:04:03.1617839Z ##[group]/datum/unit_test/handcuff_punch +2023-11-12T09:04:03.1949728Z PASS /datum/unit_test/handcuff_punch 0s +2023-11-12T09:04:03.1950695Z ##[endgroup] +2023-11-12T09:04:03.2665996Z ##[group]/datum/unit_test/handcuff_bite +2023-11-12T09:04:03.3310134Z PASS /datum/unit_test/handcuff_bite 0.1s +2023-11-12T09:04:03.3311967Z ##[endgroup] +2023-11-12T09:04:03.3720567Z ##[group]/datum/unit_test/component_duping +2023-11-12T09:04:03.3725700Z PASS /datum/unit_test/component_duping 0s +2023-11-12T09:04:03.3728116Z ##[endgroup] +2023-11-12T09:04:03.3854948Z ##[group]/datum/unit_test/confusion_symptom +2023-11-12T09:04:03.4020935Z PASS /datum/unit_test/confusion_symptom 0.1s +2023-11-12T09:04:03.4023437Z ##[endgroup] +2023-11-12T09:04:03.4660129Z ##[group]/datum/unit_test/connect_loc_basic +2023-11-12T09:04:03.4667486Z PASS /datum/unit_test/connect_loc_basic 0s +2023-11-12T09:04:03.4669665Z ##[endgroup] +2023-11-12T09:04:03.5206421Z ##[group]/datum/unit_test/connect_loc_change_turf +2023-11-12T09:04:03.5219191Z PASS /datum/unit_test/connect_loc_change_turf 0s +2023-11-12T09:04:03.5221198Z ##[endgroup] +2023-11-12T09:04:03.5413589Z ##[group]/datum/unit_test/connect_loc_multiple_on_turf +2023-11-12T09:04:03.5422679Z PASS /datum/unit_test/connect_loc_multiple_on_turf 0s +2023-11-12T09:04:03.5424576Z ##[endgroup] +2023-11-12T09:04:03.5552785Z ##[group]/datum/unit_test/reagent_container_sanity +2023-11-12T09:04:03.8101359Z PASS /datum/unit_test/reagent_container_sanity 0.3s +2023-11-12T09:04:03.8102486Z ##[endgroup] +2023-11-12T09:04:03.9680842Z ##[group]/datum/unit_test/crayon_naming +2023-11-12T09:04:03.9683784Z PASS /datum/unit_test/crayon_naming 0s +2023-11-12T09:04:03.9686430Z ##[endgroup] +2023-11-12T09:04:03.9815420Z ##[group]/datum/unit_test/dcs_get_id_from_arguments +2023-11-12T09:04:03.9822614Z PASS /datum/unit_test/dcs_get_id_from_arguments 0s +2023-11-12T09:04:03.9825219Z ##[endgroup] +2023-11-12T09:04:03.9952914Z ##[group]/datum/unit_test/designs +2023-11-12T09:04:04.0032294Z PASS /datum/unit_test/designs 0.1s +2023-11-12T09:04:04.0034986Z ##[endgroup] +2023-11-12T09:04:04.0184498Z ##[group]/datum/unit_test/dismemberment +2023-11-12T09:04:04.0687805Z PASS /datum/unit_test/dismemberment 0s +2023-11-12T09:04:04.0690374Z ##[endgroup] +2023-11-12T09:04:04.1062552Z ##[group]/datum/unit_test/door_access_check +2023-11-12T09:04:04.1315486Z PASS /datum/unit_test/door_access_check 0s +2023-11-12T09:04:04.1318637Z ##[endgroup] +2023-11-12T09:04:04.1659906Z ##[group]/datum/unit_test/contents_barfer +2023-11-12T09:04:04.1881762Z PASS /datum/unit_test/contents_barfer 0s +2023-11-12T09:04:04.1884275Z ##[endgroup] +2023-11-12T09:04:04.2328534Z ##[group]/datum/unit_test/space_dragon_expiration +2023-11-12T09:04:04.2672064Z PASS /datum/unit_test/space_dragon_expiration 0s +2023-11-12T09:04:04.2674522Z ##[endgroup] +2023-11-12T09:04:04.3282341Z ##[group]/datum/unit_test/glass_style_icons +2023-11-12T09:04:04.3517947Z PASS /datum/unit_test/glass_style_icons 0s +2023-11-12T09:04:04.3520368Z ##[endgroup] +2023-11-12T09:04:04.3761901Z ##[group]/datum/unit_test/glass_style_functionality +2023-11-12T09:04:04.3773186Z PASS /datum/unit_test/glass_style_functionality 0s +2023-11-12T09:04:04.3775791Z ##[endgroup] +2023-11-12T09:04:04.3908269Z ##[group]/datum/unit_test/drink_icons +2023-11-12T09:04:04.4155215Z PASS /datum/unit_test/drink_icons 0.1s +2023-11-12T09:04:04.4157609Z ##[endgroup] +2023-11-12T09:04:04.4303228Z ##[group]/datum/unit_test/dummy_spawn_species +2023-11-12T09:04:05.4828810Z PASS /datum/unit_test/dummy_spawn_species 1s +2023-11-12T09:04:05.4829704Z ##[endgroup] +2023-11-12T09:04:05.5166735Z ##[group]/datum/unit_test/dummy_spawn_outfit +2023-11-12T09:04:05.5400845Z Job type /datum/job/ai could not be retrieved from SSjob +2023-11-12T09:04:06.0232636Z PASS /datum/unit_test/dummy_spawn_outfit 0.5s +2023-11-12T09:04:06.0234589Z ##[endgroup] +2023-11-12T09:04:06.0505202Z ##[group]/datum/unit_test/dynamic_roundstart_ruleset_sanity +2023-11-12T09:04:06.0508804Z PASS /datum/unit_test/dynamic_roundstart_ruleset_sanity 0s +2023-11-12T09:04:06.0511050Z ##[endgroup] +2023-11-12T09:04:06.0637233Z ##[group]/datum/unit_test/dynamic_unique_antag_flags +2023-11-12T09:04:06.0640294Z PASS /datum/unit_test/dynamic_unique_antag_flags 0s +2023-11-12T09:04:06.0642513Z ##[endgroup] +2023-11-12T09:04:06.0770713Z ##[group]/datum/unit_test/egg_glands +2023-11-12T09:04:06.1407083Z PASS /datum/unit_test/egg_glands 0.1s +2023-11-12T09:04:06.1408405Z ##[endgroup] +2023-11-12T09:04:06.1628261Z ##[group]/datum/unit_test/emoting +2023-11-12T09:04:06.1818671Z PASS /datum/unit_test/emoting 0s +2023-11-12T09:04:06.1821362Z ##[endgroup] +2023-11-12T09:04:06.2077157Z ##[group]/datum/unit_test/ensure_subtree_operational_datum +2023-11-12T09:04:08.1731821Z PASS /datum/unit_test/ensure_subtree_operational_datum 1.9s +2023-11-12T09:04:08.1733285Z ##[endgroup] +2023-11-12T09:04:08.7539706Z ##[group]/datum/unit_test/explosion_action +2023-11-12T09:04:08.8465799Z PASS /datum/unit_test/explosion_action 0.1s +2023-11-12T09:04:08.8468184Z ##[endgroup] +2023-11-12T09:04:08.9010946Z ##[group]/datum/unit_test/fish_size_weight +2023-11-12T09:04:08.9019514Z PASS /datum/unit_test/fish_size_weight 0s +2023-11-12T09:04:08.9022220Z ##[endgroup] +2023-11-12T09:04:08.9154882Z ##[group]/datum/unit_test/fish_breeding +2023-11-12T09:04:08.9227664Z PASS /datum/unit_test/fish_breeding 0s +2023-11-12T09:04:08.9230704Z ##[endgroup] +2023-11-12T09:04:08.9389958Z ##[group]/datum/unit_test/fish_evolution +2023-11-12T09:04:08.9418165Z PASS /datum/unit_test/fish_evolution 0s +2023-11-12T09:04:08.9421366Z ##[endgroup] +2023-11-12T09:04:08.9631338Z ##[group]/datum/unit_test/fish_scanning +2023-11-12T09:04:08.9635076Z PASS /datum/unit_test/fish_scanning 0s +2023-11-12T09:04:08.9638063Z ##[endgroup] +2023-11-12T09:04:08.9772162Z ##[group]/datum/unit_test/font_awesome_icons +2023-11-12T09:04:08.9779113Z CSS Actual: 96991 +2023-11-12T09:04:09.3976724Z PASS /datum/unit_test/font_awesome_icons 0.4s +2023-11-12T09:04:09.3978084Z ##[endgroup] +2023-11-12T09:04:09.4388919Z ##[group]/datum/unit_test/food_edibility_check +2023-11-12T09:04:11.4659822Z PASS /datum/unit_test/food_edibility_check 2s +2023-11-12T09:04:11.4661512Z ##[endgroup] +2023-11-12T09:04:11.4957968Z ##[group]/datum/unit_test/full_heal_heals_organs +2023-11-12T09:04:11.5147883Z PASS /datum/unit_test/full_heal_heals_organs 0.1s +2023-11-12T09:04:11.5149360Z ##[endgroup] +2023-11-12T09:04:11.5413116Z ##[group]/datum/unit_test/full_heal_regenerates_organs +2023-11-12T09:04:11.5651258Z PASS /datum/unit_test/full_heal_regenerates_organs 0s +2023-11-12T09:04:11.5653018Z ##[endgroup] +2023-11-12T09:04:11.6325061Z ##[group]/datum/unit_test/full_heal_damage_types +2023-11-12T09:04:11.6518216Z PASS /datum/unit_test/full_heal_damage_types 0s +2023-11-12T09:04:11.6519698Z ##[endgroup] +2023-11-12T09:04:11.7209709Z ##[group]/datum/unit_test/atmospheric_gas_transfer +2023-11-12T09:04:11.7227226Z PASS /datum/unit_test/atmospheric_gas_transfer 0s +2023-11-12T09:04:11.7228891Z ##[endgroup] +2023-11-12T09:04:11.7822095Z ##[group]/datum/unit_test/get_turf_pixel +2023-11-12T09:04:11.7849880Z PASS /datum/unit_test/get_turf_pixel 0s +2023-11-12T09:04:11.7851756Z ##[endgroup] +2023-11-12T09:04:11.8495917Z ##[group]/datum/unit_test/geyser +2023-11-12T09:04:11.8516781Z PASS /datum/unit_test/geyser 0s +2023-11-12T09:04:11.8518776Z ##[endgroup] +2023-11-12T09:04:11.9115770Z ##[group]/datum/unit_test/greyscale_item_icon_states +2023-11-12T09:04:11.9172841Z PASS /datum/unit_test/greyscale_item_icon_states 0s +2023-11-12T09:04:11.9174524Z ##[endgroup] +2023-11-12T09:04:11.9770664Z ##[group]/datum/unit_test/greyscale_color_count +2023-11-12T09:04:11.9908294Z PASS /datum/unit_test/greyscale_color_count 0s +2023-11-12T09:04:11.9910694Z ##[endgroup] +2023-11-12T09:04:12.0513128Z ##[group]/datum/unit_test/hallucination_icons +2023-11-12T09:04:12.2294786Z PASS /datum/unit_test/hallucination_icons 0.2s +2023-11-12T09:04:12.2296061Z ##[endgroup] +2023-11-12T09:04:12.2752905Z ##[group]/datum/unit_test/heretic_knowledge +2023-11-12T09:04:12.2797900Z PASS /datum/unit_test/heretic_knowledge 0s +2023-11-12T09:04:12.2800226Z ##[endgroup] +2023-11-12T09:04:12.3526741Z ##[group]/datum/unit_test/heretic_main_paths +2023-11-12T09:04:12.3530666Z PASS /datum/unit_test/heretic_main_paths 0s +2023-11-12T09:04:12.3532858Z ##[endgroup] +2023-11-12T09:04:12.3985035Z ##[group]/datum/unit_test/heretic_rituals +2023-11-12T09:04:12.4878733Z PASS /datum/unit_test/heretic_rituals 0.1s +2023-11-12T09:04:12.4880607Z ##[endgroup] +2023-11-12T09:04:12.5120786Z ##[group]/datum/unit_test/high_five +2023-11-12T09:04:12.5591361Z PASS /datum/unit_test/high_five 0s +2023-11-12T09:04:12.5593593Z ##[endgroup] +2023-11-12T09:04:12.6154998Z ##[group]/datum/unit_test/high_five_too_slow +2023-11-12T09:04:12.6462178Z PASS /datum/unit_test/high_five_too_slow 0s +2023-11-12T09:04:12.6464631Z ##[endgroup] +2023-11-12T09:04:12.6825675Z ##[group]/datum/unit_test/high_five_walk_away +2023-11-12T09:04:12.7302468Z PASS /datum/unit_test/high_five_walk_away 0.1s +2023-11-12T09:04:12.7304078Z ##[endgroup] +2023-11-12T09:04:12.7849321Z ##[group]/datum/unit_test/hanukkah_2123 +2023-11-12T09:04:12.7857129Z PASS /datum/unit_test/hanukkah_2123 0s +2023-11-12T09:04:12.7859467Z ##[endgroup] +2023-11-12T09:04:12.7985283Z ##[group]/datum/unit_test/ramadan_2165 +2023-11-12T09:04:12.7988232Z PASS /datum/unit_test/ramadan_2165 0s +2023-11-12T09:04:12.7990308Z ##[endgroup] +2023-11-12T09:04:12.8115461Z ##[group]/datum/unit_test/thanksgiving_2020 +2023-11-12T09:04:12.8118309Z PASS /datum/unit_test/thanksgiving_2020 0s +2023-11-12T09:04:12.8120732Z ##[endgroup] +2023-11-12T09:04:12.8276159Z ##[group]/datum/unit_test/mother_3683 +2023-11-12T09:04:12.8278795Z PASS /datum/unit_test/mother_3683 0s +2023-11-12T09:04:12.8281149Z ##[endgroup] +2023-11-12T09:04:12.8402992Z ##[group]/datum/unit_test/hello_2020 +2023-11-12T09:04:12.8405520Z PASS /datum/unit_test/hello_2020 0s +2023-11-12T09:04:12.8408004Z ##[endgroup] +2023-11-12T09:04:12.8529607Z ##[group]/datum/unit_test/new_year_1983 +2023-11-12T09:04:12.8531956Z PASS /datum/unit_test/new_year_1983 0s +2023-11-12T09:04:12.8534286Z ##[endgroup] +2023-11-12T09:04:12.8655830Z ##[group]/datum/unit_test/moth_week_2020 +2023-11-12T09:04:12.8735184Z PASS /datum/unit_test/moth_week_2020 0s +2023-11-12T09:04:12.8737646Z ##[endgroup] +2023-11-12T09:04:12.8963722Z ##[group]/datum/unit_test/hulk_attack +2023-11-12T09:04:12.9298282Z PASS /datum/unit_test/hulk_attack 0.1s +2023-11-12T09:04:12.9300378Z ##[endgroup] +2023-11-12T09:04:12.9631065Z ##[group]/datum/unit_test/hulk_north_star +2023-11-12T09:04:12.9971964Z PASS /datum/unit_test/hulk_north_star 0s +2023-11-12T09:04:12.9974198Z ##[endgroup] +2023-11-12T09:04:13.0684879Z ##[group]/datum/unit_test/human_through_recycler +2023-11-12T09:04:13.1042839Z PASS /datum/unit_test/human_through_recycler 0.1s +2023-11-12T09:04:13.1045346Z ##[endgroup] +2023-11-12T09:04:13.1302366Z ##[group]/datum/unit_test/hunger_curse +2023-11-12T09:04:13.1487751Z PASS /datum/unit_test/hunger_curse 0s +2023-11-12T09:04:13.1490362Z ##[endgroup] +2023-11-12T09:04:13.1724484Z ##[group]/datum/unit_test/hydroponics_extractor_storage +2023-11-12T09:04:13.2045321Z PASS /datum/unit_test/hydroponics_extractor_storage 0.1s +2023-11-12T09:04:13.2047744Z ##[endgroup] +2023-11-12T09:04:13.2424994Z ##[group]/datum/unit_test/hydroponics_harvest +2023-11-12T09:04:13.3172098Z PASS /datum/unit_test/hydroponics_harvest 0.1s +2023-11-12T09:04:13.3173538Z ##[endgroup] +2023-11-12T09:04:13.3896863Z ##[group]/datum/unit_test/hydroponics_self_mutation +2023-11-12T09:04:13.4546321Z PASS /datum/unit_test/hydroponics_self_mutation 0.1s +2023-11-12T09:04:13.4548349Z ##[endgroup] +2023-11-12T09:04:13.5127280Z ##[group]/datum/unit_test/hydroponics_validate_genes +2023-11-12T09:04:13.5761114Z PASS /datum/unit_test/hydroponics_validate_genes 0s +2023-11-12T09:04:13.5765353Z ##[endgroup] +2023-11-12T09:04:13.5897676Z ##[group]/datum/unit_test/defined_inhand_icon_states +2023-11-12T09:04:14.5257265Z Notice - Possible inhand icon matches found. It is best to be explicit with inhand sprite values. +2023-11-12T09:04:14.5260490Z /obj/item/clothing/head/costume/lizard does not have an inhand_icon_state value - Possible matching sprites for "lizard" found in: 'icons/mob/inhands/animal_item_lefthand.dmi' & 'icons/mob/inhands/animal_item_righthand.dmi' +2023-11-12T09:04:14.5265334Z /obj/item/clothing/head/costume/paper_hat does not have an inhand_icon_state value - Possible matching sprites for "paper" found in: 'icons/mob/inhands/items_lefthand.dmi' & 'icons/mob/inhands/items_righthand.dmi' +2023-11-12T09:04:14.5269130Z /obj/item/clothing/head/collectable/paper does not have an inhand_icon_state value - Possible matching sprites for "paper" found in: 'icons/mob/inhands/items_lefthand.dmi' & 'icons/mob/inhands/items_righthand.dmi' +2023-11-12T09:04:14.5272911Z /obj/item/clothing/head/cowboy does not have an inhand_icon_state value - Possible matching sprites for "cowboy_hat_brown" found in: 'icons/mob/inhands/clothing/hats_lefthand.dmi' & 'icons/mob/inhands/clothing/hats_righthand.dmi' +2023-11-12T09:04:14.5276899Z /obj/item/clothing/head/chaplain/habit_veil does not have an inhand_icon_state value - Possible matching sprites for "nun_hood_alt" found in: 'icons/mob/inhands/clothing/hats_lefthand.dmi' & 'icons/mob/inhands/clothing/hats_righthand.dmi' +2023-11-12T09:04:14.5280655Z /obj/item/clothing/mask/animal/small/fox does not have an inhand_icon_state value - Possible matching sprites for "fox" found in: 'icons/mob/inhands/pets_held_rh.dmi' & 'icons/mob/inhands/pets_held_lh.dmi' +2023-11-12T09:04:14.5284605Z /obj/item/clothing/mask/animal/small/fox/cursed does not have an inhand_icon_state value - Possible matching sprites for "fox" found in: 'icons/mob/inhands/pets_held_rh.dmi' & 'icons/mob/inhands/pets_held_lh.dmi' +2023-11-12T09:04:14.5288384Z /obj/item/clothing/accessory/pride does not have an inhand_icon_state value - Possible matching sprites for "pride" found in: 'icons/mob/inhands/weapons/hammers_lefthand.dmi' & 'icons/mob/inhands/weapons/hammers_righthand.dmi' +2023-11-12T09:04:14.5292328Z /obj/item/clothing/suit/apron/overalls does not have an inhand_icon_state value - Possible matching sprites for "overalls" found in: 'icons/mob/inhands/clothing/suits_righthand.dmi' & 'icons/mob/inhands/clothing/suits_lefthand.dmi' +2023-11-12T09:04:14.5296324Z /obj/item/clothing/suit/caution does not have an inhand_icon_state value - Possible matching sprites for "caution" found in: 'icons/mob/inhands/equipment/custodial_righthand.dmi' & 'icons/mob/inhands/equipment/custodial_lefthand.dmi' +2023-11-12T09:04:14.5300339Z /obj/item/clothing/suit/chaplainsuit/habit does not have an inhand_icon_state value - Possible matching sprites for "habit" found in: 'icons/mob/inhands/clothing/suits_righthand.dmi' & 'icons/mob/inhands/clothing/suits_lefthand.dmi' +2023-11-12T09:04:14.5305034Z /obj/item/clothing/glasses/hud/health/sunglasses does not have an inhand_icon_state value - Possible matching sprites for "sunhudmed" found in: 'icons/mob/inhands/clothing/glasses_righthand.dmi' & 'icons/mob/inhands/clothing/glasses_lefthand.dmi' +2023-11-12T09:04:14.5309450Z /obj/item/clothing/glasses/hud/security/sunglasses does not have an inhand_icon_state value - Possible matching sprites for "sunhudsec" found in: 'icons/mob/inhands/clothing/glasses_righthand.dmi' & 'icons/mob/inhands/clothing/glasses_lefthand.dmi' +2023-11-12T09:04:14.5313568Z /obj/item/mecha_parts/mecha_equipment/generator does not have an inhand_icon_state value - Possible matching sprites for "tesla" found in: 'icons/mob/inhands/weapons/guns_righthand.dmi' & 'icons/mob/inhands/weapons/guns_lefthand.dmi' +2023-11-12T09:04:14.5317158Z /obj/item/food/candy does not have an inhand_icon_state value - Possible matching sprites for "candy" found in: 'icons/mob/inhands/items/food_righthand.dmi' & 'icons/mob/inhands/items/food_lefthand.dmi' +2023-11-12T09:04:14.5320529Z /obj/item/food/chips does not have an inhand_icon_state value - Possible matching sprites for "chips" found in: 'icons/mob/inhands/items/food_righthand.dmi' & 'icons/mob/inhands/items/food_lefthand.dmi' +2023-11-12T09:04:14.5324489Z /obj/item/storage/bag/ore does not have an inhand_icon_state value - Possible matching sprites for "satchel" found in: 'icons/mob/inhands/equipment/backpack_righthand.dmi' & 'icons/mob/inhands/equipment/backpack_lefthand.dmi' +2023-11-12T09:04:14.5328382Z /obj/item/storage/bag/ore/cyborg does not have an inhand_icon_state value - Possible matching sprites for "satchel" found in: 'icons/mob/inhands/equipment/backpack_righthand.dmi' & 'icons/mob/inhands/equipment/backpack_lefthand.dmi' +2023-11-12T09:04:14.5332211Z /obj/item/melee/energy/blade does not have an inhand_icon_state value - Possible matching sprites for "blade" found in: 'icons/mob/inhands/weapons/swords_righthand.dmi' & 'icons/mob/inhands/weapons/swords_lefthand.dmi' +2023-11-12T09:04:14.5335835Z /obj/item/fireaxe does not have an inhand_icon_state value - Possible matching sprites for "fireaxe0" found in: 'icons/mob/inhands/weapons/axes_lefthand.dmi' & 'icons/mob/inhands/weapons/axes_righthand.dmi' +2023-11-12T09:04:14.5339617Z /obj/item/fireaxe/boneaxe does not have an inhand_icon_state value - Possible matching sprites for "bone_axe0" found in: 'icons/mob/inhands/weapons/axes_lefthand.dmi' & 'icons/mob/inhands/weapons/axes_righthand.dmi' +2023-11-12T09:04:14.5343300Z /obj/item/fireaxe/metal_h2_axe does not have an inhand_icon_state value - Possible matching sprites for "metalh2_axe0" found in: 'icons/mob/inhands/weapons/axes_lefthand.dmi' & 'icons/mob/inhands/weapons/axes_righthand.dmi' +2023-11-12T09:04:14.5347106Z /obj/item/crowbar/mechremoval does not have an inhand_icon_state value - Possible matching sprites for "mechremoval0" found in: 'icons/mob/inhands/equipment/tools_lefthand.dmi' & 'icons/mob/inhands/equipment/tools_righthand.dmi' +2023-11-12T09:04:14.5350901Z /obj/item/mod/module/medbeam does not have an inhand_icon_state value - Possible matching sprites for "chronogun" found in: 'icons/mob/inhands/weapons/guns_righthand.dmi' & 'icons/mob/inhands/weapons/guns_lefthand.dmi' +2023-11-12T09:04:14.5354609Z /obj/item/mod/module/welding does not have an inhand_icon_state value - Possible matching sprites for "welding" found in: 'icons/mob/inhands/clothing/masks_righthand.dmi' & 'icons/mob/inhands/clothing/masks_lefthand.dmi' +2023-11-12T09:04:14.5358402Z /obj/item/mod/module/mister does not have an inhand_icon_state value - Possible matching sprites for "mister" found in: 'icons/mob/inhands/equipment/mister_righthand.dmi' & 'icons/mob/inhands/equipment/mister_lefthand.dmi' +2023-11-12T09:04:14.5362405Z /obj/item/mod/module/mister/atmos does not have an inhand_icon_state value - Possible matching sprites for "mister" found in: 'icons/mob/inhands/equipment/mister_righthand.dmi' & 'icons/mob/inhands/equipment/mister_lefthand.dmi' +2023-11-12T09:04:14.5366326Z /obj/item/mod/module/jetpack does not have an inhand_icon_state value - Possible matching sprites for "jetpack" found in: 'icons/mob/inhands/equipment/jetpacks_righthand.dmi' & 'icons/mob/inhands/equipment/jetpacks_lefthand.dmi' +2023-11-12T09:04:14.5370513Z /obj/item/mod/module/flashlight does not have an inhand_icon_state value - Possible matching sprites for "flashlight" found in: 'icons/mob/inhands/items/devices_righthand.dmi' & 'icons/mob/inhands/items/devices_lefthand.dmi' +2023-11-12T09:04:14.5374077Z /obj/item/mod/module/stamp does not have an inhand_icon_state value - Possible matching sprites for "stamp" found in: 'icons/mob/inhands/items_lefthand.dmi' & 'icons/mob/inhands/items_righthand.dmi' +2023-11-12T09:04:14.5377613Z /obj/item/mod/module/holster does not have an inhand_icon_state value - Possible matching sprites for "holster" found in: 'icons/mob/inhands/equipment/belt_lefthand.dmi' & 'icons/mob/inhands/equipment/belt_righthand.dmi' +2023-11-12T09:04:14.5381427Z /obj/item/mod/module/megaphone does not have an inhand_icon_state value - Possible matching sprites for "megaphone" found in: 'icons/mob/inhands/items/megaphone_righthand.dmi' & 'icons/mob/inhands/items/megaphone_lefthand.dmi' +2023-11-12T09:04:14.5386246Z /obj/item/mod/module/drill does not have an inhand_icon_state value - Possible matching sprites for "drill" found in: 'icons/mob/inhands/equipment/medical_lefthand.dmi' & 'icons/mob/inhands/equipment/tools_lefthand.dmi' & 'icons/mob/inhands/equipment/medical_righthand.dmi' & 'icons/mob/inhands/equipment/tools_righthand.dmi' +2023-11-12T09:04:14.5390973Z /obj/item/mod/module/tem does not have an inhand_icon_state value - Possible matching sprites for "chronogun" found in: 'icons/mob/inhands/weapons/guns_righthand.dmi' & 'icons/mob/inhands/weapons/guns_lefthand.dmi' +2023-11-12T09:04:14.5394601Z /obj/item/reagent_containers/cup/soda_cans does not have an inhand_icon_state value - Possible matching sprites for "cola" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5396934Z /obj/item/reagent_containers/cup/soda_cans/random does not have an inhand_icon_state value - Possible matching sprites for "cola" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5399759Z /obj/item/reagent_containers/cup/soda_cans/cola does not have an inhand_icon_state value - Possible matching sprites for "cola" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5402114Z /obj/item/reagent_containers/cup/soda_cans/tonic does not have an inhand_icon_state value - Possible matching sprites for "tonic" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5404446Z /obj/item/reagent_containers/cup/soda_cans/sodawater does not have an inhand_icon_state value - Possible matching sprites for "sodawater" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5406584Z /obj/item/reagent_containers/cup/soda_cans/lemon_lime does not have an inhand_icon_state value - Possible matching sprites for "lemon-lime" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5408970Z /obj/item/reagent_containers/cup/soda_cans/space_up does not have an inhand_icon_state value - Possible matching sprites for "space-up" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5411153Z /obj/item/reagent_containers/cup/soda_cans/starkist does not have an inhand_icon_state value - Possible matching sprites for "starkist" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5413351Z /obj/item/reagent_containers/cup/soda_cans/space_mountain_wind does not have an inhand_icon_state value - Possible matching sprites for "space_mountain_wind" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5415775Z /obj/item/reagent_containers/cup/soda_cans/thirteenloko does not have an inhand_icon_state value - Possible matching sprites for "thirteen_loko" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5417918Z /obj/item/reagent_containers/cup/soda_cans/dr_gibb does not have an inhand_icon_state value - Possible matching sprites for "dr_gibb" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5420047Z /obj/item/reagent_containers/cup/soda_cans/pwr_game does not have an inhand_icon_state value - Possible matching sprites for "purple_can" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5422176Z /obj/item/reagent_containers/cup/soda_cans/wellcheers does not have an inhand_icon_state value - Possible matching sprites for "wellcheers" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5424331Z /obj/item/reagent_containers/cup/soda_cans/volt_energy does not have an inhand_icon_state value - Possible matching sprites for "volt_energy" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5426605Z /obj/item/reagent_containers/cup/soda_cans/melon_soda does not have an inhand_icon_state value - Possible matching sprites for "melon_soda" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5428700Z /obj/item/reagent_containers/cup/soda_cans/beer does not have an inhand_icon_state value - Possible matching sprites for "space_beer" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5430842Z /obj/item/reagent_containers/cup/soda_cans/beer/rice does not have an inhand_icon_state value - Possible matching sprites for "ebisu" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5432971Z /obj/item/reagent_containers/cup/glass/coffee does not have an inhand_icon_state value - Possible matching sprites for "coffee" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5435080Z /obj/item/reagent_containers/chem_pack does not have an inhand_icon_state value - Possible matching sprites for "chempack" found in: 'icons/mob/inhands/equipment/backpack_righthand.dmi' & 'icons/mob/inhands/equipment/backpack_lefthand.dmi' +2023-11-12T09:04:14.5437143Z /obj/item/toy/talking/codex_gigas does not have an inhand_icon_state value - Possible matching sprites for "demonomicon" found in: 'icons/mob/inhands/items/books_righthand.dmi' & 'icons/mob/inhands/items/books_lefthand.dmi' +2023-11-12T09:04:14.5439342Z /obj/item/toy/figure/chef does not have an inhand_icon_state value - Possible matching sprites for "chef" found in: 'icons/mob/inhands/clothing/suits_righthand.dmi' & 'icons/mob/inhands/clothing/suits_lefthand.dmi' +2023-11-12T09:04:14.5441474Z /obj/item/toy/figure/clown does not have an inhand_icon_state value - Possible matching sprites for "clown" found in: 'icons/mob/inhands/clothing/suits_righthand.dmi' & 'icons/mob/inhands/clothing/suits_lefthand.dmi' +2023-11-12T09:04:14.5443437Z /obj/item/toy/figure/janitor does not have an inhand_icon_state value - Possible matching sprites for "janitor" found in: 'icons/mob/inhands/clothing/suits_righthand.dmi' & 'icons/mob/inhands/clothing/suits_lefthand.dmi' +2023-11-12T09:04:14.5445333Z /obj/item/toy/cards/cardhand does not have an inhand_icon_state value - Possible matching sprites for "nothing" found in: 'icons/mob/inhands/items_lefthand.dmi' & 'icons/mob/inhands/items_righthand.dmi' +2023-11-12T09:04:14.5447188Z /obj/item/book/codex_gigas does not have an inhand_icon_state value - Possible matching sprites for "demonomicon" found in: 'icons/mob/inhands/items/books_righthand.dmi' & 'icons/mob/inhands/items/books_lefthand.dmi' +2023-11-12T09:04:14.5449271Z /obj/item/pipe_dispenser does not have an inhand_icon_state value - Possible matching sprites for "rpd" found in: 'icons/mob/inhands/equipment/tools_lefthand.dmi' & 'icons/mob/inhands/equipment/tools_righthand.dmi' +2023-11-12T09:04:14.5451184Z /obj/item/sbeacondrop does not have an inhand_icon_state value - Possible matching sprites for "beacon" found in: 'icons/mob/inhands/items/devices_righthand.dmi' & 'icons/mob/inhands/items/devices_lefthand.dmi' +2023-11-12T09:04:14.5453081Z /obj/item/sbeacondrop/bomb does not have an inhand_icon_state value - Possible matching sprites for "beacon" found in: 'icons/mob/inhands/items/devices_righthand.dmi' & 'icons/mob/inhands/items/devices_lefthand.dmi' +2023-11-12T09:04:14.5454974Z /obj/item/sbeacondrop/emp does not have an inhand_icon_state value - Possible matching sprites for "beacon" found in: 'icons/mob/inhands/items/devices_righthand.dmi' & 'icons/mob/inhands/items/devices_lefthand.dmi' +2023-11-12T09:04:14.5456921Z /obj/item/sbeacondrop/powersink does not have an inhand_icon_state value - Possible matching sprites for "beacon" found in: 'icons/mob/inhands/items/devices_righthand.dmi' & 'icons/mob/inhands/items/devices_lefthand.dmi' +2023-11-12T09:04:14.5459034Z /obj/item/sbeacondrop/clownbomb does not have an inhand_icon_state value - Possible matching sprites for "beacon" found in: 'icons/mob/inhands/items/devices_righthand.dmi' & 'icons/mob/inhands/items/devices_lefthand.dmi' +2023-11-12T09:04:14.5460981Z /obj/item/sbeacondrop/horse does not have an inhand_icon_state value - Possible matching sprites for "beacon" found in: 'icons/mob/inhands/items/devices_righthand.dmi' & 'icons/mob/inhands/items/devices_lefthand.dmi' +2023-11-12T09:04:14.5463020Z /obj/item/stack/medical/bruise_pack does not have an inhand_icon_state value - Possible matching sprites for "brutepack" found in: 'icons/mob/inhands/equipment/medical_lefthand.dmi' & 'icons/mob/inhands/equipment/medical_righthand.dmi' +2023-11-12T09:04:14.5465143Z /obj/item/stack/medical/ointment does not have an inhand_icon_state value - Possible matching sprites for "ointment" found in: 'icons/mob/inhands/equipment/medical_lefthand.dmi' & 'icons/mob/inhands/equipment/medical_righthand.dmi' +2023-11-12T09:04:14.5467227Z /obj/item/stack/tile/fairygrass does not have an inhand_icon_state value - Possible matching sprites for "tile_fairygrass" found in: 'icons/mob/inhands/items/tiles_righthand.dmi' & 'icons/mob/inhands/items/tiles_lefthand.dmi' +2023-11-12T09:04:14.5469256Z /obj/item/organ/internal/heart/gland/blood does not have an inhand_icon_state value - Possible matching sprites for "egg" found in: 'icons/mob/inhands/items/food_righthand.dmi' & 'icons/mob/inhands/items/food_lefthand.dmi' +2023-11-12T09:04:14.5471272Z /obj/item/organ/internal/heart/gland/egg does not have an inhand_icon_state value - Possible matching sprites for "egg" found in: 'icons/mob/inhands/items/food_righthand.dmi' & 'icons/mob/inhands/items/food_lefthand.dmi' +2023-11-12T09:04:14.5473406Z /obj/item/organ/internal/heart/gland/quantum does not have an inhand_icon_state value - Possible matching sprites for "emp" found in: 'icons/mob/inhands/equipment/security_lefthand.dmi' & 'icons/mob/inhands/equipment/security_righthand.dmi' +2023-11-12T09:04:14.5475638Z /obj/item/organ/internal/heart/gland/trauma does not have an inhand_icon_state value - Possible matching sprites for "emp" found in: 'icons/mob/inhands/equipment/security_lefthand.dmi' & 'icons/mob/inhands/equipment/security_righthand.dmi' +2023-11-12T09:04:14.5477679Z /obj/item/minespawner does not have an inhand_icon_state value - Possible matching sprites for "beacon" found in: 'icons/mob/inhands/items/devices_righthand.dmi' & 'icons/mob/inhands/items/devices_lefthand.dmi' +2023-11-12T09:04:14.5479615Z /obj/item/boxcutter does not have an inhand_icon_state value - Possible matching sprites for "boxcutter" found in: 'icons/mob/inhands/equipment/boxcutter_righthand.dmi' & 'icons/mob/inhands/equipment/boxcutter_lefthand.dmi' +2023-11-12T09:04:14.5482091Z /obj/item/boxcutter/extended does not have an inhand_icon_state value - Possible matching sprites for "boxcutter" found in: 'icons/mob/inhands/equipment/boxcutter_righthand.dmi' & 'icons/mob/inhands/equipment/boxcutter_lefthand.dmi' +2023-11-12T09:04:14.5484159Z /obj/item/pushbroom does not have an inhand_icon_state value - Possible matching sprites for "broom0" found in: 'icons/mob/inhands/equipment/custodial_righthand.dmi' & 'icons/mob/inhands/equipment/custodial_lefthand.dmi' +2023-11-12T09:04:14.5486168Z /obj/item/pushbroom/cyborg does not have an inhand_icon_state value - Possible matching sprites for "broom0" found in: 'icons/mob/inhands/equipment/custodial_righthand.dmi' & 'icons/mob/inhands/equipment/custodial_lefthand.dmi' +2023-11-12T09:04:14.5488176Z /obj/item/chainsaw does not have an inhand_icon_state value - Possible matching sprites for "chainsaw_off" found in: 'icons/mob/inhands/weapons/chainsaw_righthand.dmi' & 'icons/mob/inhands/weapons/chainsaw_lefthand.dmi' +2023-11-12T09:04:14.5490187Z /obj/item/chainsaw/doomslayer does not have an inhand_icon_state value - Possible matching sprites for "chainsaw_off" found in: 'icons/mob/inhands/weapons/chainsaw_righthand.dmi' & 'icons/mob/inhands/weapons/chainsaw_lefthand.dmi' +2023-11-12T09:04:14.5492367Z /obj/item/kitchen/fork does not have an inhand_icon_state value - Possible matching sprites for "fork" found in: 'icons/mob/inhands/equipment/kitchen_lefthand.dmi' & 'icons/mob/inhands/equipment/kitchen_righthand.dmi' +2023-11-12T09:04:14.5494352Z /obj/item/kitchen/spoon does not have an inhand_icon_state value - Possible matching sprites for "spoon" found in: 'icons/mob/inhands/equipment/kitchen_lefthand.dmi' & 'icons/mob/inhands/equipment/kitchen_righthand.dmi' +2023-11-12T09:04:14.5496447Z /obj/item/kitchen/spoon/plastic does not have an inhand_icon_state value - Possible matching sprites for "plastic_spoon" found in: 'icons/mob/inhands/equipment/kitchen_lefthand.dmi' & 'icons/mob/inhands/equipment/kitchen_righthand.dmi' +2023-11-12T09:04:14.5498538Z /obj/item/pitchfork does not have an inhand_icon_state value - Possible matching sprites for "pitchfork0" found in: 'icons/mob/inhands/weapons/polearms_lefthand.dmi' & 'icons/mob/inhands/weapons/polearms_righthand.dmi' +2023-11-12T09:04:14.5500478Z /obj/item/godstaff does not have an inhand_icon_state value - Possible matching sprites for "godstaff-red" found in: 'icons/mob/inhands/weapons/staves_lefthand.dmi' & 'icons/mob/inhands/weapons/staves_righthand.dmi' +2023-11-12T09:04:14.5502414Z /obj/item/godstaff/red does not have an inhand_icon_state value - Possible matching sprites for "godstaff-red" found in: 'icons/mob/inhands/weapons/staves_lefthand.dmi' & 'icons/mob/inhands/weapons/staves_righthand.dmi' +2023-11-12T09:04:14.5504543Z /obj/item/godstaff/blue does not have an inhand_icon_state value - Possible matching sprites for "godstaff-blue" found in: 'icons/mob/inhands/weapons/staves_lefthand.dmi' & 'icons/mob/inhands/weapons/staves_righthand.dmi' +2023-11-12T09:04:14.5506586Z /obj/item/singularityhammer does not have an inhand_icon_state value - Possible matching sprites for "singularity_hammer0" found in: 'icons/mob/inhands/weapons/hammers_lefthand.dmi' & 'icons/mob/inhands/weapons/hammers_righthand.dmi' +2023-11-12T09:04:14.5508606Z /obj/item/mjollnir does not have an inhand_icon_state value - Possible matching sprites for "mjollnir0" found in: 'icons/mob/inhands/weapons/hammers_lefthand.dmi' & 'icons/mob/inhands/weapons/hammers_righthand.dmi' +2023-11-12T09:04:14.5510522Z /obj/item/spear does not have an inhand_icon_state value - Possible matching sprites for "spearglass0" found in: 'icons/mob/inhands/weapons/polearms_lefthand.dmi' & 'icons/mob/inhands/weapons/polearms_righthand.dmi' +2023-11-12T09:04:14.5512535Z /obj/item/spear/explosive does not have an inhand_icon_state value - Possible matching sprites for "spearbomb0" found in: 'icons/mob/inhands/weapons/polearms_lefthand.dmi' & 'icons/mob/inhands/weapons/polearms_righthand.dmi' +2023-11-12T09:04:14.5514725Z /obj/item/spear/grey_tide does not have an inhand_icon_state value - Possible matching sprites for "spearglass0" found in: 'icons/mob/inhands/weapons/polearms_lefthand.dmi' & 'icons/mob/inhands/weapons/polearms_righthand.dmi' +2023-11-12T09:04:14.5516757Z /obj/item/spear/bonespear does not have an inhand_icon_state value - Possible matching sprites for "bone_spear0" found in: 'icons/mob/inhands/weapons/polearms_lefthand.dmi' & 'icons/mob/inhands/weapons/polearms_righthand.dmi' +2023-11-12T09:04:14.5518804Z /obj/item/spear/bamboospear does not have an inhand_icon_state value - Possible matching sprites for "bamboo_spear0" found in: 'icons/mob/inhands/weapons/polearms_lefthand.dmi' & 'icons/mob/inhands/weapons/polearms_righthand.dmi' +2023-11-12T09:04:14.5520748Z /obj/item/sticker/robot does not have an inhand_icon_state value - Possible matching sprites for "tile" found in: 'icons/mob/inhands/items/tiles_righthand.dmi' & 'icons/mob/inhands/items/tiles_lefthand.dmi' +2023-11-12T09:04:14.5522828Z /obj/item/trash/candy does not have an inhand_icon_state value - Possible matching sprites for "candy" found in: 'icons/mob/inhands/items/food_righthand.dmi' & 'icons/mob/inhands/items/food_lefthand.dmi' +2023-11-12T09:04:14.5524800Z /obj/item/trash/chips does not have an inhand_icon_state value - Possible matching sprites for "chips" found in: 'icons/mob/inhands/items/food_righthand.dmi' & 'icons/mob/inhands/items/food_lefthand.dmi' +2023-11-12T09:04:14.5526598Z /obj/item/trash/can does not have an inhand_icon_state value - Possible matching sprites for "cola" found in: 'icons/mob/inhands/items/drinks_righthand.dmi' & 'icons/mob/inhands/items/drinks_lefthand.dmi' +2023-11-12T09:04:14.5528508Z /obj/item/highfrequencyblade does not have an inhand_icon_state value - Possible matching sprites for "hfrequency0" found in: 'icons/mob/inhands/weapons/swords_righthand.dmi' & 'icons/mob/inhands/weapons/swords_lefthand.dmi' +2023-11-12T09:04:14.5530557Z /obj/item/highfrequencyblade/wizard does not have an inhand_icon_state value - Possible matching sprites for "hfrequency0" found in: 'icons/mob/inhands/weapons/swords_righthand.dmi' & 'icons/mob/inhands/weapons/swords_lefthand.dmi' +2023-11-12T09:04:14.5532581Z /obj/item/construction/rcd does not have an inhand_icon_state value - Possible matching sprites for "rcd" found in: 'icons/mob/inhands/equipment/tools_lefthand.dmi' & 'icons/mob/inhands/equipment/tools_righthand.dmi' +2023-11-12T09:04:14.5534544Z /obj/item/construction/rcd/borg does not have an inhand_icon_state value - Possible matching sprites for "rcd" found in: 'icons/mob/inhands/equipment/tools_lefthand.dmi' & 'icons/mob/inhands/equipment/tools_righthand.dmi' +2023-11-12T09:04:14.5536539Z /obj/item/construction/rcd/loaded does not have an inhand_icon_state value - Possible matching sprites for "rcd" found in: 'icons/mob/inhands/equipment/tools_lefthand.dmi' & 'icons/mob/inhands/equipment/tools_righthand.dmi' +2023-11-12T09:04:14.5538610Z /obj/item/construction/rcd/loaded/upgraded does not have an inhand_icon_state value - Possible matching sprites for "rcd" found in: 'icons/mob/inhands/equipment/tools_lefthand.dmi' & 'icons/mob/inhands/equipment/tools_righthand.dmi' +2023-11-12T09:04:14.5540806Z /obj/item/construction/rcd/ce does not have an inhand_icon_state value - Possible matching sprites for "rcd" found in: 'icons/mob/inhands/equipment/tools_lefthand.dmi' & 'icons/mob/inhands/equipment/tools_righthand.dmi' +2023-11-12T09:04:14.5542811Z /obj/item/construction/rcd/internal does not have an inhand_icon_state value - Possible matching sprites for "rcd" found in: 'icons/mob/inhands/equipment/tools_lefthand.dmi' & 'icons/mob/inhands/equipment/tools_righthand.dmi' +2023-11-12T09:04:14.5544792Z /obj/item/construction/rld does not have an inhand_icon_state value - Possible matching sprites for "rld" found in: 'icons/mob/inhands/equipment/tools_lefthand.dmi' & 'icons/mob/inhands/equipment/tools_righthand.dmi' +2023-11-12T09:04:14.5546898Z /obj/item/construction/rld/mini does not have an inhand_icon_state value - Possible matching sprites for "rld" found in: 'icons/mob/inhands/equipment/tools_lefthand.dmi' & 'icons/mob/inhands/equipment/tools_righthand.dmi' +2023-11-12T09:04:14.5548856Z /obj/item/construction/rtd does not have an inhand_icon_state value - Possible matching sprites for "rtd" found in: 'icons/mob/inhands/equipment/tools_lefthand.dmi' & 'icons/mob/inhands/equipment/tools_righthand.dmi' +2023-11-12T09:04:14.5551347Z /obj/item/construction/rtd/loaded does not have an inhand_icon_state value - Possible matching sprites for "rtd" found in: 'icons/mob/inhands/equipment/tools_lefthand.dmi' & 'icons/mob/inhands/equipment/tools_righthand.dmi' +2023-11-12T09:04:14.5553359Z /obj/item/construction/rtd/admin does not have an inhand_icon_state value - Possible matching sprites for "rtd" found in: 'icons/mob/inhands/equipment/tools_lefthand.dmi' & 'icons/mob/inhands/equipment/tools_righthand.dmi' +2023-11-12T09:04:14.5555307Z /obj/item/rcd_ammo does not have an inhand_icon_state value - Possible matching sprites for "rcdammo" found in: 'icons/mob/inhands/equipment/tools_lefthand.dmi' & 'icons/mob/inhands/equipment/tools_righthand.dmi' +2023-11-12T09:04:14.5557368Z /obj/item/rcd_ammo/large does not have an inhand_icon_state value - Possible matching sprites for "rcdammo" found in: 'icons/mob/inhands/equipment/tools_lefthand.dmi' & 'icons/mob/inhands/equipment/tools_righthand.dmi' +2023-11-12T09:04:14.5559329Z /obj/item/borg/sight/meson does not have an inhand_icon_state value - Possible matching sprites for "meson" found in: 'icons/mob/inhands/clothing/glasses_righthand.dmi' & 'icons/mob/inhands/clothing/glasses_lefthand.dmi' +2023-11-12T09:04:14.5561639Z /obj/item/harmalarm does not have an inhand_icon_state value - Possible matching sprites for "megaphone" found in: 'icons/mob/inhands/items/megaphone_righthand.dmi' & 'icons/mob/inhands/items/megaphone_lefthand.dmi' +2023-11-12T09:04:14.5564165Z /obj/item/abductor_machine_beacon does not have an inhand_icon_state value - Possible matching sprites for "beacon" found in: 'icons/mob/inhands/items/devices_righthand.dmi' & 'icons/mob/inhands/items/devices_lefthand.dmi' +2023-11-12T09:04:14.5566370Z /obj/item/abductor_machine_beacon/chem_dispenser does not have an inhand_icon_state value - Possible matching sprites for "beacon" found in: 'icons/mob/inhands/items/devices_righthand.dmi' & 'icons/mob/inhands/items/devices_lefthand.dmi' +2023-11-12T09:04:14.5568963Z /obj/item/grown/carbon_rose does not have an inhand_icon_state value - Possible matching sprites for "carbonrose" found in: 'icons/mob/inhands/weapons/plants_lefthand.dmi' & 'icons/mob/inhands/weapons/plants_righthand.dmi' +2023-11-12T09:04:14.5571469Z /obj/item/paint_palette does not have an inhand_icon_state value - Possible matching sprites for "palette" found in: 'icons/mob/inhands/equipment/palette_lefthand.dmi' & 'icons/mob/inhands/equipment/palette_righthand.dmi' +2023-11-12T09:04:14.5573366Z /obj/item/surprise_egg does not have an inhand_icon_state value - Possible matching sprites for "egg" found in: 'icons/mob/inhands/items/food_righthand.dmi' & 'icons/mob/inhands/items/food_lefthand.dmi' +2023-11-12T09:04:14.5575235Z /obj/item/experi_scanner does not have an inhand_icon_state value - Possible matching sprites for "experiscanner" found in: 'icons/mob/inhands/items/devices_righthand.dmi' & 'icons/mob/inhands/items/devices_lefthand.dmi' +2023-11-12T09:04:14.5577115Z /obj/item/fishing_hook does not have an inhand_icon_state value - Possible matching sprites for "hook" found in: 'icons/mob/inhands/weapons/melee_righthand.dmi' & 'icons/mob/inhands/weapons/melee_lefthand.dmi' +2023-11-12T09:04:14.5578938Z /obj/item/shovel/giant_wrench does not have an inhand_icon_state value - Possible matching sprites for "giant_wrench" found in: 'icons/mob/inhands/64x64_righthand.dmi' & 'icons/mob/inhands/64x64_lefthand.dmi' +2023-11-12T09:04:14.5580822Z /obj/item/cursed_katana does not have an inhand_icon_state value - Possible matching sprites for "cursed_katana" found in: 'icons/mob/inhands/weapons/swords_righthand.dmi' & 'icons/mob/inhands/weapons/swords_lefthand.dmi' +2023-11-12T09:04:14.5583032Z /obj/item/guardian_creator/tech does not have an inhand_icon_state value - Possible matching sprites for "combat_hypo" found in: 'icons/mob/inhands/equipment/medical_lefthand.dmi' & 'icons/mob/inhands/equipment/medical_righthand.dmi' +2023-11-12T09:04:14.5584953Z /obj/item/research_notes does not have an inhand_icon_state value - Possible matching sprites for "paper" found in: 'icons/mob/inhands/items_lefthand.dmi' & 'icons/mob/inhands/items_righthand.dmi' +2023-11-12T09:04:14.5586814Z /obj/item/bonesetter does not have an inhand_icon_state value - Possible matching sprites for "bonesetter" found in: 'icons/mob/inhands/equipment/medical_lefthand.dmi' & 'icons/mob/inhands/equipment/medical_righthand.dmi' +2023-11-12T09:04:14.5588821Z /obj/item/blood_filter does not have an inhand_icon_state value - Possible matching sprites for "bloodfilter" found in: 'icons/mob/inhands/equipment/medical_lefthand.dmi' & 'icons/mob/inhands/equipment/medical_righthand.dmi' +2023-11-12T09:04:14.5590945Z /obj/item/mecha_ammo/flashbang does not have an inhand_icon_state value - Possible matching sprites for "flashbang" found in: 'icons/mob/inhands/equipment/security_lefthand.dmi' & 'icons/mob/inhands/equipment/security_righthand.dmi' +2023-11-12T09:04:14.5592385Z PASS /datum/unit_test/defined_inhand_icon_states 1s +2023-11-12T09:04:14.5593067Z ##[endgroup] +2023-11-12T09:04:14.5593503Z ##[group]/datum/unit_test/json_savefiles +2023-11-12T09:04:14.5593927Z PASS /datum/unit_test/json_savefiles 0s +2023-11-12T09:04:14.5594439Z ##[endgroup] +2023-11-12T09:04:14.5697545Z ##[group]/datum/unit_test/keybinding_init +2023-11-12T09:04:14.5700044Z PASS /datum/unit_test/keybinding_init 0s +2023-11-12T09:04:14.5702215Z ##[endgroup] +2023-11-12T09:04:14.5828294Z ##[group]/datum/unit_test/knockoff_component +2023-11-12T09:04:14.6242363Z PASS /datum/unit_test/knockoff_component 0.1s +2023-11-12T09:04:14.6244697Z ##[endgroup] +2023-11-12T09:04:14.6630391Z ##[group]/datum/unit_test/language_species_swap_simple +2023-11-12T09:04:14.7587413Z PASS /datum/unit_test/language_species_swap_simple 0.1s +2023-11-12T09:04:14.7588791Z ##[endgroup] +2023-11-12T09:04:14.7909664Z ##[group]/datum/unit_test/language_species_swap_complex +2023-11-12T09:04:14.8535770Z PASS /datum/unit_test/language_species_swap_complex 0.1s +2023-11-12T09:04:14.8537437Z ##[endgroup] +2023-11-12T09:04:14.8839470Z ##[group]/datum/unit_test/language_species_change_other_known +2023-11-12T09:04:14.9795952Z PASS /datum/unit_test/language_species_change_other_known 0.1s +2023-11-12T09:04:14.9797030Z ##[endgroup] +2023-11-12T09:04:15.0435933Z ##[group]/datum/unit_test/language_mind_transfer +2023-11-12T09:04:15.1107127Z PASS /datum/unit_test/language_mind_transfer 0.1s +2023-11-12T09:04:15.1109587Z ##[endgroup] +2023-11-12T09:04:15.2112030Z ##[group]/datum/unit_test/language_mind_swap +2023-11-12T09:04:15.2925264Z PASS /datum/unit_test/language_mind_swap 0s +2023-11-12T09:04:15.2927698Z ##[endgroup] +2023-11-12T09:04:15.3795431Z ##[group]/datum/unit_test/book_of_babel +2023-11-12T09:04:15.4462613Z PASS /datum/unit_test/book_of_babel 0.1s +2023-11-12T09:04:15.4464636Z ##[endgroup] +2023-11-12T09:04:15.4773421Z ##[group]/datum/unit_test/lesserform +2023-11-12T09:04:15.6945571Z PASS /datum/unit_test/lesserform 0.2s +2023-11-12T09:04:15.6948228Z ##[endgroup] +2023-11-12T09:04:15.7353723Z ##[group]/datum/unit_test/limbsanity +2023-11-12T09:04:15.7943636Z PASS /datum/unit_test/limbsanity 0s +2023-11-12T09:04:15.7944637Z ##[endgroup] +2023-11-12T09:04:15.8094514Z ##[group]/datum/unit_test/limb_height_adjustment +2023-11-12T09:04:15.8922884Z PASS /datum/unit_test/limb_height_adjustment 0s +2023-11-12T09:04:15.8924726Z ##[endgroup] +2023-11-12T09:04:15.9430586Z ##[group]/datum/unit_test/ling_decap +2023-11-12T09:04:15.9835506Z PASS /datum/unit_test/ling_decap 0s +2023-11-12T09:04:15.9839509Z ##[endgroup] +2023-11-12T09:04:16.0140352Z ##[group]/datum/unit_test/normal_decap +2023-11-12T09:04:16.0424498Z PASS /datum/unit_test/normal_decap 0s +2023-11-12T09:04:16.0426983Z ##[endgroup] +2023-11-12T09:04:16.0805164Z ##[group]/datum/unit_test/liver/skeleton +2023-11-12T09:04:16.1038545Z PASS /datum/unit_test/liver/skeleton 0.1s +2023-11-12T09:04:16.1041112Z ##[endgroup] +2023-11-12T09:04:16.1284821Z ##[group]/datum/unit_test/liver/plasmaman +2023-11-12T09:04:16.1580562Z PASS /datum/unit_test/liver/plasmaman 0s +2023-11-12T09:04:16.1583210Z ##[endgroup] +2023-11-12T09:04:16.2153103Z ##[group]/datum/unit_test/load_map_security +2023-11-12T09:04:16.2161683Z map directory not in whitelist: data/load_map_security_temp for map runtimestation +2023-11-12T09:04:16.2164604Z PASS /datum/unit_test/load_map_security 0s +2023-11-12T09:04:16.2167411Z ##[endgroup] +2023-11-12T09:04:16.2305620Z ##[group]/datum/unit_test/lungs/lungs_sanity +2023-11-12T09:04:16.2992950Z PASS /datum/unit_test/lungs/lungs_sanity 0s +2023-11-12T09:04:16.2993961Z ##[endgroup] +2023-11-12T09:04:16.3555743Z ##[group]/datum/unit_test/lungs/lungs_sanity_plasmaman +2023-11-12T09:04:16.3893402Z PASS /datum/unit_test/lungs/lungs_sanity_plasmaman 0s +2023-11-12T09:04:16.3896070Z ##[endgroup] +2023-11-12T09:04:16.4363609Z ##[group]/datum/unit_test/lungs/lungs_sanity_ashwalker +2023-11-12T09:04:16.4534765Z PASS /datum/unit_test/lungs/lungs_sanity_ashwalker 0s +2023-11-12T09:04:16.4537484Z ##[endgroup] +2023-11-12T09:04:16.5268598Z ##[group]/datum/unit_test/machine_disassembly +2023-11-12T09:04:16.5331398Z PASS /datum/unit_test/machine_disassembly 0s +2023-11-12T09:04:16.5334165Z ##[endgroup] +2023-11-12T09:04:16.5965192Z ##[group]/datum/unit_test/mafia +2023-11-12T09:04:16.9361333Z PASS /datum/unit_test/mafia 0.4s +2023-11-12T09:04:16.9362885Z ##[endgroup] +2023-11-12T09:04:17.0130362Z ##[group]/datum/unit_test/job_roundstart_spawnpoints +2023-11-12T09:04:17.0143039Z PASS /datum/unit_test/job_roundstart_spawnpoints 0s +2023-11-12T09:04:17.0145274Z ##[endgroup] +2023-11-12T09:04:17.0659056Z ##[group]/datum/unit_test/mecha_damage +2023-11-12T09:04:17.1110027Z PASS /datum/unit_test/mecha_damage 0.1s +2023-11-12T09:04:17.1112178Z ##[endgroup] +2023-11-12T09:04:17.2054159Z ##[group]/datum/unit_test/test_human_base +2023-11-12T09:04:17.2287354Z PASS /datum/unit_test/test_human_base 0s +2023-11-12T09:04:17.2289454Z ##[endgroup] +2023-11-12T09:04:17.2929615Z ##[group]/datum/unit_test/test_human_bone +2023-11-12T09:04:17.3157404Z PASS /datum/unit_test/test_human_bone 0.1s +2023-11-12T09:04:17.3160356Z ##[endgroup] +2023-11-12T09:04:17.3434694Z ##[group]/datum/unit_test/merge_type +2023-11-12T09:04:17.3440046Z PASS /datum/unit_test/merge_type 0s +2023-11-12T09:04:17.3442753Z ##[endgroup] +2023-11-12T09:04:17.3573048Z ##[group]/datum/unit_test/metabolization +2023-11-12T09:04:17.6960389Z PASS /datum/unit_test/metabolization 0.3s +2023-11-12T09:04:17.6963225Z ##[endgroup] +2023-11-12T09:04:17.7388896Z ##[group]/datum/unit_test/on_mob_end_metabolize +2023-11-12T09:04:17.7590192Z PASS /datum/unit_test/on_mob_end_metabolize 0s +2023-11-12T09:04:17.7592863Z ##[endgroup] +2023-11-12T09:04:17.7841810Z ##[group]/datum/unit_test/addictions +2023-11-12T09:04:17.8425631Z PASS /datum/unit_test/addictions 0.1s +2023-11-12T09:04:17.8428724Z ##[endgroup] +2023-11-12T09:04:17.9023556Z ##[group]/datum/unit_test/actions_moved_on_mind_transfer +2023-11-12T09:04:17.9228877Z PASS /datum/unit_test/actions_moved_on_mind_transfer 0s +2023-11-12T09:04:17.9231703Z ##[endgroup] +2023-11-12T09:04:17.9679832Z ##[group]/datum/unit_test/missing_icons +2023-11-12T09:04:24.5752532Z PASS /datum/unit_test/missing_icons 6.6s +2023-11-12T09:04:24.5754181Z ##[endgroup] +2023-11-12T09:04:24.6466600Z ##[group]/datum/unit_test/mob_chains +2023-11-12T09:04:24.6632928Z PASS /datum/unit_test/mob_chains 0s +2023-11-12T09:04:24.6635968Z ##[endgroup] +2023-11-12T09:04:24.7913005Z ##[group]/datum/unit_test/mob_faction +2023-11-12T09:04:28.5066463Z PASS /datum/unit_test/mob_faction 3.8s +2023-11-12T09:04:28.5069188Z ##[endgroup] +2023-11-12T09:04:31.6163193Z ##[group]/datum/unit_test/mob_spawn +2023-11-12T09:04:31.6427245Z PASS /datum/unit_test/mob_spawn 0s +2023-11-12T09:04:31.6431419Z ##[endgroup] +2023-11-12T09:04:32.0058055Z ##[group]/datum/unit_test/modsuit_checks +2023-11-12T09:04:32.2811166Z PASS /datum/unit_test/modsuit_checks 0.2s +2023-11-12T09:04:32.2812528Z ##[endgroup] +2023-11-12T09:04:32.3511926Z ##[group]/datum/unit_test/modular_map_loader +2023-11-12T09:04:32.3521874Z PASS /datum/unit_test/modular_map_loader 0s +2023-11-12T09:04:32.3523808Z ##[endgroup] +2023-11-12T09:04:32.4142704Z ##[group]/datum/unit_test/mouse_bite_cable +2023-11-12T09:04:32.4246879Z PASS /datum/unit_test/mouse_bite_cable 0s +2023-11-12T09:04:32.4248567Z ##[endgroup] +2023-11-12T09:04:32.4874261Z ##[group]/datum/unit_test/mutant_hands +2023-11-12T09:04:32.5112259Z PASS /datum/unit_test/mutant_hands 0.1s +2023-11-12T09:04:32.5113850Z ##[endgroup] +2023-11-12T09:04:32.5849921Z ##[group]/datum/unit_test/mutant_hands_with_nodrop +2023-11-12T09:04:32.6040138Z PASS /datum/unit_test/mutant_hands_with_nodrop 0.1s +2023-11-12T09:04:32.6041689Z ##[endgroup] +2023-11-12T09:04:32.6773675Z ##[group]/datum/unit_test/mutant_hands_carry +2023-11-12T09:04:32.7131388Z PASS /datum/unit_test/mutant_hands_carry 0.1s +2023-11-12T09:04:32.7133185Z ##[endgroup] +2023-11-12T09:04:32.7786446Z ##[group]/datum/unit_test/mutant_organs +2023-11-12T09:04:34.2934214Z PASS /datum/unit_test/mutant_organs 1.5s +2023-11-12T09:04:34.2935313Z ##[endgroup] +2023-11-12T09:04:34.6462244Z ##[group]/datum/unit_test/novaflower_burn +2023-11-12T09:04:34.6850680Z PASS /datum/unit_test/novaflower_burn 0s +2023-11-12T09:04:34.6852577Z ##[endgroup] +2023-11-12T09:04:34.7556767Z ##[group]/datum/unit_test/nuke_cinematic +2023-11-12T09:04:39.0321508Z PASS /datum/unit_test/nuke_cinematic 4.3s +2023-11-12T09:04:39.0323281Z ##[endgroup] +2023-11-12T09:04:39.0458593Z ##[group]/datum/unit_test/objectives_category +2023-11-12T09:04:39.0479702Z PASS /datum/unit_test/objectives_category 0s +2023-11-12T09:04:39.0482187Z ##[endgroup] +2023-11-12T09:04:39.0633771Z ##[group]/datum/unit_test/operating_table +2023-11-12T09:04:39.0971239Z PASS /datum/unit_test/operating_table 0s +2023-11-12T09:04:39.0973601Z ##[endgroup] +2023-11-12T09:04:39.1707308Z ##[group]/datum/unit_test/orderable_items +2023-11-12T09:04:39.3304868Z PASS /datum/unit_test/orderable_items 0.2s +2023-11-12T09:04:39.3307041Z ##[endgroup] +2023-11-12T09:04:39.4628600Z ##[group]/datum/unit_test/organ_set_bonus_id +2023-11-12T09:04:39.4631127Z PASS /datum/unit_test/organ_set_bonus_id 0s +2023-11-12T09:04:39.4632993Z ##[endgroup] +2023-11-12T09:04:39.4763602Z ##[group]/datum/unit_test/organ_set_bonus_sanity +2023-11-12T09:04:39.7566200Z PASS /datum/unit_test/organ_set_bonus_sanity 0.3s +2023-11-12T09:04:39.7567687Z ##[endgroup] +2023-11-12T09:04:39.8948309Z ##[group]/datum/unit_test/organ_sanity +2023-11-12T09:04:39.8957864Z PASS /datum/unit_test/organ_sanity 0s +2023-11-12T09:04:39.8960612Z ##[endgroup] +2023-11-12T09:04:39.9099785Z ##[group]/datum/unit_test/organ_damage +2023-11-12T09:04:39.9663107Z PASS /datum/unit_test/organ_damage 0s +2023-11-12T09:04:39.9665107Z ##[endgroup] +2023-11-12T09:04:40.0023907Z ##[group]/datum/unit_test/outfit_sanity +2023-11-12T09:04:52.5011539Z PASS /datum/unit_test/outfit_sanity 12.5s +2023-11-12T09:04:52.5013136Z ##[endgroup] +2023-11-12T09:04:52.5847995Z ##[group]/datum/unit_test/oxyloss_suffocation +2023-11-12T09:04:52.6033624Z PASS /datum/unit_test/oxyloss_suffocation 0.1s +2023-11-12T09:04:52.6035713Z ##[endgroup] +2023-11-12T09:04:52.6523199Z ##[group]/datum/unit_test/paintings +2023-11-12T09:04:52.6718185Z PASS /datum/unit_test/paintings 0s +2023-11-12T09:04:52.6720334Z ##[endgroup] +2023-11-12T09:04:52.6860350Z ##[group]/datum/unit_test/pills +2023-11-12T09:04:52.7049829Z PASS /datum/unit_test/pills 0.1s +2023-11-12T09:04:52.7051614Z ##[endgroup] +2023-11-12T09:04:52.7284869Z ##[group]/datum/unit_test/plane_double_transform +2023-11-12T09:04:52.7568954Z PASS /datum/unit_test/plane_double_transform 0s +2023-11-12T09:04:52.7570947Z ##[endgroup] +2023-11-12T09:04:52.8088783Z ##[group]/datum/unit_test/plane_dupe_detector +2023-11-12T09:04:52.8092292Z PASS /datum/unit_test/plane_dupe_detector 0s +2023-11-12T09:04:52.8094235Z ##[endgroup] +2023-11-12T09:04:52.8223651Z ##[group]/datum/unit_test/plantgrowth +2023-11-12T09:04:52.9104725Z PASS /datum/unit_test/plantgrowth 0.1s +2023-11-12T09:04:52.9106537Z ##[endgroup] +2023-11-12T09:04:52.9238426Z ##[group]/datum/unit_test/preference_species +2023-11-12T09:04:52.9241982Z PASS /datum/unit_test/preference_species 0s +2023-11-12T09:04:52.9243985Z ##[endgroup] +2023-11-12T09:04:52.9366837Z ##[group]/datum/unit_test/preferences_implement_everything +2023-11-12T09:04:52.9767879Z PASS /datum/unit_test/preferences_implement_everything 0s +2023-11-12T09:04:52.9769887Z ##[endgroup] +2023-11-12T09:04:53.0386005Z ##[group]/datum/unit_test/preferences_valid_savefile_key +2023-11-12T09:04:53.0390164Z PASS /datum/unit_test/preferences_valid_savefile_key 0s +2023-11-12T09:04:53.0392300Z ##[endgroup] +2023-11-12T09:04:53.0533180Z ##[group]/datum/unit_test/preferences_valid_main_feature_name +2023-11-12T09:04:53.0536519Z PASS /datum/unit_test/preferences_valid_main_feature_name 0s +2023-11-12T09:04:53.0538733Z ##[endgroup] +2023-11-12T09:04:53.0666858Z ##[group]/datum/unit_test/preferences_should_generate_icons_sanity +2023-11-12T09:04:53.5932797Z PASS /datum/unit_test/preferences_should_generate_icons_sanity 0.5s +2023-11-12T09:04:53.5934463Z ##[endgroup] +2023-11-12T09:04:53.6200764Z ##[group]/datum/unit_test/projectile_movetypes +2023-11-12T09:04:53.6204485Z PASS /datum/unit_test/projectile_movetypes 0s +2023-11-12T09:04:53.6206834Z ##[endgroup] +2023-11-12T09:04:53.6336940Z ##[group]/datum/unit_test/gun_go_bang +2023-11-12T09:04:53.6829687Z PASS /datum/unit_test/gun_go_bang 0s +2023-11-12T09:04:53.6830843Z ##[endgroup] +2023-11-12T09:04:53.7230698Z ##[group]/datum/unit_test/quirk_icons +2023-11-12T09:04:53.7234275Z PASS /datum/unit_test/quirk_icons 0s +2023-11-12T09:04:53.7236777Z ##[endgroup] +2023-11-12T09:04:53.7365585Z ##[group]/datum/unit_test/range_return +2023-11-12T09:04:53.7369094Z PASS /datum/unit_test/range_return 0s +2023-11-12T09:04:53.7371240Z ##[endgroup] +2023-11-12T09:04:53.7500465Z ##[group]/datum/unit_test/frame_stacking +2023-11-12T09:04:53.7979971Z PASS /datum/unit_test/frame_stacking 0s +2023-11-12T09:04:53.7981883Z ##[endgroup] +2023-11-12T09:04:53.8318167Z ##[group]/datum/unit_test/reagent_container_defaults +2023-11-12T09:04:54.0941417Z PASS /datum/unit_test/reagent_container_defaults 0.2s +2023-11-12T09:04:54.0943278Z ##[endgroup] +2023-11-12T09:04:54.2270413Z ##[group]/datum/unit_test/reagent_id_typos +2023-11-12T09:04:54.2286982Z PASS /datum/unit_test/reagent_id_typos 0s +2023-11-12T09:04:54.2289435Z ##[endgroup] +2023-11-12T09:04:54.2420053Z ##[group]/datum/unit_test/reagent_mob_expose +2023-11-12T09:04:54.2723656Z PASS /datum/unit_test/reagent_mob_expose 0s +2023-11-12T09:04:54.2726334Z ##[endgroup] +2023-11-12T09:04:54.3099472Z ##[group]/datum/unit_test/reagent_mob_procs +2023-11-12T09:04:54.3289033Z PASS /datum/unit_test/reagent_mob_procs 0s +2023-11-12T09:04:54.3291717Z ##[endgroup] +2023-11-12T09:04:54.3541628Z ##[group]/datum/unit_test/reagent_names +2023-11-12T09:04:55.1766396Z PASS /datum/unit_test/reagent_names 0.8s +2023-11-12T09:04:55.1768837Z ##[endgroup] +2023-11-12T09:04:55.2029840Z ##[group]/datum/unit_test/reagent_recipe_collisions +2023-11-12T09:04:56.8716958Z PASS /datum/unit_test/reagent_recipe_collisions 1.6s +2023-11-12T09:04:56.8718508Z ##[endgroup] +2023-11-12T09:04:56.8869144Z ##[group]/datum/unit_test/reagent_transfer +2023-11-12T09:04:56.8878975Z PASS /datum/unit_test/reagent_transfer 0s +2023-11-12T09:04:56.8880828Z ##[endgroup] +2023-11-12T09:04:56.9011226Z ##[group]/datum/unit_test/required_map_items +2023-11-12T09:04:56.9014244Z PASS /datum/unit_test/required_map_items 0s +2023-11-12T09:04:56.9016215Z ##[endgroup] +2023-11-12T09:04:56.9145903Z ##[group]/datum/unit_test/stop_drop_and_roll +2023-11-12T09:04:56.9332587Z PASS /datum/unit_test/stop_drop_and_roll 0s +2023-11-12T09:04:56.9334766Z ##[endgroup] +2023-11-12T09:04:56.9894372Z ##[group]/datum/unit_test/container_resist +2023-11-12T09:04:57.0133852Z PASS /datum/unit_test/container_resist 0.1s +2023-11-12T09:04:57.0136482Z ##[endgroup] +2023-11-12T09:04:57.0869981Z ##[group]/datum/unit_test/get_message_mods +2023-11-12T09:04:57.1036296Z PASS /datum/unit_test/get_message_mods 0.1s +2023-11-12T09:04:57.1038377Z ##[endgroup] +2023-11-12T09:04:57.1761766Z ##[group]/datum/unit_test/say_signal +2023-11-12T09:04:57.1785738Z PASS /datum/unit_test/say_signal 0s +2023-11-12T09:04:57.1787867Z ##[endgroup] +2023-11-12T09:04:57.2275108Z ##[group]/datum/unit_test/translate_language +2023-11-12T09:04:57.2445118Z PASS /datum/unit_test/translate_language 0s +2023-11-12T09:04:57.2447197Z ##[endgroup] +2023-11-12T09:04:57.2776300Z ##[group]/datum/unit_test/speech +2023-11-12T09:04:57.3273922Z PASS /datum/unit_test/speech 0.1s +2023-11-12T09:04:57.3276048Z ##[endgroup] +2023-11-12T09:04:57.3648311Z ##[group]/datum/unit_test/screenshot_antag_icons +2023-11-12T09:04:57.3655596Z screenshot_antag_icons_cyberpolice was put in data/screenshots_new +2023-11-12T09:04:57.3668195Z screenshot_antag_icons_fugitive was put in data/screenshots_new +2023-11-12T09:04:57.3673743Z screenshot_antag_icons_loneoperative was put in data/screenshots_new +2023-11-12T09:04:57.3918428Z screenshot_antag_icons_sentiencepotionspawn was put in data/screenshots_new +2023-11-12T09:04:57.3925180Z screenshot_antag_icons_traitor was put in data/screenshots_new +2023-11-12T09:04:57.4212360Z screenshot_antag_icons_malfai was put in data/screenshots_new +2023-11-12T09:04:57.4244403Z screenshot_antag_icons_bloodbrother was put in data/screenshots_new +2023-11-12T09:04:57.4250630Z screenshot_antag_icons_changeling was put in data/screenshots_new +2023-11-12T09:04:57.4282149Z screenshot_antag_icons_heretic was put in data/screenshots_new +2023-11-12T09:04:57.4292701Z screenshot_antag_icons_wizard was put in data/screenshots_new +2023-11-12T09:04:57.4322992Z screenshot_antag_icons_cultist was put in data/screenshots_new +2023-11-12T09:04:57.4335181Z screenshot_antag_icons_operative was put in data/screenshots_new +2023-11-12T09:04:57.4347253Z screenshot_antag_icons_clownoperative was put in data/screenshots_new +2023-11-12T09:04:57.4360316Z screenshot_antag_icons_headrevolutionary was put in data/screenshots_new +2023-11-12T09:04:57.4362553Z screenshot_antag_icons_syndicateinfiltrator was put in data/screenshots_new +2023-11-12T09:04:57.4364249Z screenshot_antag_icons_provocateur was put in data/screenshots_new +2023-11-12T09:04:57.4365976Z screenshot_antag_icons_hereticsmuggler was put in data/screenshots_new +2023-11-12T09:04:57.4367872Z screenshot_antag_icons_stowawaychangeling was put in data/screenshots_new +2023-11-12T09:04:57.4369724Z screenshot_antag_icons_wizardmidround was put in data/screenshots_new +2023-11-12T09:04:57.4371538Z screenshot_antag_icons_operativemidround was put in data/screenshots_new +2023-11-12T09:04:57.4836255Z screenshot_antag_icons_blob was put in data/screenshots_new +2023-11-12T09:04:57.4913104Z screenshot_antag_icons_xenomorph was put in data/screenshots_new +2023-11-12T09:04:57.4918547Z screenshot_antag_icons_nightmare was put in data/screenshots_new +2023-11-12T09:04:57.4972641Z screenshot_antag_icons_spacedragon was put in data/screenshots_new +2023-11-12T09:04:57.4978863Z screenshot_antag_icons_abductor was put in data/screenshots_new +2023-11-12T09:04:57.4984390Z screenshot_antag_icons_spaceninja was put in data/screenshots_new +2023-11-12T09:04:57.5142179Z screenshot_antag_icons_revenant was put in data/screenshots_new +2023-11-12T09:04:57.5158225Z screenshot_antag_icons_sentientdisease was put in data/screenshots_new +2023-11-12T09:04:57.5164048Z screenshot_antag_icons_changelingmidround was put in data/screenshots_new +2023-11-12T09:04:57.5175747Z screenshot_antag_icons_paradoxclone was put in data/screenshots_new +2023-11-12T09:04:57.5177675Z screenshot_antag_icons_syndicatesleeperagent was put in data/screenshots_new +2023-11-12T09:04:57.5295585Z screenshot_antag_icons_blobinfection was put in data/screenshots_new +2023-11-12T09:04:57.5313285Z screenshot_antag_icons_obsessed was put in data/screenshots_new +2023-11-12T09:04:57.5315517Z screenshot_antag_icons_malfaimidround was put in data/screenshots_new +2023-11-12T09:04:57.5319787Z PASS /datum/unit_test/screenshot_antag_icons 0.2s +2023-11-12T09:04:57.5322595Z ##[endgroup] +2023-11-12T09:04:57.5541756Z ##[group]/datum/unit_test/screenshot_basic +2023-11-12T09:04:57.5545037Z screenshot_basic_red was put in data/screenshots_new +2023-11-12T09:04:57.5548126Z PASS /datum/unit_test/screenshot_basic 0s +2023-11-12T09:04:57.5550758Z ##[endgroup] +2023-11-12T09:04:57.5683479Z ##[group]/datum/unit_test/screenshot_dynamic_human_icons +2023-11-12T09:04:57.8350756Z screenshot_dynamic_human_icons_syndicate_commando was put in data/screenshots_new +2023-11-12T09:04:57.8354817Z PASS /datum/unit_test/screenshot_dynamic_human_icons 0.3s +2023-11-12T09:04:57.8357024Z ##[endgroup] +2023-11-12T09:04:57.8497778Z ##[group]/datum/unit_test/screenshot_humanoids +2023-11-12T09:04:58.2541589Z screenshot_humanoids__datum_species_lizard was put in data/screenshots_new +2023-11-12T09:04:58.8071729Z screenshot_humanoids__datum_species_moth was put in data/screenshots_new +2023-11-12T09:04:59.0481483Z screenshot_humanoids__datum_species_shadow was put in data/screenshots_new +2023-11-12T09:04:59.2204964Z screenshot_humanoids__datum_species_shadow_nightmare was put in data/screenshots_new +2023-11-12T09:04:59.4446438Z screenshot_humanoids__datum_species_abductor was put in data/screenshots_new +2023-11-12T09:04:59.9025529Z screenshot_humanoids__datum_species_human was put in data/screenshots_new +2023-11-12T09:05:00.3720324Z screenshot_humanoids__datum_species_human_tallboy was put in data/screenshots_new +2023-11-12T09:05:00.8410192Z screenshot_humanoids__datum_species_human_felinid was put in data/screenshots_new +2023-11-12T09:05:01.3919326Z screenshot_humanoids__datum_species_human_krokodil_addict was put in data/screenshots_new +2023-11-12T09:05:01.5050044Z screenshot_humanoids__datum_species_monkey was put in data/screenshots_new +2023-11-12T09:05:01.6332131Z screenshot_humanoids__datum_species_monkey_human_legged was put in data/screenshots_new +2023-11-12T09:05:01.8078163Z screenshot_humanoids__datum_species_monkey_monkey_freak was put in data/screenshots_new +2023-11-12T09:05:01.9204604Z screenshot_humanoids__datum_species_monkey_holodeck was put in data/screenshots_new +2023-11-12T09:05:02.2703729Z screenshot_humanoids__datum_species_android was put in data/screenshots_new +2023-11-12T09:05:02.5066397Z screenshot_humanoids__datum_species_dullahan was put in data/screenshots_new +2023-11-12T09:05:02.8821597Z screenshot_humanoids__datum_species_ethereal was put in data/screenshots_new +2023-11-12T09:05:03.0618503Z screenshot_humanoids__datum_species_ethereal_lustrous was put in data/screenshots_new +2023-11-12T09:05:03.6054858Z screenshot_humanoids__datum_species_fly was put in data/screenshots_new +2023-11-12T09:05:03.7723456Z screenshot_humanoids__datum_species_golem was put in data/screenshots_new +2023-11-12T09:05:04.2399263Z screenshot_humanoids__datum_species_jelly was put in data/screenshots_new +2023-11-12T09:05:04.7039511Z screenshot_humanoids__datum_species_jelly_slime was put in data/screenshots_new +2023-11-12T09:05:05.1607461Z screenshot_humanoids__datum_species_jelly_luminescent was put in data/screenshots_new +2023-11-12T09:05:05.6194475Z screenshot_humanoids__datum_species_jelly_stargazer was put in data/screenshots_new +2023-11-12T09:05:05.9809404Z screenshot_humanoids__datum_species_lizard_ashwalker was put in data/screenshots_new +2023-11-12T09:05:06.3898218Z screenshot_humanoids__datum_species_lizard_silverscale was put in data/screenshots_new +2023-11-12T09:05:06.6851305Z screenshot_humanoids__datum_species_mush was put in data/screenshots_new +2023-11-12T09:05:07.0392950Z screenshot_humanoids__datum_species_plasmaman was put in data/screenshots_new +2023-11-12T09:05:07.5136767Z screenshot_humanoids__datum_species_pod was put in data/screenshots_new +2023-11-12T09:05:07.7567133Z screenshot_humanoids__datum_species_skeleton was put in data/screenshots_new +2023-11-12T09:05:08.2342975Z screenshot_humanoids__datum_species_snail was put in data/screenshots_new +2023-11-12T09:05:08.6975763Z screenshot_humanoids__datum_species_vampire was put in data/screenshots_new +2023-11-12T09:05:09.2496544Z screenshot_humanoids__datum_species_zombie was put in data/screenshots_new +2023-11-12T09:05:09.8588009Z screenshot_humanoids__datum_species_zombie_infectious was put in data/screenshots_new +2023-11-12T09:05:09.8591473Z PASS /datum/unit_test/screenshot_humanoids 12s +2023-11-12T09:05:09.8593884Z ##[endgroup] +2023-11-12T09:05:10.3359233Z ##[group]/datum/unit_test/screenshot_husk +2023-11-12T09:05:10.4814584Z screenshot_husk_body was put in data/screenshots_new +2023-11-12T09:05:10.5100421Z screenshot_husk_body_missing_limbs was put in data/screenshots_new +2023-11-12T09:05:10.5103760Z PASS /datum/unit_test/screenshot_husk 0.2s +2023-11-12T09:05:10.5105844Z ##[endgroup] +2023-11-12T09:05:10.5738946Z ##[group]/datum/unit_test/screenshot_saturnx +2023-11-12T09:05:10.7302951Z screenshot_saturnx_invisibility was put in data/screenshots_new +2023-11-12T09:05:10.7306714Z PASS /datum/unit_test/screenshot_saturnx 0.2s +2023-11-12T09:05:10.7309565Z ##[endgroup] +2023-11-12T09:05:10.7993117Z ##[group]/datum/unit_test/security_levels +2023-11-12T09:05:10.7995233Z PASS /datum/unit_test/security_levels 0s +2023-11-12T09:05:10.7997473Z ##[endgroup] +2023-11-12T09:05:10.8718075Z ##[group]/datum/unit_test/security_officer_roundstart_distribution +2023-11-12T09:05:10.9829621Z PASS /datum/unit_test/security_officer_roundstart_distribution 0.1s +2023-11-12T09:05:10.9831233Z ##[endgroup] +2023-11-12T09:05:11.0917739Z ##[group]/datum/unit_test/security_officer_latejoin_distribution +2023-11-12T09:05:11.3756560Z PASS /datum/unit_test/security_officer_latejoin_distribution 0.3s +2023-11-12T09:05:11.3757917Z ##[endgroup] +2023-11-12T09:05:11.6159233Z ##[group]/datum/unit_test/servingtray +2023-11-12T09:05:11.6420663Z PASS /datum/unit_test/servingtray 0s +2023-11-12T09:05:11.6422707Z ##[endgroup] +2023-11-12T09:05:11.6722939Z ##[group]/datum/unit_test/simple_animal_freeze +2023-11-12T09:05:11.6727308Z PASS /datum/unit_test/simple_animal_freeze 0s +2023-11-12T09:05:11.6729459Z ##[endgroup] +2023-11-12T09:05:11.6858248Z ##[group]/datum/unit_test/siunit +2023-11-12T09:05:11.6862565Z PASS /datum/unit_test/siunit 0s +2023-11-12T09:05:11.6864627Z ##[endgroup] +2023-11-12T09:05:11.6994032Z ##[group]/datum/unit_test/slime_mood +2023-11-12T09:05:11.7086306Z PASS /datum/unit_test/slime_mood 0.1s +2023-11-12T09:05:11.7089418Z ##[endgroup] +2023-11-12T09:05:11.7646724Z ##[group]/datum/unit_test/slips +2023-11-12T09:05:11.7998254Z PASS /datum/unit_test/slips 0s +2023-11-12T09:05:11.7999914Z ##[endgroup] +2023-11-12T09:05:11.8832258Z ##[group]/datum/unit_test/spawn_humans +2023-11-12T09:05:16.9174068Z PASS /datum/unit_test/spawn_humans 5.1s +2023-11-12T09:05:16.9175480Z ##[endgroup] +2023-11-12T09:05:16.9826971Z ##[group]/datum/unit_test/human_default_traits +2023-11-12T09:05:16.9992542Z PASS /datum/unit_test/human_default_traits 0s +2023-11-12T09:05:16.9994648Z ##[endgroup] +2023-11-12T09:05:17.0453589Z ##[group]/datum/unit_test/spawn_mobs +2023-11-12T09:05:17.3110840Z PASS /datum/unit_test/spawn_mobs 0.3s +2023-11-12T09:05:17.3113201Z ##[endgroup] +2023-11-12T09:05:17.8604911Z ##[group]/datum/unit_test/species_change_clothing +2023-11-12T09:05:18.0037169Z PASS /datum/unit_test/species_change_clothing 0.2s +2023-11-12T09:05:18.0039927Z ##[endgroup] +2023-11-12T09:05:18.0594811Z ##[group]/datum/unit_test/species_change_held_items +2023-11-12T09:05:18.1241794Z PASS /datum/unit_test/species_change_held_items 0.1s +2023-11-12T09:05:18.1244171Z ##[endgroup] +2023-11-12T09:05:18.1531271Z ##[group]/datum/unit_test/species_change_organs +2023-11-12T09:05:18.2175195Z PASS /datum/unit_test/species_change_organs 0.1s +2023-11-12T09:05:18.2177564Z ##[endgroup] +2023-11-12T09:05:18.2917259Z ##[group]/datum/unit_test/species_config_sanity +2023-11-12T09:05:18.2920181Z PASS /datum/unit_test/species_config_sanity 0s +2023-11-12T09:05:18.2922846Z ##[endgroup] +2023-11-12T09:05:18.3062818Z ##[group]/datum/unit_test/species_unique_id +2023-11-12T09:05:18.3065971Z PASS /datum/unit_test/species_unique_id 0s +2023-11-12T09:05:18.3068171Z ##[endgroup] +2023-11-12T09:05:18.3222639Z ##[group]/datum/unit_test/species_whitelist_check +2023-11-12T09:05:18.3225988Z PASS /datum/unit_test/species_whitelist_check 0s +2023-11-12T09:05:18.3228060Z ##[endgroup] +2023-11-12T09:05:18.3393256Z ##[group]/datum/unit_test/spell_invocations +2023-11-12T09:05:18.3397536Z PASS /datum/unit_test/spell_invocations 0s +2023-11-12T09:05:18.3400085Z ##[endgroup] +2023-11-12T09:05:18.3530030Z ##[group]/datum/unit_test/shadow_jaunt +2023-11-12T09:05:18.3711590Z PASS /datum/unit_test/shadow_jaunt 0s +2023-11-12T09:05:18.3713925Z ##[endgroup] +2023-11-12T09:05:18.4080468Z ##[group]/datum/unit_test/mind_swap_spell +2023-11-12T09:05:18.4445059Z PASS /datum/unit_test/mind_swap_spell 0s +2023-11-12T09:05:18.4447973Z ##[endgroup] +2023-11-12T09:05:18.4831097Z ##[group]/datum/unit_test/spell_names +2023-11-12T09:05:18.4836690Z PASS /datum/unit_test/spell_names 0s +2023-11-12T09:05:18.4839793Z ##[endgroup] +2023-11-12T09:05:18.4973281Z ##[group]/datum/unit_test/shapeshift_spell_validity +2023-11-12T09:05:18.4982346Z PASS /datum/unit_test/shapeshift_spell_validity 0s +2023-11-12T09:05:18.4985502Z ##[endgroup] +2023-11-12T09:05:18.5118193Z ##[group]/datum/unit_test/shapeshift_spell +2023-11-12T09:05:31.3590354Z PASS /datum/unit_test/shapeshift_spell 12.8s +2023-11-12T09:05:31.3593257Z ##[endgroup] +2023-11-12T09:05:31.3839062Z ##[group]/datum/unit_test/shapeshift_holoparasites +2023-11-12T09:05:31.4236915Z PASS /datum/unit_test/shapeshift_holoparasites 0.1s +2023-11-12T09:05:31.4240548Z ##[endgroup] +2023-11-12T09:05:31.4609174Z ##[group]/datum/unit_test/shapeshift_health +2023-11-12T09:05:32.0958569Z PASS /datum/unit_test/shapeshift_health 0.6s +2023-11-12T09:05:32.0961165Z ##[endgroup] +2023-11-12T09:05:32.2270540Z ##[group]/datum/unit_test/spritesheets +2023-11-12T09:05:32.2310129Z PASS /datum/unit_test/spritesheets 0s +2023-11-12T09:05:32.2313287Z ##[endgroup] +2023-11-12T09:05:32.2444065Z ##[group]/datum/unit_test/stack_singular_name +2023-11-12T09:05:32.2449554Z PASS /datum/unit_test/stack_singular_name 0s +2023-11-12T09:05:32.2452311Z ##[endgroup] +2023-11-12T09:05:32.2582343Z ##[group]/datum/unit_test/station_traits +2023-11-12T09:05:32.2586458Z PASS /datum/unit_test/station_traits 0s +2023-11-12T09:05:32.2589532Z ##[endgroup] +2023-11-12T09:05:32.3273087Z ##[group]/datum/unit_test/status_effect_ticks +2023-11-12T09:05:32.3278478Z PASS /datum/unit_test/status_effect_ticks 0s +2023-11-12T09:05:32.3282046Z ##[endgroup] +2023-11-12T09:05:32.3883615Z ##[group]/datum/unit_test/stomach +2023-11-12T09:05:32.4148653Z PASS /datum/unit_test/stomach 0.1s +2023-11-12T09:05:32.4152041Z ##[endgroup] +2023-11-12T09:05:32.4474665Z ##[group]/datum/unit_test/strip_menu_ui_status +2023-11-12T09:05:32.4955743Z PASS /datum/unit_test/strip_menu_ui_status 0s +2023-11-12T09:05:32.4959231Z ##[endgroup] +2023-11-12T09:05:32.5763081Z ##[group]/datum/unit_test/stun +2023-11-12T09:05:32.5938628Z PASS /datum/unit_test/stun 0s +2023-11-12T09:05:32.5941798Z ##[endgroup] +2023-11-12T09:05:32.6174955Z ##[group]/datum/unit_test/knockdown +2023-11-12T09:05:32.6344357Z PASS /datum/unit_test/knockdown 0s +2023-11-12T09:05:32.6347424Z ##[endgroup] +2023-11-12T09:05:32.6656807Z ##[group]/datum/unit_test/paralyze +2023-11-12T09:05:32.6830553Z PASS /datum/unit_test/paralyze 0s +2023-11-12T09:05:32.6834151Z ##[endgroup] +2023-11-12T09:05:32.7067888Z ##[group]/datum/unit_test/unconsciousness +2023-11-12T09:05:32.7247146Z PASS /datum/unit_test/unconsciousness 0s +2023-11-12T09:05:32.7250770Z ##[endgroup] +2023-11-12T09:05:32.7494899Z ##[group]/datum/unit_test/stun_absorb +2023-11-12T09:05:32.7661160Z PASS /datum/unit_test/stun_absorb 0s +2023-11-12T09:05:32.7664703Z ##[endgroup] +2023-11-12T09:05:32.7898786Z ##[group]/datum/unit_test/subsystem_init +2023-11-12T09:05:32.7903149Z PASS /datum/unit_test/subsystem_init 0s +2023-11-12T09:05:32.7906701Z ##[endgroup] +2023-11-12T09:05:32.8135238Z ##[group]/datum/unit_test/suit_storage_icons +2023-11-12T09:05:34.6162263Z 1 - /obj/item/gun/ballistic/shotgun/hook using invalid icon_state, "hookshotgun" +2023-11-12T09:05:34.6285969Z 2 - /obj/item/gun/ballistic/automatic/surplus using invalid icon_state, "surplus" +2023-11-12T09:05:34.6466661Z 3 - /obj/item/melee/baton/security/cattleprod/telecrystalprod using invalid icon_state, "telecrystalprod" +2023-11-12T09:05:34.6533245Z 4 - /obj/item/melee/sickly_blade/void using invalid icon_state, "void_blade" +2023-11-12T09:05:34.6538232Z 5 - /obj/item/melee/sickly_blade/cosmic using invalid icon_state, "cosmic_blade" +2023-11-12T09:05:34.6541373Z 6 - /obj/item/melee/sickly_blade/lock using invalid icon_state, "key_blade" +2023-11-12T09:05:34.6628237Z 7 - /obj/item/radio/headset/syndicate/alt using invalid worn_icon_state, "syndie_headset" +2023-11-12T09:05:34.6633020Z 8 - /obj/item/radio/headset/headset_sec using invalid worn_icon_state, "sec_headset" +2023-11-12T09:05:34.6636156Z 9 - /obj/item/radio/headset/headset_sec/alt using invalid worn_icon_state, "sec_headset_alt" +2023-11-12T09:05:34.6639243Z 10 - /obj/item/radio/headset/headset_eng using invalid worn_icon_state, "eng_headset" +2023-11-12T09:05:34.6642514Z 11 - /obj/item/radio/headset/headset_rob using invalid worn_icon_state, "rob_headset" +2023-11-12T09:05:34.6645779Z 12 - /obj/item/radio/headset/headset_med using invalid worn_icon_state, "med_headset" +2023-11-12T09:05:34.6649005Z 13 - /obj/item/radio/headset/headset_sci using invalid worn_icon_state, "sci_headset" +2023-11-12T09:05:34.6652244Z 14 - /obj/item/radio/headset/headset_medsci using invalid worn_icon_state, "medsci_headset" +2023-11-12T09:05:34.6655462Z 15 - /obj/item/radio/headset/headset_srvsec using invalid worn_icon_state, "srvsec_headset" +2023-11-12T09:05:34.6658687Z 16 - /obj/item/radio/headset/headset_srvmed using invalid worn_icon_state, "srv_headset" +2023-11-12T09:05:34.6661917Z 17 - /obj/item/radio/headset/headset_com using invalid worn_icon_state, "com_headset" +2023-11-12T09:05:34.6667219Z 18 - /obj/item/radio/headset/heads/captain/alt using invalid worn_icon_state, "com_headset_alt" +2023-11-12T09:05:34.6670732Z 19 - /obj/item/radio/headset/headset_cargo using invalid worn_icon_state, "cargo_headset" +2023-11-12T09:05:34.6673230Z 20 - /obj/item/radio/headset/headset_cargo/mining using invalid worn_icon_state, "mine_headset" +2023-11-12T09:05:34.6675625Z 21 - /obj/item/radio/headset/headset_cent using invalid worn_icon_state, "cent_headset" +2023-11-12T09:05:34.6678128Z 22 - /obj/item/radio/headset/headset_cent/alt using invalid worn_icon_state, "cent_headset_alt" +2023-11-12T09:05:34.6972394Z 23 - /obj/item/toy/foam_runic_scepter using invalid worn_icon_state, "vendor_staff" +2023-11-12T09:05:34.7033817Z 24 - /obj/item/cultivator/rake using invalid icon_state, "rake" +2023-11-12T09:05:34.7038164Z 25 - /obj/item/hatchet/wooden using invalid icon_state, "woodhatchet" +2023-11-12T09:05:34.7039900Z 26 - /obj/item/hatchet/cutterblade using invalid icon_state, "cutterblade" +2023-11-12T09:05:34.7408592Z 27 - /obj/item/access_key using invalid icon_state, "access_key" +2023-11-12T09:05:34.7458044Z 28 - /obj/item/key/janitor using invalid icon_state, "keyjanitor" +2023-11-12T09:05:34.8393427Z 29 - /obj/item/universal_scanner using invalid icon_state, "export scanner" +2023-11-12T09:05:34.8476665Z 30 - /obj/item/nullrod/tribal_knife using invalid icon_state, "crysknife" +2023-11-12T09:05:34.8491387Z 31 - /obj/item/organ/internal/monster_core using invalid icon_state, "hivelord_core" +2023-11-12T09:05:34.8493709Z 32 - /obj/item/organ/internal/monster_core/brimdust_sac using invalid icon_state, "brim_sac" +2023-11-12T09:05:34.8496411Z 33 - /obj/item/organ/internal/monster_core/regenerative_core/legion using invalid icon_state, "legion_core" +2023-11-12T09:05:34.8498777Z 34 - /obj/item/organ/internal/monster_core/rush_gland using invalid icon_state, "lobster_gland" +2023-11-12T09:05:34.8538527Z 35 - /obj/item/abductor/gizmo using invalid icon_state, "gizmo_scan" +2023-11-12T09:05:34.8540751Z 36 - /obj/item/abductor/silencer using invalid icon_state, "silencer" +2023-11-12T09:05:34.8543252Z 37 - /obj/item/abductor/mind_device using invalid icon_state, "mind_device_message" +2023-11-12T09:05:34.8545406Z 38 - /obj/item/abductor/alien_omnitool using invalid icon_state, "omnitool" +2023-11-12T09:05:34.8552089Z 39 - /obj/item/banner using invalid icon_state, "banner" +2023-11-12T09:05:34.8554713Z 40 - /obj/item/banner/security using invalid icon_state, "banner_security" +2023-11-12T09:05:34.8557066Z 41 - /obj/item/banner/medical using invalid icon_state, "banner_medical" +2023-11-12T09:05:34.8559349Z 42 - /obj/item/banner/science using invalid icon_state, "banner_science" +2023-11-12T09:05:34.8561592Z 43 - /obj/item/banner/cargo using invalid icon_state, "banner_cargo" +2023-11-12T09:05:34.8564170Z 44 - /obj/item/banner/engineering using invalid icon_state, "banner_engineering" +2023-11-12T09:05:34.8566536Z 45 - /obj/item/banner/red using invalid icon_state, "banner-red" +2023-11-12T09:05:34.8568980Z 46 - /obj/item/banner/blue using invalid icon_state, "banner-blue" +2023-11-12T09:05:34.8576281Z 47 - /obj/item/claymore/cutlass using invalid worn_icon_state, "cutlass" +2023-11-12T09:05:34.8580270Z 48 - /obj/item/claymore/highlander/robot using invalid icon_state, "claymore_cyborg" +2023-11-12T09:05:34.8582334Z 49 - /obj/item/pillow using invalid icon_state, "pillow_1_t" +2023-11-12T09:05:34.8584899Z 50 - /obj/item/pillow/clown using invalid icon_state, "pillow_5_t" +2023-11-12T09:05:34.8587221Z 51 - /obj/item/pillow/mime using invalid icon_state, "pillow_6_t" +2023-11-12T09:05:34.8626613Z 52 - /obj/item/gun/magic/staff/chaos/true_wabbajack using invalid icon_state, "the_wabbajack" +2023-11-12T09:05:34.8633965Z 53 - /obj/item/gun/magic/staff/locker using invalid worn_icon_state, "lockerstaff" +2023-11-12T09:05:34.8636381Z 54 - /obj/item/gun/magic/staff/flying using invalid worn_icon_state, "flightstaff" +2023-11-12T09:05:34.8657485Z 55 - /obj/item/melee/energy/sword/pirate using invalid icon_state, "e_cutlass" +2023-11-12T09:05:34.8659958Z 56 - /obj/item/clothing/glasses/eyepatch using invalid icon_state, "eyepatch" +2023-11-12T09:05:34.8662250Z 57 - /obj/item/clothing/glasses/eyepatch/medical using invalid icon_state, "eyepatch_medical" +2023-11-12T09:05:34.8976969Z 58 - /obj/item/melee/energy/sword using invalid icon_state, "e_sword" +2023-11-12T09:05:34.8979094Z 59 - /obj/item/melee/energy/sword/cyborg/saw using invalid icon_state, "esaw" +2023-11-12T09:05:34.8988519Z 60 - /obj/item/tank/jetpack/improvised using invalid worn_icon_state, "jetpack-improvised" +2023-11-12T09:05:34.8993419Z 61 - /obj/item/multitool using invalid icon_state, "multitool" +2023-11-12T09:05:34.8996418Z 62 - /obj/item/multitool/cyborg using invalid icon_state, "multitool_cyborg" +2023-11-12T09:05:34.8998725Z 63 - /obj/item/multitool/circuit using invalid icon_state, "multitool_circuit" +2023-11-12T09:05:34.9001342Z 64 - /obj/item/assembly/flash/handheld using invalid icon_state, "flash" +2023-11-12T09:05:34.9004166Z 65 - /obj/item/clothing/mask/cigarette using invalid icon_state, "cigoff" +2023-11-12T09:05:34.9006481Z 66 - /obj/item/clothing/mask/cigarette/rollie using invalid icon_state, "spliffoff" +2023-11-12T09:05:34.9008788Z 67 - /obj/item/clothing/mask/cigarette/candy using invalid icon_state, "candyoff" +2023-11-12T09:05:34.9011087Z 68 - /obj/item/clothing/mask/cigarette/cigar using invalid icon_state, "cigaroff" +2023-11-12T09:05:34.9013684Z 69 - /obj/item/clothing/mask/cigarette/cigar/cohiba using invalid icon_state, "cigar2off" +2023-11-12T09:05:34.9016282Z 70 - /obj/item/clothing/mask/cigarette/pipe using invalid icon_state, "pipeoff" +2023-11-12T09:05:34.9019334Z 71 - /obj/item/clothing/mask/cigarette/pipe/cobpipe using invalid icon_state, "cobpipeoff" +2023-11-12T09:05:34.9021398Z 72 - /obj/item/disk using invalid icon_state, "datadisk0" +2023-11-12T09:05:34.9023878Z 73 - /obj/item/disk/holodisk using invalid icon_state, "holodisk" +2023-11-12T09:05:34.9026566Z 74 - /obj/item/disk/nuclear using invalid icon_state, "nucleardisk" +2023-11-12T09:05:34.9029044Z 75 - /obj/item/disk/surgery using invalid icon_state, "datadisk1" +2023-11-12T09:05:34.9031722Z 76 - /obj/item/disk/cargo/bluespace_pod using invalid icon_state, "cargodisk" +2023-11-12T09:05:34.9034253Z 77 - /obj/item/disk/design_disk/bepis using invalid icon_state, "rndmajordisk" +2023-11-12T09:05:34.9036755Z 78 - /obj/item/melee/powerfist using invalid icon_state, "powerfist" +2023-11-12T09:05:34.9044549Z 79 - /obj/item/melee/skateboard using invalid icon_state, "skateboard_held" +2023-11-12T09:05:34.9047217Z 80 - /obj/item/melee/skateboard/pro using invalid icon_state, "skateboard2_held" +2023-11-12T09:05:34.9049673Z 81 - /obj/item/melee/skateboard/hoverboard using invalid icon_state, "hoverboard_red_held" +2023-11-12T09:05:34.9052014Z 82 - /obj/item/melee/skateboard/hoverboard/admin using invalid icon_state, "hoverboard_nt_held" +2023-11-12T09:05:34.9054102Z 83 - /obj/item/melee/baseball_bat using invalid icon_state, "baseball_bat" +2023-11-12T09:05:34.9056494Z 84 - /obj/item/melee/baseball_bat/homerun using invalid icon_state, "baseball_bat_home" +2023-11-12T09:05:34.9058758Z 85 - /obj/item/melee/baseball_bat/ablative using invalid icon_state, "baseball_bat_metal" +2023-11-12T09:05:34.9061041Z 86 - /obj/item/melee/flyswatter using invalid icon_state, "flyswatter" +2023-11-12T09:05:34.9065209Z 87 - /obj/item/melee/energy/axe using invalid icon_state, "axe" +2023-11-12T09:05:34.9067917Z 88 - /obj/item/melee/energy/blade using invalid icon_state, "blade" +2023-11-12T09:05:34.9070409Z 89 - /obj/item/melee/energy/blade/hardlight using invalid icon_state, "lightblade" +2023-11-12T09:05:34.9072647Z 90 - /obj/item/melee/synthetic_arm_blade using invalid icon_state, "arm_blade" +2023-11-12T09:05:34.9074881Z 91 - /obj/item/melee/sabre using invalid icon_state, "sabre" +2023-11-12T09:05:34.9077162Z 92 - /obj/item/melee/beesword using invalid worn_icon_state, "stinger" +2023-11-12T09:05:34.9079597Z 93 - /obj/item/melee/supermatter_sword using invalid icon_state, "supermatter_sword_balanced" +2023-11-12T09:05:34.9085130Z 94 - /obj/item/melee/cleric_mace using invalid worn_icon_state, "default_worn" +2023-11-12T09:05:34.9087426Z 95 - /obj/item/melee/rune_carver using invalid icon_state, "rune_carver" +2023-11-12T09:05:34.9089642Z 96 - /obj/item/melee/ghost_sword using invalid icon_state, "spectral" +2023-11-12T09:05:34.9099563Z 97 - /obj/item/storage/lockbox/medal using invalid icon_state, "medalbox+l" +2023-11-12T09:05:34.9101839Z 98 - /obj/item/storage/bag/trash using invalid icon_state, "trashbag" +2023-11-12T09:05:34.9104337Z 99 - /obj/item/storage/bag/trash/bluespace using invalid icon_state, "bluetrashbag" +2023-11-12T09:05:34.9106526Z 100 - /obj/item/cane using invalid icon_state, "cane" +2023-11-12T09:05:34.9109148Z 101 - /obj/item/cane/white using invalid icon_state, "cane_white" +2023-11-12T09:05:34.9127968Z 102 - /obj/item/clothing/mask/facehugger/toy using invalid worn_icon_state, "facehugger" +2023-11-12T09:05:34.9129996Z 103 - /obj/item/kitchen/fork using invalid icon_state, "fork" +2023-11-12T09:05:34.9132741Z 104 - /obj/item/kitchen/fork/plastic using invalid icon_state, "plastic_fork" +2023-11-12T09:05:34.9137903Z 105 - /obj/item/kitchen/spoon using invalid icon_state, "spoon" +2023-11-12T09:05:34.9140308Z 106 - /obj/item/kitchen/spoon/plastic using invalid icon_state, "plastic_spoon" +2023-11-12T09:05:34.9142537Z 107 - /obj/item/kitchen/spoon/soup_ladle using invalid icon_state, "ladle" +2023-11-12T09:05:34.9144673Z 108 - /obj/item/kitchen/tongs using invalid icon_state, "tongs" +2023-11-12T09:05:34.9192479Z 109 - /obj/item/bonesetter using invalid icon_state, "bonesetter" +2023-11-12T09:05:34.9194966Z 110 - /obj/item/cautery using invalid icon_state, "cautery" +2023-11-12T09:05:34.9197552Z 111 - /obj/item/cautery/advanced using invalid icon_state, "e_cautery" +2023-11-12T09:05:34.9200017Z 112 - /obj/item/cautery/cruel using invalid icon_state, "cruelcautery" +2023-11-12T09:05:34.9202572Z 113 - /obj/item/hemostat using invalid icon_state, "hemostat" +2023-11-12T09:05:34.9205055Z 114 - /obj/item/hemostat/supermatter using invalid icon_state, "supermatter_tongs" +2023-11-12T09:05:34.9207385Z 115 - /obj/item/hemostat/cruel using invalid icon_state, "cruelhemostat" +2023-11-12T09:05:34.9209542Z 116 - /obj/item/retractor using invalid icon_state, "retractor" +2023-11-12T09:05:34.9211950Z 117 - /obj/item/retractor/advanced using invalid icon_state, "adv_retractor" +2023-11-12T09:05:34.9214520Z 118 - /obj/item/retractor/cruel using invalid icon_state, "cruelretractor" +2023-11-12T09:05:34.9216984Z 119 - /obj/item/scalpel using invalid icon_state, "scalpel" +2023-11-12T09:05:34.9219596Z 120 - /obj/item/scalpel/supermatter using invalid icon_state, "supermatter_scalpel" +2023-11-12T09:05:34.9221828Z 121 - /obj/item/scalpel/advanced using invalid icon_state, "e_scalpel" +2023-11-12T09:05:34.9224110Z 122 - /obj/item/scalpel/cruel using invalid icon_state, "cruelscalpel" +2023-11-12T09:05:34.9226426Z 123 - /obj/item/surgical_drapes using invalid icon_state, "surgical_drapes" +2023-11-12T09:05:34.9230490Z 124 - /obj/item/crowbar/mechremoval using invalid icon_state, "mechremoval0" +2023-11-12T09:05:34.9245013Z 125 - /obj/item/crowbar/hammer using invalid icon_state, "clawhammer" +2023-11-12T09:05:34.9274002Z PASS /datum/unit_test/suit_storage_icons 2.1s +2023-11-12T09:05:34.9277303Z ##[endgroup] +2023-11-12T09:05:35.0051949Z ##[group]/datum/unit_test/amputation +2023-11-12T09:05:35.0418593Z PASS /datum/unit_test/amputation 0s +2023-11-12T09:05:35.0421400Z ##[endgroup] +2023-11-12T09:05:35.0919237Z ##[group]/datum/unit_test/brain_surgery +2023-11-12T09:05:35.1251285Z PASS /datum/unit_test/brain_surgery 0.1s +2023-11-12T09:05:35.1254329Z ##[endgroup] +2023-11-12T09:05:35.1587969Z ##[group]/datum/unit_test/head_transplant +2023-11-12T09:05:35.2257286Z PASS /datum/unit_test/head_transplant 0.1s +2023-11-12T09:05:35.2260747Z ##[endgroup] +2023-11-12T09:05:35.2834393Z ##[group]/datum/unit_test/multiple_surgeries +2023-11-12T09:05:35.3338834Z PASS /datum/unit_test/multiple_surgeries 0.1s +2023-11-12T09:05:35.3341725Z ##[endgroup] +2023-11-12T09:05:35.4031367Z ##[group]/datum/unit_test/start_tend_wounds +2023-11-12T09:05:35.4361296Z PASS /datum/unit_test/start_tend_wounds 0s +2023-11-12T09:05:35.4364716Z ##[endgroup] +2023-11-12T09:05:35.4772361Z ##[group]/datum/unit_test/tend_wounds +2023-11-12T09:05:35.5590830Z PASS /datum/unit_test/tend_wounds 0.1s +2023-11-12T09:05:35.5594252Z ##[endgroup] +2023-11-12T09:05:35.6747135Z ##[group]/datum/unit_test/tail_wag +2023-11-12T09:05:35.8571590Z PASS /datum/unit_test/tail_wag 0.2s +2023-11-12T09:05:35.8574630Z ##[endgroup] +2023-11-12T09:05:35.8824009Z ##[group]/datum/unit_test/teleporter +2023-11-12T09:05:35.9106477Z PASS /datum/unit_test/teleporter 0.1s +2023-11-12T09:05:35.9109891Z ##[endgroup] +2023-11-12T09:05:35.9363555Z ##[group]/datum/unit_test/tgui_create_message +2023-11-12T09:05:35.9367522Z PASS /datum/unit_test/tgui_create_message 0s +2023-11-12T09:05:35.9370812Z ##[endgroup] +2023-11-12T09:05:35.9501436Z ##[group]/datum/unit_test/timer_sanity +2023-11-12T09:05:35.9504464Z PASS /datum/unit_test/timer_sanity 0s +2023-11-12T09:05:35.9508070Z ##[endgroup] +2023-11-12T09:05:35.9637540Z ##[group]/datum/unit_test/trait_addition_and_removal +2023-11-12T09:05:35.9642216Z PASS /datum/unit_test/trait_addition_and_removal 0s +2023-11-12T09:05:35.9645763Z ##[endgroup] +2023-11-12T09:05:35.9828636Z ##[group]/datum/unit_test/traitor +2023-11-12T09:05:37.5946953Z PASS /datum/unit_test/traitor 1.6s +2023-11-12T09:05:37.5948067Z ##[endgroup] +2023-11-12T09:05:38.4317615Z ##[group]/datum/unit_test/traitor_mail_content_check +2023-11-12T09:05:38.4490029Z PASS /datum/unit_test/traitor_mail_content_check 0s +2023-11-12T09:05:38.4491508Z ##[endgroup] +2023-11-12T09:05:38.4962906Z ##[group]/datum/unit_test/trauma_granting +2023-11-12T09:05:38.5450644Z PASS /datum/unit_test/trauma_granting 0.1s +2023-11-12T09:05:38.5452259Z ##[endgroup] +2023-11-12T09:05:38.5799327Z ##[group]/datum/unit_test/turf_icons +2023-11-12T09:05:39.0838086Z PASS /datum/unit_test/turf_icons 0.5s +2023-11-12T09:05:39.0839541Z ##[endgroup] +2023-11-12T09:05:39.1032413Z ##[group]/datum/unit_test/tutorial_sanity +2023-11-12T09:05:39.1035529Z PASS /datum/unit_test/tutorial_sanity 0s +2023-11-12T09:05:39.1037920Z ##[endgroup] +2023-11-12T09:05:39.1166898Z ##[group]/datum/unit_test/verify_config_tags +2023-11-12T09:05:39.1172282Z PASS /datum/unit_test/verify_config_tags 0s +2023-11-12T09:05:39.1174748Z ##[endgroup] +2023-11-12T09:05:39.1303312Z ##[group]/datum/unit_test/verify_emoji_names +2023-11-12T09:05:39.1306816Z PASS /datum/unit_test/verify_emoji_names 0s +2023-11-12T09:05:39.1309155Z ##[endgroup] +2023-11-12T09:05:39.1436423Z ##[group]/datum/unit_test/moth_food +2023-11-12T09:05:39.1899509Z PASS /datum/unit_test/moth_food 0s +2023-11-12T09:05:39.1901926Z ##[endgroup] +2023-11-12T09:05:39.2373626Z ##[group]/datum/unit_test/golem_food +2023-11-12T09:05:39.2647161Z PASS /datum/unit_test/golem_food 0s +2023-11-12T09:05:39.2649458Z ##[endgroup] +2023-11-12T09:05:39.2901012Z ##[group]/datum/unit_test/wizard_loadout +2023-11-12T09:05:39.3687154Z PASS /datum/unit_test/wizard_loadout 0.1s +2023-11-12T09:05:39.3689468Z ##[endgroup] +2023-11-12T09:05:39.4375880Z ##[group]/datum/unit_test/worn_icons +2023-11-12T09:05:40.0482290Z PASS /datum/unit_test/worn_icons 0.6s +2023-11-12T09:05:40.0483826Z ##[endgroup] +2023-11-12T09:05:40.0625703Z ##[group]/datum/unit_test/find_reference_sanity +2023-11-12T09:05:40.0632296Z PASS /datum/unit_test/find_reference_sanity 0s +2023-11-12T09:05:40.0634532Z ##[endgroup] +2023-11-12T09:05:40.0765341Z ##[group]/datum/unit_test/find_reference_baseline +2023-11-12T09:05:40.0771322Z PASS /datum/unit_test/find_reference_baseline 0s +2023-11-12T09:05:40.0773723Z ##[endgroup] +2023-11-12T09:05:40.0904726Z ##[group]/datum/unit_test/find_reference_exotic +2023-11-12T09:05:40.0910664Z PASS /datum/unit_test/find_reference_exotic 0s +2023-11-12T09:05:40.0913091Z ##[endgroup] +2023-11-12T09:05:40.1081989Z ##[group]/datum/unit_test/find_reference_esoteric +2023-11-12T09:05:40.1091594Z PASS /datum/unit_test/find_reference_esoteric 0s +2023-11-12T09:05:40.1093910Z ##[endgroup] +2023-11-12T09:05:40.1356236Z ##[group]/datum/unit_test/find_reference_null_key_entry +2023-11-12T09:05:40.1361917Z PASS /datum/unit_test/find_reference_null_key_entry 0s +2023-11-12T09:05:40.1364019Z ##[endgroup] +2023-11-12T09:05:40.1495527Z ##[group]/datum/unit_test/find_reference_assoc_investigation +2023-11-12T09:05:40.1501290Z PASS /datum/unit_test/find_reference_assoc_investigation 0s +2023-11-12T09:05:40.1503468Z ##[endgroup] +2023-11-12T09:05:40.1629204Z ##[group]/datum/unit_test/find_reference_static_investigation +2023-11-12T09:05:40.4955432Z PASS /datum/unit_test/find_reference_static_investigation 0.3s +2023-11-12T09:05:40.4956809Z ##[endgroup] +2023-11-12T09:05:40.5106809Z ##[group]/datum/unit_test/area_contents +2023-11-12T09:05:41.5891675Z PASS /datum/unit_test/area_contents 1s +2023-11-12T09:05:41.5893012Z ##[endgroup] +2023-11-12T09:05:41.6151445Z ##[group]/datum/unit_test/atmospherics_sanity +2023-11-12T09:05:41.6152255Z No starting areas found, defaulting... +2023-11-12T09:05:41.6155445Z Marking all station areas as goal areas due to marker at (2, 254, 2) +2023-11-12T09:05:42.2832551Z PASS /datum/unit_test/atmospherics_sanity 0.6s +2023-11-12T09:05:42.2834628Z ##[endgroup] +2023-11-12T09:05:42.3215674Z ##[group]/datum/unit_test/fish_rescue_hook +2023-11-12T09:05:49.5841266Z PASS /datum/unit_test/fish_rescue_hook 7.2s +2023-11-12T09:05:49.5842563Z ##[endgroup] +2023-11-12T09:05:49.6648561Z ##[group]/datum/unit_test/leash/no_teleport +2023-11-12T09:05:49.7264798Z PASS /datum/unit_test/leash/no_teleport 0.1s +2023-11-12T09:05:49.7267230Z ##[endgroup] +2023-11-12T09:05:49.7411212Z ##[group]/datum/unit_test/leash/will_teleport +2023-11-12T09:05:49.7421861Z PASS /datum/unit_test/leash/will_teleport 0s +2023-11-12T09:05:49.7424432Z ##[endgroup] +2023-11-12T09:05:49.7571233Z ##[group]/datum/unit_test/leash/limit_range +2023-11-12T09:05:49.7577430Z PASS /datum/unit_test/leash/limit_range 0s +2023-11-12T09:05:49.7579955Z ##[endgroup] +2023-11-12T09:05:49.7749544Z ##[group]/datum/unit_test/mapload_space_verification +2023-11-12T09:05:50.3597291Z PASS /datum/unit_test/mapload_space_verification 0.6s +2023-11-12T09:05:50.3598841Z ##[endgroup] +2023-11-12T09:05:50.3862628Z ##[group]/datum/unit_test/mob_damage +2023-11-12T09:05:50.4877049Z PASS /datum/unit_test/mob_damage 0.1s +2023-11-12T09:05:50.4878381Z ##[endgroup] +2023-11-12T09:05:50.5135873Z ##[group]/datum/unit_test/mob_damage/basic +2023-11-12T09:05:50.5174197Z PASS /datum/unit_test/mob_damage/basic 0s +2023-11-12T09:05:50.5176179Z ##[endgroup] +2023-11-12T09:05:50.5348335Z ##[group]/datum/unit_test/modify_fantasy_variable +2023-11-12T09:06:17.8433778Z PASS /datum/unit_test/modify_fantasy_variable 27.3s +2023-11-12T09:06:17.8434791Z ##[endgroup] +2023-11-12T09:06:24.9200774Z ##[group]/datum/unit_test/monkey_business +2023-11-12T09:06:44.1178950Z [09:06:44] Runtime in timer.dm,125: Invalid timer: Timer: Timer: 2433 ([0x2100859b]), TTR: 328041, wait:2 Flags: TIMER_CLIENT_TIME, TIMER_STOPPABLE, callBack: [0x2105a831], callBack.object: /datum/looping_sound/showering[0x210085b4](/datum/looping_sound/showering), callBack.delegate:/datum/looping_sound/proc/start_sound_loop(), source: code/datums/looping_sounds/_looping_sound.dm:220Prev: NULL, Next: NULL, SPENT(328041), QDELETED, NO CALLBACK world.time: 942.5, head_offset: 600, practical_offset: 686, REALTIMEOFDAY: 328041 +2023-11-12T09:06:44.1182762Z proc name: fire (/datum/controller/subsystem/timer/fire) +2023-11-12T09:06:44.1191977Z src: Sound Loops (/datum/controller/subsystem/timer/sound_loops) +2023-11-12T09:06:44.1192834Z call stack: +2023-11-12T09:06:44.1193480Z Sound Loops (/datum/controller/subsystem/timer/sound_loops): fire(0) +2023-11-12T09:06:44.1194547Z Sound Loops (/datum/controller/subsystem/timer/sound_loops): fire(0) +2023-11-12T09:06:44.1195659Z Sound Loops (/datum/controller/subsystem/timer/sound_loops): ignite(0) +2023-11-12T09:06:44.1196597Z Master (/datum/controller/master): RunQueue() +2023-11-12T09:06:44.1201550Z Master (/datum/controller/master): Loop(2) +2023-11-12T09:06:44.1202483Z Master (/datum/controller/master): StartProcessing(0) +2023-11-12T09:07:03.3211396Z ##[error][09:06:44] Runtime in timer.dm,125: Invalid timer: Timer: Timer: 2433 ([0x2100859b]), TTR: 328041, wait:2 Flags: TIMER_CLIENT_TIME, TIMER_STOPPABLE, callBack: [0x2105a831], callBack.object: /datum/looping_sound/showering[0x210085b4](/datum/looping_sound/showering), callBack.delegate:/datum/looping_sound/proc/start_sound_loop(), source: code/datums/looping_sounds/_looping_sound.dm:220Prev: NULL, Next: NULL, SPENT(328041), QDELETED, NO CALLBACK world.time: 942.5, head_offset: 600, practical_offset: 686, REALTIMEOFDAY: 328041 + proc name: fire (/datum/controller/subsystem/timer/fire) + src: Sound Loops (/datum/controller/subsystem/timer/sound_loops) + call stack: + Sound Loops (/datum/controller/subsystem/timer/sound_loops): fire(0) + Sound Loops (/datum/controller/subsystem/timer/sound_loops): fire(0) + Sound Loops (/datum/controller/subsystem/timer/sound_loops): ignite(0) + Master (/datum/controller/master): RunQueue() + Master (/datum/controller/master): Loop(2) + Master (/datum/controller/master): StartProcessing(0) +2023-11-12T09:07:03.3224436Z FAILURE #1: [09:06:44] Runtime in timer.dm,125: Invalid timer: Timer: Timer: 2433 ([0x2100859b]), TTR: 328041, wait:2 Flags: TIMER_CLIENT_TIME, TIMER_STOPPABLE, callBack: [0x2105a831], callBack.object: /datum/looping_sound/showering[0x210085b4](/datum/looping_sound/showering), callBack.delegate:/datum/looping_sound/proc/start_sound_loop(), source: code/datums/looping_sounds/_looping_sound.dm:220Prev: NULL, Next: NULL, SPENT(328041), QDELETED, NO CALLBACK world.time: 942.5, head_offset: 600, practical_offset: 686, REALTIMEOFDAY: 328041 +2023-11-12T09:07:03.3226826Z proc name: fire (/datum/controller/subsystem/timer/fire) +2023-11-12T09:07:03.3227626Z src: Sound Loops (/datum/controller/subsystem/timer/sound_loops) +2023-11-12T09:07:03.3228077Z call stack: +2023-11-12T09:07:03.3228462Z Sound Loops (/datum/controller/subsystem/timer/sound_loops): fire(0) +2023-11-12T09:07:03.3229045Z Sound Loops (/datum/controller/subsystem/timer/sound_loops): fire(0) +2023-11-12T09:07:03.3229619Z Sound Loops (/datum/controller/subsystem/timer/sound_loops): ignite(0) +2023-11-12T09:07:03.3230129Z Master (/datum/controller/master): RunQueue() +2023-11-12T09:07:03.3230524Z Master (/datum/controller/master): Loop(2) +2023-11-12T09:07:03.3231037Z Master (/datum/controller/master): StartProcessing(0) at timer.dm:125 +2023-11-12T09:07:03.3231712Z ##[endgroup] +2023-11-12T09:07:03.3232839Z ##[error]FAIL /datum/unit_test/monkey_business 38.4s +2023-11-12T09:07:05.4669397Z ##[group]/datum/unit_test/strange_reagent +2023-11-12T09:07:09.1986629Z PASS /datum/unit_test/strange_reagent 3.7s +2023-11-12T09:07:09.1988202Z ##[endgroup] +2023-11-12T09:07:11.6843550Z ##[group]/datum/unit_test/create_and_destroy +2023-11-12T09:07:36.2863567Z No elevator ID for elevator music provided at Test Room (126,126,14). +2023-11-12T09:08:13.7560132Z PASS /datum/unit_test/create_and_destroy 62.1s +2023-11-12T09:08:13.7561471Z ##[endgroup] +2023-11-12T09:08:13.7852782Z ##[group]/datum/unit_test/dcs_check_list_arguments +2023-11-12T09:08:13.7940678Z PASS /datum/unit_test/dcs_check_list_arguments 0s +2023-11-12T09:08:13.7942424Z ##[endgroup] +2023-11-12T09:08:15.2400236Z Shutting down Chat subsystem... +2023-11-12T09:08:15.2402039Z Shutting down Init Profiler subsystem... +2023-11-12T09:08:15.2404881Z Shutting down Ban Cache subsystem... +2023-11-12T09:08:15.2407209Z Shutting down Stat Panels subsystem... +2023-11-12T09:08:15.2409633Z Shutting down Explosions subsystem... +2023-11-12T09:08:15.2412008Z Shutting down Pathfinder subsystem... +2023-11-12T09:08:15.2414438Z Shutting down Minor Mapping subsystem... +2023-11-12T09:08:15.2416820Z Shutting down Shuttle subsystem... +2023-11-12T09:08:15.2420930Z Warning: Subsystem `Shuttle` slept 2 times. +2023-11-12T09:08:15.2421633Z Shutting down Lighting subsystem... +2023-11-12T09:08:15.2423743Z Shutting down XKeyScore subsystem... +2023-11-12T09:08:15.2425667Z Shutting down PRISM subsystem... +2023-11-12T09:08:15.2427615Z Shutting down Icon Smoothing subsystem... +2023-11-12T09:08:15.2429451Z Shutting down Assets subsystem... +2023-11-12T09:08:15.2431258Z Shutting down Vote subsystem... +2023-11-12T09:08:15.2433223Z Shutting down Persistent Paintings subsystem... +2023-11-12T09:08:15.2435113Z Shutting down Persistence subsystem... +2023-11-12T09:08:15.2437033Z Shutting down Atmospherics subsystem... +2023-11-12T09:08:15.2439009Z Shutting down Wiremod Composite Templates subsystem... +2023-11-12T09:08:15.2440741Z Shutting down Wet floors subsystem... +2023-11-12T09:08:15.2443279Z Shutting down Weather subsystem... +2023-11-12T09:08:15.2445531Z Shutting down Wardrobe subsystem... +2023-11-12T09:08:15.2447137Z Shutting down Verb Manager subsystem... +2023-11-12T09:08:15.2448994Z Shutting down Tutorials subsystem... +2023-11-12T09:08:15.2450888Z Shutting down Transport subsystem... +2023-11-12T09:08:15.2452762Z Shutting down Traitor subsystem... +2023-11-12T09:08:15.2454635Z Shutting down Throwing subsystem... +2023-11-12T09:08:15.2456529Z Shutting down tgui subsystem... +2023-11-12T09:08:15.2458543Z Shutting down Supermatter Cascade subsystem... +2023-11-12T09:08:15.2460380Z Shutting down Sun subsystem... +2023-11-12T09:08:15.2462254Z Shutting down Stock Market subsystem... +2023-11-12T09:08:15.2464168Z Shutting down Speech Controller subsystem... +2023-11-12T09:08:15.2466003Z Shutting down Space Drift subsystem... +2023-11-12T09:08:15.2467944Z Shutting down Smoke subsystem... +2023-11-12T09:08:15.2469878Z Shutting down Singularity subsystem... +2023-11-12T09:08:15.2472104Z Shutting down Radioactive Nebula subsystem... +2023-11-12T09:08:15.2473961Z Shutting down Radio subsystem... +2023-11-12T09:08:15.2476202Z Shutting down Radiation subsystem... +2023-11-12T09:08:15.2477898Z Shutting down Projectiles subsystem... +2023-11-12T09:08:15.2479832Z Shutting down Processing subsystem... +2023-11-12T09:08:15.2482409Z Shutting down Points of Interest subsystem... +2023-11-12T09:08:15.2484346Z Shutting down Plumbing subsystem... +2023-11-12T09:08:15.2486233Z Shutting down Ping subsystem... +2023-11-12T09:08:15.2488172Z Shutting down Parallax subsystem... +2023-11-12T09:08:15.2490092Z Shutting down pAI subsystem... +2023-11-12T09:08:15.2492038Z Shutting down Overlay subsystem... +2023-11-12T09:08:15.7359113Z Shutting down Objects subsystem... +2023-11-12T09:08:15.7360449Z Shutting down Obj Tab Items subsystem... +2023-11-12T09:08:15.7363590Z Shutting down NPC Pool subsystem... +2023-11-12T09:08:15.7365241Z Shutting down Night Shift subsystem... +2023-11-12T09:08:15.7367764Z Shutting down Movement Loops subsystem... +2023-11-12T09:08:15.7369511Z Shutting down Movement Handler subsystem... +2023-11-12T09:08:15.7371589Z Shutting down MouseEntered subsystem... +2023-11-12T09:08:15.7373527Z Shutting down Mood subsystem... +2023-11-12T09:08:15.7375649Z Shutting down Modular Computers subsystem... +2023-11-12T09:08:15.7377558Z Shutting down Mobs subsystem... +2023-11-12T09:08:15.7379600Z Shutting down Materials subsystem... +2023-11-12T09:08:15.7381572Z Shutting down Lua Scripting subsystem... +2023-11-12T09:08:15.7505514Z Shutting down Library Loading subsystem... +2023-11-12T09:08:15.7507489Z Shutting down Lag Switch subsystem... +2023-11-12T09:08:15.7509583Z Shutting down Idling NPC Pool subsystem... +2023-11-12T09:08:15.7511671Z Shutting down Hyperspace Drift subsystem... +2023-11-12T09:08:15.7513591Z Shutting down Foam subsystem... +2023-11-12T09:08:15.7515516Z Shutting down Fluid subsystem... +2023-11-12T09:08:15.7517494Z Shutting down Fishing subsystem... +2023-11-12T09:08:15.7519635Z Shutting down Fast Processing subsystem... +2023-11-12T09:08:15.7521688Z Shutting down Escape Menu subsystem... +2023-11-12T09:08:15.7523697Z Shutting down Eigenstates subsystem... +2023-11-12T09:08:15.7525621Z Shutting down Disease subsystem... +2023-11-12T09:08:15.7527699Z Shutting down Digital Clocks subsystem... +2023-11-12T09:08:15.7529722Z Shutting down Datum Component System subsystem... +2023-11-12T09:08:15.7531714Z Shutting down Conveyor Belts subsystem... +2023-11-12T09:08:15.7533950Z Shutting down Communications subsystem... +2023-11-12T09:08:15.7536091Z Shutting down Clock Component subsystem... +2023-11-12T09:08:15.7538058Z Shutting down Cliff Falling subsystem... +2023-11-12T09:08:15.7540124Z Shutting down Circuit Components subsystem... +2023-11-12T09:08:15.7542040Z Shutting down Burning subsystem... +2023-11-12T09:08:15.7544007Z Shutting down Blackmarket subsystem... +2023-11-12T09:08:15.7545998Z Shutting down Basic Avoidance subsystem... +2023-11-12T09:08:15.7547937Z Shutting down Aura Healing subsystem... +2023-11-12T09:08:15.7549860Z Shutting down Augury subsystem... +2023-11-12T09:08:15.7552123Z Shutting down Asset Loading subsystem... +2023-11-12T09:08:15.7553815Z Shutting down Area Contents subsystem... +2023-11-12T09:08:15.7555740Z Shutting down Antag HUDs subsystem... +2023-11-12T09:08:15.7557720Z Shutting down Ambience subsystem... +2023-11-12T09:08:15.7559697Z Shutting down Addiction subsystem... +2023-11-12T09:08:15.7562910Z Shutting down Acid subsystem... +2023-11-12T09:08:15.7564740Z Shutting down Timer subsystem... +2023-11-12T09:08:15.7566504Z Shutting down Sound Loops subsystem... +2023-11-12T09:08:15.7568731Z Shutting down Runechat subsystem... +2023-11-12T09:08:15.7570746Z Shutting down Queue Links subsystem... +2023-11-12T09:08:15.7572695Z Shutting down Skills subsystem... +2023-11-12T09:08:15.7574685Z Shutting down Machines subsystem... +2023-11-12T09:08:15.7576634Z Shutting down Language subsystem... +2023-11-12T09:08:15.7578608Z Shutting down Atoms subsystem... +2023-11-12T09:08:15.7601367Z Shutting down Text To Speech subsystem... +2023-11-12T09:08:15.7603675Z Shutting down Restaurant subsystem... +2023-11-12T09:08:15.7605588Z Shutting down Economy subsystem... +2023-11-12T09:08:15.7607616Z Shutting down Spatial Grid subsystem... +2023-11-12T09:08:15.7609600Z Shutting down Time Tracking subsystem... +2023-11-12T09:08:15.7611597Z Shutting down Research subsystem... +2023-11-12T09:08:15.7613755Z Shutting down Early Assets subsystem... +2023-11-12T09:08:15.7615768Z Shutting down Mapping subsystem... +2023-11-12T09:08:15.7617822Z Shutting down Trading Card Game subsystem... +2023-11-12T09:08:15.7619966Z Shutting down Ticker subsystem... +2023-11-12T09:08:15.7622043Z Warning: Subsystem `Ticker` slept 1 times. +2023-11-12T09:08:15.7644481Z Unable to locate admins backup file. +2023-11-12T09:08:15.7654489Z Shutting down AI Controller Ticker subsystem... +2023-11-12T09:08:15.7656545Z Shutting down AI Behavior Ticker subsystem... +2023-11-12T09:08:15.7658539Z Shutting down AI movement subsystem... +2023-11-12T09:08:15.7660519Z Shutting down Jobs subsystem... +2023-11-12T09:08:15.7662633Z Shutting down IDs and Access subsystem... +2023-11-12T09:08:15.7664623Z Shutting down Events subsystem... +2023-11-12T09:08:15.7666630Z Shutting down Reagents subsystem... +2023-11-12T09:08:15.7668611Z Shutting down Quirks subsystem... +2023-11-12T09:08:15.7670631Z Shutting down Station subsystem... +2023-11-12T09:08:15.7672688Z Shutting down Achievements subsystem... +2023-11-12T09:08:15.7674715Z Shutting down Discord subsystem... +2023-11-12T09:08:15.7676785Z Shutting down Security Level subsystem... +2023-11-12T09:08:15.7678830Z Shutting down Vis contents overlays subsystem... +2023-11-12T09:08:15.7680780Z Shutting down Greyscale subsystem... +2023-11-12T09:08:15.7683265Z Shutting down Instruments subsystem... +2023-11-12T09:08:15.7685284Z Shutting down Sounds subsystem... +2023-11-12T09:08:15.7687269Z Shutting down Input subsystem... +2023-11-12T09:08:15.7689286Z Shutting down Server Tasks subsystem... +2023-11-12T09:08:15.7691440Z Shutting down Blackbox subsystem... +2023-11-12T09:08:15.7700214Z Shutting down Database subsystem... +2023-11-12T09:08:15.7709204Z Shutting down Garbage subsystem... +2023-11-12T09:08:18.8763587Z Shutting down Title Screen subsystem... +2023-11-12T09:08:18.8783727Z Shutting down Profiler subsystem... +2023-11-12T09:08:18.8789879Z Shutdown complete +2023-11-12T09:08:18.8797124Z Test run failed! +2023-11-12T09:08:18.8797462Z Total runtimes: 1 +2023-11-12T09:08:18.8797716Z Unit Tests failed! +2023-11-12T09:08:22.0106377Z cat: ci_test/data/logs/ci/clean_run.lk: No such file or directory +2023-11-12T09:08:22.0116872Z ##[error]Process completed with exit code 1. +2023-11-12T09:08:22.0170857Z ##[group]Run actions/upload-artifact@v3 +2023-11-12T09:08:22.0171222Z with: +2023-11-12T09:08:22.0171467Z name: test_artifacts_tramstation +2023-11-12T09:08:22.0171798Z path: data/screenshots_new/ +2023-11-12T09:08:22.0172089Z retention-days: 1 +2023-11-12T09:08:22.0172354Z if-no-files-found: warn +2023-11-12T09:08:22.0172621Z ##[endgroup] +2023-11-12T09:08:22.1010805Z With the provided path, there will be 77 files uploaded +2023-11-12T09:08:22.1013040Z Starting artifact upload +2023-11-12T09:08:22.1014930Z For more detailed logs during the artifact upload process, enable step-debugging: https://docs.github.com/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging#enabling-step-debug-logging +2023-11-12T09:08:22.1016085Z Artifact name is valid! +2023-11-12T09:08:22.1655325Z Container for artifact "test_artifacts_tramstation" successfully created. Starting upload of file(s) +2023-11-12T09:08:25.4511686Z Total size of all the files uploaded is 104264 bytes +2023-11-12T09:08:25.4513089Z File upload process has finished. Finalizing the artifact upload +2023-11-12T09:08:25.4967864Z Artifact has been finalized. All files have been successfully uploaded! +2023-11-12T09:08:25.4968795Z +2023-11-12T09:08:25.4969438Z The raw size of all the files that were specified for upload is 104534 bytes +2023-11-12T09:08:25.4995080Z The size of all the files that were uploaded is 104264 bytes. This takes into account any gzip compression used to reduce the upload size, time and storage +2023-11-12T09:08:25.4996373Z +2023-11-12T09:08:25.5000590Z Note: The size of downloaded zips can differ significantly from the reported size. For more information see: https://github.com/actions/upload-artifact#zipped-artifact-downloads +2023-11-12T09:08:25.5002432Z +2023-11-12T09:08:25.5002844Z Artifact test_artifacts_tramstation has been successfully uploaded! +2023-11-12T09:08:25.5131976Z ##[group]Run tgstation/byond-client-compatibility-check@v3 +2023-11-12T09:08:25.5132416Z with: +2023-11-12T09:08:25.5132646Z dmb-location: tgstation.dmb +2023-11-12T09:08:25.5132971Z max-required-client-version: 514 +2023-11-12T09:08:25.5133284Z ##[endgroup] +2023-11-12T09:08:25.5322365Z ##[group]Run (( 514 )) +2023-11-12T09:08:25.5322641Z (( 514 )) +2023-11-12T09:08:25.5367699Z shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0} +2023-11-12T09:08:25.5368129Z ##[endgroup] +2023-11-12T09:08:25.5463568Z ##[group]Run echo "required-client-version=$(( $( head -n2 tgstation.dmb | tail -n1 | cut -d " " -f 4 ) ))" >> $GITHUB_OUTPUT +2023-11-12T09:08:25.5464593Z echo "required-client-version=$(( $( head -n2 tgstation.dmb | tail -n1 | cut -d " " -f 4 ) ))" >> $GITHUB_OUTPUT +2023-11-12T09:08:25.5503899Z shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0} +2023-11-12T09:08:25.5504317Z ##[endgroup] +2023-11-12T09:08:25.5643709Z ##[group]Run (( 514 <= 514 )) +2023-11-12T09:08:25.5644042Z (( 514 <= 514 )) +2023-11-12T09:08:25.5682534Z shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0} +2023-11-12T09:08:25.5682953Z ##[endgroup] +2023-11-12T09:08:25.5835969Z Post job cleanup. +2023-11-12T09:08:25.6654082Z [command]/usr/bin/git version +2023-11-12T09:08:25.6698640Z git version 2.42.0 +2023-11-12T09:08:25.6737360Z Temporarily overriding HOME='/home/runner/work/_temp/8c7eca89-05a8-49f5-91d4-2ad2b8c1f35c' before making global git config changes +2023-11-12T09:08:25.6738762Z Adding repository directory to the temporary git global config as a safe directory +2023-11-12T09:08:25.6742986Z [command]/usr/bin/git config --global --add safe.directory /home/runner/work/tgstation/tgstation +2023-11-12T09:08:25.6784154Z [command]/usr/bin/git config --local --name-only --get-regexp core\.sshCommand +2023-11-12T09:08:25.6822086Z [command]/usr/bin/git submodule foreach --recursive sh -c "git config --local --name-only --get-regexp 'core\.sshCommand' && git config --local --unset-all 'core.sshCommand' || :" +2023-11-12T09:08:25.7132368Z [command]/usr/bin/git config --local --name-only --get-regexp http\.https\:\/\/github\.com\/\.extraheader +2023-11-12T09:08:25.7163927Z http.https://github.com/.extraheader +2023-11-12T09:08:25.7175279Z [command]/usr/bin/git config --local --unset-all http.https://github.com/.extraheader +2023-11-12T09:08:25.7216423Z [command]/usr/bin/git submodule foreach --recursive sh -c "git config --local --name-only --get-regexp 'http\.https\:\/\/github\.com\/\.extraheader' && git config --local --unset-all 'http.https://github.com/.extraheader' || :" +2023-11-12T09:08:25.7590917Z Print service container logs: c43e2a4f7a0044eda3c3640d7583be1f_mysqllatest_210664 +2023-11-12T09:08:25.7595897Z ##[command]/usr/bin/docker logs --details 37a3cfd21d3298b61164877b4eaf9717ee52eda64115ae9cd1aef5206d293ded +2023-11-12T09:08:25.7722763Z 2023-11-12 08:59:57+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.2.0-1.el8 started. +2023-11-12T09:08:25.7724170Z 2023-11-12 08:59:57+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' +2023-11-12T09:08:25.7726315Z 2023-11-12T08:59:57.323609Z 0 [System] [MY-015017] [Server] MySQL Server Initialization - start. +2023-11-12T09:08:25.7728493Z 2023-11-12T08:59:57.324887Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead. +2023-11-12T09:08:25.7730639Z 2023-11-12 08:59:57+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.2.0-1.el8 started. +2023-11-12T09:08:25.7731931Z 2023-11-12 08:59:57+00:00 [Note] [Entrypoint]: Initializing database files +2023-11-12T09:08:25.7733478Z 2023-11-12T08:59:57.324980Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.2.0) initializing of server in progress as process 80 +2023-11-12T09:08:25.7735422Z 2023-11-12T08:59:57.329733Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started. +2023-11-12T09:08:25.7736806Z 2023-11-12T08:59:57.538012Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended. +2023-11-12T09:08:25.7737953Z 2023-11-12 09:00:00+00:00 [Note] [Entrypoint]: Database files initialized +2023-11-12T09:08:25.7738945Z 2023-11-12 09:00:00+00:00 [Note] [Entrypoint]: Starting temporary server +2023-11-12T09:08:25.7739945Z 2023-11-12 09:00:00+00:00 [Note] [Entrypoint]: Temporary server started. +2023-11-12T09:08:25.7740898Z '/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock' +2023-11-12T09:08:25.7741615Z +2023-11-12T09:08:25.7742199Z 2023-11-12 09:00:02+00:00 [Note] [Entrypoint]: Stopping temporary server +2023-11-12T09:08:25.7743236Z 2023-11-12 09:00:03+00:00 [Note] [Entrypoint]: Temporary server stopped +2023-11-12T09:08:25.7744003Z +2023-11-12T09:08:25.7744708Z 2023-11-12 09:00:03+00:00 [Note] [Entrypoint]: MySQL init process done. Ready for start up. +2023-11-12T09:08:25.7746704Z 2023-11-12T08:59:58.210653Z 6 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option. +2023-11-12T09:08:25.7748648Z 2023-11-12T09:00:00.300732Z 0 [System] [MY-015018] [Server] MySQL Server Initialization - end. +2023-11-12T09:08:25.7749899Z 2023-11-12T09:00:00.347787Z 0 [System] [MY-015015] [Server] MySQL Server - start. +2023-11-12T09:08:25.7751901Z 2023-11-12T09:00:00.530321Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead. +2023-11-12T09:08:25.7754106Z 2023-11-12T09:00:00.531123Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.2.0) starting as process 124 +2023-11-12T09:08:25.7756278Z 2023-11-12T09:00:00.541412Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started. +2023-11-12T09:08:25.7757517Z 2023-11-12T09:00:00.630355Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended. +2023-11-12T09:08:25.7758462Z 2023-11-12T09:00:00.815198Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed. +2023-11-12T09:08:25.7759637Z 2023-11-12T09:00:00.815226Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel. +2023-11-12T09:08:25.7761631Z 2023-11-12T09:00:00.816463Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory. +2023-11-12T09:08:25.7763033Z 2023-11-12T09:00:00.828404Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: /var/run/mysqld/mysqlx.sock +2023-11-12T09:08:25.7764603Z 2023-11-12T09:00:00.828529Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.2.0' socket: '/var/run/mysqld/mysqld.sock' port: 0 MySQL Community Server - GPL. +2023-11-12T09:08:25.7765734Z 2023-11-12T09:00:00.829953Z 0 [System] [MY-015016] [Server] MySQL Server - end. +2023-11-12T09:08:25.7766430Z Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it. +2023-11-12T09:08:25.7767184Z Warning: Unable to load '/usr/share/zoneinfo/leap-seconds.list' as time zone. Skipping it. +2023-11-12T09:08:25.7767935Z Warning: Unable to load '/usr/share/zoneinfo/leapseconds' as time zone. Skipping it. +2023-11-12T09:08:25.7768649Z Warning: Unable to load '/usr/share/zoneinfo/tzdata.zi' as time zone. Skipping it. +2023-11-12T09:08:25.7769346Z Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it. +2023-11-12T09:08:25.7770052Z Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it. +2023-11-12T09:08:25.7770961Z 2023-11-12T09:00:02.470903Z 10 [System] [MY-013172] [Server] Received SHUTDOWN from user root. Shutting down mysqld (Version: 8.2.0). +2023-11-12T09:08:25.7772265Z 2023-11-12T09:00:03.257971Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.2.0) MySQL Community Server - GPL. +2023-11-12T09:08:25.7773173Z 2023-11-12T09:00:03.260270Z 0 [System] [MY-015016] [Server] MySQL Server - end. +2023-11-12T09:08:25.7773836Z 2023-11-12T09:00:03.482460Z 0 [System] [MY-015015] [Server] MySQL Server - start. +2023-11-12T09:08:25.7774963Z 2023-11-12T09:00:03.659729Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead. +2023-11-12T09:08:25.7776201Z 2023-11-12T09:00:03.661194Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.2.0) starting as process 1 +2023-11-12T09:08:25.7777020Z 2023-11-12T09:00:03.666529Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started. +2023-11-12T09:08:25.7777756Z 2023-11-12T09:00:03.752233Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended. +2023-11-12T09:08:25.7778518Z 2023-11-12T09:00:03.907357Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed. +2023-11-12T09:08:25.7779564Z 2023-11-12T09:00:03.907387Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel. +2023-11-12T09:08:25.7781056Z 2023-11-12T09:00:03.908492Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory. +2023-11-12T09:08:25.7782533Z 2023-11-12T09:00:03.922214Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock +2023-11-12T09:08:25.7783946Z 2023-11-12T09:00:03.922317Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.2.0' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL. +2023-11-12T09:08:25.7784877Z +2023-11-12T09:08:25.7790536Z Stop and remove container: c43e2a4f7a0044eda3c3640d7583be1f_mysqllatest_210664 +2023-11-12T09:08:25.7796028Z ##[command]/usr/bin/docker rm --force 37a3cfd21d3298b61164877b4eaf9717ee52eda64115ae9cd1aef5206d293ded +2023-11-12T09:08:26.0454956Z 37a3cfd21d3298b61164877b4eaf9717ee52eda64115ae9cd1aef5206d293ded +2023-11-12T09:08:26.0480580Z Remove container network: github_network_bc2270e2d9644957ba98982ec5cf35f2 +2023-11-12T09:08:26.0487395Z ##[command]/usr/bin/docker network rm github_network_bc2270e2d9644957ba98982ec5cf35f2 +2023-11-12T09:08:26.3137535Z github_network_bc2270e2d9644957ba98982ec5cf35f2 +2023-11-12T09:08:26.3289510Z Cleaning up orphan processes