diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index 936040432b..ac86912c84 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -153,18 +153,20 @@ GLOBAL_LIST_INIT(ai_core_display_screens, list( "Yes-Man" )) -/proc/resolve_ai_icon(input) +/proc/resolve_ai_icon(input, radial_preview = FALSE) if(!input || !(input in GLOB.ai_core_display_screens)) return "ai" - else - if(input == "Random") - input = pick(GLOB.ai_core_display_screens - "Random") - if(input == "Portrait") - var/datum/portrait_picker/tgui = new(usr)//create the datum - tgui.ui_interact(usr)//datum has a tgui component, here we open the window - return "ai-portrait" //just take this until they decide + if(radial_preview) return "ai-[lowertext(input)]" + if(input == "Random") + input = pick(GLOB.ai_core_display_screens - "Random") + if(input == "Portrait") + var/datum/portrait_picker/tgui = new(usr)//create the datum + tgui.ui_interact(usr)//datum has a tgui component, here we open the window + return "ai-portrait" //just take this until they decide + return "ai-[lowertext(input)]" + GLOBAL_LIST_INIT(security_depts_prefs, list(SEC_DEPT_RANDOM, SEC_DEPT_NONE, SEC_DEPT_ENGINEERING, SEC_DEPT_MEDICAL, SEC_DEPT_SCIENCE, SEC_DEPT_SUPPLY)) //Backpacks diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index a582fa03e4..fbda722e4f 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -331,6 +331,7 @@ return . = anchored anchored = anchorvalue + SEND_SIGNAL(src, COMSIG_OBJ_SETANCHORED, anchorvalue) // SEND_SIGNAL(src, COMSIG_MOVABLE_SET_ANCHORED, anchorvalue) /atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 8d7a8c047a..e37fd13106 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -137,7 +137,7 @@ Class Procs: GLOB.machines += src if(ispath(circuit, /obj/item/circuitboard)) - circuit = new circuit + circuit = new circuit(src) circuit.apply_default_parts(src) if(!speed_process && init_process) @@ -361,11 +361,11 @@ Class Procs: /obj/machinery/deconstruct(disassembled = TRUE) if(!(flags_1 & NODECONSTRUCT_1)) on_deconstruction() - if(component_parts && component_parts.len) + if(LAZYLEN(component_parts)) spawn_frame(disassembled) for(var/obj/item/I in component_parts) I.forceMove(loc) - component_parts.Cut() + LAZYCLEARLIST(component_parts) qdel(src) /obj/machinery/proc/spawn_frame(disassembled) @@ -539,12 +539,17 @@ Class Procs: /obj/machinery/Exited(atom/movable/AM, atom/newloc) . = ..() + // if(AM == occupant) + // set_occupant(null) if (AM == occupant) SEND_SIGNAL(src, COMSIG_MACHINE_EJECT_OCCUPANT, occupant) occupant = null + if(AM == circuit && circuit.loc != src) + component_parts -= AM //TODO: make the cmp part functions use lazyX + circuit = null -/obj/machinery/proc/adjust_item_drop_location(atom/movable/AM) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8 - var/md5 = md5(AM.name) // Oh, and it's deterministic too. A specific item will always drop from the same slot. +/obj/machinery/proc/adjust_item_drop_location(atom/movable/AM) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8 + var/md5 = md5(AM.name) // Oh, and it's deterministic too. A specific item will always drop from the same slot. for (var/i in 1 to 32) . += hex2num(md5[i]) . = . % 9 diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm index 16081db2c1..0c628ba43e 100644 --- a/code/game/machinery/computer/_computer.dm +++ b/code/game/machinery/computer/_computer.dm @@ -17,20 +17,16 @@ /obj/machinery/computer/Initialize(mapload, obj/item/circuitboard/C) . = ..() + power_change() - if(!QDELETED(C)) - qdel(circuit) - circuit = C - C.moveToNullspace() /obj/machinery/computer/Destroy() - QDEL_NULL(circuit) - return ..() + . = ..() /obj/machinery/computer/process() if(stat & (NOPOWER|BROKEN)) - return 0 - return 1 + return FALSE + return TRUE /obj/machinery/computer/ratvar_act() if(!clockwork) @@ -87,25 +83,32 @@ switch(damage_type) if(BRUTE) if(stat & BROKEN) - playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, TRUE) else - playsound(src.loc, 'sound/effects/glasshit.ogg', 75, 1) + playsound(src.loc, 'sound/effects/glasshit.ogg', 75, TRUE) if(BURN) - playsound(src.loc, 'sound/items/welder.ogg', 100, 1) + playsound(src.loc, 'sound/items/welder.ogg', 100, TRUE) /obj/machinery/computer/obj_break(damage_flag) - if(circuit && !(flags_1 & NODECONSTRUCT_1)) //no circuit, no breaking - if(!(stat & BROKEN)) - playsound(loc, 'sound/effects/glassbr3.ogg', 100, 1) - stat |= BROKEN - update_icon() - set_light(0) + if(!circuit) //no circuit, no breaking + return + . = ..() + if(. && !(stat & BROKEN)) + stat |= BROKEN + playsound(loc, 'sound/effects/glassbr3.ogg', 100, TRUE) + set_light(0) + update_icon() /obj/machinery/computer/emp_act(severity) . = ..() if (!(. & EMP_PROTECT_SELF)) - if(prob(severity/1.8)) - obj_break("energy") + switch(severity) + if(1) + if(prob(50)) + obj_break("energy") + if(2) + if(prob(10)) + obj_break("energy") /obj/machinery/computer/deconstruct(disassembled = TRUE, mob/user) on_deconstruction() @@ -114,12 +117,14 @@ var/obj/structure/frame/computer/A = new /obj/structure/frame/computer(src.loc) A.setDir(dir) A.circuit = circuit - A.setAnchored(TRUE) + // Circuit removal code is handled in /obj/machinery/Exited() + circuit.forceMove(A) + A.set_anchored(TRUE) if(stat & BROKEN) if(user) to_chat(user, "The broken glass falls out.") else - playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, TRUE) new /obj/item/shard(drop_location()) new /obj/item/shard(drop_location()) A.state = 3 @@ -129,8 +134,11 @@ to_chat(user, "You disconnect the monitor.") A.state = 4 A.icon_state = "4" - circuit = null for(var/obj/C in src) C.forceMove(loc) - qdel(src) + +/obj/machinery/computer/AltClick(mob/user) + . = ..() + if(!user.canUseTopic(src, !issilicon(user)) || !(stat & (NOPOWER|BROKEN))) + return diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index e325ab96a4..ce8171405f 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -132,7 +132,6 @@ events = new icon_state += "-open" add_radio() - add_cabin() spark_system.set_up(2, 0, src) spark_system.attach(src) smoke_system.set_up(3, src) @@ -153,6 +152,7 @@ /obj/mecha/LateInitialize() . = ..() add_airtank() + add_cabin() /obj/mecha/get_cell() return cell @@ -255,9 +255,8 @@ cell = new /obj/item/stock_parts/cell/high/plus(src) /obj/mecha/proc/add_cabin() - cabin_air = new + cabin_air = new(200) cabin_air.set_temperature(T20C) - cabin_air.set_volume(200) cabin_air.set_moles(/datum/gas/oxygen,O2STANDARD*cabin_air.return_volume()/(R_IDEAL_GAS_EQUATION*cabin_air.return_temperature())) cabin_air.set_moles(/datum/gas/nitrogen,N2STANDARD*cabin_air.return_volume()/(R_IDEAL_GAS_EQUATION*cabin_air.return_temperature())) return cabin_air diff --git a/code/game/objects/items/tanks/tank_types.dm b/code/game/objects/items/tanks/tank_types.dm index 325e49dd7a..84f2098b06 100644 --- a/code/game/objects/items/tanks/tank_types.dm +++ b/code/game/objects/items/tanks/tank_types.dm @@ -58,7 +58,6 @@ /obj/item/tank/internals/air name = "air tank" desc = "Mixed anyone?" - icon_state = "air" item_state = "air" force = 10 dog_fashion = /datum/dog_fashion/back diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index dcd67bf1f2..f0edf7ee1d 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -80,9 +80,9 @@ SStgui.close_uis(src) . = ..() +/// @depricated DO NOT USE /obj/proc/setAnchored(anchorvalue) - SEND_SIGNAL(src, COMSIG_OBJ_SETANCHORED, anchorvalue) - anchored = anchorvalue + set_anchored(anchorvalue) /obj/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, messy_throw = TRUE) . = ..() diff --git a/code/game/objects/structures/artstuff.dm b/code/game/objects/structures/artstuff.dm index 47584a1775..9b2f305b42 100644 --- a/code/game/objects/structures/artstuff.dm +++ b/code/game/objects/structures/artstuff.dm @@ -16,12 +16,12 @@ //Adding canvases /obj/structure/easel/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/canvas)) - var/obj/item/canvas/C = I - user.dropItemToGround(C) - painting = C - C.forceMove(get_turf(src)) - C.layer = layer+0.1 - user.visible_message("[user] puts \the [C] on \the [src].","You place \the [C] on \the [src].") + var/obj/item/canvas/canvas = I + user.dropItemToGround(canvas) + painting = canvas + canvas.forceMove(get_turf(src)) + canvas.layer = layer+0.1 + user.visible_message("[user] puts \the [canvas] on \the [src].","You place \the [canvas] on \the [src].") else return ..() @@ -40,13 +40,14 @@ desc = "Draw out your soul on this canvas!" icon = 'icons/obj/artstuff.dmi' icon_state = "11x11" + // flags_1 = UNPAINTABLE_1 resistance_flags = FLAMMABLE var/width = 11 var/height = 11 var/list/grid var/canvas_color = "#ffffff" //empty canvas color var/used = FALSE - var/painting_name //Painting name, this is set after framing. + var/painting_name = "Untitled Artwork" //Painting name, this is set after framing. var/finalized = FALSE //Blocks edits var/author_ckey var/icon_generated = FALSE @@ -132,17 +133,19 @@ /obj/item/canvas/update_overlays() . = ..() - if(!icon_generated) - if(used) - var/mutable_appearance/detail = mutable_appearance(icon,"[icon_state]wip") - detail.pixel_x = 1 - detail.pixel_y = 1 - . += detail - else + if(icon_generated) var/mutable_appearance/detail = mutable_appearance(generated_icon) detail.pixel_x = 1 detail.pixel_y = 1 . += detail + return + if(!used) + return + + var/mutable_appearance/detail = mutable_appearance(icon, "[icon_state]wip") + detail.pixel_x = 1 + detail.pixel_y = 1 + . += detail /obj/item/canvas/proc/generate_proper_overlay() if(icon_generated) @@ -167,8 +170,8 @@ if(!I) return if(istype(I, /obj/item/toy/crayon)) - var/obj/item/toy/crayon/C = I - return C.paint_color + var/obj/item/toy/crayon/crayon = I + return crayon.paint_color else if(istype(I, /obj/item/pen)) var/obj/item/pen/P = I switch(P.colour) @@ -184,7 +187,7 @@ /obj/item/canvas/proc/try_rename(mob/user) var/new_name = stripped_input(user,"What do you want to name the painting?") - if(!painting_name && new_name && user.canUseTopic(src,BE_CLOSE)) + if(new_name != painting_name && new_name && user.canUseTopic(src,BE_CLOSE)) painting_name = new_name SStgui.update_uis(src) @@ -215,12 +218,23 @@ framed_offset_x = 5 framed_offset_y = 6 +/obj/item/canvas/twentyfour_twentyfour + name = "ai universal standard canvas" + desc = "Besides being very large, the AI can accept these as a display from their internal database after you've hung it up." + icon_state = "24x24" + width = 24 + height = 24 + pixel_x = 2 + pixel_y = 1 + framed_offset_x = 4 + framed_offset_y = 5 + /obj/item/wallframe/painting name = "painting frame" desc = "The perfect showcase for your favorite deathtrap memories." icon = 'icons/obj/decals.dmi' - custom_materials = null - flags_1 = 0 + custom_materials = list(/datum/material/wood = 2000) + flags_1 = NONE icon_state = "frame-empty" result_path = /obj/structure/sign/painting @@ -229,8 +243,13 @@ desc = "Art or \"Art\"? You decide." icon = 'icons/obj/decals.dmi' icon_state = "frame-empty" + // base_icon_state = "frame" + custom_materials = list(/datum/material/wood = 2000) buildable_sign = FALSE - var/obj/item/canvas/C + ///Canvas we're currently displaying. + var/obj/item/canvas/current_canvas + ///Description set when canvas is added. + var/desc_with_canvas var/persistence_id /obj/structure/sign/painting/Initialize(mapload, dir, building) @@ -242,64 +261,78 @@ if(building) pixel_x = (dir & 3)? 0 : (dir == 4 ? -30 : 30) pixel_y = (dir & 3)? (dir ==1 ? -30 : 30) : 0 + desc = current_canvas ? desc_with_canvas : initial(desc) /obj/structure/sign/painting/Destroy() . = ..() SSpersistence.painting_frames -= src /obj/structure/sign/painting/attackby(obj/item/I, mob/user, params) - if(!C && istype(I, /obj/item/canvas)) + if(!current_canvas && istype(I, /obj/item/canvas)) frame_canvas(user,I) - else if(C && !C.painting_name && istype(I,/obj/item/pen)) + else if(current_canvas && current_canvas.painting_name == initial(current_canvas.painting_name) && istype(I,/obj/item/pen)) try_rename(user) else return ..() /obj/structure/sign/painting/examine(mob/user) . = ..() - if(C) - C.ui_interact(user) + if(persistence_id) + . += "Any painting placed here will be archived at the end of the shift." + if(current_canvas) + current_canvas.ui_interact(user) + . += "Use wirecutters to remove the painting." /obj/structure/sign/painting/wirecutter_act(mob/living/user, obj/item/I) . = ..() - if(C) - C.forceMove(drop_location()) - C = null + if(current_canvas) + current_canvas.forceMove(drop_location()) + current_canvas = null to_chat(user, "You remove the painting from the frame.") update_icon() return TRUE /obj/structure/sign/painting/proc/frame_canvas(mob/user,obj/item/canvas/new_canvas) if(user.transferItemToLoc(new_canvas,src)) - C = new_canvas - if(!C.finalized) - C.finalize(user) - to_chat(user,"You frame [C].") + current_canvas = new_canvas + if(!current_canvas.finalized) + current_canvas.finalize(user) + to_chat(user,"You frame [current_canvas].") update_icon() /obj/structure/sign/painting/proc/try_rename(mob/user) - if(!C.painting_name) - C.try_rename(user) + if(current_canvas.painting_name == initial(current_canvas.painting_name)) + current_canvas.try_rename(user) + +// /obj/structure/sign/painting/update_name(updates) +// name = current_canvas ? "painting - [current_canvas.painting_name]" : initial(name) +// return ..() + +// /obj/structure/sign/painting/update_desc(updates) +// desc = current_canvas ? desc_with_canvas : initial(desc) +// return ..() /obj/structure/sign/painting/update_icon_state() - . = ..() - if(C && C.generated_icon) - icon_state = null - else + // icon_state = "[base_icon_state]-[current_canvas?.generated_icon ? "overlay" : "empty"]" + if(current_canvas?.generated_icon) icon_state = "frame-empty" - + else + icon_state = null // or "frame-empty" + return ..() /obj/structure/sign/painting/update_overlays() . = ..() - if(C && C.generated_icon) - var/mutable_appearance/MA = mutable_appearance(C.generated_icon) - MA.pixel_x = C.framed_offset_x - MA.pixel_y = C.framed_offset_y - . += MA - var/mutable_appearance/frame = mutable_appearance(C.icon,"[C.icon_state]frame") - frame.pixel_x = C.framed_offset_x - 1 - frame.pixel_y = C.framed_offset_y - 1 - . += frame + if(!current_canvas?.generated_icon) + return + + var/mutable_appearance/MA = mutable_appearance(current_canvas.generated_icon) + MA.pixel_x = current_canvas.framed_offset_x + MA.pixel_y = current_canvas.framed_offset_y + . += MA + var/mutable_appearance/frame = mutable_appearance(current_canvas.icon,"[current_canvas.icon_state]frame") + frame.pixel_x = current_canvas.framed_offset_x - 1 + frame.pixel_y = current_canvas.framed_offset_y - 1 + . += frame /obj/structure/sign/painting/proc/load_persistent() if(!persistence_id) @@ -310,6 +343,10 @@ var/title = chosen["title"] var/author = chosen["ckey"] var/png = "data/paintings/[persistence_id]/[chosen["md5"]].png" + if(!title) + title = "Untitled Artwork" //Should prevent NULL named art from loading as NULL, if you're still getting the admin log chances are persistence is broken + if(!title) + message_admins("Painting with NO TITLE loaded on a [persistence_id] frame in [get_area(src)]. Please delete it, it is saved in the database with no name and will create bad assets.") if(!fexists(png)) stack_trace("Persistent painting [chosen["md5"]].png was not found in [persistence_id] directory.") return @@ -328,17 +365,20 @@ new_canvas.finalized = TRUE new_canvas.painting_name = title new_canvas.author_ckey = author - C = new_canvas + new_canvas.name = "painting - [title]" + current_canvas = new_canvas update_icon() /obj/structure/sign/painting/proc/save_persistent() - if(!persistence_id || !C) + if(!persistence_id || !current_canvas) return if(sanitize_filename(persistence_id) != persistence_id) stack_trace("Invalid persistence_id - [persistence_id]") return - var/data = C.get_data_string() - var/md5 = md5(data) + if(!current_canvas.painting_name) + current_canvas.painting_name = "Untitled Artwork" + var/data = current_canvas.get_data_string() + var/md5 = md5(lowertext(data)) var/list/current = SSpersistence.paintings[persistence_id] if(!current) current = list() @@ -347,10 +387,10 @@ return var/png_directory = "data/paintings/[persistence_id]/" var/png_path = png_directory + "[md5].png" - var/result = rustg_dmi_create_png(png_path,"[C.width]","[C.height]",data) + var/result = rustg_dmi_create_png(png_path,"[current_canvas.width]","[current_canvas.height]",data) if(result) CRASH("Error saving persistent painting: [result]") - current += list(list("title" = C.painting_name , "md5" = md5, "ckey" = C.author_ckey)) + current += list(list("title" = current_canvas.painting_name , "md5" = md5, "ckey" = current_canvas.author_ckey)) SSpersistence.paintings[persistence_id] = current /obj/item/canvas/proc/fill_grid_from_icon(icon/I) @@ -361,12 +401,21 @@ //Presets for art gallery mapping, for paintings to be shared across stations /obj/structure/sign/painting/library + name = "\improper Public Painting Exhibit mounting" + desc = "For art pieces hung by the public." + desc_with_canvas = "A piece of art (or \"art\"). Anyone could've hung it." persistence_id = "library" /obj/structure/sign/painting/library_secure + name = "\improper Curated Painting Exhibit mounting" + desc = "For masterpieces hand-picked by the curator." + desc_with_canvas = "A masterpiece hand-picked by the curator, supposedly." persistence_id = "library_secure" /obj/structure/sign/painting/library_private // keep your smut away from prying eyes, or non-librarians at least + name = "\improper Private Painting Exhibit mounting" + desc = "For art pieces deemed too subversive or too illegal to be shared outside of curators." + desc_with_canvas = "A painting hung away from lesser minds." persistence_id = "library_private" /obj/structure/sign/painting/vv_get_dropdown() @@ -379,11 +428,11 @@ if(!check_rights(NONE)) return var/mob/user = usr - if(!persistence_id || !C) + if(!persistence_id || !current_canvas) to_chat(user,"This is not a persistent painting.") return - var/md5 = md5(C.get_data_string()) - var/author = C.author_ckey + var/md5 = md5(lowertext(current_canvas.get_data_string())) + var/author = current_canvas.author_ckey var/list/current = SSpersistence.paintings[persistence_id] if(current) for(var/list/entry in current) @@ -392,7 +441,8 @@ var/png = "data/paintings/[persistence_id]/[md5].png" fdel(png) for(var/obj/structure/sign/painting/P in SSpersistence.painting_frames) - if(P.C && md5(P.C.get_data_string()) == md5) - QDEL_NULL(P.C) + if(P.current_canvas && md5(P.current_canvas.get_data_string()) == md5) + QDEL_NULL(P.current_canvas) + P.update_icon() log_admin("[key_name(user)] has deleted a persistent painting made by [author].") message_admins("[key_name_admin(user)] has deleted persistent painting made by [author].") diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index e0e1d91ba9..ce6a5dcda1 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -200,7 +200,7 @@ if(option == "Random") iconstates[option] = image(icon = src.icon, icon_state = "ai-random") continue - iconstates[option] = image(icon = src.icon, icon_state = resolve_ai_icon(option)) + iconstates[option] = image(icon = src.icon, icon_state = resolve_ai_icon(option, radial_preview = TRUE)) view_core() var/ai_core_icon = show_radial_menu(src, src , iconstates, radius = 42) diff --git a/code/modules/mob/living/silicon/robot/update_icons.dm b/code/modules/mob/living/silicon/robot/update_icons.dm index a567446e9e..088c93cff1 100644 --- a/code/modules/mob/living/silicon/robot/update_icons.dm +++ b/code/modules/mob/living/silicon/robot/update_icons.dm @@ -23,13 +23,17 @@ if(module.cyborg_base_icon == "robot") icon = 'icons/mob/robots.dmi' pixel_x = initial(pixel_x) - if(stat != DEAD && !(IsUnconscious() ||IsStun() || IsKnockdown() || IsParalyzed() || low_power_mode)) //Not dead, not stunned. + if(stat != DEAD && !(IsUnconscious() || IsStun() || IsParalyzed() || low_power_mode)) //Not dead, not stunned. if(!eye_lights) eye_lights = new() - if(lamp_intensity > 2) + if(lamp_enabled || lamp_doom) eye_lights.icon_state = "[module.special_light_key ? "[module.special_light_key]":"[module.cyborg_base_icon]"]_l" + eye_lights.color = lamp_doom? COLOR_RED : lamp_color + eye_lights.plane = 19 //glowy eyes else eye_lights.icon_state = "[module.special_light_key ? "[module.special_light_key]":"[module.cyborg_base_icon]"]_e[is_servant_of_ratvar(src) ? "_r" : ""]" + eye_lights.color = COLOR_WHITE + eye_lights.plane = -1 eye_lights.icon = icon add_overlay(eye_lights) diff --git a/icons/mob/AI.dmi b/icons/mob/AI.dmi index 33c33aaee2..279a3e76ef 100644 Binary files a/icons/mob/AI.dmi and b/icons/mob/AI.dmi differ