mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-12 07:33:34 +01:00
Merge with upstream/master
This commit is contained in:
@@ -1025,7 +1025,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
|
||||
M.equip_to_slot_or_del(new /obj/item/clothing/glasses/meson/cyber(M), slot_glasses)
|
||||
M.equip_to_slot_or_del(new /obj/item/clothing/mask/breath(M), slot_wear_mask)
|
||||
M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/singuloth(M), slot_head)
|
||||
M.equip_to_slot_or_del(new /obj/item/weapon/claymore(M), slot_belt)
|
||||
M.equip_to_slot_or_del(new /obj/item/weapon/claymore/ceremonial(M), slot_belt)
|
||||
M.equip_to_slot_or_del(new /obj/item/weapon/tank/oxygen(M), slot_s_store)
|
||||
M.equip_to_slot_or_del(new /obj/item/weapon/twohanded/knighthammer(M), slot_back)
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ var/intercom_range_display_status = 0
|
||||
del(C)
|
||||
|
||||
if(camera_range_display_status)
|
||||
for(var/obj/machinery/camera/C in cameranet.viewpoints)
|
||||
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!
|
||||
|
||||
@@ -68,7 +68,7 @@ var/intercom_range_display_status = 0
|
||||
|
||||
var/list/obj/machinery/camera/CL = list()
|
||||
|
||||
for(var/obj/machinery/camera/C in cameranet.viewpoints)
|
||||
for(var/obj/machinery/camera/C in cameranet.cameras)
|
||||
CL += C
|
||||
|
||||
var/output = {"<B>CAMERA ANOMALIES REPORT</B><HR>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
if(!status)
|
||||
status = 1
|
||||
bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]"
|
||||
message_admins("[key_name_admin(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]")
|
||||
msg_admin_attack("[key_name_admin(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]")
|
||||
user << "<span class='notice'>A pressure hole has been bored to [bombtank] valve. \The [bombtank] can now be ignited.</span>"
|
||||
else
|
||||
status = 0
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
firstquery.Execute()
|
||||
while(firstquery.NextRow())
|
||||
if(text2num(firstquery.item[1]) == default_slot)
|
||||
var/DBQuery/query = dbcon.NewQuery("UPDATE characters SET OOC_Notes='[sql_sanitize_text(metadata)]',real_name='[sql_sanitize_text(real_name)]',name_is_always_random='[be_random_name]',gender='[gender]',age='[age]',species='[sql_sanitize_text(species)]',language='[sql_sanitize_text(language)]',hair_red='[r_hair]',hair_green='[g_hair]',hair_blue='[b_hair]',facial_red='[r_facial]',facial_green='[g_facial]',facial_blue='[b_facial]',skin_tone='[s_tone]',skin_red='[r_skin]',skin_green='[g_skin]',skin_blue='[b_skin]',hair_style_name='[sql_sanitize_text(h_style)]',facial_style_name='[sql_sanitize_text(f_style)]',eyes_red='[r_eyes]',eyes_green='[g_eyes]',eyes_blue='[b_eyes]',underwear='[underwear]',undershirt='[undershirt]',backbag='[backbag]',b_type='[b_type]',alternate_option='[alternate_option]',job_support_high='[job_support_high]',job_support_med='[job_support_med]',job_support_low='[job_support_low]',job_medsci_high='[job_medsci_high]',job_medsci_med='[job_medsci_med]',job_medsci_low='[job_medsci_low]',job_engsec_high='[job_engsec_high]',job_engsec_med='[job_engsec_med]',job_engsec_low='[job_engsec_low]',job_karma_high='[job_karma_high]',job_karma_med='[job_karma_med]',job_karma_low='[job_karma_low]',flavor_text='[sql_sanitize_text(flavor_text)]',med_record='[sql_sanitize_text(med_record)]',sec_record='[sql_sanitize_text(sec_record)]',gen_record='[sql_sanitize_text(gen_record)]',player_alt_titles='[sql_sanitize_text(playertitlelist)]',be_special='[be_special]',disabilities='[disabilities]',organ_data='[organlist]',nanotrasen_relation='[nanotrasen_relation]', speciesprefs='[speciesprefs]' WHERE ckey='[C.ckey]' AND slot='[default_slot]'")
|
||||
var/DBQuery/query = dbcon.NewQuery("UPDATE characters SET OOC_Notes='[sql_sanitize_text(metadata)]',real_name='[sql_sanitize_text(real_name)]',name_is_always_random='[be_random_name]',gender='[gender]',age='[age]',species='[sql_sanitize_text(species)]',language='[sql_sanitize_text(language)]',hair_red='[r_hair]',hair_green='[g_hair]',hair_blue='[b_hair]',facial_red='[r_facial]',facial_green='[g_facial]',facial_blue='[b_facial]',skin_tone='[s_tone]',skin_red='[r_skin]',skin_green='[g_skin]',skin_blue='[b_skin]',hair_style_name='[sql_sanitize_text(h_style)]',facial_style_name='[sql_sanitize_text(f_style)]',eyes_red='[r_eyes]',eyes_green='[g_eyes]',eyes_blue='[b_eyes]',underwear='[underwear]',undershirt='[undershirt]',backbag='[backbag]',b_type='[b_type]',alternate_option='[alternate_option]',job_support_high='[job_support_high]',job_support_med='[job_support_med]',job_support_low='[job_support_low]',job_medsci_high='[job_medsci_high]',job_medsci_med='[job_medsci_med]',job_medsci_low='[job_medsci_low]',job_engsec_high='[job_engsec_high]',job_engsec_med='[job_engsec_med]',job_engsec_low='[job_engsec_low]',job_karma_high='[job_karma_high]',job_karma_med='[job_karma_med]',job_karma_low='[job_karma_low]',flavor_text='[sql_sanitize_text(flavor_text)]',med_record='[sql_sanitize_text(med_record)]',sec_record='[sql_sanitize_text(sec_record)]',gen_record='[sql_sanitize_text(gen_record)]',player_alt_titles='[playertitlelist]',be_special='[be_special]',disabilities='[disabilities]',organ_data='[organlist]',nanotrasen_relation='[nanotrasen_relation]', speciesprefs='[speciesprefs]' WHERE ckey='[C.ckey]' AND slot='[default_slot]'")
|
||||
if(!query.Execute())
|
||||
var/err = query.ErrorMsg()
|
||||
log_game("SQL ERROR during character slot saving. Error : \[[err]\]\n")
|
||||
|
||||
@@ -26,4 +26,18 @@
|
||||
|
||||
/obj/item/clothing/suit/storage/hear_talk(mob/M, var/msg)
|
||||
pockets.hear_talk(M, msg)
|
||||
..()
|
||||
..()
|
||||
|
||||
/obj/item/clothing/suit/storage/proc/return_inv()
|
||||
|
||||
var/list/L = list( )
|
||||
|
||||
L += src.contents
|
||||
|
||||
for(var/obj/item/weapon/storage/S in src)
|
||||
L += S.return_inv()
|
||||
for(var/obj/item/weapon/gift/G in src)
|
||||
L += G.gift
|
||||
if (istype(G.gift, /obj/item/weapon/storage))
|
||||
L += G.gift:return_inv()
|
||||
return L
|
||||
@@ -40,6 +40,20 @@
|
||||
hold.hear_talk(M, msg, verb, speaking)
|
||||
..()
|
||||
|
||||
/obj/item/clothing/accessory/storage/proc/return_inv()
|
||||
|
||||
var/list/L = list( )
|
||||
|
||||
L += src.contents
|
||||
|
||||
for(var/obj/item/weapon/storage/S in src)
|
||||
L += S.return_inv()
|
||||
for(var/obj/item/weapon/gift/G in src)
|
||||
L += G.gift
|
||||
if (istype(G.gift, /obj/item/weapon/storage))
|
||||
L += G.gift:return_inv()
|
||||
return L
|
||||
|
||||
/obj/item/clothing/accessory/storage/attack_self(mob/user as mob)
|
||||
if (has_suit) //if we are part of a suit
|
||||
hold.open(user)
|
||||
|
||||
@@ -185,12 +185,12 @@
|
||||
return null
|
||||
|
||||
var/list/L = list()
|
||||
for(var/obj/machinery/camera/C in cameranet.viewpoints)
|
||||
for(var/obj/machinery/camera/C in cameranet.cameras)
|
||||
var/list/temp = C.network & key.networks
|
||||
if(temp.len)
|
||||
L.Add(C)
|
||||
|
||||
camera_sort(L)
|
||||
cameranet.process_sort()
|
||||
|
||||
return L
|
||||
verify_machine(var/obj/machinery/camera/C,var/datum/file/camnet_key/key = null)
|
||||
|
||||
@@ -68,8 +68,7 @@
|
||||
|
||||
for (var/mob/living/silicon/ai/aiPlayer in player_list)
|
||||
if (aiPlayer.client)
|
||||
var/law = ""
|
||||
aiPlayer.set_zeroth_law(law)
|
||||
aiPlayer.clear_zeroth_law()
|
||||
aiPlayer << "\red <b>You have detected a change in your laws information:</b>"
|
||||
aiPlayer << "Laws Updated: [law]"
|
||||
aiPlayer << "Laws Updated: Zeroth law removed."
|
||||
..()
|
||||
@@ -112,7 +112,7 @@ var/list/ai_list = list()
|
||||
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, \
|
||||
/mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/botcall, /mob/living/silicon/ai/proc/control_integrated_radio, /mob/living/silicon/ai/proc/control_hud, /mob/living/silicon/ai/proc/change_arrival_message)
|
||||
/mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/botcall, /mob/living/silicon/ai/proc/control_integrated_radio, /mob/living/silicon/ai/proc/control_hud, /mob/living/silicon/ai/proc/change_arrival_message, /mob/living/silicon/ai/proc/ai_store_location, /mob/living/silicon/ai/proc/ai_goto_location, /mob/living/silicon/ai/proc/ai_remove_location)
|
||||
|
||||
if(!safety)//Only used by AIize() to successfully spawn an AI.
|
||||
if (!B)//If there is no player/brain inside.
|
||||
@@ -127,7 +127,7 @@ var/list/ai_list = list()
|
||||
verbs.Remove(,/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, \
|
||||
/mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \
|
||||
/mob/living/silicon/ai/proc/toggle_camera_light,/mob/living/silicon/ai/verb/pick_icon,/mob/living/silicon/ai/proc/control_hud)
|
||||
/mob/living/silicon/ai/proc/toggle_camera_light,/mob/living/silicon/ai/verb/pick_icon,/mob/living/silicon/ai/proc/control_hud, /mob/living/silicon/ai/proc/change_arrival_message)
|
||||
laws = new /datum/ai_laws/alienmov
|
||||
else
|
||||
B.brainmob.mind.transfer_to(src)
|
||||
@@ -406,7 +406,7 @@ var/list/ai_list = list()
|
||||
unset_machine()
|
||||
src << browse(null, t1)
|
||||
if (href_list["switchcamera"])
|
||||
switchCamera(locate(href_list["switchcamera"])) in cameranet.viewpoints
|
||||
switchCamera(locate(href_list["switchcamera"])) in cameranet.cameras
|
||||
if (href_list["showalerts"])
|
||||
ai_alerts()
|
||||
//Carn: holopad requests
|
||||
@@ -584,15 +584,14 @@ var/list/ai_list = list()
|
||||
if(control_disabled)
|
||||
src << "Wireless communication is disabled."
|
||||
return
|
||||
var/turf/ai_current_turf = get_turf(src)
|
||||
var/ai_Zlevel = ai_current_turf.z
|
||||
var/ai_allowed_Zlevel = list(1,3,5)
|
||||
var/d
|
||||
var/area/bot_area
|
||||
d += "<A HREF=?src=\ref[src];botrefresh=\ref[Bot]>Query network status</A><br>"
|
||||
d += "<table width='100%'><tr><td width='40%'><h3>Name</h3></td><td width='20%'><h3>Status</h3></td><td width='30%'><h3>Location</h3></td><td width='10%'><h3>Control</h3></td></tr>"
|
||||
|
||||
for (Bot in aibots)
|
||||
if(Bot.z == ai_Zlevel && !Bot.remote_disabled) //Only non-emagged bots on the same Z-level are detected!
|
||||
if((Bot.z in ai_allowed_Zlevel) && !Bot.remote_disabled) //Only non-emagged bots on the allowed Z-level are detected!
|
||||
bot_area = get_area(Bot)
|
||||
d += "<tr><td width='30%'>[Bot.hacked ? "<span class='bad'>(!) </span>[Bot.name]" : Bot.name] ([Bot.bot_type_name])</td>"
|
||||
//If the bot is on, it will display the bot's current mode status. If the bot is not mode, it will just report "Idle". "Inactive if it is not on at all.
|
||||
@@ -631,8 +630,6 @@ var/list/ai_list = list()
|
||||
|
||||
/mob/living/silicon/ai/proc/switchCamera(var/obj/machinery/camera/C)
|
||||
|
||||
src.cameraFollow = null
|
||||
|
||||
if (!C || stat == 2) //C.can_use())
|
||||
return 0
|
||||
|
||||
@@ -706,7 +703,6 @@ var/list/ai_list = list()
|
||||
set category = "AI Commands"
|
||||
set name = "Jump To Network"
|
||||
unset_machine()
|
||||
src.cameraFollow = null
|
||||
var/cameralist[0]
|
||||
|
||||
if(usr.stat == 2)
|
||||
@@ -715,11 +711,11 @@ var/list/ai_list = list()
|
||||
|
||||
var/mob/living/silicon/ai/U = usr
|
||||
|
||||
for (var/obj/machinery/camera/C in cameranet.viewpoints)
|
||||
for (var/obj/machinery/camera/C in cameranet.cameras)
|
||||
if(!C.can_use())
|
||||
continue
|
||||
|
||||
var/list/tempnetwork = difflist(C.network,RESTRICTED_CAMERA_NETWORKS,1)
|
||||
var/list/tempnetwork = difflist(C.network,restricted_camera_networks,1)
|
||||
if(tempnetwork.len)
|
||||
for(var/i in tempnetwork)
|
||||
cameralist[i] = i
|
||||
@@ -733,7 +729,7 @@ var/list/ai_list = list()
|
||||
if(isnull(network))
|
||||
network = old_network // If nothing is selected
|
||||
else
|
||||
for(var/obj/machinery/camera/C in cameranet.viewpoints)
|
||||
for(var/obj/machinery/camera/C in cameranet.cameras)
|
||||
if(!C.can_use())
|
||||
continue
|
||||
if(network in C.network)
|
||||
@@ -912,3 +908,52 @@ var/list/ai_list = list()
|
||||
src << "Accessing Subspace Transceiver control..."
|
||||
if (src.aiRadio)
|
||||
src.aiRadio.interact(src)
|
||||
|
||||
|
||||
/mob/living/silicon/ai/proc/open_nearest_door(mob/living/target as mob)
|
||||
if(!istype(target)) return
|
||||
spawn(0)
|
||||
if(istype(target, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate))
|
||||
src << "Unable to locate an airlock"
|
||||
return
|
||||
if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate))
|
||||
src << "Unable to locate an airlock"
|
||||
return
|
||||
if(istype(H.head, /obj/item/clothing/head/helmet/space/space_ninja) && !H.head.canremove)
|
||||
src << "Unable to locate an airlock"
|
||||
return
|
||||
if(H.digitalcamo)
|
||||
src << "Unable to locate an airlock"
|
||||
return
|
||||
if (!near_camera(target))
|
||||
src << "Target is not near any active cameras."
|
||||
return
|
||||
var/obj/machinery/door/airlock/tobeopened
|
||||
var/dist = -1
|
||||
for(var/obj/machinery/door/airlock/D in range(3,target))
|
||||
if(!D.density) continue
|
||||
if(dist < 0)
|
||||
dist = get_dist(D, target)
|
||||
//world << dist
|
||||
tobeopened = D
|
||||
else
|
||||
if(dist > get_dist(D, target))
|
||||
dist = get_dist(D, target)
|
||||
//world << dist
|
||||
tobeopened = D
|
||||
//world << "found [tobeopened.name] closer"
|
||||
else
|
||||
//world << "[D.name] not close enough | [get_dist(D, target)] | [dist]"
|
||||
if(tobeopened)
|
||||
switch(alert(src, "Do you want to open \the [tobeopened] for [target]?","Doorknob_v2a.exe","Yes","No"))
|
||||
if("Yes")
|
||||
var/nhref = "src=\ref[tobeopened];aiEnable=7"
|
||||
tobeopened.Topic(nhref, params2list(nhref), tobeopened, 1)
|
||||
src << "\blue You've opened \the [tobeopened] for [target]."
|
||||
if("No")
|
||||
src << "\red You deny the request."
|
||||
else
|
||||
src << "\red You've failed to open an airlock for [target]"
|
||||
return
|
||||
@@ -1,25 +1,156 @@
|
||||
/datum/visibility_network/cameras
|
||||
ChunkType = /datum/visibility_chunk/camera
|
||||
// CAMERA NET
|
||||
//
|
||||
// The datum containing all the chunks.
|
||||
|
||||
/datum/visibility_network/cameras/getViewpointFromMob(var/mob/currentMob)
|
||||
var/mob/living/silicon/robot/currentRobot=currentMob
|
||||
if(currentRobot)
|
||||
return currentRobot.camera
|
||||
return FALSE
|
||||
var/datum/cameranet/cameranet = new()
|
||||
|
||||
/datum/visibility_network/cameras/validViewpoint(var/viewpoint)
|
||||
var/obj/machinery/camera/c = viewpoint
|
||||
if (!c)
|
||||
return FALSE
|
||||
return c.can_use()
|
||||
/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()
|
||||
var/cameras_unsorted = 1
|
||||
// The chunks of the map, mapping the areas that the cameras can see.
|
||||
var/list/chunks = list()
|
||||
var/ready = 0
|
||||
|
||||
/datum/cameranet/proc/process_sort()
|
||||
if(cameras_unsorted)
|
||||
cameras = dd_sortedObjectList(cameras)
|
||||
cameras_unsorted = 0
|
||||
|
||||
// adding some indirection so that I don't have to edit a ton of files
|
||||
/datum/visibility_network/cameras/proc/addCamera(var/camera)
|
||||
return addViewpoint(camera)
|
||||
// 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 (chunks[key])
|
||||
|
||||
/datum/visibility_network/cameras/proc/removeCamera(var/camera)
|
||||
return removeViewpoint(camera)
|
||||
// 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(!chunks[key])
|
||||
chunks[key] = new /datum/camerachunk(null, x, y, z)
|
||||
|
||||
/datum/visibility_network/cameras/proc/checkCameraVis(var/atom/target)
|
||||
return checkCanSee(target)
|
||||
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/chunk in remove)
|
||||
var/datum/camerachunk/c = chunk
|
||||
c.remove(ai)
|
||||
|
||||
for(var/chunk in add)
|
||||
var/datum/camerachunk/c = chunk
|
||||
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)
|
||||
if(c.can_use())
|
||||
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. Since portable cameras can be in ANY chunk.
|
||||
|
||||
/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 - 8) & ~0xf
|
||||
var/y1 = max(0, T.y - 8) & ~0xf
|
||||
var/x2 = min(world.maxx, T.x + 8) & ~0xf
|
||||
var/y2 = min(world.maxy, T.y + 8) & ~0xf
|
||||
|
||||
//world << "X1: [x1] - Y1: [y1] - X2: [x2] - Y2: [y2]"
|
||||
|
||||
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)
|
||||
return checkTurfVis(position)
|
||||
|
||||
/datum/cameranet/proc/checkTurfVis(var/turf/position)
|
||||
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(chunk.visibleTurfs[position])
|
||||
return 1
|
||||
return 0
|
||||
|
||||
// Debug verb for VVing the chunk that the turf is in.
|
||||
/*
|
||||
/turf/verb/view_chunk()
|
||||
set src in world
|
||||
|
||||
if(cameranet.chunkGenerated(x, y, z))
|
||||
var/datum/camerachunk/chunk = cameranet.getCameraChunk(x, y, z)
|
||||
usr.client.debug_variables(chunk)
|
||||
*/
|
||||
@@ -1,23 +1,168 @@
|
||||
/datum/visibility_chunk/camera
|
||||
#define UPDATE_BUFFER 25 // 2.5 seconds
|
||||
|
||||
/datum/visibility_chunk/camera/validViewpoint(var/viewpoint)
|
||||
var/obj/machinery/camera/c = viewpoint
|
||||
if(!c)
|
||||
return FALSE
|
||||
if(!c.can_use())
|
||||
return FALSE
|
||||
var/turf/point = locate(src.x + 8, src.y + 8, src.z)
|
||||
if(get_dist(point, c) > 24)
|
||||
return FALSE
|
||||
return TRUE
|
||||
// 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
|
||||
var/x = 0
|
||||
var/y = 0
|
||||
var/z = 0
|
||||
|
||||
/datum/visibility_chunk/camera/getVisibleTurfsForViewpoint(var/viewpoint)
|
||||
var/obj/machinery/camera/c = viewpoint
|
||||
return c.can_see()
|
||||
// Add an AI eye to the chunk, then update if changed.
|
||||
|
||||
/datum/camerachunk/proc/add(mob/aiEye/ai)
|
||||
if(!ai.ai)
|
||||
return
|
||||
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)
|
||||
if(!ai.ai)
|
||||
return
|
||||
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(!visibleTurfs[loc])
|
||||
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()
|
||||
|
||||
set background = 1
|
||||
|
||||
var/list/newVisibleTurfs = list()
|
||||
|
||||
for(var/camera in cameras)
|
||||
var/obj/machinery/camera/c = camera
|
||||
|
||||
if(!c)
|
||||
continue
|
||||
|
||||
if(!c.can_use())
|
||||
continue
|
||||
|
||||
var/turf/point = locate(src.x + 8, src.y + 8, src.z)
|
||||
if(get_dist(point, c) > 24)
|
||||
continue
|
||||
|
||||
for(var/turf/t in c.can_see())
|
||||
newVisibleTurfs[t] = t
|
||||
|
||||
// Removes turf that isn't in turfs.
|
||||
newVisibleTurfs &= turfs
|
||||
|
||||
var/list/visAdded = newVisibleTurfs - visibleTurfs
|
||||
var/list/visRemoved = visibleTurfs - newVisibleTurfs
|
||||
|
||||
visibleTurfs = newVisibleTurfs
|
||||
obscuredTurfs = turfs - newVisibleTurfs
|
||||
|
||||
for(var/turf in visAdded)
|
||||
var/turf/t = turf
|
||||
if(t.obscured)
|
||||
obscured -= t.obscured
|
||||
for(var/eye in seenby)
|
||||
var/mob/aiEye/m = eye
|
||||
if(!m || !m.ai)
|
||||
continue
|
||||
if(m.ai.client)
|
||||
m.ai.client.images -= t.obscured
|
||||
|
||||
for(var/turf in visRemoved)
|
||||
var/turf/t = turf
|
||||
if(obscuredTurfs[t])
|
||||
if(!t.obscured)
|
||||
t.obscured = image('icons/effects/cameravis.dmi', t, "black", 15)
|
||||
|
||||
obscured += t.obscured
|
||||
for(var/eye in seenby)
|
||||
var/mob/aiEye/m = eye
|
||||
if(!m || !m.ai)
|
||||
seenby -= m
|
||||
continue
|
||||
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
|
||||
|
||||
src.x = x
|
||||
src.y = y
|
||||
src.z = z
|
||||
|
||||
/datum/visibility_chunk/camera/findNearbyViewpoints()
|
||||
for(var/obj/machinery/camera/c in range(16, locate(x + 8, y + 8, z)))
|
||||
if(c.can_use())
|
||||
viewpoints += c
|
||||
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] = t
|
||||
|
||||
for(var/camera in cameras)
|
||||
var/obj/machinery/camera/c = camera
|
||||
if(!c)
|
||||
continue
|
||||
|
||||
if(!c.can_use())
|
||||
continue
|
||||
|
||||
for(var/turf/t in c.can_see())
|
||||
visibleTurfs[t] = t
|
||||
|
||||
// Removes turf that isn't in turfs.
|
||||
visibleTurfs &= turfs
|
||||
|
||||
obscuredTurfs = turfs - visibleTurfs
|
||||
|
||||
for(var/turf in obscuredTurfs)
|
||||
var/turf/t = turf
|
||||
if(!t.obscured)
|
||||
t.obscured = image('icons/effects/cameravis.dmi', t, "black", 15)
|
||||
obscured += t.obscured
|
||||
|
||||
#undef UPDATE_BUFFER
|
||||
@@ -1,13 +1,12 @@
|
||||
// AI EYE
|
||||
//
|
||||
// A mob that the AI controls to look around the station with.
|
||||
// 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"
|
||||
icon = 'icons/mob/AI.dmi'
|
||||
icon_state = "eye"
|
||||
alpha = 127
|
||||
icon = 'icons/obj/status_display.dmi' // For AI friend secret shh :o
|
||||
var/list/visibleCameraChunks = list()
|
||||
var/mob/living/silicon/ai/ai = null
|
||||
density = 0
|
||||
status_flags = GODMODE // You can't damage it.
|
||||
@@ -15,20 +14,16 @@
|
||||
see_in_dark = 7
|
||||
invisibility = INVISIBILITY_AI_EYE
|
||||
|
||||
/mob/aiEye/New()
|
||||
..()
|
||||
visibility_interface = new /datum/visibility_interface/ai_eye(src)
|
||||
|
||||
// Movement code. Returns 0 to stop air movement from moving it.
|
||||
/mob/aiEye/Move()
|
||||
return 0
|
||||
|
||||
// Hide popout menu verbs
|
||||
/mob/aiEye/examine()
|
||||
/mob/aiEye/examine(atom/A as mob|obj|turf in view())
|
||||
set popup_menu = 0
|
||||
set src = usr.contents
|
||||
return 0
|
||||
|
||||
|
||||
/mob/aiEye/pull()
|
||||
set popup_menu = 0
|
||||
set src = usr.contents
|
||||
@@ -41,11 +36,15 @@
|
||||
|
||||
// Use this when setting the aiEye's location.
|
||||
// It will also stream the chunk that the new loc is in.
|
||||
/mob/aiEye/setLoc(var/T, var/cancel_tracking = 1)
|
||||
|
||||
/mob/aiEye/setLoc(var/T)
|
||||
if(ai)
|
||||
if(!isturf(ai.loc))
|
||||
return
|
||||
|
||||
if(cancel_tracking)
|
||||
ai.ai_cancel_tracking()
|
||||
|
||||
T = get_turf(T)
|
||||
loc = T
|
||||
cameranet.visibility(src)
|
||||
@@ -55,9 +54,12 @@
|
||||
if(ai.holo)
|
||||
ai.holo.move_hologram()
|
||||
|
||||
/mob/aiEye/proc/getLoc()
|
||||
|
||||
/mob/aiEye/Move()
|
||||
return 0
|
||||
if(ai)
|
||||
if(!isturf(ai.loc) || !ai.client)
|
||||
return
|
||||
return ai.eyeobj.loc
|
||||
|
||||
// AI MOVEMENT
|
||||
|
||||
@@ -70,7 +72,6 @@
|
||||
var/acceleration = 1
|
||||
var/obj/machinery/hologram/holopad/holo = null
|
||||
|
||||
|
||||
// Intiliaze the eye by assigning it's "ai" variable to us. Then set it's loc to us.
|
||||
/mob/living/silicon/ai/New()
|
||||
..()
|
||||
@@ -79,7 +80,7 @@
|
||||
spawn(5)
|
||||
eyeobj.loc = src.loc
|
||||
|
||||
/mob/living/silicon/ai/Destroy()
|
||||
/mob/living/silicon/ai/Del()
|
||||
eyeobj.ai = null
|
||||
del(eyeobj) // No AI, no Eye
|
||||
..()
|
||||
@@ -88,9 +89,7 @@
|
||||
if(istype(usr, /mob/living/silicon/ai))
|
||||
var/mob/living/silicon/ai/AI = usr
|
||||
if(AI.eyeobj && AI.client.eye == AI.eyeobj)
|
||||
AI.cameraFollow = null
|
||||
if (isturf(src.loc) || isturf(src))
|
||||
AI.eyeobj.setLoc(src)
|
||||
AI.eyeobj.setLoc(src)
|
||||
|
||||
// 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.
|
||||
@@ -114,23 +113,24 @@
|
||||
else
|
||||
user.sprint = initial
|
||||
|
||||
user.cameraFollow = null
|
||||
|
||||
//user.unset_machine() //Uncomment this if it causes problems.
|
||||
//user.lightNearbyCamera()
|
||||
|
||||
|
||||
// Return to the Core.
|
||||
/mob/living/silicon/ai/proc/view_core()
|
||||
|
||||
/mob/living/silicon/ai/proc/core()
|
||||
set category = "AI Commands"
|
||||
set name = "AI Core"
|
||||
|
||||
view_core()
|
||||
|
||||
|
||||
/mob/living/silicon/ai/proc/view_core()
|
||||
current = null
|
||||
cameraFollow = null
|
||||
unset_machine()
|
||||
|
||||
if(src.eyeobj && src.loc)
|
||||
src.eyeobj.z = src.z
|
||||
src.eyeobj.loc = src.loc
|
||||
else
|
||||
if(!src.eyeobj)
|
||||
src << "ERROR: Eyeobj not found. Creating new eye..."
|
||||
src.eyeobj = new(src.loc)
|
||||
src.eyeobj.ai = src
|
||||
@@ -138,11 +138,11 @@
|
||||
|
||||
if(client && client.eye)
|
||||
client.eye = src
|
||||
|
||||
for(var/datum/visibility_chunk/camera/c in eyeobj.visibility_interface.visible_chunks)
|
||||
for(var/datum/camerachunk/c in eyeobj.visibleCameraChunks)
|
||||
c.remove(eyeobj)
|
||||
src.eyeobj.setLoc(src)
|
||||
|
||||
/mob/living/silicon/ai/verb/toggle_acceleration()
|
||||
/mob/living/silicon/ai/proc/toggle_acceleration()
|
||||
set category = "AI Commands"
|
||||
set name = "Toggle Camera Acceleration"
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
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 Destroy().
|
||||
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
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
WHERE IS EVERYTHING?
|
||||
|
||||
cameraNetwork.dm = Everything about the cameraNetwork datum.
|
||||
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.
|
||||
|
||||
@@ -1,3 +1,80 @@
|
||||
#define BORG_CAMERA_BUFFER 30
|
||||
|
||||
//UPDATE TRIGGERS, when the chunk (and the surrounding chunks) should update.
|
||||
|
||||
// TURFS
|
||||
|
||||
/turf
|
||||
var/image/obscured
|
||||
|
||||
/turf/proc/visibilityChanged()
|
||||
if(ticker)
|
||||
cameranet.updateVisibility(src)
|
||||
|
||||
/turf/simulated/Del()
|
||||
visibilityChanged()
|
||||
..()
|
||||
|
||||
/turf/simulated/New()
|
||||
..()
|
||||
visibilityChanged()
|
||||
|
||||
|
||||
|
||||
// STRUCTURES
|
||||
|
||||
/obj/structure/Del()
|
||||
if(ticker)
|
||||
cameranet.updateVisibility(src)
|
||||
..()
|
||||
|
||||
/obj/structure/New()
|
||||
..()
|
||||
if(ticker)
|
||||
cameranet.updateVisibility(src)
|
||||
|
||||
// EFFECTS
|
||||
|
||||
/obj/effect/Del()
|
||||
if(ticker)
|
||||
cameranet.updateVisibility(src)
|
||||
..()
|
||||
|
||||
/obj/effect/New()
|
||||
..()
|
||||
if(ticker)
|
||||
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)
|
||||
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/var/updating = 0
|
||||
|
||||
/mob/living/silicon/robot/Move()
|
||||
var/oldLoc = src.loc
|
||||
. = ..()
|
||||
if(.)
|
||||
if(src.camera && src.camera.network.len)
|
||||
if(!updating)
|
||||
updating = 1
|
||||
spawn(BORG_CAMERA_BUFFER)
|
||||
if(oldLoc != src.loc)
|
||||
cameranet.updatePortableCamera(src.camera)
|
||||
updating = 0
|
||||
|
||||
// CAMERA
|
||||
|
||||
// An addition to deactivate which removes/adds the camera from the chunk list based on if it works or not.
|
||||
@@ -5,23 +82,29 @@
|
||||
/obj/machinery/camera/deactivate(user as mob, var/choice = 1)
|
||||
..(user, choice)
|
||||
if(src.can_use())
|
||||
cameranet.addViewpoint(src)
|
||||
cameranet.addCamera(src)
|
||||
else
|
||||
src.SetLuminosity(0)
|
||||
cameranet.removeViewpoint(src)
|
||||
cameranet.removeCamera(src)
|
||||
|
||||
/obj/machinery/camera/New()
|
||||
..()
|
||||
cameranet.viewpoints += src //Camera must be added to global list of all cameras no matter what...
|
||||
var/list/open_networks = difflist(network,RESTRICTED_CAMERA_NETWORKS) //...but if all of camera's networks are restricted, it only works for specific camera consoles.
|
||||
//Camera must be added to global list of all cameras no matter what...
|
||||
if(cameranet.cameras_unsorted || !ticker)
|
||||
cameranet.cameras += src
|
||||
cameranet.cameras_unsorted = 1
|
||||
else
|
||||
dd_insertObjectList(cameranet.cameras, src)
|
||||
|
||||
var/list/open_networks = difflist(network,restricted_camera_networks) //...but if all of camera's networks are restricted, it only works for specific camera consoles.
|
||||
if(open_networks.len) //If there is at least one open network, chunk is available for AI usage.
|
||||
cameranet.addViewpoint(src)
|
||||
cameranet.addCamera(src)
|
||||
|
||||
/obj/machinery/camera/Del()
|
||||
cameranet.viewpoints -= src
|
||||
var/list/open_networks = difflist(network,RESTRICTED_CAMERA_NETWORKS)
|
||||
cameranet.cameras -= src
|
||||
var/list/open_networks = difflist(network,restricted_camera_networks)
|
||||
if(open_networks.len)
|
||||
cameranet.removeViewpoint(src)
|
||||
cameranet.removeCamera(src)
|
||||
..()
|
||||
|
||||
#undef BORG_CAMERA_BUFFER
|
||||
@@ -1,10 +0,0 @@
|
||||
/datum/visibility_interface/ai_eye
|
||||
chunk_type = /datum/visibility_chunk/camera
|
||||
|
||||
/datum/visibility_interface/ai_eye/getClient()
|
||||
var/mob/aiEye/eye = controller
|
||||
if (!eye)
|
||||
return FALSE
|
||||
if (!eye.ai)
|
||||
return FALSE
|
||||
return eye.ai.client
|
||||
@@ -23,6 +23,10 @@
|
||||
/mob/living/silicon/ai/proc/set_zeroth_law(var/law, var/law_borg)
|
||||
src.laws_sanity_check()
|
||||
src.laws.set_zeroth_law(law, law_borg)
|
||||
|
||||
/mob/living/silicon/ai/proc/clear_zeroth_law(var/law_borg)
|
||||
src.laws_sanity_check()
|
||||
src.laws.clear_zeroth_law(law_borg)
|
||||
|
||||
/mob/living/silicon/ai/proc/add_inherent_law(var/law)
|
||||
src.laws_sanity_check()
|
||||
|
||||
@@ -77,6 +77,10 @@
|
||||
laws_sanity_check()
|
||||
laws.set_zeroth_law(law)
|
||||
|
||||
/mob/living/silicon/robot/proc/clear_zeroth_law()
|
||||
laws_sanity_check()
|
||||
laws.clear_zeroth_law()
|
||||
|
||||
/mob/living/silicon/robot/proc/add_inherent_law(var/law)
|
||||
laws_sanity_check()
|
||||
laws.add_inherent_law(law)
|
||||
|
||||
+1
-1
@@ -30,4 +30,4 @@
|
||||
icon_living = "Syndifox"
|
||||
icon_dead = "Syndifox_dead"
|
||||
flags = IS_SYNTHETIC|NO_BREATHE
|
||||
faction = list("syndicate")
|
||||
faction = list("syndicate")
|
||||
@@ -57,18 +57,20 @@
|
||||
client.verbs |= H.species.abilities
|
||||
|
||||
CallHook("Login", list("client" = src.client, "mob" = src))
|
||||
|
||||
|
||||
//Update morgues on login/logout
|
||||
if (stat == DEAD)
|
||||
var/obj/structure/morgue/Morgue = null
|
||||
var/mob/living/carbon/human/C = null
|
||||
if (istype(src,/mob/dead/observer)) //We're a ghost, let's find our corpse
|
||||
var/mob/dead/observer/G = src
|
||||
if(!G.mind) //This'll probably break morgue sprites, but the line under the next If statement causes runtimes with Assume Direct Control.
|
||||
return
|
||||
if (G.can_reenter_corpse && G.mind.current)
|
||||
C = G.mind.current
|
||||
else if (istype(src,/mob/living/carbon/human))
|
||||
C = src
|
||||
|
||||
|
||||
if (C) //We found our corpse, is it inside a morgue?
|
||||
if (istype(C.loc,/obj/structure/morgue))
|
||||
Morgue = C.loc
|
||||
@@ -78,4 +80,4 @@
|
||||
Morgue = B.loc
|
||||
if (Morgue)
|
||||
Morgue.update()
|
||||
|
||||
|
||||
|
||||
@@ -10,18 +10,20 @@
|
||||
if(admins_number == 0) //Apparently the admin logging out is no longer an admin at this point, so we have to check this towards 0 and not towards 1. Awell.
|
||||
send2adminirc("[key_name(src)] logged out - no more admins online.")
|
||||
..()
|
||||
|
||||
|
||||
//Update morgues on login/logout
|
||||
if (stat == DEAD)
|
||||
var/obj/structure/morgue/Morgue = null
|
||||
var/mob/living/carbon/human/C = null
|
||||
if (istype(src,/mob/dead/observer)) //We're a ghost, let's find our corpse
|
||||
var/mob/dead/observer/G = src
|
||||
if(!G.mind) //This'll probably break morgue sprites, but the line under the next If statement causes runtimes with Assume Direct Control.
|
||||
return 1
|
||||
if (G.can_reenter_corpse && G.mind.current)
|
||||
C = G.mind.current
|
||||
else if (istype(src,/mob/living/carbon/human))
|
||||
C = src
|
||||
|
||||
|
||||
if (C) //We found our corpse, is it inside a morgue?
|
||||
if (istype(C.loc,/obj/structure/morgue))
|
||||
Morgue = C.loc
|
||||
|
||||
@@ -161,6 +161,14 @@ proc/hasorgans(A)
|
||||
|
||||
/proc/hsl2rgb(h, s, l)
|
||||
return
|
||||
|
||||
proc/hassensorlevel(A, var/level)
|
||||
var/mob/living/carbon/human/H = A
|
||||
if(istype(H) && istype(H.w_uniform, /obj/item/clothing/under))
|
||||
var/obj/item/clothing/under/U = H.w_uniform
|
||||
return U.sensor_mode >= level
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
/proc/check_zone(zone)
|
||||
|
||||
@@ -19,54 +19,6 @@ It reuses a lot of code from the AIEye cameraNetwork. In order to work properly,
|
||||
if (vp)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/datum/visibility_chunk/cult/validViewpoint(var/atom/viewpoint)
|
||||
var/turf/point = locate(src.x + 8, src.y + 8, src.z)
|
||||
if(get_dist(point, viewpoint) > 24)
|
||||
return FALSE
|
||||
|
||||
if (isCultRune(viewpoint) || isCultViewpoint(viewpoint))
|
||||
return viewpoint:can_use()
|
||||
return FALSE
|
||||
|
||||
|
||||
/datum/visibility_chunk/cult/getVisibleTurfsForViewpoint(var/viewpoint)
|
||||
var/obj/effect/rune/rune = viewpoint
|
||||
if (rune)
|
||||
return rune.can_see()
|
||||
var/obj/cult_viewpoint/cvp = viewpoint
|
||||
if (cvp)
|
||||
return cvp.can_see()
|
||||
return null
|
||||
|
||||
|
||||
/datum/visibility_chunk/cult/findNearbyViewpoints()
|
||||
for(var/obj/cult_viewpoint/vp in range(16, locate(x + 8, y + 8, z)))
|
||||
if(vp.can_use())
|
||||
viewpoints += vp
|
||||
for(var/obj/effect/rune/rune in range(16, locate(x + 8, y + 8, z)))
|
||||
viewpoints += rune
|
||||
|
||||
|
||||
/datum/visibility_network/cult
|
||||
ChunkType = /datum/visibility_chunk/cult
|
||||
|
||||
|
||||
/datum/visibility_network/cult/validViewpoint(var/viewpoint)
|
||||
if (isCultRune(viewpoint) || isCultViewpoint(viewpoint))
|
||||
return viewpoint:can_use()
|
||||
return FALSE
|
||||
|
||||
/datum/visibility_network/cult/getViewpointFromMob(var/mob/currentMob)
|
||||
for(var/obj/cult_viewpoint/currentView in currentMob)
|
||||
return currentView
|
||||
return FALSE
|
||||
|
||||
|
||||
/datum/visibility_interface/cult
|
||||
chunk_type = /datum/visibility_chunk/cult
|
||||
|
||||
|
||||
/*
|
||||
RUNE JUNK
|
||||
|
||||
@@ -52,7 +52,6 @@ mob/spirit/proc/Spirit_Move(direct)
|
||||
mob/spirit/setLoc(var/T)
|
||||
T = get_turf(T)
|
||||
loc = T
|
||||
cultNetwork.visibility(src)
|
||||
|
||||
mob/spirit/verb/toggle_acceleration()
|
||||
set category = "Spirit"
|
||||
|
||||
@@ -38,9 +38,6 @@ mob/spirit/New()
|
||||
|
||||
loc = pick(latejoin)
|
||||
|
||||
// hook them to the cult visibility network
|
||||
visibility_interface = new /datum/visibility_interface/cult(src)
|
||||
|
||||
// no nameless spirits
|
||||
if (!name)
|
||||
name = "Boogyman"
|
||||
|
||||
@@ -18,9 +18,6 @@ var/obj/cult_viewpoint/list/cult_viewpoints = list()
|
||||
/obj/cult_viewpoint/New(var/mob/target)
|
||||
owner = target
|
||||
//src.loc = owner
|
||||
owner.addToVisibilityNetwork(cultNetwork)
|
||||
cultNetwork.viewpoints+=src
|
||||
cultNetwork.addViewpoint(src)
|
||||
cult_viewpoints+=src
|
||||
//handle_missing_mask()
|
||||
..()
|
||||
@@ -28,10 +25,7 @@ var/obj/cult_viewpoint/list/cult_viewpoints = list()
|
||||
|
||||
/obj/cult_viewpoint/Del()
|
||||
processing_objects.Remove(src)
|
||||
cultNetwork.viewpoints-=src
|
||||
cultNetwork.removeViewpoint(src)
|
||||
cult_viewpoints-=src
|
||||
owner.removeFromVisibilityNetwork(cultNetwork)
|
||||
..()
|
||||
return
|
||||
|
||||
@@ -134,6 +128,8 @@ var/obj/cult_viewpoint/list/cult_viewpoints = list()
|
||||
|
||||
|
||||
/obj/cult_viewpoint/proc/get_display_name()
|
||||
if(istype(src,/obj/effect/rune))
|
||||
return name
|
||||
if (!owner)
|
||||
return
|
||||
if (cult_name)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
json_writer
|
||||
proc
|
||||
WriteObject(list/L)
|
||||
WriteObject(list/L, cached_data = null)
|
||||
. = "{"
|
||||
var/i = 1
|
||||
for(var/k in L)
|
||||
@@ -9,6 +9,8 @@ json_writer
|
||||
. += {"\"[k]\":[write(val)]"}
|
||||
if(i++ < L.len)
|
||||
. += ","
|
||||
if(cached_data)
|
||||
. = copytext(., 1, lentext(.)) + ",\"cached\":[cached_data]}"
|
||||
.+= "}"
|
||||
|
||||
write(val)
|
||||
|
||||
@@ -7,6 +7,6 @@ proc
|
||||
var/static/json_reader/_jsonr = new()
|
||||
return _jsonr.ReadObject(_jsonr.ScanJson(json))
|
||||
|
||||
list2json(list/L)
|
||||
list2json(list/L, var/cached_data = null)
|
||||
var/static/json_writer/_jsonw = new()
|
||||
return _jsonw.WriteObject(L)
|
||||
return _jsonw.WriteObject(L, cached_data)
|
||||
|
||||
@@ -58,6 +58,9 @@ nanoui is used to open and update nano browser uis
|
||||
var/is_auto_updating = 0
|
||||
// the current status/visibility of the ui
|
||||
var/status = STATUS_INTERACTIVE
|
||||
|
||||
var/cached_data = null
|
||||
|
||||
|
||||
// Only allow users with a certain user.stat to get updates. Defaults to 0 (concious)
|
||||
var/allowed_user_stat = 0 // -1 = ignore, 0 = alive, 1 = unconcious or alive, 2 = dead concious or alive
|
||||
@@ -370,7 +373,7 @@ nanoui is used to open and update nano browser uis
|
||||
template_data_json = list2json(templates)
|
||||
|
||||
var/list/send_data = get_send_data(initial_data)
|
||||
var/initial_data_json = list2json(send_data)
|
||||
var/initial_data_json = list2json(send_data, cached_data)
|
||||
|
||||
var/url_parameters_json = list2json(list("src" = "\ref[src]"))
|
||||
|
||||
@@ -450,6 +453,17 @@ nanoui is used to open and update nano browser uis
|
||||
var/params = "\ref[src]"
|
||||
|
||||
winset(user, window_id, "on-close=\"nanoclose [params]\"")
|
||||
|
||||
/**
|
||||
* Appends already processed json txt to the list2json proc when setting initial-data and data pushes
|
||||
* Used for data that is fucking huge like manifests and camera lists that doesn't change often.
|
||||
* And we only want to process them when they change.
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/load_cached_data(var/data)
|
||||
cached_data = data
|
||||
return
|
||||
|
||||
/**
|
||||
* Push data to an already open UI window
|
||||
@@ -464,7 +478,7 @@ nanoui is used to open and update nano browser uis
|
||||
var/list/send_data = get_send_data(data)
|
||||
|
||||
//user << list2json(data) // used for debugging
|
||||
user << output(list2params(list(list2json(send_data))),"[window_id].browser:receiveUpdateData")
|
||||
user << output(list2params(list(list2json(send_data,cached_data))),"[window_id].browser:receiveUpdateData")
|
||||
|
||||
/**
|
||||
* This Topic() proc is called whenever a user clicks on a link within a Nano UI
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
P.internal_organs = list()
|
||||
P.internal_organs += src
|
||||
H.internal_organs_by_name[name] = src
|
||||
H.internal_organs |= src
|
||||
owner = H
|
||||
return
|
||||
|
||||
@@ -196,7 +197,7 @@
|
||||
src.damage += 0.2 * process_accuracy
|
||||
//Damaged one shares the fun
|
||||
else
|
||||
var/datum/organ/internal/O = pick(owner.internal_organs_by_name)
|
||||
var/datum/organ/internal/O = pick(owner.internal_organs)
|
||||
if(O)
|
||||
O.damage += 0.2 * process_accuracy
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
src.directwired = 1
|
||||
|
||||
/obj/machinery/power/emitter/Destroy()
|
||||
message_admins("Emitter deleted at ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
|
||||
msg_admin_attack("Emitter deleted at ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
|
||||
log_game("Emitter deleted at ([x],[y],[z])")
|
||||
investigate_log("<font color='red'>deleted</font> at ([x],[y],[z])","singulo")
|
||||
..()
|
||||
|
||||
@@ -350,6 +350,6 @@ field_generator power level display
|
||||
if(O.last_warning && temp)
|
||||
if((world.time - O.last_warning) > 50) //to stop message-spam
|
||||
temp = 0
|
||||
message_admins("A singulo exists and a containment field has failed.",1)
|
||||
msg_admin_attack("A singulo exists and a containment field has failed.",1)
|
||||
investigate_log("has <font color='red'>failed</font> whilst a singulo exists.","singulo")
|
||||
O.last_warning = world.time
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
|
||||
var/obj/item/device/assembly_holder/H = W
|
||||
if (istype(H.a_left,/obj/item/device/assembly/igniter) || istype(H.a_right,/obj/item/device/assembly/igniter))
|
||||
message_admins("[key_name_admin(user)] rigged fueltank at ([loc.x],[loc.y],[loc.z]) for explosion.")
|
||||
msg_admin_attack("[key_name_admin(user)] rigged fueltank at ([loc.x],[loc.y],[loc.z]) for explosion.")
|
||||
log_game("[key_name(user)] rigged fueltank at ([loc.x],[loc.y],[loc.z]) for explosion.")
|
||||
|
||||
rig = W
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
/datum/surgery_step/brain/saw_skull
|
||||
allowed_tools = list(
|
||||
/obj/item/weapon/circular_saw = 100, \
|
||||
/obj/item/weapon/hatchet = 75
|
||||
/obj/item/weapon/hatchet = 75, \
|
||||
/obj/item/weapon/melee/arm_blade = 60 // Dr. Chang E. Ling, MD
|
||||
)
|
||||
|
||||
min_duration = 50
|
||||
@@ -67,7 +68,8 @@
|
||||
/datum/surgery_step/brain/saw_spine
|
||||
allowed_tools = list(
|
||||
/obj/item/weapon/circular_saw = 100, \
|
||||
/obj/item/weapon/hatchet = 75
|
||||
/obj/item/weapon/hatchet = 75, \
|
||||
/obj/item/weapon/melee/arm_blade = 60
|
||||
)
|
||||
|
||||
min_duration = 50
|
||||
|
||||
@@ -187,7 +187,8 @@
|
||||
/datum/surgery_step/generic/cut_limb
|
||||
allowed_tools = list(
|
||||
/obj/item/weapon/circular_saw = 100, \
|
||||
/obj/item/weapon/hatchet = 75
|
||||
/obj/item/weapon/hatchet = 75, \
|
||||
/obj/item/weapon/melee/arm_blade = 60
|
||||
)
|
||||
|
||||
min_duration = 110
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
/datum/surgery_step/ribcage/saw_ribcage
|
||||
allowed_tools = list(
|
||||
/obj/item/weapon/circular_saw = 100, \
|
||||
/obj/item/weapon/hatchet = 75
|
||||
/obj/item/weapon/hatchet = 75, \
|
||||
/obj/item/weapon/melee/arm_blade = 60
|
||||
)
|
||||
|
||||
min_duration = 50
|
||||
@@ -146,7 +147,7 @@
|
||||
user.visible_message(msg, self_msg)
|
||||
|
||||
target.op_stage.ribcage = 0
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// ALIEN EMBRYO SURGERY //
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user