mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-12 18:03:13 +00:00
488 lines
15 KiB
Plaintext
488 lines
15 KiB
Plaintext
/* Photography!
|
|
* Contains:
|
|
* Camera
|
|
* Camera Film
|
|
* Photos
|
|
* Photo Albums
|
|
* AI Photography
|
|
*/
|
|
|
|
/*
|
|
* Film
|
|
*/
|
|
/obj/item/device/camera_film
|
|
name = "film cartridge"
|
|
icon = 'icons/obj/items.dmi'
|
|
desc = "A camera film cartridge. Insert it into a camera to reload it."
|
|
icon_state = "film"
|
|
item_state = "electropack"
|
|
w_class = 1
|
|
burn_state = FLAMMABLE
|
|
|
|
/*
|
|
* Photo
|
|
*/
|
|
/obj/item/weapon/photo
|
|
name = "photo"
|
|
icon = 'icons/obj/items.dmi'
|
|
icon_state = "photo"
|
|
item_state = "paper"
|
|
w_class = 1
|
|
burn_state = FLAMMABLE
|
|
burntime = 5
|
|
var/icon/img //Big photo image
|
|
var/scribble //Scribble on the back.
|
|
var/blueprints = 0 //Does it include the blueprints?
|
|
var/sillynewscastervar //Photo objects with this set to 1 will not be ejected by a newscaster. Only gets set to 1 if a silicon puts one of their images into a newscaster
|
|
|
|
|
|
/obj/item/weapon/photo/attack_self(mob/user)
|
|
user.examinate(src)
|
|
|
|
|
|
/obj/item/weapon/photo/attackby(obj/item/weapon/P, mob/user, params)
|
|
if(istype(P, /obj/item/weapon/pen) || istype(P, /obj/item/toy/crayon))
|
|
var/txt = sanitize(input(user, "What would you like to write on the back?", "Photo Writing", null) as text)
|
|
txt = copytext(txt, 1, 128)
|
|
if(loc == user && user.stat == 0)
|
|
scribble = txt
|
|
..()
|
|
|
|
|
|
/obj/item/weapon/photo/examine(mob/user)
|
|
..()
|
|
|
|
if(in_range(user, src))
|
|
show(user)
|
|
else
|
|
user << "<span class='warning'>You need to get closer to get a good look at this photo!</span>"
|
|
|
|
|
|
/obj/item/weapon/photo/proc/show(mob/user)
|
|
user << browse_rsc(img, "tmp_photo.png")
|
|
user << browse("<html><head><title>[name]</title></head>" \
|
|
+ "<body style='overflow:hidden;margin:0;text-align:center'>" \
|
|
+ "<img src='tmp_photo.png' width='192' style='-ms-interpolation-mode:nearest-neighbor' />" \
|
|
+ "[scribble ? "<br>Written on the back:<br><i>[scribble]</i>" : ""]"\
|
|
+ "</body></html>", "window=book;size=192x[scribble ? 400 : 192]")
|
|
onclose(user, "[name]")
|
|
|
|
|
|
/obj/item/weapon/photo/verb/rename()
|
|
set name = "Rename photo"
|
|
set category = "Object"
|
|
set src in usr
|
|
|
|
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 && usr.canmove && !usr.restrained())
|
|
name = "photo[(n_name ? text("- '[n_name]'") : null)]"
|
|
add_fingerprint(usr)
|
|
|
|
/obj/item/weapon/photo/proc/photocreate(inicon, inimg, indesc, inblueprints)
|
|
icon = inicon
|
|
img = inimg
|
|
desc = indesc
|
|
blueprints = inblueprints
|
|
|
|
/*
|
|
* Photo album
|
|
*/
|
|
/obj/item/weapon/storage/photo_album
|
|
name = "photo album"
|
|
icon = 'icons/obj/items.dmi'
|
|
icon_state = "album"
|
|
item_state = "briefcase"
|
|
can_hold = list(/obj/item/weapon/photo)
|
|
burn_state = FLAMMABLE
|
|
|
|
/*
|
|
* Camera
|
|
*/
|
|
/obj/item/device/camera
|
|
name = "camera"
|
|
icon = 'icons/obj/items.dmi'
|
|
desc = "A polaroid camera."
|
|
icon_state = "camera"
|
|
item_state = "electropack"
|
|
w_class = 2
|
|
flags = CONDUCT
|
|
slot_flags = SLOT_BELT
|
|
materials = list(MAT_METAL=2000)
|
|
var/pictures_max = 10
|
|
var/pictures_left = 10
|
|
var/on = 1
|
|
var/blueprints = 0 //are blueprints visible in the current photo being created?
|
|
var/list/aipictures = list() //Allows for storage of pictures taken by AI, in a similar manner the datacore stores info. Keeping this here allows us to share some procs w/ regualar camera
|
|
var/see_ghosts = 0 //for the spoop of it
|
|
|
|
|
|
/obj/item/device/camera/CheckParts()
|
|
var/obj/item/device/camera/C = locate(/obj/item/device/camera) in contents
|
|
if(C)
|
|
pictures_max = C.pictures_max
|
|
pictures_left = C.pictures_left
|
|
visible_message("[C] has been imbued with godlike power!")
|
|
qdel(C)
|
|
|
|
|
|
/obj/item/device/camera/spooky
|
|
name = "camera obscura"
|
|
desc = "A polaroid camera, some say it can see ghosts!"
|
|
see_ghosts = 1
|
|
|
|
/obj/item/device/camera/detective
|
|
name = "Detective's camera"
|
|
desc = "A polaroid camera with extra capacity for crime investigations."
|
|
pictures_max = 30
|
|
pictures_left = 30
|
|
|
|
|
|
/obj/item/device/camera/siliconcam //camera AI can take pictures with
|
|
name = "silicon photo camera"
|
|
var/in_camera_mode = 0
|
|
|
|
/obj/item/device/camera/siliconcam/ai_camera //camera AI can take pictures with
|
|
name = "AI photo camera"
|
|
|
|
/obj/item/device/camera/siliconcam/robot_camera //camera cyborgs can take pictures with.. needs it's own because of verb CATEGORY >.>
|
|
name = "Cyborg photo camera"
|
|
|
|
/obj/item/device/camera/siliconcam/robot_camera/verb/borgprinting()
|
|
set category ="Robot Commands"
|
|
set name = "Print Image"
|
|
set src in usr
|
|
|
|
if(usr.stat == DEAD)
|
|
return //won't work if dead
|
|
borgprint()
|
|
|
|
/obj/item/device/camera/attack(mob/living/carbon/human/M, mob/user)
|
|
return
|
|
|
|
|
|
/obj/item/device/camera/attackby(obj/item/I, mob/user, params)
|
|
if(istype(I, /obj/item/device/camera_film))
|
|
if(pictures_left)
|
|
user << "<span class='notice'>[src] still has some film in it!</span>"
|
|
return
|
|
if(!user.unEquip(I))
|
|
return
|
|
user << "<span class='notice'>You insert [I] into [src].</span>"
|
|
qdel(I)
|
|
pictures_left = pictures_max
|
|
return
|
|
..()
|
|
|
|
|
|
/obj/item/device/camera/examine(mob/user)
|
|
..()
|
|
user << "It has [pictures_left] photos left."
|
|
|
|
|
|
/obj/item/device/camera/proc/camera_get_icon(list/turfs, turf/center)
|
|
var/atoms[] = list()
|
|
for(var/turf/T in turfs)
|
|
atoms.Add(T)
|
|
for(var/atom/movable/A in T)
|
|
if(A.invisibility)
|
|
if(see_ghosts)
|
|
if(istype(A, /mob/dead/observer))
|
|
var/mob/dead/observer/O = A
|
|
if(O.orbiting) //so you dont see ghosts following people like antags, etc.
|
|
continue
|
|
else
|
|
continue
|
|
atoms.Add(A)
|
|
|
|
var/list/sorted = list()
|
|
var/j
|
|
for(var/i = 1 to atoms.len)
|
|
var/atom/c = atoms[i]
|
|
for(j = sorted.len, j > 0, --j)
|
|
var/atom/c2 = sorted[j]
|
|
if(c2.layer <= c.layer)
|
|
break
|
|
sorted.Insert(j+1, c)
|
|
|
|
var/icon/res = icon('icons/effects/96x96.dmi', "")
|
|
|
|
for(var/atom/A in sorted)
|
|
var/icon/img = getFlatIcon(A)
|
|
if(istype(A, /mob/living) && A:lying)
|
|
img.Turn(A:lying)
|
|
|
|
var/offX = 32 * (A.x - center.x) + A.pixel_x + 33
|
|
var/offY = 32 * (A.y - center.y) + A.pixel_y + 33
|
|
if(istype(A, /atom/movable))
|
|
offX += A:step_x
|
|
offY += A:step_y
|
|
|
|
res.Blend(img, blendMode2iconMode(A.blend_mode), offX, offY)
|
|
|
|
if(istype(A, /obj/item/areaeditor/blueprints))
|
|
blueprints = 1
|
|
|
|
for(var/turf/T in turfs)
|
|
res.Blend(getFlatIcon(T.loc), blendMode2iconMode(T.blend_mode), 32 * (T.x - center.x) + 33, 32 * (T.y - center.y) + 33)
|
|
|
|
return res
|
|
|
|
|
|
/obj/item/device/camera/proc/camera_get_mobs(turf/the_turf)
|
|
var/mob_detail
|
|
for(var/mob/M in the_turf)
|
|
if(M.invisibility)
|
|
if(see_ghosts && istype(M,/mob/dead/observer))
|
|
var/mob/dead/observer/O = M
|
|
if(O.orbiting)
|
|
continue
|
|
if(!mob_detail)
|
|
mob_detail = "You can see a g-g-g-g-ghooooost! "
|
|
else
|
|
mob_detail += "You can also see a g-g-g-g-ghooooost!"
|
|
else
|
|
continue
|
|
|
|
var/holding = null
|
|
|
|
if(istype(M, /mob/living))
|
|
var/mob/living/L = M
|
|
if(L.l_hand || L.r_hand)
|
|
if(L.l_hand) holding = "They are holding \a [L.l_hand]"
|
|
if(L.r_hand)
|
|
if(holding)
|
|
holding += " and \a [L.r_hand]"
|
|
else
|
|
holding = "They are holding \a [L.r_hand]"
|
|
|
|
if(!mob_detail)
|
|
mob_detail = "You can see [L] on the photo[L.health < 75 ? " - [L] looks hurt":""].[holding ? " [holding]":"."]. "
|
|
else
|
|
mob_detail += "You can also see [L] on the photo[L.health < 75 ? " - [L] looks hurt":""].[holding ? " [holding]":"."]."
|
|
|
|
|
|
return mob_detail
|
|
|
|
|
|
/obj/item/device/camera/proc/captureimage(atom/target, mob/user, flag) //Proc for both regular and AI-based camera to take the image
|
|
var/mobs = ""
|
|
var/isAi = istype(user, /mob/living/silicon/ai)
|
|
var/list/seen
|
|
if(!isAi) //crappy check, but without it AI photos would be subject to line of sight from the AI Eye object. Made the best of it by moving the sec camera check inside
|
|
if(user.client) //To make shooting through security cameras possible
|
|
seen = get_hear(world.view, user.client.eye) //To make shooting through security cameras possible
|
|
else
|
|
seen = get_hear(world.view, user)
|
|
else
|
|
seen = get_hear(world.view, target)
|
|
|
|
var/list/turfs = list()
|
|
for(var/turf/T in range(1, target))
|
|
if(T in seen)
|
|
if(isAi && !cameranet.checkTurfVis(T))
|
|
continue
|
|
else
|
|
turfs += T
|
|
mobs += camera_get_mobs(T)
|
|
|
|
var/icon/temp = icon('icons/effects/96x96.dmi',"")
|
|
temp.Blend("#000", ICON_OVERLAY)
|
|
temp.Blend(camera_get_icon(turfs, target), ICON_OVERLAY)
|
|
|
|
if(!issilicon(user))
|
|
printpicture(user, temp, mobs, flag)
|
|
else
|
|
aipicture(user, temp, mobs, isAi, blueprints)
|
|
|
|
|
|
|
|
|
|
/obj/item/device/camera/proc/printpicture(mob/user, icon/temp, mobs, flag) //Normal camera proc for creating photos
|
|
var/obj/item/weapon/photo/P = new/obj/item/weapon/photo(get_turf(src))
|
|
if(Adjacent(user)) //needed because of TK
|
|
user.put_in_hands(P)
|
|
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)
|
|
P.icon = ic
|
|
P.img = temp
|
|
P.desc = mobs
|
|
P.pixel_x = rand(-10, 10)
|
|
P.pixel_y = rand(-10, 10)
|
|
|
|
if(blueprints)
|
|
P.blueprints = 1
|
|
blueprints = 0
|
|
|
|
|
|
/obj/item/device/camera/proc/aipicture(mob/user, icon/temp, mobs, isAi) //instead of printing a picture like a regular camera would, we do this instead for the AI
|
|
|
|
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)
|
|
|
|
var/injectblueprints = 1
|
|
if(blueprints)
|
|
injectblueprints = 1
|
|
blueprints = 0
|
|
|
|
if(isAi)
|
|
injectaialbum(icon, img, desc, pixel_x, pixel_y, injectblueprints)
|
|
else
|
|
injectmasteralbum(icon, img, desc, pixel_x, pixel_y, injectblueprints)
|
|
|
|
|
|
|
|
/datum/picture
|
|
var/name = "image"
|
|
var/list/fields = list()
|
|
|
|
|
|
/obj/item/device/camera/proc/injectaialbum(icon, img, desc, pixel_x, pixel_y, blueprintsinject) //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] (taken by [src.loc.name])"
|
|
P.fields["icon"] = icon
|
|
P.fields["img"] = img
|
|
P.fields["desc"] = desc
|
|
P.fields["pixel_x"] = pixel_x
|
|
P.fields["pixel_y"] = pixel_y
|
|
P.fields["blueprints"] = blueprintsinject
|
|
|
|
aipictures += P
|
|
usr << "<span class='unconscious'>Image recorded</span>" //feedback to the AI player that the picture was taken
|
|
|
|
/obj/item/device/camera/proc/injectmasteralbum(icon, img, desc, pixel_x, pixel_y, blueprintsinject) //stores image information to a list similar to that of the datacore
|
|
var/numberer = 1
|
|
var/mob/living/silicon/robot/C = src.loc
|
|
if(C.connected_ai)
|
|
for(var/datum/picture in C.connected_ai.aicamera.aipictures)
|
|
numberer++
|
|
var/datum/picture/P = new()
|
|
P.fields["name"] = "Image [numberer] (taken by [src.loc.name])"
|
|
P.fields["icon"] = icon
|
|
P.fields["img"] = img
|
|
P.fields["desc"] = desc
|
|
P.fields["pixel_x"] = pixel_x
|
|
P.fields["pixel_y"] = pixel_y
|
|
P.fields["blueprints"] = blueprintsinject
|
|
|
|
C.connected_ai.aicamera.aipictures += P
|
|
usr << "<span class='unconscious'>Image recorded and saved to remote database</span>" //feedback to the Cyborg player that the picture was taken
|
|
else
|
|
injectaialbum(icon, img, desc, pixel_x, pixel_y, blueprintsinject)
|
|
|
|
/obj/item/device/camera/siliconcam/proc/selectpicture(obj/item/device/camera/siliconcam/targetloc)
|
|
var/list/nametemp = list()
|
|
var/find
|
|
if(targetloc.aipictures.len == 0)
|
|
usr << "<span class='boldannounce'>No images saved</span>"
|
|
return
|
|
for(var/datum/picture/t in targetloc.aipictures)
|
|
nametemp += t.fields["name"]
|
|
find = input("Select image (numbered in order taken)") in nametemp
|
|
for(var/datum/picture/q in targetloc.aipictures)
|
|
if(q.fields["name"] == find)
|
|
return q
|
|
|
|
/obj/item/device/camera/siliconcam/proc/viewpichelper(obj/item/device/camera/siliconcam/targetloc)
|
|
var/obj/item/weapon/photo/P = new/obj/item/weapon/photo()
|
|
var/datum/picture/selection = selectpicture(targetloc)
|
|
if(selection)
|
|
P.photocreate(selection.fields["icon"], selection.fields["img"], selection.fields["desc"])
|
|
P.pixel_x = selection.fields["pixel_x"]
|
|
P.pixel_y = selection.fields["pixel_y"]
|
|
|
|
P.show(usr)
|
|
usr << P.desc
|
|
qdel(P) //so 10 thousand picture items are not left in memory should an AI take them and then view them all
|
|
|
|
/obj/item/device/camera/siliconcam/proc/viewpictures(user)
|
|
if(isrobot(user)) // Cyborg
|
|
var/mob/living/silicon/robot/C = src.loc
|
|
var/obj/item/device/camera/siliconcam/Cinfo
|
|
if(C.connected_ai)
|
|
Cinfo = C.connected_ai.aicamera
|
|
viewpichelper(Cinfo)
|
|
else
|
|
Cinfo = C.aicamera
|
|
viewpichelper(Cinfo)
|
|
else // AI
|
|
var/Ainfo = src
|
|
viewpichelper(Ainfo)
|
|
|
|
/obj/item/device/camera/afterattack(atom/target, mob/user, flag)
|
|
if(!on || !pictures_left || ismob(target.loc) || !isturf(target.loc))
|
|
return
|
|
if(user.Adjacent(target))
|
|
var/list/bad_targets = list(/obj/structure, /obj/item/weapon/storage)
|
|
if(is_type_in_list(target, bad_targets))
|
|
return
|
|
|
|
captureimage(target, user, flag)
|
|
|
|
playsound(loc, pick('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg'), 75, 1, -3)
|
|
|
|
pictures_left--
|
|
user << "<span class='notice'>[pictures_left] photos left.</span>"
|
|
icon_state = "camera_off"
|
|
on = 0
|
|
spawn(64)
|
|
icon_state = "camera"
|
|
on = 1
|
|
|
|
/obj/item/device/camera/siliconcam/proc/toggle_camera_mode()
|
|
if(in_camera_mode)
|
|
camera_mode_off()
|
|
else
|
|
camera_mode_on()
|
|
|
|
/obj/item/device/camera/siliconcam/proc/camera_mode_off()
|
|
src.in_camera_mode = 0
|
|
usr << "<B>Camera Mode deactivated</B>"
|
|
|
|
/obj/item/device/camera/siliconcam/proc/camera_mode_on()
|
|
src.in_camera_mode = 1
|
|
usr << "<B>Camera Mode activated</B>"
|
|
|
|
/obj/item/device/camera/siliconcam/robot_camera/proc/borgprint()
|
|
var/list/nametemp = list()
|
|
var/find
|
|
var/datum/picture/selection
|
|
var/mob/living/silicon/robot/C = src.loc
|
|
var/obj/item/device/camera/siliconcam/targetcam = null
|
|
if(C.toner < 20)
|
|
usr << "Insufficent toner to print image."
|
|
return
|
|
if(C.connected_ai)
|
|
targetcam = C.connected_ai.aicamera
|
|
else
|
|
targetcam = C.aicamera
|
|
if(targetcam.aipictures.len == 0)
|
|
usr << "<span class='userdanger'>No images saved</span>"
|
|
return
|
|
for(var/datum/picture/t in targetcam.aipictures)
|
|
nametemp += t.fields["name"]
|
|
find = input("Select image (numbered in order taken)") in nametemp
|
|
for(var/datum/picture/q in targetcam.aipictures)
|
|
if(q.fields["name"] == find)
|
|
selection = q
|
|
break
|
|
var/obj/item/weapon/photo/p = new /obj/item/weapon/photo(C.loc)
|
|
p.photocreate(selection.fields["icon"], selection.fields["img"], selection.fields["desc"], selection.fields["blueprints"])
|
|
p.pixel_x = rand(-10, 10)
|
|
p.pixel_y = rand(-10, 10)
|
|
C.toner -= 20 //Cyborgs are very ineffeicient at printing an image
|
|
visible_message("[C.name] spits out a photograph from a narrow slot on it's chassis.")
|
|
usr << "<span class='notice'>You print a photograph.</span>"
|