-Ported/continued AI Freelook. AIs can now look around like a ghost with the exception that they cannot see what cameras cannot see. Meaning if you're in maintenance, and there's no cameras near you, the AI will not know what you are doing. This also means there's no X-Ray vision cameras anymore. I've added documentation to freelook.dm which explains how the system works, if anyone is interested in adding anything. More information here: http://nanotrasen.com/phpBB3/viewtopic.php?f=7&t=9675

-I've added some cameras to rooms that should have cameras but were previously depending on other camera's using their X-Ray vision in order to see into a room.

-AIs have a multitool in their contents that they can use to interact with the telecommunication machines.

-Added "Follow" for observers. Works the same as AI tracking without checking if they can track.

-Added a range to how far Cyborgs can interact with machines. This is to stop Cyborgs from interacting with machines through cameras, which could be used to easily disable the AI.

git-svn-id: http://tgstation13.googlecode.com/svn/trunk@4531 316c924e-a436-60f5-8080-3fe189b3f50e
This commit is contained in:
giacomand@gmail.com
2012-08-25 05:34:33 +00:00
parent 34b1d3de38
commit 683662f3b6
26 changed files with 9165 additions and 6470 deletions
+4
View File
@@ -320,6 +320,10 @@ Turf and target are seperate in case you want to teleport some distance from a t
oldname = null//don't bother with the records update crap
world << "<b>[newname] is the AI!</b>"
world << sound('sound/AI/newAI.ogg')
for(var/mob/aiEye/E in mob_list)
if(E.ai && E.ai == src)
E.name = "[newname] (AI Eye)"
break
fully_replace_character_name(oldname,newname)
+61 -120
View File
@@ -1,39 +1,3 @@
var/global/list/obj/machinery/camera/Cameras = list()
/obj/machinery/camera/New()
Cameras += src
..()
/obj/machinery/camera/Del()
Cameras -= src
..()
// Double clicking turfs to move to nearest camera
/turf/proc/move_camera_by_click()
if (usr.stat)
return ..()
if (world.time <= usr:lastDblClick+2)
return ..()
//try to find the closest working camera in the same area, switch to it
var/area/A = get_area(src)
var/best_dist = INFINITY //infinity
var/best_cam = null
for(var/obj/machinery/camera/C in A)
if(usr:network != C.network) continue
if(!C.status) continue // ignore disabled cameras
var/dist = get_dist(src, C)
if(dist < best_dist)
best_dist = dist
best_cam = C
if(!best_cam)
return ..()
usr:lastDblClick = world.time
usr:switchCamera(best_cam)
/mob/living/silicon/ai/proc/ai_camera_list()
set category = "AI Commands"
set name = "Show Camera List"
@@ -55,26 +19,33 @@ var/global/list/obj/machinery/camera/Cameras = list()
var/list/namecounts = list()
var/list/humans = list()
var/list/others = list()
for(var/mob/living/M in mob_list)
//Cameras can't track people wearing an agent card or a ninja hood.
var/human = 0
if(istype(M, /mob/living/carbon/human))
human = 1
if(istype(M:wear_id, /obj/item/weapon/card/id/syndicate))
continue
if(istype(M:head, /obj/item/clothing/head/helmet/space/space_ninja)&&!M:head:canremove)
continue
if(!istype(M.loc, /turf)) //in a closet or something, AI can't see him anyways
continue
if(istype(M.loc.loc, /area/wizard_station))
continue
if(M.invisibility)//cloaked
// Easy checks first.
// Don't detect mobs on Centcom. Since the wizard den is on Centcomm, we only need this.
if(M.loc.z == 2)
continue
if(M == usr)
continue
if(M.invisibility)//cloaked
continue
if(M.digitalcamo)
continue
if(M.loc.z == 2) // Don't detect mobs on Centcom
// Human check
var/human = 0
if(istype(M, /mob/living/carbon/human))
human = 1
var/mob/living/carbon/human/H = M
//Cameras can't track people wearing an agent card or a ninja hood.
if(istype(H.wear_id, /obj/item/weapon/card/id/syndicate))
continue
if(istype(H.head, /obj/item/clothing/head/helmet/space/space_ninja))
var/obj/item/clothing/head/helmet/space/space_ninja/hood = H.head
if(!hood.canremove)
continue
// Now, are they viewable by a camera? (This is last because it's the most intensive check)
if(!cameranet.checkCameraVis(M))
continue
var/name = M.name
@@ -104,9 +75,10 @@ var/global/list/obj/machinery/camera/Cameras = list()
var/mob/living/silicon/ai/U = usr
U.cameraFollow = target
U << text("Now tracking [] on camera.", target.name)
if (U.machine == null)
U.machine = U
//U << text("Now tracking [] on camera.", target.name)
//if (U.machine == null)
// U.machine = U
U << "Now tracking [target.name] on camera."
spawn (0)
while (U.cameraFollow == target)
@@ -117,7 +89,7 @@ var/global/list/obj/machinery/camera/Cameras = list()
U << "Follow camera mode terminated."
U.cameraFollow = null
return
if(istype(target:head, /obj/item/clothing/head/helmet/space/space_ninja)&&!target:head:canremove)
if(istype(target:head, /obj/item/clothing/head/helmet/space/space_ninja) && !target:head:canremove)
U << "Follow camera mode terminated."
U.cameraFollow = null
return
@@ -132,47 +104,14 @@ var/global/list/obj/machinery/camera/Cameras = list()
return
else if (!target || !istype(target.loc, /turf)) //in a closet
U << "Target is not on or near any active cameras on the station. We'll check again in 5 seconds (unless you use the cancel-camera verb)."
sleep(40) //because we're sleeping another second after this (a few lines down)
sleep(30) //because we're sleeping another second after this (a few lines down)
continue
else if(!cameranet.checkCameraVis(target))
U << "Target is not on or near any active cameras on the station. We'll check again in 5 seconds (unless you use the cancel-camera verb)."
sleep(30) //because we're sleeping another second after this (a few lines down)
continue
var/obj/machinery/camera/C = U.current
if ((C && istype(C, /obj/machinery/camera)) || C==null)
if(isrobot(target))
var/mob/living/silicon/robot/R = target
C = R.camera
U.reset_view(C)
else
var/closestDist = -1
if (C!=null)
if (C.status)
closestDist = get_dist(C, target)
//U << text("Dist = [] for camera []", closestDist, C.name)
var/zmatched = 0
if (closestDist > 7 || closestDist == -1)
//check other cameras
var/obj/machinery/camera/closest = C
for(var/obj/machinery/camera/C2 in Cameras)
if (C2.network == src.network)
if (C2.z == target.z)
zmatched = 1
if (C2.status)
var/dist = get_dist(C2, target)
if ((dist < closestDist) || (closestDist == -1))
closestDist = dist
closest = C2
//U << text("Closest camera dist = [], for camera []", closestDist, closest.area.name)
if (closest != C)
U.reset_view(closest)
//use_power(50)
if (zmatched == 0)
U << "Target is not on or near any active cameras on the station. We'll check again in 5 seconds (unless you use the cancel-camera verb)."
sleep(40) //because we're sleeping another second after this (a few lines down)
else
U << "Follow camera mode ended."
U.cameraFollow = null
U.eyeobj.setLoc(get_turf(target))
sleep(10)
/proc/camera_sort(list/L)
@@ -191,7 +130,6 @@ var/global/list/obj/machinery/camera/Cameras = list()
L.Swap(j, j + 1)
return L
/mob/living/silicon/ai/attack_ai(var/mob/user as mob)
if (user != src)
return
@@ -199,13 +137,8 @@ var/global/list/obj/machinery/camera/Cameras = list()
if (stat == 2)
return
// If they cancel then just put them back to their old camera
var/obj/machinery/camera/tempC = src.current
user.machine = src
switchCamera(null)
var/list/L = list()
for (var/obj/machinery/camera/C in Cameras)
for (var/obj/machinery/camera/C in cameranet.cameras)
L.Add(C)
camera_sort(L)
@@ -214,19 +147,15 @@ var/global/list/obj/machinery/camera/Cameras = list()
D["Cancel"] = "Cancel"
for (var/obj/machinery/camera/C in L)
if (C.network == src.network)
D[text("[][]", C.c_tag, (C.status ? null : " (Deactivated)"))] = C
D[text("[][]", C.c_tag, (C.can_use() ? null : " (Deactivated)"))] = C
var/t = input(user, "Which camera should you change to?") as null|anything in D
if (!t || t == "Cancel")
if(tempC && tempC.status)
switchCamera(tempC)
else
switchCamera(null)
return 0
var/obj/machinery/camera/C = D[t]
switchCamera(C)
src.eyeobj.setLoc(C)
return
@@ -234,13 +163,15 @@ var/global/list/obj/machinery/camera/Cameras = list()
if(prob(100/(hardened + severity)))
icon_state = "cameraemp"
network = null //Not the best way but it will do. I think.
cameranet.removeCamera(src)
stat |= EMPED
sd_SetLuminosity(0)
spawn(900)
network = initial(network)
icon_state = initial(icon_state)
for(var/mob/living/silicon/ai/O in mob_list)
if (O.current == src)
O.cancel_camera()
O << "Your connection to the camera has been lost."
stat &= ~EMPED
if(can_use())
cameranet.addCamera(src)
for(var/mob/O in mob_list)
if (istype(O.machine, /obj/machinery/computer/security))
var/obj/machinery/computer/security/S = O.machine
@@ -266,9 +197,9 @@ var/global/list/obj/machinery/camera/Cameras = list()
/obj/machinery/camera/attack_ai(var/mob/living/silicon/ai/user as mob)
if (!istype(user))
return
if (src.network != user.network || !(src.status))
if (!src.can_use())
return
user.reset_view(src)
user.eyeobj.setLoc(get_turf(src))
/obj/machinery/camera/attack_paw(mob/living/carbon/alien/humanoid/user as mob)
if(!istype(user))
@@ -329,7 +260,7 @@ var/global/list/obj/machinery/camera/Cameras = list()
case.motion = 1
del(src)
else if (istype(W, /obj/item/weapon/camera_bug))
if (!src.status)
if (!src.can_use())
user << "\blue Camera non-functional"
return
if (src.bugged)
@@ -381,10 +312,6 @@ var/global/list/obj/machinery/camera/Cameras = list()
// now disconnect anyone using the camera
//Apparently, this will disconnect anyone even if the camera was re-activated.
//I guess that doesn't matter since they can't use it anyway?
for(var/mob/living/silicon/ai/O in player_list)
if (O.current == src)
O.cancel_camera()
O << "Your connection to the camera has been lost."
for(var/mob/O in player_list)
if (istype(O.machine, /obj/machinery/computer/security))
var/obj/machinery/computer/security/S = O.machine
@@ -393,6 +320,13 @@ var/global/list/obj/machinery/camera/Cameras = list()
O.reset_view(null)
O << "The screen bursts into static."
/obj/machinery/camera/proc/can_use()
if(!status)
return 0
if(stat & EMPED)
return 0
return 1
/atom/proc/auto_turn()
//Automatically turns based on nearby walls.
var/turf/simulated/wall/T = null
@@ -414,10 +348,17 @@ var/global/list/obj/machinery/camera/Cameras = list()
//Return a working camera that can see a given mob
//or null if none
/proc/seen_by_camera(var/mob/M)
for(var/obj/machinery/camera/C in oview(4, M))
if(C.can_use()) // check if camera disabled
return C
break
return null
for(var/obj/machinery/camera/C in oview(M))
if(C.status) // check if camera disabled
/proc/near_range_camera(var/mob/M)
for(var/obj/machinery/camera/C in range(4, M))
if(C.can_use()) // check if camera disabled
return C
break
return null
return null
+14 -7
View File
@@ -30,10 +30,11 @@
attack_hand(var/mob/user as mob)
if(stat & (NOPOWER|BROKEN)) return
user.machine = src
if(!isAI(user))
user.machine = src
var/list/L = list()
for (var/obj/machinery/camera/C in Cameras)
for (var/obj/machinery/camera/C in cameranet.cameras)
L.Add(C)
camera_sort(L)
@@ -56,14 +57,20 @@
return 0
if(C)
if ((get_dist(user, src) > 1 || user.machine != src || user.blinded || !( user.canmove ) || !( C.status )) && (!istype(user, /mob/living/silicon/ai)))
if(!C.status)
if ((get_dist(user, src) > 1 || user.machine != src || user.blinded || !( user.canmove ) || !( C.can_use() )) && (!istype(user, /mob/living/silicon/ai)))
if(!C.can_use() && !isAI(user))
src.current = null
return 0
else
src.current = C
use_power(50)
spawn( 5 )
if(isAI(user))
var/mob/living/silicon/ai/A = user
A.eyeobj.setLoc(get_turf(C))
A.client.eye = A.eyeobj
else
src.current = C
use_power(50)
spawn(5)
attack_hand(user)
return
+8 -6
View File
@@ -31,9 +31,8 @@ Possible to do for anyone motivated enough:
/*There are pretty much only three ways to interact here.
I don't need to check for client since they're clicking on an object.
This may change in the future but for now will suffice.*/
if(user.client.eye!=src)//Set client eye on the object if it's not already.
user.current = src
user.reset_view(src)
if(user.eyeobj.loc != src.loc)//Set client eye on the object if it's not already.
user.eyeobj.setLoc(get_turf(src))
else if(!hologram)//If there is no hologram, possibly make one.
activate_holo(user)
else if(master==user)//If there is a hologram, remove it. But only if the user is the master. Otherwise do nothing.
@@ -41,7 +40,7 @@ Possible to do for anyone motivated enough:
return
/obj/machinery/hologram/holopad/proc/activate_holo(mob/living/silicon/ai/user)
if(!(stat & NOPOWER)&&user.client.eye==src)//If the projector has power and client eye is on it.
if(!(stat & NOPOWER) && user.eyeobj.loc == src.loc)//If the projector has power and client eye is on it.
if(!hologram)//If there is not already a hologram.
create_holo(user)//Create one.
for(var/mob/M in viewers())
@@ -76,6 +75,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
hologram.name = "AI hologram"//If someone decides to right click.
sd_SetLuminosity(1)//To make the pad glowy.
icon_state = "holopad1"
A.current = src
master = A//AI is the master.
use_power = 2//Active power usage.
return 1
@@ -83,6 +83,8 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
/obj/machinery/hologram/holopad/proc/clear_holo()
hologram.sd_SetLuminosity(0)//Clear lighting.
del(hologram)//Get rid of hologram.
if(master.current == src)
master.current = null
master = null//Null the master, since no-one is using it now.
sd_SetLuminosity(0)//Clear lighting for the parent.
icon_state = "holopad0"
@@ -91,8 +93,8 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
/obj/machinery/hologram/holopad/process()
if(hologram)//If there is a hologram.
if(master&&!master.stat&&master.client&&master.client.eye==src)//If there is an AI attached, it's not incapacitated, it has a client, and the client eye is centered on the projector.
if( !(get_dist(src,hologram.loc)>3||stat & NOPOWER) )//If the hologram is not out of bounds and the machine has power.
if(master && !master.stat && master.client && master.eyeobj.loc == src.loc)//If there is an AI attached, it's not incapacitated, it has a client, and the client eye is centered on the projector.
if(!(stat & NOPOWER))//If the machine has power.
return 1
clear_holo()//If not, we want to get rid of the hologram.
return 1
+7 -1
View File
@@ -184,7 +184,13 @@ Class Procs:
return 0
/obj/machinery/attack_ai(mob/user as mob)
return src.attack_hand(user)
if(isrobot(user))
// For some reason attack_robot doesn't work
// This is to stop robots from using cameras to remotely control machines.
if(user.client && user.client.eye == user)
return src.attack_hand(user)
else
return src.attack_hand(user)
/obj/machinery/attack_paw(mob/user as mob)
return src.attack_hand(user)
+1881
View File
File diff suppressed because it is too large Load Diff
+20
View File
@@ -0,0 +1,20 @@
/mob/living/silicon/ai/proc/ai_statuschange()
set category = "AI Commands"
set name = "AI Status"
if(usr.stat == 2)
usr <<"You cannot change your emotional status because you are dead!"
return
var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Sad", "BSOD", "Blank", "Problems?", "Awesome", "Facepalm", "Friend Computer")
var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions
for (var/obj/machinery/ai_status_display/AISD in world) //change status
spawn( 0 )
AISD.emotion = emote
for (var/obj/machinery/status_display/SD in world) //if Friend Computer, change ALL displays
if(emote=="Friend Computer")
spawn(0)
SD.friendc = 1
else
spawn(0)
SD.friendc = 0
return
+2 -2
View File
@@ -58,7 +58,7 @@ var/intercom_range_display_status = 0
del(C)
if(camera_range_display_status)
for(var/obj/machinery/camera/C in Cameras)
for(var/obj/machinery/camera/C in cameranet.cameras)
new/obj/effect/debugging/camera_range(C.loc)
feedback_add_details("admin_verb","mCRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -74,7 +74,7 @@ var/intercom_range_display_status = 0
var/list/obj/machinery/camera/CL = list()
for(var/obj/machinery/camera/C in Cameras)
for(var/obj/machinery/camera/C in cameranet.cameras)
CL += C
var/output = {"<B>CAMERA ANNOMALITIES REPORT</B><HR>
@@ -174,6 +174,21 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
L+=T
usr.loc = pick(L)
/mob/dead/observer/verb/follow()
set category = "Ghost"
set name = "Follow" // "Haunt"
set desc = "Follow and haunt a mob."
if(istype(usr, /mob/dead/observer))
var/mob/target = input("Please, select a player!", "Jump to Mob", null, null) as null|anything in sortAtom(mob_list)
if(target)
spawn(0)
var/turf/pos = get_turf(src)
while(src.loc == pos)
src.loc = get_turf(target)
pos = src.loc
sleep(15)
/mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak
set category = "Ghost"
+62 -25
View File
@@ -17,6 +17,7 @@
var/ioncheck[1]
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
//MALFUNCTION
var/datum/AI_Module/module_picker/malf_picker
@@ -69,6 +70,8 @@
aiPDA.ownjob = "AI"
aiPDA.name = name + " (" + aiPDA.ownjob + ")"
aiMulti = new(src)
if (istype(loc, /turf))
verbs.Add(/mob/living/silicon/ai/proc/ai_call_shuttle,/mob/living/silicon/ai/proc/ai_camera_track, \
/mob/living/silicon/ai/proc/ai_camera_list, /mob/living/silicon/ai/proc/ai_network_change, \
@@ -101,7 +104,7 @@
/mob/living/silicon/ai/verb/pick_icon()
set category = "AI Commands"
set name = "Change AI Core Display"
set name = "Set AI Core Display"
if(stat || aiRestorePowerRoutine)
return
@@ -292,7 +295,7 @@
machine = null
src << browse(null, t1)
if (href_list["switchcamera"])
switchCamera(locate(href_list["switchcamera"]))
switchCamera(locate(href_list["switchcamera"])) in cameranet.cameras
if (href_list["showalerts"])
ai_alerts()
@@ -325,15 +328,15 @@
statelaws()
if (href_list["track"])
var/mob/target = locate(href_list["track"])
var/mob/living/silicon/ai/A = locate(href_list["track2"])
var/mob/target = locate(href_list["track"]) in mob_list
var/mob/living/silicon/ai/A = locate(href_list["track2"]) in mob_list
if(A && target)
A.ai_actual_track(target)
return
else if (href_list["faketrack"])
var/mob/target = locate(href_list["track"])
var/mob/living/silicon/ai/A = locate(href_list["track2"])
var/mob/target = locate(href_list["track"]) in mob_list
var/mob/living/silicon/ai/A = locate(href_list["track2"]) in mob_list
if(A && target)
A.cameraFollow = target
@@ -437,14 +440,15 @@
/mob/living/silicon/ai/proc/switchCamera(var/obj/machinery/camera/C)
src.cameraFollow = null
if (!C || stat == 2 || !C.status || C.network != network)
machine = null
reset_view(null)
if (!C || stat == 2 || !C.can_use())
//machine = null
//reset_view(null)
return 0
// ok, we're alive, camera is good and in our network...
eyeobj.setLoc(get_turf(C))
machine = src
reset_view(C)
return 1
/mob/living/silicon/ai/triggerAlarm(var/class, area/A, var/O, var/alarmsource)
@@ -468,7 +472,7 @@
C = O
L[A.name] = list(A, (C) ? C : O, list(alarmsource))
if (O)
if (C && C.status)
if (C && C.can_use())
src << "--- [class] alarm detected in [A.name]! (<A HREF=?src=\ref[src];switchcamera=\ref[C]>[C.c_tag]</A>)"
else if (CL && CL.len)
var/foo = 0
@@ -504,17 +508,17 @@
/mob/living/silicon/ai/cancel_camera()
set category = "AI Commands"
set name = "Cancel Camera View"
reset_view(null)
machine = null
//reset_view(null)
//machine = null
src.cameraFollow = null
//Replaces /mob/living/silicon/ai/verb/change_network() in ai.dm & camera.dm
//Adds in /mob/living/silicon/ai/proc/ai_network_change() instead
//Addition by Mord_Sith to define AI's network change ability
/mob/living/silicon/ai/proc/ai_network_change()
set category = "AI Commands"
set name = "Change Camera Network"
reset_view(null)
set name = "Jump To Network"
machine = null
src.cameraFollow = null
var/cameralist[0]
@@ -523,8 +527,10 @@
usr << "You can't change your camera network because you are dead!"
return
for (var/obj/machinery/camera/C in Cameras)
if(!C.status)
var/mob/living/silicon/ai/U = usr
for (var/obj/machinery/camera/C in cameranet.cameras)
if(!C.can_use())
continue
if(C.network == "AI Satellite")
if (ticker.mode.name == "AI malfunction")
@@ -535,10 +541,17 @@
else
if(C.network != "CREED" && C.network != "thunder" && C.network != "RD" && C.network != "toxins" && C.network != "Prison")
cameralist[C.network] = C.network
network = input(usr, "Which network would you like to view?") as null|anything in cameralist
var/old_network = network
network = input(U, "Which network would you like to view?") as null|anything in cameralist
if(isnull(network))
network = initial(network) // If nothing is selected, default to SS13 (or the initial network)
network = old_network // If nothing is selected
else
for(var/obj/machinery/camera/C in cameranet.cameras)
if(!C.can_use())
continue
if(C.network == network)
U.eyeobj.setLoc(get_turf(C))
break
src << "\blue Switched to [network] camera network."
//End of code by Mord_Sith
@@ -620,15 +633,39 @@
//Toggles the luminosity and applies it by re-entereing the camera.
/mob/living/silicon/ai/proc/toggle_camera_light()
set name = "Toggle camera light"
set name = "Toggle Camera Light"
set desc = "Toggles the light on the camera the AI is looking through."
set category = "AI Commands"
if(!current)
usr << "\red You are not looking through a camera right now."
return
camera_light_on = !camera_light_on
reset_view(current)
src << "Camera lights [camera_light_on ? "activated" : "deactivated"]."
if(!camera_light_on)
if(src.current)
src.current.sd_SetLuminosity(0)
else
src.lightNearbyCamera()
// Handled camera lighting, when toggled.
// It will get the nearest camera via range, it wouldn't matter
/mob/living/silicon/ai/proc/lightNearbyCamera(var/lum)
if(camera_light_on && camera_light_on < world.timeofday)
if(src.current)
// I have to use range instead of view or the darkness gets in the way.
var/camera = near_range_camera(src.eyeobj)
if(camera && src.current != camera)
src.current.sd_SetLuminosity(0)
src.current = camera
src.current.sd_SetLuminosity(lum)
else if(isnull(camera))
src.current.sd_SetLuminosity(0)
src.current = null
camera_light_on = world.timeofday + 1 * 10 // Update the light every 2 seconds.
else
src.current = near_range_camera(src.eyeobj)
if(src.current) src.current.sd_SetLuminosity(lum)
#undef AI_CAMERA_LUMINOSITY
@@ -4,6 +4,7 @@
icon_state = "ai-crash"
update_canmove()
src.eyeobj.setLoc(get_turf(src))
if(blind) blind.layer = 0
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
see_in_dark = 8
@@ -0,0 +1,134 @@
// CAMERA NET
//
// The datum containing all the chunks.
var/datum/cameranet/cameranet = new()
/datum/cameranet
// The cameras on the map, no matter if they work or not. Updated in obj/machinery/camera.dm by New() and Del().
var/list/cameras = list()
// The chunks of the map, mapping the areas that the cameras can see.
var/list/chunks = list()
var/ready = 0
// Checks if a chunk has been Generated in x, y, z.
/datum/cameranet/proc/chunkGenerated(x, y, z)
x &= ~0xf
y &= ~0xf
var/key = "[x],[y],[z]"
return key in chunks
// Returns the chunk in the x, y, z.
// If there is no chunk, it creates a new chunk and returns that.
/datum/cameranet/proc/getCameraChunk(x, y, z)
x &= ~0xf
y &= ~0xf
var/key = "[x],[y],[z]"
if(!(key in chunks))
chunks[key] = new /datum/camerachunk(null, x, y, z)
return chunks[key]
// Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set.
/datum/cameranet/proc/visibility(mob/aiEye/ai)
// 0xf = 15
var/x1 = max(0, ai.x - 16) & ~0xf
var/y1 = max(0, ai.y - 16) & ~0xf
var/x2 = min(world.maxx, ai.x + 16) & ~0xf
var/y2 = min(world.maxy, ai.y + 16) & ~0xf
var/list/visibleChunks = list()
for(var/x = x1; x <= x2; x += 16)
for(var/y = y1; y <= y2; y += 16)
visibleChunks += getCameraChunk(x, y, ai.z)
var/list/remove = ai.visibleCameraChunks - visibleChunks
var/list/add = visibleChunks - ai.visibleCameraChunks
for(var/datum/camerachunk/c in remove)
c.remove(ai)
for(var/datum/camerachunk/c in add)
c.add(ai)
// Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open.
/datum/cameranet/proc/updateVisibility(atom/A, var/opacity_check = 1)
if(!ticker || (opacity_check && !A.opacity))
return
majorChunkChange(A, 2)
/datum/cameranet/proc/updateChunk(x, y, z)
// 0xf = 15
if(!chunkGenerated(x, y, z))
return
var/datum/camerachunk/chunk = getCameraChunk(x, y, z)
chunk.hasChanged()
// Removes a camera from a chunk.
/datum/cameranet/proc/removeCamera(obj/machinery/camera/c)
majorChunkChange(c, 0)
// Add a camera to a chunk.
/datum/cameranet/proc/addCamera(obj/machinery/camera/c)
if(c.can_use())
majorChunkChange(c, 1)
// Used for Cyborg cameras. It is the same as "add" but named differently for easier readability
// and to allow the user know what it is for. Since portable cameras can be in ANY chunk, we have to
// all it to be added to all chunks. If the camera is disabled, it will instead remove.
/datum/cameranet/proc/updatePortableCamera(obj/machinery/camera/c)
if(c.can_use())
majorChunkChange(c, 1)
else
majorChunkChange(c, 0)
// Never access this proc directly!!!!
// This will update the chunk and all the surrounding chunks.
// It will also add the atom to the cameras list if you set the choice to 1.
// Setting the choice to 0 will remove the camera from the chunks.
// If you want to update the chunks around an object, without adding/removing a camera, use choice 2.
/datum/cameranet/proc/majorChunkChange(atom/c, var/choice)
// 0xf = 15
if(!c)
return
var/turf/T = get_turf(c)
if(T)
var/x1 = max(0, T.x - 16) & ~0xf
var/y1 = max(0, T.y - 16) & ~0xf
var/x2 = min(world.maxx, T.x + 16) & ~0xf
var/y2 = min(world.maxy, T.y + 16) & ~0xf
for(var/x = x1; x <= x2; x += 16)
for(var/y = y1; y <= y2; y += 16)
if(chunkGenerated(x, y, T.z))
var/datum/camerachunk/chunk = getCameraChunk(x, y, T.z)
if(choice == 0)
// Remove the camera.
chunk.cameras -= c
else if(choice == 1)
// You can't have the same camera in the list twice.
chunk.cameras |= c
chunk.hasChanged()
// Will check if a mob is on a viewable turf. Returns 1 if it is, otherwise returns 0.
/datum/cameranet/proc/checkCameraVis(mob/living/target as mob)
// 0xf = 15
var/turf/position = get_turf(target)
var/datum/camerachunk/chunk = getCameraChunk(position.x, position.y, position.z)
if(chunk)
if(chunk.changed)
chunk.hasChanged(1) // Update now, no matter if it's visible or not.
if(position in chunk.visibleTurfs)
return 1
return 0
@@ -0,0 +1,135 @@
#define UPDATE_BUFFER 15
// CAMERA CHUNK
//
// A 16x16 grid of the map with a list of turfs that can be seen, are visible and are dimmed.
// Allows the AI Eye to stream these chunks and know what it can and cannot see.
/datum/camerachunk
var/list/obscuredTurfs = list()
var/list/visibleTurfs = list()
var/list/obscured = list()
var/list/cameras = list()
var/list/turfs = list()
var/list/seenby = list()
var/visible = 0
var/changed = 0
var/updating = 0
// Add an AI eye to the chunk, then update if changed.
/datum/camerachunk/proc/add(mob/aiEye/ai)
ai.visibleCameraChunks += src
if(ai.ai.client)
ai.ai.client.images += obscured
visible++
seenby += ai
if(changed && !updating)
update()
// Remove an AI eye from the chunk, then update if changed.
/datum/camerachunk/proc/remove(mob/aiEye/ai)
ai.visibleCameraChunks -= src
if(ai.ai.client)
ai.ai.client.images -= obscured
seenby -= ai
if(visible > 0)
visible--
// Called when a chunk has changed. I.E: A wall was deleted.
/datum/camerachunk/proc/visibilityChanged(turf/loc)
if(!(loc in visibleTurfs))
return
hasChanged()
// Updates the chunk, makes sure that it doesn't update too much. If the chunk isn't being watched it will
// instead be flagged to update the next time an AI Eye moves near it.
/datum/camerachunk/proc/hasChanged(var/update_now = 0)
if(visible || update_now)
if(!updating)
updating = 1
spawn(UPDATE_BUFFER) // Batch large changes, such as many doors opening or closing at once
update()
updating = 0
else
changed = 1
// The actual updating. It gathers the visible turfs from cameras and puts them into the appropiate lists.
/datum/camerachunk/proc/update()
var/list/newVisibleTurfs = list()
for(var/obj/machinery/camera/c in cameras)
if(!c.can_use())
continue
var/turf/pos = get_turf(c)
if(pos)
for(var/turf/t in hear(7, pos))
if(t in turfs)
newVisibleTurfs += t
var/list/visAdded = newVisibleTurfs - visibleTurfs
var/list/visRemoved = visibleTurfs - newVisibleTurfs
visibleTurfs = newVisibleTurfs
obscuredTurfs = turfs - newVisibleTurfs
for(var/turf/t in visAdded)
if(t.obscured)
obscured -= t.obscured
for(var/mob/aiEye/m in seenby)
if(m.ai.client)
m.ai.client.images -= t.obscured
for(var/turf/t in visRemoved)
if(t in obscuredTurfs)
if(!t.obscured)
t.obscured = image('effects/cameravis.dmi', t, "black", 15)
obscured += t.obscured
for(var/mob/aiEye/m in seenby)
if(!m)
seenby -= m
if(m.ai.client)
m.ai.client.images += t.obscured
// Create a new camera chunk, since the chunks are made as they are needed.
/datum/camerachunk/New(loc, x, y, z)
// 0xf = 15
x &= ~0xf
y &= ~0xf
for(var/obj/machinery/camera/c in range(16, locate(x + 8, y + 8, z)))
if(c.can_use())
cameras += c
for(var/turf/t in range(10, locate(x + 8, y + 8, z)))
if(t.x >= x && t.y >= y && t.x < x + 16 && t.y < y + 16)
turfs += t
for(var/obj/machinery/camera/c in cameras)
if(!c.can_use())
continue
var/turf/pos = get_turf(c)
if(pos)
for(var/turf/t in hear(7, pos))
if(t in turfs)
visibleTurfs += t
obscuredTurfs = turfs - visibleTurfs
for(var/turf/t in obscuredTurfs)
if(!t.obscured)
t.obscured = image('effects/cameravis.dmi', t, "black", 15)
obscured += t.obscured
#undef UPDATE_BUFFER
@@ -0,0 +1,70 @@
// AI EYE
//
// An invisible (no icon) mob that the AI controls to look around the station with.
// It streams chunks as it moves around, which will show it what the AI can and cannot see.
/mob/aiEye
name = "Inactive AI Eye"
var/list/visibleCameraChunks = list()
var/mob/living/silicon/ai/ai = null
density = 0
nodamage = 1 // You can't damage it.
// Movement code. Returns 0 to stop air movement from moving it.
/mob/aiEye/Move()
return 0
// Use this when setting the aiEye's location.
// It will also stream the chunk that the new loc is in.
/mob/aiEye/proc/setLoc(var/T)
T = get_turf(T)
loc = T
cameranet.visibility(src)
// AI MOVEMENT
// The AI's "eye". Described on the top of the page.
/mob/living/silicon/ai/var/mob/aiEye/eyeobj = new()
// Intiliaze the eye by assigning it's "ai" variable to us. Then set it's loc to us.
/mob/living/silicon/ai/New()
..()
eyeobj.ai = src
spawn(5)
eyeobj.loc = src.loc
eyeobj.name = "[src.name] (AI Eye)" // Give it a name
/mob/living/silicon/ai/Del()
eyeobj.ai = null
del(eyeobj) // No AI, no Eye
..()
// This will move the AIEye. It will also cause lights near the eye to light up, if toggled.
// This is handled in the proc below this one.
/client/AIMove(n, direct, var/mob/living/silicon/ai/user)
user.eyeobj.setLoc(get_turf(get_step(user.eyeobj, direct)))
user.cameraFollow = null
src.eye = user.eyeobj
//user.machine = null //Uncomment this if it causes problems.
user.lightNearbyCamera()
// Return to the Core.
/mob/living/silicon/ai/verb/core()
set category = "AI Commands"
set name = "AI Core"
current = null
cameraFollow = null
machine = null
src.eyeobj.loc = src.loc
if(client && client.eye)
client.eye = src
for(var/datum/camerachunk/c in eyeobj.visibleCameraChunks)
c.remove(eyeobj)
@@ -0,0 +1,51 @@
// CREDITS
/*
Initial code credit for this goes to Uristqwerty.
Debugging, functionality, all comments and porting by Giacom.
Everything about freelook (or what we can put in here) will be stored here.
WHAT IS THIS?
This is a replacement for the current camera movement system, of the AI. Before this, the AI had to move between cameras and could
only see what the cameras could see. Not only this but the cameras could see through walls, which created problems.
With this, the AI controls an "AI Eye" mob, which moves just like a ghost; such as moving through walls and being invisible to players.
The AI's eye is set to this mob and then we use a system (explained below) to determine what the cameras around the AI Eye can and
cannot see. If the camera cannot see a turf, it will black it out, otherwise it won't and the AI will be able to see it.
This creates several features, such as.. no more see-through-wall cameras, easier to control camera movement, easier tracking,
the AI only being able to track mobs which are visible to a camera, only trackable mobs appearing on the mob list and many more.
HOW IT WORKS
It works by first creating a camera network datum. Inside of this camera network are "chunks" (which will be
explained later) and "cameras". The cameras list is kept up to date by obj/machinery/camera/New() and Del().
Next the camera network has chunks. These chunks are a 16x16 tile block of turfs and cameras contained inside the chunk.
These turfs are then sorted out based on what the cameras can and cannot see. If none of the cameras can see the turf, inside
the 16x16 block, it is listed as an "obscured" turf. Meaning the AI won't be able to see it.
HOW IT UPDATES
The camera network uses a streaming method in order to effeciently update chunks. Since the server will have doors opening, doors closing,
turf being destroyed and other lag inducing stuff, we want to update it under certain conditions and not every tick.
The chunks are not created straight away, only when an AI eye moves into it's area is when it gets created.
One a chunk is created, when a non glass door opens/closes or an opacity turf is destroyed, we check to see if an AI Eye is looking in the area.
We do this with the "seenby" list, which updates everytime an AI is near a chunk. If there is an AI eye inside the area, we update the chunk
that the changed atom is inside and all surrounding chunks, since a camera's vision could leak onto another chunk. If there is no AI Eye, we instead
flag the chunk to update whenever it is loaded by an AI Eye. This is basically how the chunks update and keep it in sync. We then add some lag reducing
measures, such as an UPDATE_BUFFER which stops a chunk from updating too many times in a certain time-frame, only updating if the changed atom was blocking
sight; for example, we don't update glass airlocks or floors.
WHERE IS EVERYTHING?
cameranet.dm = Everything about the cameranet datum.
chunk.dm = Everything about the chunk datum.
eye.dm = Everything about the AI and the AIEye.
updating.dm = Everything about triggers that will update chunks.
*/
@@ -0,0 +1,76 @@
//UPDATE TRIGGERS, when the chunk (and the surrounding chunks) should update.
// TURFS
/turf
var/image/obscured
/turf/proc/visibilityChanged()
cameranet.updateVisibility(src)
/atom/proc/move_camera_by_click()
if(istype(usr, /mob/living/silicon/ai))
var/mob/living/silicon/ai/AI = usr
if(AI.client.eye == AI.eyeobj)
AI.eyeobj.setLoc(src)
/turf/simulated/Del()
visibilityChanged()
..()
/turf/simulated/New()
..()
visibilityChanged()
// STRUCTURES
/obj/structure/Del()
cameranet.updateVisibility(src)
..()
/obj/structure/New()
..()
cameranet.updateVisibility(src)
// DOORS
// Simply updates the visibility of the area when it opens/closes/destroyed.
/obj/machinery/door/update_nearby_tiles(need_rebuild)
. = ..(need_rebuild)
// Glass door glass = 1
// don't check then?
if(!glass)
cameranet.updateVisibility(src, 0)
// ROBOT MOVEMENT
// Update the portable camera everytime the Robot moves.
// This might be laggy, comment it out if there are problems.
/mob/living/silicon/robot/Move()
. = ..()
if(.)
if(src.camera)
cameranet.updatePortableCamera(src.camera)
// CAMERA
// An addition to deactivate which removes/adds the camera from the chunk list based on if it works or not.
/obj/machinery/camera/deactivate(user as mob, var/choice = 1)
..(user, choice)
if(src.can_use())
cameranet.addCamera(src)
else
src.sd_SetLuminosity(0)
cameranet.removeCamera(src)
/obj/machinery/camera/New()
..()
cameranet.cameras += src
cameranet.addCamera(src)
/obj/machinery/camera/Del()
cameranet.cameras -= src
cameranet.removeCamera(src)
..()
@@ -22,4 +22,5 @@
if(O)
O.mode = 1
O.emotion = "Neutral"
src.core()
return
@@ -6,4 +6,5 @@
if (client)
client.eye = loc
client.perspective = EYE_PERSPECTIVE
src.core()
return
+1 -15
View File
@@ -13,20 +13,6 @@
var/obj/machinery/camera/closest = null
var/atom/old = (user.current?user.current : user.loc)
if(istype(user.loc, /obj/item/clothing/suit/space/space_ninja))//To make ninja suit AI holograms work.
var/obj/item/clothing/suit/space/space_ninja/S = user.loc//Ease of use.
if(S.hologram)//If there is a hologram.
S.hologram.loc = get_step(S.hologram, direct)
S.hologram.dir = direct
return//Whatever the case, return since you can't move anyway.
if(user.client)//To make AI holograms work. They will relay directions as long as they are centered on the object.
var/obj/machinery/hologram/holopad/T = user.client.eye//Client eye centers on an object.
if(istype(T)&&T.hologram&&T.master==user)//If there is a hologram and its master is the user.
T.hologram.loc = get_step(T.hologram, direct)
T.hologram.dir = direct
return//Relay move and then return if that's the case.
if(!old) return
var/dx = 0
@@ -43,7 +29,7 @@
var/area/A = get_area(old)
var/list/old_types = dd_text2list("[A.type]", "/")
for(var/obj/machinery/camera/current in Cameras)
for(var/obj/machinery/camera/current in cameranet.cameras)
if(user.network != current.network) continue
if(!current.status) continue // ignore disabled cameras
@@ -29,7 +29,7 @@
modtype = "Synd"
radio = new /obj/item/device/radio/borg(src)
if(!scrambledcodes)
if(!scrambledcodes && !camera)
camera = new /obj/machinery/camera(src)
camera.c_tag = real_name
camera.network = "SS13"
@@ -63,6 +63,7 @@
if(BORG_WIRE_CAMERA)
if (!isnull(src.camera) && !scrambledcodes)
src.camera.status = 1
src.camera.deactivate(usr, 0) // Will kick anyone who is watching the Cyborg's camera.
src.interact(usr)
+5 -4
View File
@@ -26,9 +26,10 @@
robot_talk(message)
else if ((copytext(message, 1, 3) == ":h") || (copytext(message, 1, 3) == ":H"))
if(isAI(src)&&client)//For patching directly into AI holopads.
var/mob/living/silicon/ai/U = src
message = copytext(message, 3)
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
holopad_talk(message)
U.holopad_talk(message)
else//Will not allow anyone by an active AI to use this function.
src << "This function is not available to you."
return
@@ -38,7 +39,7 @@
return ..(message)
//For holopads only. Usable by AI.
/mob/living/proc/holopad_talk(var/message)
/mob/living/silicon/ai/proc/holopad_talk(var/message)
log_say("[key_name(src)] : [message]")
@@ -47,8 +48,8 @@
if (!message)
return
var/obj/machinery/hologram/holopad/T = client.eye//Client eye centers on an object.
if(istype(T)&&T.hologram&&T.master==src)//If there is a hologram and its master is the user.
var/obj/machinery/hologram/holopad/T = locate(/obj/machinery/hologram/holopad) in src.eyeobj.loc
if(istype(T) && T.hologram && T.master==src)//If there is a hologram and its master is the user.
var/message_a = say_quote(message)
//Human-like, sorta, heard by those who understand humans.
+2
View File
@@ -744,6 +744,8 @@
if (user.stat)
user << "\red You must be conscious to use this [src]!"
return 0
if(!user.client)
return 0
if ( ! (istype(user, /mob/living/carbon/human) || \
istype(user, /mob/living/silicon) || \
istype(user, /mob/living/carbon/monkey) /*&& ticker && ticker.mode.name == "monkey"*/) )
+9
View File
@@ -49,6 +49,15 @@ should be listed in the changelog upon commit tho. Thanks. -->
<!-- To take advantage of the pretty new format (well it was new when I wrote this anyway), open the "add-to-changelog.html" file in any browser and add the stuff and then generate the html code and paste it here -->
<div class="commit sansserif">
<h2 class="date">August 25, 2012</h2>
<h3 class="author">Giacom updated:</h3>
<ul class="changes bgimages16">
<li class="experiment">AIs can now look around like a ghost with the exception that they cannot see what cameras cannot see. Meaning if you're in maintenance, and there's no cameras near you, the AI will not know what you are doing. This also means there's no X-Ray vision cameras anymore.</li>
<li class="tweak">AIs can add links to Telecommunication Machines. Added some cameras for areas that should have it but instead relied on cameras nearby for vision.</li>
</ul>
</div>
<div class="commit sansserif">
<h2 class="date">August 24, 2012</h2>
<h3 class="author">Sieve updated:</h3>
+6292 -6289
View File
File diff suppressed because it is too large Load Diff
+311
View File
@@ -5,6 +5,266 @@
// END_INTERNALS
// BEGIN_FILE_DIR
#define FILE_DIR .
#define FILE_DIR ".svn"
#define FILE_DIR ".svn/pristine"
#define FILE_DIR ".svn/pristine/00"
#define FILE_DIR ".svn/pristine/01"
#define FILE_DIR ".svn/pristine/02"
#define FILE_DIR ".svn/pristine/03"
#define FILE_DIR ".svn/pristine/04"
#define FILE_DIR ".svn/pristine/05"
#define FILE_DIR ".svn/pristine/06"
#define FILE_DIR ".svn/pristine/07"
#define FILE_DIR ".svn/pristine/08"
#define FILE_DIR ".svn/pristine/09"
#define FILE_DIR ".svn/pristine/0a"
#define FILE_DIR ".svn/pristine/0b"
#define FILE_DIR ".svn/pristine/0c"
#define FILE_DIR ".svn/pristine/0d"
#define FILE_DIR ".svn/pristine/0e"
#define FILE_DIR ".svn/pristine/0f"
#define FILE_DIR ".svn/pristine/10"
#define FILE_DIR ".svn/pristine/11"
#define FILE_DIR ".svn/pristine/12"
#define FILE_DIR ".svn/pristine/13"
#define FILE_DIR ".svn/pristine/14"
#define FILE_DIR ".svn/pristine/15"
#define FILE_DIR ".svn/pristine/16"
#define FILE_DIR ".svn/pristine/17"
#define FILE_DIR ".svn/pristine/18"
#define FILE_DIR ".svn/pristine/19"
#define FILE_DIR ".svn/pristine/1a"
#define FILE_DIR ".svn/pristine/1b"
#define FILE_DIR ".svn/pristine/1c"
#define FILE_DIR ".svn/pristine/1d"
#define FILE_DIR ".svn/pristine/1e"
#define FILE_DIR ".svn/pristine/1f"
#define FILE_DIR ".svn/pristine/20"
#define FILE_DIR ".svn/pristine/21"
#define FILE_DIR ".svn/pristine/22"
#define FILE_DIR ".svn/pristine/23"
#define FILE_DIR ".svn/pristine/24"
#define FILE_DIR ".svn/pristine/25"
#define FILE_DIR ".svn/pristine/26"
#define FILE_DIR ".svn/pristine/27"
#define FILE_DIR ".svn/pristine/28"
#define FILE_DIR ".svn/pristine/29"
#define FILE_DIR ".svn/pristine/2a"
#define FILE_DIR ".svn/pristine/2b"
#define FILE_DIR ".svn/pristine/2c"
#define FILE_DIR ".svn/pristine/2d"
#define FILE_DIR ".svn/pristine/2e"
#define FILE_DIR ".svn/pristine/2f"
#define FILE_DIR ".svn/pristine/30"
#define FILE_DIR ".svn/pristine/31"
#define FILE_DIR ".svn/pristine/32"
#define FILE_DIR ".svn/pristine/33"
#define FILE_DIR ".svn/pristine/34"
#define FILE_DIR ".svn/pristine/35"
#define FILE_DIR ".svn/pristine/36"
#define FILE_DIR ".svn/pristine/37"
#define FILE_DIR ".svn/pristine/38"
#define FILE_DIR ".svn/pristine/39"
#define FILE_DIR ".svn/pristine/3a"
#define FILE_DIR ".svn/pristine/3b"
#define FILE_DIR ".svn/pristine/3c"
#define FILE_DIR ".svn/pristine/3d"
#define FILE_DIR ".svn/pristine/3e"
#define FILE_DIR ".svn/pristine/3f"
#define FILE_DIR ".svn/pristine/40"
#define FILE_DIR ".svn/pristine/41"
#define FILE_DIR ".svn/pristine/42"
#define FILE_DIR ".svn/pristine/43"
#define FILE_DIR ".svn/pristine/44"
#define FILE_DIR ".svn/pristine/45"
#define FILE_DIR ".svn/pristine/46"
#define FILE_DIR ".svn/pristine/47"
#define FILE_DIR ".svn/pristine/48"
#define FILE_DIR ".svn/pristine/49"
#define FILE_DIR ".svn/pristine/4a"
#define FILE_DIR ".svn/pristine/4b"
#define FILE_DIR ".svn/pristine/4c"
#define FILE_DIR ".svn/pristine/4d"
#define FILE_DIR ".svn/pristine/4e"
#define FILE_DIR ".svn/pristine/4f"
#define FILE_DIR ".svn/pristine/50"
#define FILE_DIR ".svn/pristine/51"
#define FILE_DIR ".svn/pristine/52"
#define FILE_DIR ".svn/pristine/53"
#define FILE_DIR ".svn/pristine/54"
#define FILE_DIR ".svn/pristine/55"
#define FILE_DIR ".svn/pristine/56"
#define FILE_DIR ".svn/pristine/57"
#define FILE_DIR ".svn/pristine/58"
#define FILE_DIR ".svn/pristine/59"
#define FILE_DIR ".svn/pristine/5a"
#define FILE_DIR ".svn/pristine/5b"
#define FILE_DIR ".svn/pristine/5c"
#define FILE_DIR ".svn/pristine/5d"
#define FILE_DIR ".svn/pristine/5e"
#define FILE_DIR ".svn/pristine/5f"
#define FILE_DIR ".svn/pristine/60"
#define FILE_DIR ".svn/pristine/61"
#define FILE_DIR ".svn/pristine/62"
#define FILE_DIR ".svn/pristine/63"
#define FILE_DIR ".svn/pristine/64"
#define FILE_DIR ".svn/pristine/65"
#define FILE_DIR ".svn/pristine/66"
#define FILE_DIR ".svn/pristine/67"
#define FILE_DIR ".svn/pristine/68"
#define FILE_DIR ".svn/pristine/69"
#define FILE_DIR ".svn/pristine/6a"
#define FILE_DIR ".svn/pristine/6b"
#define FILE_DIR ".svn/pristine/6c"
#define FILE_DIR ".svn/pristine/6d"
#define FILE_DIR ".svn/pristine/6e"
#define FILE_DIR ".svn/pristine/6f"
#define FILE_DIR ".svn/pristine/70"
#define FILE_DIR ".svn/pristine/71"
#define FILE_DIR ".svn/pristine/72"
#define FILE_DIR ".svn/pristine/73"
#define FILE_DIR ".svn/pristine/74"
#define FILE_DIR ".svn/pristine/75"
#define FILE_DIR ".svn/pristine/76"
#define FILE_DIR ".svn/pristine/77"
#define FILE_DIR ".svn/pristine/78"
#define FILE_DIR ".svn/pristine/79"
#define FILE_DIR ".svn/pristine/7a"
#define FILE_DIR ".svn/pristine/7b"
#define FILE_DIR ".svn/pristine/7c"
#define FILE_DIR ".svn/pristine/7d"
#define FILE_DIR ".svn/pristine/7e"
#define FILE_DIR ".svn/pristine/7f"
#define FILE_DIR ".svn/pristine/80"
#define FILE_DIR ".svn/pristine/81"
#define FILE_DIR ".svn/pristine/82"
#define FILE_DIR ".svn/pristine/83"
#define FILE_DIR ".svn/pristine/84"
#define FILE_DIR ".svn/pristine/85"
#define FILE_DIR ".svn/pristine/86"
#define FILE_DIR ".svn/pristine/87"
#define FILE_DIR ".svn/pristine/88"
#define FILE_DIR ".svn/pristine/89"
#define FILE_DIR ".svn/pristine/8a"
#define FILE_DIR ".svn/pristine/8b"
#define FILE_DIR ".svn/pristine/8c"
#define FILE_DIR ".svn/pristine/8d"
#define FILE_DIR ".svn/pristine/8e"
#define FILE_DIR ".svn/pristine/8f"
#define FILE_DIR ".svn/pristine/90"
#define FILE_DIR ".svn/pristine/91"
#define FILE_DIR ".svn/pristine/92"
#define FILE_DIR ".svn/pristine/93"
#define FILE_DIR ".svn/pristine/94"
#define FILE_DIR ".svn/pristine/95"
#define FILE_DIR ".svn/pristine/96"
#define FILE_DIR ".svn/pristine/97"
#define FILE_DIR ".svn/pristine/98"
#define FILE_DIR ".svn/pristine/99"
#define FILE_DIR ".svn/pristine/9a"
#define FILE_DIR ".svn/pristine/9b"
#define FILE_DIR ".svn/pristine/9c"
#define FILE_DIR ".svn/pristine/9d"
#define FILE_DIR ".svn/pristine/9e"
#define FILE_DIR ".svn/pristine/9f"
#define FILE_DIR ".svn/pristine/a0"
#define FILE_DIR ".svn/pristine/a1"
#define FILE_DIR ".svn/pristine/a2"
#define FILE_DIR ".svn/pristine/a3"
#define FILE_DIR ".svn/pristine/a4"
#define FILE_DIR ".svn/pristine/a5"
#define FILE_DIR ".svn/pristine/a6"
#define FILE_DIR ".svn/pristine/a7"
#define FILE_DIR ".svn/pristine/a8"
#define FILE_DIR ".svn/pristine/a9"
#define FILE_DIR ".svn/pristine/aa"
#define FILE_DIR ".svn/pristine/ab"
#define FILE_DIR ".svn/pristine/ac"
#define FILE_DIR ".svn/pristine/ad"
#define FILE_DIR ".svn/pristine/ae"
#define FILE_DIR ".svn/pristine/af"
#define FILE_DIR ".svn/pristine/b0"
#define FILE_DIR ".svn/pristine/b1"
#define FILE_DIR ".svn/pristine/b2"
#define FILE_DIR ".svn/pristine/b3"
#define FILE_DIR ".svn/pristine/b4"
#define FILE_DIR ".svn/pristine/b5"
#define FILE_DIR ".svn/pristine/b6"
#define FILE_DIR ".svn/pristine/b7"
#define FILE_DIR ".svn/pristine/b8"
#define FILE_DIR ".svn/pristine/b9"
#define FILE_DIR ".svn/pristine/ba"
#define FILE_DIR ".svn/pristine/bb"
#define FILE_DIR ".svn/pristine/bc"
#define FILE_DIR ".svn/pristine/bd"
#define FILE_DIR ".svn/pristine/be"
#define FILE_DIR ".svn/pristine/bf"
#define FILE_DIR ".svn/pristine/c0"
#define FILE_DIR ".svn/pristine/c1"
#define FILE_DIR ".svn/pristine/c2"
#define FILE_DIR ".svn/pristine/c3"
#define FILE_DIR ".svn/pristine/c4"
#define FILE_DIR ".svn/pristine/c5"
#define FILE_DIR ".svn/pristine/c6"
#define FILE_DIR ".svn/pristine/c7"
#define FILE_DIR ".svn/pristine/c8"
#define FILE_DIR ".svn/pristine/c9"
#define FILE_DIR ".svn/pristine/ca"
#define FILE_DIR ".svn/pristine/cb"
#define FILE_DIR ".svn/pristine/cc"
#define FILE_DIR ".svn/pristine/cd"
#define FILE_DIR ".svn/pristine/ce"
#define FILE_DIR ".svn/pristine/cf"
#define FILE_DIR ".svn/pristine/d0"
#define FILE_DIR ".svn/pristine/d1"
#define FILE_DIR ".svn/pristine/d2"
#define FILE_DIR ".svn/pristine/d3"
#define FILE_DIR ".svn/pristine/d4"
#define FILE_DIR ".svn/pristine/d5"
#define FILE_DIR ".svn/pristine/d6"
#define FILE_DIR ".svn/pristine/d7"
#define FILE_DIR ".svn/pristine/d8"
#define FILE_DIR ".svn/pristine/d9"
#define FILE_DIR ".svn/pristine/da"
#define FILE_DIR ".svn/pristine/db"
#define FILE_DIR ".svn/pristine/dc"
#define FILE_DIR ".svn/pristine/dd"
#define FILE_DIR ".svn/pristine/de"
#define FILE_DIR ".svn/pristine/df"
#define FILE_DIR ".svn/pristine/e0"
#define FILE_DIR ".svn/pristine/e1"
#define FILE_DIR ".svn/pristine/e2"
#define FILE_DIR ".svn/pristine/e3"
#define FILE_DIR ".svn/pristine/e4"
#define FILE_DIR ".svn/pristine/e5"
#define FILE_DIR ".svn/pristine/e6"
#define FILE_DIR ".svn/pristine/e7"
#define FILE_DIR ".svn/pristine/e8"
#define FILE_DIR ".svn/pristine/e9"
#define FILE_DIR ".svn/pristine/ea"
#define FILE_DIR ".svn/pristine/eb"
#define FILE_DIR ".svn/pristine/ec"
#define FILE_DIR ".svn/pristine/ed"
#define FILE_DIR ".svn/pristine/ee"
#define FILE_DIR ".svn/pristine/ef"
#define FILE_DIR ".svn/pristine/f0"
#define FILE_DIR ".svn/pristine/f1"
#define FILE_DIR ".svn/pristine/f2"
#define FILE_DIR ".svn/pristine/f3"
#define FILE_DIR ".svn/pristine/f4"
#define FILE_DIR ".svn/pristine/f5"
#define FILE_DIR ".svn/pristine/f6"
#define FILE_DIR ".svn/pristine/f7"
#define FILE_DIR ".svn/pristine/f8"
#define FILE_DIR ".svn/pristine/f9"
#define FILE_DIR ".svn/pristine/fa"
#define FILE_DIR ".svn/pristine/fb"
#define FILE_DIR ".svn/pristine/fc"
#define FILE_DIR ".svn/pristine/fd"
#define FILE_DIR ".svn/pristine/fe"
#define FILE_DIR ".svn/pristine/ff"
#define FILE_DIR "bot"
#define FILE_DIR "bot/Marakov"
#define FILE_DIR "code"
#define FILE_DIR "code/ATMOSPHERICS"
#define FILE_DIR "code/ATMOSPHERICS/components"
@@ -25,6 +285,7 @@
#define FILE_DIR "code/game/area"
#define FILE_DIR "code/game/asteroid"
#define FILE_DIR "code/game/gamemodes"
#define FILE_DIR "code/game/gamemodes/alien"
#define FILE_DIR "code/game/gamemodes/blob"
#define FILE_DIR "code/game/gamemodes/blob/blobs"
#define FILE_DIR "code/game/gamemodes/changeling"
@@ -121,6 +382,7 @@
#define FILE_DIR "code/modules/mob/living/carbon/monkey"
#define FILE_DIR "code/modules/mob/living/silicon"
#define FILE_DIR "code/modules/mob/living/silicon/ai"
#define FILE_DIR "code/modules/mob/living/silicon/ai/freelook"
#define FILE_DIR "code/modules/mob/living/silicon/decoy"
#define FILE_DIR "code/modules/mob/living/silicon/pai"
#define FILE_DIR "code/modules/mob/living/silicon/robot"
@@ -172,6 +434,38 @@
#define FILE_DIR "code/WorkInProgress/mapload"
#define FILE_DIR "code/WorkInProgress/organs"
#define FILE_DIR "code/WorkInProgress/virus2"
#define FILE_DIR "config"
#define FILE_DIR "config/names"
#define FILE_DIR "data"
#define FILE_DIR "data/logs"
#define FILE_DIR "data/logs/2012"
#define FILE_DIR "data/logs/2012/07-July"
#define FILE_DIR "data/logs/2012/08-August"
#define FILE_DIR "data/player_saves"
#define FILE_DIR "data/player_saves/c"
#define FILE_DIR "data/player_saves/c/calasmere"
#define FILE_DIR "data/player_saves/c/cheridan"
#define FILE_DIR "data/player_saves/c/cindikate"
#define FILE_DIR "data/player_saves/d"
#define FILE_DIR "data/player_saves/d/darktechnomancer"
#define FILE_DIR "data/player_saves/d/doohl"
#define FILE_DIR "data/player_saves/g"
#define FILE_DIR "data/player_saves/g/giacomand"
#define FILE_DIR "data/player_saves/g/giacomt"
#define FILE_DIR "data/player_saves/m"
#define FILE_DIR "data/player_saves/m/milofaust"
#define FILE_DIR "data/player_saves/n"
#define FILE_DIR "data/player_saves/n/nodrak"
#define FILE_DIR "data/player_saves/p"
#define FILE_DIR "data/player_saves/p/petethegoat"
#define FILE_DIR "data/player_saves/r"
#define FILE_DIR "data/player_saves/r/rockdtben"
#define FILE_DIR "data/player_saves/s"
#define FILE_DIR "data/player_saves/s/s0ldi3rkr4s0"
#define FILE_DIR "data/player_saves/t"
#define FILE_DIR "data/player_saves/t/tanknut"
#define FILE_DIR "data/player_saves/t/terranaut"
#define FILE_DIR "data/player_saves/t/thunder12345"
#define FILE_DIR "html"
#define FILE_DIR "icons"
#define FILE_DIR "icons/effects"
@@ -186,6 +480,7 @@
#define FILE_DIR "icons/obj/machines"
#define FILE_DIR "icons/obj/pipes"
#define FILE_DIR "icons/pda_icons"
#define FILE_DIR "icons/PSD files"
#define FILE_DIR "icons/spideros_icons"
#define FILE_DIR "icons/Testing"
#define FILE_DIR "icons/turf"
@@ -194,6 +489,7 @@
#define FILE_DIR "interface"
#define FILE_DIR "maps"
#define FILE_DIR "maps/RandomZLevels"
#define FILE_DIR "music"
#define FILE_DIR "sound"
#define FILE_DIR "sound/AI"
#define FILE_DIR "sound/ambience"
@@ -206,8 +502,18 @@
#define FILE_DIR "sound/piano"
#define FILE_DIR "sound/voice"
#define FILE_DIR "sound/weapons"
#define FILE_DIR "SQL"
#define FILE_DIR "tools"
#define FILE_DIR "tools/Redirector"
#define FILE_DIR "tools/Runtime Condenser"
#define FILE_DIR "tools/UnstandardnessTestForDM"
#define FILE_DIR "tools/UnstandardnessTestForDM/UnstandardnessTestForDM"
#define FILE_DIR "tools/UnstandardnessTestForDM/UnstandardnessTestForDM/bin"
#define FILE_DIR "tools/UnstandardnessTestForDM/UnstandardnessTestForDM/bin/Debug"
#define FILE_DIR "tools/UnstandardnessTestForDM/UnstandardnessTestForDM/obj"
#define FILE_DIR "tools/UnstandardnessTestForDM/UnstandardnessTestForDM/obj/x86"
#define FILE_DIR "tools/UnstandardnessTestForDM/UnstandardnessTestForDM/obj/x86/Debug"
#define FILE_DIR "tools/UnstandardnessTestForDM/UnstandardnessTestForDM/Properties"
// END_FILE_DIR
// BEGIN_PREFERENCES
@@ -989,6 +1295,11 @@
#include "code\modules\mob\living\silicon\ai\logout.dm"
#include "code\modules\mob\living\silicon\ai\move.dm"
#include "code\modules\mob\living\silicon\ai\say.dm"
#include "code\modules\mob\living\silicon\ai\freelook\cameranet.dm"
#include "code\modules\mob\living\silicon\ai\freelook\chunk.dm"
#include "code\modules\mob\living\silicon\ai\freelook\eye.dm"
#include "code\modules\mob\living\silicon\ai\freelook\read_me.dm"
#include "code\modules\mob\living\silicon\ai\freelook\update_triggers.dm"
#include "code\modules\mob\living\silicon\decoy\death.dm"
#include "code\modules\mob\living\silicon\decoy\decoy.dm"
#include "code\modules\mob\living\silicon\decoy\life.dm"