From 0e82de2d396024bdbea7fff334ce0173a8db1279 Mon Sep 17 00:00:00 2001 From: PsiOmega Date: Mon, 28 Jul 2014 17:30:51 +0200 Subject: [PATCH] Makes it possible for the AI to take and view images. Conflicts: baystation12.int code/modules/mob/living/silicon/ai/ai.dm code/modules/mob/transform_procs.dm code/modules/paperwork/photography.dm --- baystation12.dme | 1 + code/_onclick/ai.dm | 5 + code/modules/mob/living/silicon/ai/ai.dm | 3 + code/modules/mob/transform_procs.dm | 2 + code/modules/paperwork/ai_photography.dm | 96 +++++++++++++ code/modules/paperwork/photography.dm | 172 +++++++++++------------ 6 files changed, 193 insertions(+), 86 deletions(-) create mode 100644 code/modules/paperwork/ai_photography.dm diff --git a/baystation12.dme b/baystation12.dme index 8024f3fa119..141e1bcce0d 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1191,6 +1191,7 @@ #include "code\modules\organs\pain.dm" #include "code\modules\organs\skeleton.dm" #include "code\modules\organs\wound.dm" +#include "code\modules\paperwork\ai_photography.dm" #include "code\modules\paperwork\carbonpaper.dm" #include "code\modules\paperwork\clipboard.dm" #include "code\modules\paperwork\filingcabinet.dm" diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 29cc39f57d2..b25e05168d3 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -51,6 +51,11 @@ if(control_disabled || stat || world.time <= next_move) return next_move = world.time + 9 + if(aicamera.in_camera_mode) + aicamera.camera_mode_off() + aicamera.captureimage(A, usr) + return + /* AI restrained() currently does nothing if(restrained()) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index a325090c828..dce72f27419 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -31,6 +31,7 @@ var/list/ai_list = list() var/icon/holo_icon//Default is assigned when AI is created. var/obj/item/device/pda/ai/aiPDA = null var/obj/item/device/multitool/aiMulti = null + var/obj/item/device/camera/ai_camera/aicamera = null var/custom_sprite = 0 //For our custom sprites var/alienAI = 0 @@ -94,6 +95,8 @@ var/list/ai_list = list() radio = new(src) radio.myAi = src + aicamera = new/obj/item/device/camera/ai_camera(src) + if (istype(loc, /turf)) verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \ /mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \ diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index b7f9a04a98d..0831b75a3f1 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -127,6 +127,8 @@ O.verbs += /mob/living/silicon/ai/proc/show_laws_verb O.verbs += /mob/living/silicon/ai/proc/ai_statuschange + O.verbs += /mob/living/silicon/ai/proc/ai_take_image + O.verbs += /mob/living/silicon/ai/proc/ai_view_images O.job = "AI" diff --git a/code/modules/paperwork/ai_photography.dm b/code/modules/paperwork/ai_photography.dm new file mode 100644 index 00000000000..ea8bdeef0df --- /dev/null +++ b/code/modules/paperwork/ai_photography.dm @@ -0,0 +1,96 @@ +/************** +* AI-specific * +**************/ +/datum/picture + var/name = "image" + var/list/fields = list() + +obj/item/device/camera/ai_camera //camera AI can take pictures with + name = "AI photo camera" + var/in_camera_mode = 0 + var/list/aipictures = list() + +/obj/item/device/camera/ai_camera/proc/injectaialbum(var/icon, var/img, var/desc, var/pixel_x, var/pixel_y) //stores image information to a list similar to that of the datacore + var/numberer = 1 + for(var/datum/picture in src.aipictures) + numberer++ + var/datum/picture/P = new() + P.fields["name"] = "Image [numberer]" + P.fields["icon"] = icon + P.fields["img"] = img + P.fields["desc"] = desc + P.fields["pixel_x"] = pixel_x + P.fields["pixel_y"] = pixel_y + + aipictures += P + usr << "Image recorded" + +/obj/item/device/camera/ai_camera/proc/viewpictures() + var/list/nametemp = list() + var/find + var/datum/picture/selection + if(src.aipictures.len == 0) + usr << "No images saved" + return + for(var/datum/picture/t in src.aipictures) + nametemp += t.fields["name"] + find = input("Select image (numbered in order taken)") in nametemp + var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() + for(var/datum/picture/q in src.aipictures) + if(q.fields["name"] == find) + selection = q + break + P.icon = selection.fields["icon"] + P.img = selection.fields["img"] + P.desc = selection.fields["desc"] + P.pixel_x = selection.fields["pixel_x"] + P.pixel_y = selection.fields["pixel_y"] + + P.show(usr) + usr << P.desc + + // TG uses a special garbage collector.. qdel(P) + del(P) //so 10 thousand pictures items are not left in memory should an AI take them and then view them all. + +/obj/item/device/camera/ai_camera/printpicture(mob/user, icon/temp, mobs, flag) + var/icon/small_img = icon(temp) + var/icon/ic = icon('icons/obj/items.dmi',"photo") + small_img.Scale(8, 8) + ic.Blend(small_img,ICON_OVERLAY, 10, 13) + var/icon = ic + var/img = temp + var/desc = mobs + var/pixel_x = rand(-10, 10) + var/pixel_y = rand(-10, 10) + + injectaialbum(icon, img, desc, pixel_x, pixel_y) + +/obj/item/device/camera/ai_camera/can_capture_turf(turf/T, mob/user) + var/mob/living/silicon/ai = user + return ai.TurfAdjacent(T) + +/obj/item/device/camera/ai_camera/proc/toggle_camera_mode() + if(in_camera_mode) + camera_mode_off() + else + camera_mode_on() + +/obj/item/device/camera/ai_camera/proc/camera_mode_off() + src.in_camera_mode = 0 + usr << "Camera Mode deactivated" + +/obj/item/device/camera/ai_camera/proc/camera_mode_on() + src.in_camera_mode = 1 + usr << "Camera Mode activated" + +/mob/living/silicon/ai/proc/ai_take_image() + set category = "AI Commands" + set name = "Take Image" + set desc = "Takes an image" + aicamera.toggle_camera_mode() + +/mob/living/silicon/ai/proc/ai_view_images() + set category = "AI Commands" + set name = "View Images" + set desc = "View images" + aicamera.viewpictures() \ No newline at end of file diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index df08827c44e..01c654cce36 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -53,10 +53,10 @@ /obj/item/weapon/photo/proc/show(mob/user as mob) user << browse_rsc(img, "tmp_photo.png") user << browse("[name]" \ - + "" \ - + "" \ - + "[scribble ? "
Written on the back:
[scribble]" : ""]"\ - + "", "window=book;size=192x[scribble ? 400 : 192]") + + "" \ + + "
Written on the back:
[scribble]" : ]"\ + + "", "window=book;size=200x[scribble ? 400 : 200]") onclose(user, "[name]") return @@ -68,7 +68,7 @@ var/n_name = copytext(sanitize(input(usr, "What would you like to label the photo?", "Photo Labelling", null) as text), 1, MAX_NAME_LEN) //loc.loc check is for making possible renaming photos in clipboards if(( (loc == usr || (loc.loc && loc.loc == usr)) && usr.stat == 0)) - name = "photo[(n_name ? text("- '[n_name]'") : null)]" + name = "[(n_name ? text("[n_name]") : "photo")]" add_fingerprint(usr) return @@ -85,7 +85,7 @@ /obj/item/weapon/storage/photo_album/MouseDrop(obj/over_object as obj) - if((istype(usr, /mob/living/carbon/human) || (ticker && ticker.mode.name == "monkey"))) + if((istype(usr, /mob/living/carbon/human))) var/mob/M = usr if(!( istype(over_object, /obj/screen) )) return ..() @@ -119,7 +119,7 @@ w_class = 2.0 flags = FPRINT | CONDUCT | TABLEPASS slot_flags = SLOT_BELT - m_amt = 2000 +// matter = list("metal" = 2000) var/pictures_max = 10 var/pictures_left = 10 var/on = 1 @@ -152,51 +152,41 @@ ..() -/obj/item/device/camera/proc/get_icon(list/turfs, turf/center) - +/obj/item/device/camera/proc/get_icon(turf/the_turf as turf) //Bigger icon base to capture those icons that were shifted to the next tile //i.e. pretty much all wall-mounted machinery var/icon/res = icon('icons/effects/96x96.dmi', "") - // Initialize the photograph to black. - res.Blend("#000", ICON_OVERLAY) + + var/icon/turficon = build_composite_icon(the_turf) + res.Blend(turficon, ICON_OVERLAY, 33, 33) var/atoms[] = list() - for(var/turf/the_turf in turfs) - // Add outselves to the list of stuff to draw - atoms.Add(the_turf); - // As well as anything that isn't invisible. - for(var/atom/A in the_turf) - if(A.invisibility) continue - atoms.Add(A) + for(var/atom/A in the_turf) + if(A.invisibility) continue + atoms.Add(A) - // Sort the atoms into their layers - var/list/sorted = sort_atoms_by_layer(atoms) + //Sorting icons based on levels + var/gap = atoms.len + var/swapped = 1 + while (gap > 1 || swapped) + swapped = 0 + if(gap > 1) + gap = round(gap / 1.247330950103979) + if(gap < 1) + gap = 1 + for(var/i = 1; gap + i <= atoms.len; i++) + var/atom/l = atoms[i] //Fucking hate + var/atom/r = atoms[gap+i] //how lists work here + if(l.layer > r.layer) //no "atoms[i].layer" for me + atoms.Swap(i, gap + i) + swapped = 1 - for(var/i; i <= sorted.len; i++) - var/atom/A = sorted[i] + for(var/i; i <= atoms.len; i++) + var/atom/A = atoms[i] if(A) - var/icon/img = getFlatIcon(A)//build_composite_icon(A) - - // If what we got back is actually a picture, draw it. + var/icon/img = getFlatIcon(A, A.dir)//build_composite_icon(A) if(istype(img, /icon)) - // Check if we're looking at a mob that's lying down - if(istype(A, /mob/living) && A:lying) - // If they are, apply that effect to their picture. - img.BecomeLying() - // Calculate where we are relative to the center of the photo - var/xoff = (A.x - center.x) * 32 - var/yoff = (A.y - center.y) * 32 - if (istype(A,/atom/movable)) - xoff+=A:step_x - yoff+=A:step_y - res.Blend(img, blendMode2iconMode(A.blend_mode), 33 + A.pixel_x + xoff, 33 + A.pixel_y + yoff) - - // Lastly, render any contained effects on top. - for(var/turf/the_turf in turfs) - // Calculate where we are relative to the center of the photo - var/xoff = (the_turf.x - center.x) * 32 - var/yoff = (the_turf.y - center.y) * 32 - res.Blend(getFlatIcon(the_turf.loc), blendMode2iconMode(the_turf.blend_mode),33 + xoff,33 + yoff) + res.Blend(new/icon(img, "", A.dir), ICON_OVERLAY, 33 + A.pixel_x, 33 + A.pixel_y) return res @@ -222,50 +212,8 @@ /obj/item/device/camera/afterattack(atom/target as mob|obj|turf|area, mob/user as mob, flag) if(!on || !pictures_left || ismob(target.loc)) return + captureimage(target, user, flag) - var/x_c = target.x - 1 - var/y_c = target.y + 1 - var/z_c = target.z - - - var/list/turfs = list() - var/mobs = "" - for(var/i = 1; i <= 3; i++) - for(var/j = 1; j <= 3; j++) - var/turf/T = locate(x_c, y_c, z_c) - var/mob/dummy = new(T) //Go go visibility check dummy - var/viewer = user - if(user.client) //To make shooting through security cameras possible - viewer = user.client.eye - if(dummy in viewers(world.view, viewer)) - turfs.Add(T) - mobs += get_mobs(T) - dummy.loc = null - dummy = null //Alas, nameless creature //garbage collect it instead - x_c++ - y_c-- - x_c = x_c - 3 - - var/icon/photoimage = get_icon(turfs, target) - - var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() - P.loc = user.loc - if(!user.get_inactive_hand()) - user.put_in_inactive_hand(P) - var/icon/small_img = icon(photoimage) - var/icon/tiny_img = icon(photoimage) - var/icon/ic = icon('icons/obj/items.dmi',"photo") - var/icon/pc = icon('icons/obj/bureaucracy.dmi', "photo") - small_img.Scale(8, 8) - tiny_img.Scale(4, 4) - ic.Blend(small_img,ICON_OVERLAY, 10, 13) - pc.Blend(tiny_img,ICON_OVERLAY, 12, 19) - P.icon = ic - P.tiny = pc - P.img = photoimage - P.desc = mobs - P.pixel_x = rand(-10, 10) - P.pixel_y = rand(-10, 10) playsound(loc, pick('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg'), 75, 1, -3) pictures_left-- @@ -277,6 +225,58 @@ icon_state = icon_on on = 1 +/obj/item/device/camera/proc/can_capture_turf(turf/T, mob/user) + var/mob/dummy = new(T) //Go go visibility check dummy + var/viewer = user + if(user.client) //To make shooting through security cameras possible + viewer = user.client.eye + var/can_see = (dummy in viewers(world.view, viewer)) != null + + dummy.loc = null + dummy = null //Alas, nameless creature //garbage collect it instead + return can_see + +/obj/item/device/camera/proc/captureimage(atom/target, mob/user, flag) + var/x_c = target.x - 1 + var/y_c = target.y + 1 + var/z_c = target.z + + var/icon/temp = icon('icons/effects/96x96.dmi',"") + var/icon/black = icon('icons/turf/space.dmi', "black") + var/mobs = "" + for(var/i = 1; i <= 3; i++) + for(var/j = 1; j <= 3; j++) + var/turf/T = locate(x_c, y_c, z_c) + if(can_capture_turf(T, user)) + temp.Blend(get_icon(T), ICON_OVERLAY, 32 * (j-1-1), 32 - 32 * (i-1)) + mobs += get_mobs(T, user) + else + temp.Blend(black, ICON_OVERLAY, 32 * (j-1), 64 - 32 * (i-1)) + x_c++ + y_c-- + x_c = x_c - 3 + + printpicture(user, temp, mobs, flag) + +/obj/item/device/camera/proc/printpicture(mob/user, icon/temp, mobs, flag) + var/obj/item/weapon/photo/P = new/obj/item/weapon/photo() + P.loc = user.loc + if(!user.get_inactive_hand()) + user.put_in_inactive_hand(P) + var/icon/small_img = icon(temp) + var/icon/tiny_img = icon(temp) + var/icon/ic = icon('icons/obj/items.dmi',"photo") + var/icon/pc = icon('icons/obj/bureaucracy.dmi', "photo") + small_img.Scale(8, 8) + tiny_img.Scale(4, 4) + ic.Blend(small_img,ICON_OVERLAY, 10, 13) + pc.Blend(tiny_img,ICON_OVERLAY, 12, 19) + P.icon = ic + P.tiny = pc + P.img = temp + P.desc = mobs + P.pixel_x = rand(-10, 10) + P.pixel_y = rand(-10, 10) /************** *video camera *