mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 18:32:03 +00:00
788 lines
25 KiB
Plaintext
788 lines
25 KiB
Plaintext
var/list/ai_list = list()
|
|
|
|
//Not sure why this is necessary...
|
|
/proc/AutoUpdateAI(obj/subject)
|
|
var/is_in_use = 0
|
|
if (subject!=null)
|
|
for(var/A in ai_list)
|
|
var/mob/living/silicon/ai/M = A
|
|
if ((M.client && M.machine == subject))
|
|
is_in_use = 1
|
|
subject.attack_ai(M)
|
|
return is_in_use
|
|
|
|
|
|
/mob/living/silicon/ai
|
|
name = "AI"
|
|
icon = 'icons/mob/AI.dmi'//
|
|
icon_state = "ai"
|
|
anchored = 1 // -- TLE
|
|
density = 1
|
|
status_flags = CANSTUN|CANPARALYSE
|
|
var/list/network = list("SS13")
|
|
var/obj/machinery/camera/current = null
|
|
var/list/connected_robots = list()
|
|
var/aiRestorePowerRoutine = 0
|
|
//var/list/laws = list()
|
|
var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list())
|
|
var/viewalerts = 0
|
|
var/lawcheck[1]
|
|
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
|
|
var/custom_sprite = 0 //For our custom sprites
|
|
var/obj/item/device/camera/ai_camera/aicamera = null
|
|
//Hud stuff
|
|
|
|
//MALFUNCTION
|
|
var/datum/module_picker/malf_picker
|
|
var/processing_time = 100
|
|
var/list/datum/AI_Module/current_modules = list()
|
|
var/fire_res_on_core = 0
|
|
|
|
var/control_disabled = 0 // Set to 1 to stop AI from interacting via Click() -- TLE
|
|
var/malfhacking = 0 // More or less a copy of the above var, so that malf AIs can hack and still get new cyborgs -- NeoFite
|
|
|
|
var/obj/machinery/power/apc/malfhack = null
|
|
var/explosive = 0 //does the AI explode when it dies?
|
|
|
|
var/mob/living/silicon/ai/parent = null
|
|
var/camera_light_on = 0
|
|
var/list/obj/machinery/camera/lit_cameras = list()
|
|
|
|
var/datum/trackable/track = new()
|
|
|
|
var/last_paper_seen = null
|
|
var/can_shunt = 1
|
|
var/last_announcement = ""
|
|
|
|
/mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = 0)
|
|
var/list/possibleNames = ai_names
|
|
|
|
var/pickedName = null
|
|
while(!pickedName)
|
|
pickedName = pick(ai_names)
|
|
for (var/mob/living/silicon/ai/A in mob_list)
|
|
if (A.real_name == pickedName && possibleNames.len > 1) //fixing the theoretically possible infinite loop
|
|
possibleNames -= pickedName
|
|
pickedName = null
|
|
|
|
real_name = pickedName
|
|
name = real_name
|
|
anchored = 1
|
|
canmove = 0
|
|
density = 1
|
|
loc = loc
|
|
|
|
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1"))
|
|
|
|
proc_holder_list = new()
|
|
|
|
//Determine the AI's lawset
|
|
if(L && istype(L,/datum/ai_laws)) src.laws = L
|
|
else src.laws = getLawset(src)
|
|
|
|
verbs += /mob/living/silicon/ai/proc/show_laws_verb
|
|
|
|
aiPDA = new/obj/item/device/pda/ai(src)
|
|
aiPDA.owner = name
|
|
aiPDA.ownjob = "AI"
|
|
aiPDA.name = name + " (" + aiPDA.ownjob + ")"
|
|
|
|
aiMulti = new(src)
|
|
aicamera = new/obj/item/device/camera/ai_camera(src)
|
|
|
|
if (istype(loc, /turf))
|
|
verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \
|
|
/mob/living/silicon/ai/proc/ai_statuschange, \
|
|
/mob/living/silicon/ai/proc/ai_hologram_change, \
|
|
/mob/living/silicon/ai/proc/toggle_camera_light)
|
|
|
|
if(!safety)//Only used by AIize() to successfully spawn an AI.
|
|
if (!B)//If there is no player/brain inside.
|
|
new/obj/structure/AIcore/deactivated(loc)//New empty terminal.
|
|
del(src)//Delete AI.
|
|
return
|
|
else
|
|
if (B.brainmob.mind)
|
|
B.brainmob.mind.transfer_to(src)
|
|
|
|
src << "<B>You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras).</B>"
|
|
src << "<B>To look at other parts of the station, click on yourself to get a camera menu.</B>"
|
|
src << "<B>While observing through a camera, you can use most (networked) devices which you can see, such as computers, APCs, intercoms, doors, etc.</B>"
|
|
src << "To use something, simply click on it."
|
|
src << "Use say :b to speak to your cyborgs through binary."
|
|
if (!(ticker && ticker.mode && (mind in ticker.mode.malf_ai)))
|
|
show_laws()
|
|
src << "<b>These laws may be changed by other players, or by you being the traitor.</b>"
|
|
|
|
job = "AI"
|
|
ai_list += src
|
|
..()
|
|
return
|
|
|
|
/mob/living/silicon/ai/Destroy()
|
|
ai_list -= src
|
|
..()
|
|
|
|
/mob/living/silicon/ai/verb/pick_icon()
|
|
set category = "AI Commands"
|
|
set name = "Set AI Core Display"
|
|
if(stat || aiRestorePowerRoutine)
|
|
return
|
|
/* Jesus christ, more of this shit?
|
|
if(!custom_sprite) //Check to see if custom sprite time, checking the appopriate file to change a var
|
|
var/file = file2text("config/custom_sprites.txt")
|
|
var/lines = text2list(file, "\n")
|
|
|
|
for(var/line in lines)
|
|
// split & clean up
|
|
var/list/Entry = text2list(line, "-")
|
|
for(var/i = 1 to Entry.len)
|
|
Entry[i] = trim(Entry[i])
|
|
|
|
if(Entry.len < 2)
|
|
continue;
|
|
|
|
if(Entry[1] == src.ckey && Entry[2] == src.real_name)
|
|
custom_sprite = 1 //They're in the list? Custom sprite time
|
|
icon = 'icons/mob/custom-synthetic.dmi'
|
|
*/
|
|
//if(icon_state == initial(icon_state))
|
|
var/icontype = ""
|
|
/* Nuked your hidden shit.*/
|
|
if (custom_sprite == 1) icontype = ("Custom")//automagically selects custom sprite if one is available
|
|
else icontype = input("Select an icon!", "AI", null, null) in list("Monochrome", "Blue", "Inverted", "Text", "Smiley", "Angry", "Dorf", "Matrix", "Bliss", "Firewall", "Green", "Red", "Broken Output", "Triumvirate", "Triumvirate Static", "Searif", "Ravensdale", "Serithi", "Static", "Wasp", "Robert House", "Red October", "Fabulous", "Girl", "Girl Malf", "Boy", "Boy Malf", "Four-Leaf")
|
|
switch(icontype)
|
|
if("Custom") icon_state = "[src.ckey]-ai"
|
|
if("Clown") icon_state = "ai-clown2"
|
|
if("Monochrome") icon_state = "ai-mono"
|
|
if("Inverted") icon_state = "ai-u"
|
|
if("Firewall") icon_state = "ai-magma"
|
|
if("Green") icon_state = "ai-wierd"
|
|
if("Red") icon_state = "ai-malf"
|
|
if("Broken Output") icon_state = "ai-static"
|
|
if("Text") icon_state = "ai-text"
|
|
if("Smiley") icon_state = "ai-smiley"
|
|
if("Matrix") icon_state = "ai-matrix"
|
|
if("Angry") icon_state = "ai-angryface"
|
|
if("Dorf") icon_state = "ai-dorf"
|
|
if("Bliss") icon_state = "ai-bliss"
|
|
if("Triumvirate") icon_state = "ai-triumvirate"
|
|
if("Triumvirate Static") icon_state = "ai-triumvirate-malf"
|
|
if("Searif") icon_state = "ai-searif"
|
|
if("Ravensdale") icon_state = "ai-ravensdale"
|
|
if("Serithi") icon_state = "ai-serithi"
|
|
if("Static") icon_state = "ai-fuzz"
|
|
if("Wasp") icon_state = "ai-wasp"
|
|
if("Robert House") icon_state = "ai-president"
|
|
if("Red October") icon_state = "ai-soviet"
|
|
if("Girl") icon_state = "ai-girl"
|
|
if("Girl Malf") icon_state = "ai-girl-malf"
|
|
if("Boy") icon_state = "ai-boy"
|
|
if("Boy Malf") icon_state = "ai-boy-malf"
|
|
if("Fabulous") icon_state = "ai-fabulous"
|
|
if("Four-Leaf") icon_state = "ai-4chan"
|
|
else icon_state = "ai"
|
|
//else
|
|
//usr <<"You can only change your display once!"
|
|
//return
|
|
|
|
|
|
// displays the malf_ai information if the AI is the malf
|
|
/mob/living/silicon/ai/show_malf_ai()
|
|
if(ticker.mode.name == "AI malfunction")
|
|
var/datum/game_mode/malfunction/malf = ticker.mode
|
|
for (var/datum/mind/malfai in malf.malf_ai)
|
|
if (mind == malfai) // are we the evil one?
|
|
if (malf.apcs >= 3)
|
|
stat(null, "Time until station control secured: [max(malf.AI_win_timeleft/(malf.apcs/3), 0)] seconds")
|
|
|
|
|
|
/mob/living/silicon/ai/proc/ai_alerts()
|
|
|
|
// AUTOFIXED BY fix_string_idiocy.py
|
|
// C:\Users\Rob\Documents\Projects\vgstation13\code\modules\mob\living\silicon\ai\ai.dm:195: var/dat = "<HEAD><TITLE>Current Station Alerts</TITLE><META HTTP-EQUIV='Refresh' CONTENT='10'></HEAD><BODY>\n"
|
|
var/dat = {"<HEAD><TITLE>Current Station Alerts</TITLE><META HTTP-EQUIV='Refresh' CONTENT='10'></HEAD><BODY>\n
|
|
<A HREF='?src=\ref[src];mach_close=aialerts'>Close</A><BR><BR>"}
|
|
// END AUTOFIX
|
|
for (var/cat in alarms)
|
|
dat += text("<B>[]</B><BR>\n", cat)
|
|
var/list/L = alarms[cat]
|
|
if (L.len)
|
|
for (var/alarm in L)
|
|
var/list/alm = L[alarm]
|
|
var/area/A = alm[1]
|
|
var/C = alm[2]
|
|
var/list/sources = alm[3]
|
|
dat += "<NOBR>"
|
|
if (C && istype(C, /list))
|
|
var/dat2 = ""
|
|
for (var/obj/machinery/camera/I in C)
|
|
dat2 += text("[]<A HREF=?src=\ref[];switchcamera=\ref[]>[]</A>", (dat2=="") ? "" : " | ", src, I, I.c_tag)
|
|
dat += text("-- [] ([])", A.name, (dat2!="") ? dat2 : "No Camera")
|
|
else if (C && istype(C, /obj/machinery/camera))
|
|
var/obj/machinery/camera/Ctmp = C
|
|
dat += text("-- [] (<A HREF=?src=\ref[];switchcamera=\ref[]>[]</A>)", A.name, src, C, Ctmp.c_tag)
|
|
else
|
|
dat += text("-- [] (No Camera)", A.name)
|
|
if (sources.len > 1)
|
|
dat += text("- [] sources", sources.len)
|
|
dat += "</NOBR><BR>\n"
|
|
else
|
|
dat += "-- All Systems Nominal<BR>\n"
|
|
dat += "<BR>\n"
|
|
|
|
viewalerts = 1
|
|
src << browse(dat, "window=aialerts&can_close=0")
|
|
|
|
// this verb lets the ai see the stations manifest
|
|
/mob/living/silicon/ai/proc/ai_roster()
|
|
show_station_manifest()
|
|
|
|
/mob/living/silicon/ai/proc/ai_call_shuttle()
|
|
if(src.stat == 2)
|
|
src << "You can't call the shuttle because you are dead!"
|
|
return
|
|
if(istype(usr,/mob/living/silicon/ai))
|
|
var/mob/living/silicon/ai/AI = src
|
|
if(AI.control_disabled)
|
|
usr << "Wireless control is disabled!"
|
|
return
|
|
|
|
var/confirm = alert("Are you sure you want to call the shuttle?", "Confirm Shuttle Call", "Yes", "No")
|
|
|
|
if(confirm == "Yes")
|
|
call_shuttle_proc(src)
|
|
|
|
// hack to display shuttle timer
|
|
if(emergency_shuttle.online)
|
|
var/obj/machinery/computer/communications/C = locate() in machines
|
|
if(C)
|
|
C.post_status("shuttle")
|
|
|
|
return
|
|
|
|
/mob/living/silicon/ai/proc/ai_cancel_call()
|
|
set category = "AI Commands"
|
|
if(src.stat == 2)
|
|
src << "You can't send the shuttle back because you are dead!"
|
|
return
|
|
if(istype(usr,/mob/living/silicon/ai))
|
|
var/mob/living/silicon/ai/AI = src
|
|
if(AI.control_disabled)
|
|
src << "Wireless control is disabled!"
|
|
return
|
|
recall_shuttle(src)
|
|
return
|
|
|
|
/mob/living/silicon/ai/check_eye(var/mob/user as mob)
|
|
if (!current)
|
|
return null
|
|
user.reset_view(current)
|
|
return 1
|
|
|
|
/mob/living/silicon/ai/blob_act()
|
|
if(flags & INVULNERABLE)
|
|
return
|
|
if (stat != 2)
|
|
adjustBruteLoss(60)
|
|
updatehealth()
|
|
return 1
|
|
return 0
|
|
|
|
/mob/living/silicon/ai/restrained()
|
|
return 0
|
|
|
|
/mob/living/silicon/ai/emp_act(severity)
|
|
if(flags & INVULNERABLE)
|
|
return
|
|
|
|
if (prob(30))
|
|
switch(pick(1,2))
|
|
if(1)
|
|
view_core()
|
|
if(2)
|
|
ai_call_shuttle()
|
|
..()
|
|
|
|
/mob/living/silicon/ai/ex_act(severity)
|
|
if(flags & INVULNERABLE)
|
|
return
|
|
|
|
if(!blinded)
|
|
flick("flash", flash)
|
|
|
|
switch(severity)
|
|
if(1.0)
|
|
if (stat != 2)
|
|
adjustBruteLoss(100)
|
|
adjustFireLoss(100)
|
|
if(2.0)
|
|
if (stat != 2)
|
|
adjustBruteLoss(60)
|
|
adjustFireLoss(60)
|
|
if(3.0)
|
|
if (stat != 2)
|
|
adjustBruteLoss(30)
|
|
|
|
updatehealth()
|
|
|
|
|
|
/mob/living/silicon/ai/Topic(href, href_list)
|
|
if(usr != src)
|
|
return
|
|
..()
|
|
if (href_list["mach_close"])
|
|
if (href_list["mach_close"] == "aialerts")
|
|
viewalerts = 0
|
|
var/t1 = text("window=[]", href_list["mach_close"])
|
|
unset_machine()
|
|
src << browse(null, t1)
|
|
if (href_list["switchcamera"])
|
|
switchCamera(locate(href_list["switchcamera"])) in cameranet.cameras
|
|
if (href_list["showalerts"])
|
|
ai_alerts()
|
|
|
|
if(href_list["show_paper"])
|
|
if(last_paper_seen)
|
|
src << browse(last_paper_seen, "window=show_paper")
|
|
//Carn: holopad requests
|
|
if (href_list["jumptoholopad"])
|
|
var/obj/machinery/hologram/holopad/H = locate(href_list["jumptoholopad"])
|
|
if(stat == CONSCIOUS)
|
|
if(H)
|
|
H.attack_ai(src) //may as well recycle
|
|
else
|
|
src << "<span class='notice'>Unable to locate the holopad.</span>"
|
|
|
|
if(href_list["say_word"])
|
|
play_vox_word(href_list["say_word"], null, src)
|
|
return
|
|
|
|
if (href_list["lawc"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite
|
|
var/L = text2num(href_list["lawc"])
|
|
switch(lawcheck[L+1])
|
|
if ("Yes") lawcheck[L+1] = "No"
|
|
if ("No") lawcheck[L+1] = "Yes"
|
|
// src << text ("Switching Law [L]'s report status to []", lawcheck[L+1])
|
|
checklaws()
|
|
|
|
if (href_list["lawi"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite
|
|
var/L = text2num(href_list["lawi"])
|
|
switch(ioncheck[L])
|
|
if ("Yes") ioncheck[L] = "No"
|
|
if ("No") ioncheck[L] = "Yes"
|
|
// src << text ("Switching Law [L]'s report status to []", lawcheck[L+1])
|
|
checklaws()
|
|
|
|
if (href_list["laws"]) // With how my law selection code works, I changed statelaws from a verb to a proc, and call it through my law selection panel. --NeoFite
|
|
statelaws()
|
|
|
|
if (href_list["track"])
|
|
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"]) in mob_list
|
|
var/mob/living/silicon/ai/A = locate(href_list["track2"]) in mob_list
|
|
if(A && target)
|
|
|
|
A.cameraFollow = target
|
|
A << text("Now tracking [] on camera.", target.name)
|
|
if (usr.machine == null)
|
|
usr.machine = usr
|
|
|
|
while (src.cameraFollow == target)
|
|
usr << "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)
|
|
continue
|
|
|
|
return
|
|
|
|
return
|
|
|
|
/mob/living/silicon/ai/meteorhit(obj/O as obj)
|
|
if(flags & INVULNERABLE)
|
|
return
|
|
for(var/mob/M in viewers(src, null))
|
|
M.show_message(text("\red [] has been hit by []", src, O), 1)
|
|
//Foreach goto(19)
|
|
if (health > 0)
|
|
adjustBruteLoss(30)
|
|
if ((O.icon_state == "flaming"))
|
|
adjustFireLoss(40)
|
|
updatehealth()
|
|
return
|
|
|
|
/mob/living/silicon/ai/bullet_act(var/obj/item/projectile/Proj)
|
|
..(Proj)
|
|
updatehealth()
|
|
return 2
|
|
|
|
/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M as mob)
|
|
if (!ticker)
|
|
M << "You cannot attack people before the game has started."
|
|
return
|
|
|
|
if (istype(loc, /turf) && istype(loc.loc, /area/start))
|
|
M << "No attacking people at spawn, you jackass."
|
|
return
|
|
|
|
switch(M.a_intent)
|
|
|
|
if ("help")
|
|
for(var/mob/O in viewers(src, null))
|
|
if ((O.client && !( O.blinded )))
|
|
O.show_message(text("\blue [M] caresses [src]'s plating with its scythe like arm."), 1)
|
|
|
|
else //harm
|
|
var/damage = rand(10, 20)
|
|
if (prob(90))
|
|
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
|
|
for(var/mob/O in viewers(src, null))
|
|
if ((O.client && !( O.blinded )))
|
|
O.show_message(text("\red <B>[] has slashed at []!</B>", M, src), 1)
|
|
if(prob(8))
|
|
flick("noise", flash)
|
|
adjustBruteLoss(damage)
|
|
updatehealth()
|
|
else
|
|
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1)
|
|
for(var/mob/O in viewers(src, null))
|
|
if ((O.client && !( O.blinded )))
|
|
O.show_message(text("\red <B>[] took a swipe at []!</B>", M, src), 1)
|
|
return
|
|
|
|
/mob/living/silicon/ai/attack_hand(mob/living/carbon/M as mob)
|
|
if(ishuman(M))//Checks to see if they are ninja
|
|
if(istype(M:gloves, /obj/item/clothing/gloves/space_ninja)&&M:gloves:candrain&&!M:gloves:draining)
|
|
if(M:wear_suit:s_control)
|
|
M:wear_suit:transfer_ai("AICORE", "NINJASUIT", src, M)
|
|
else
|
|
M << "\red <b>ERROR</b>: \black Remote access channel disabled."
|
|
return
|
|
|
|
|
|
/mob/living/silicon/ai/attack_animal(mob/living/simple_animal/M as mob)
|
|
if(M.melee_damage_upper == 0)
|
|
M.emote("[M.friendly] [src]")
|
|
else
|
|
if(M.attack_sound)
|
|
playsound(loc, M.attack_sound, 50, 1, 1)
|
|
for(var/mob/O in viewers(src, null))
|
|
O.show_message("\red <B>[M]</B> [M.attacktext] [src]!", 1)
|
|
M.attack_log += text("\[[time_stamp()]\] <font color='red'>attacked [src.name] ([src.ckey])</font>")
|
|
src.attack_log += text("\[[time_stamp()]\] <font color='orange'>was attacked by [M.name] ([M.ckey])</font>")
|
|
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
|
adjustBruteLoss(damage)
|
|
updatehealth()
|
|
|
|
/mob/living/silicon/ai/reset_view(atom/A)
|
|
if (camera_light_on)
|
|
light_cameras()
|
|
if(istype(A,/obj/machinery/camera))
|
|
current = A
|
|
..()
|
|
|
|
|
|
/mob/living/silicon/ai/proc/switchCamera(var/obj/machinery/camera/C)
|
|
|
|
src.cameraFollow = null
|
|
|
|
if (!C || stat == 2) //C.can_use())
|
|
return 0
|
|
|
|
if(!src.eyeobj)
|
|
view_core()
|
|
return
|
|
// ok, we're alive, camera is good and in our network...
|
|
eyeobj.setLoc(get_turf(C))
|
|
//machine = src
|
|
|
|
return 1
|
|
|
|
/mob/living/silicon/ai/triggerAlarm(var/class, area/A, var/O, var/alarmsource)
|
|
if (stat == 2)
|
|
return 1
|
|
var/list/L = alarms[class]
|
|
for (var/I in L)
|
|
if (I == A.name)
|
|
var/list/alarm = L[I]
|
|
var/list/sources = alarm[3]
|
|
if (!(alarmsource in sources))
|
|
sources += alarmsource
|
|
return 1
|
|
var/obj/machinery/camera/C = null
|
|
var/list/CL = null
|
|
if (O && istype(O, /list))
|
|
CL = O
|
|
if (CL.len == 1)
|
|
C = CL[1]
|
|
else if (O && istype(O, /obj/machinery/camera))
|
|
C = O
|
|
L[A.name] = list(A, (C) ? C : O, list(alarmsource))
|
|
if (O)
|
|
if (C && C.can_use())
|
|
queueAlarm("--- [class] alarm detected in [A.name]! (<A HREF=?src=\ref[src];switchcamera=\ref[C]>[C.c_tag]</A>)", class)
|
|
else if (CL && CL.len)
|
|
var/foo = 0
|
|
var/dat2 = ""
|
|
for (var/obj/machinery/camera/I in CL)
|
|
dat2 += text("[]<A HREF=?src=\ref[];switchcamera=\ref[]>[]</A>", (!foo) ? "" : " | ", src, I, I.c_tag) //I'm not fixing this shit...
|
|
foo = 1
|
|
queueAlarm(text ("--- [] alarm detected in []! ([])", class, A.name, dat2), class)
|
|
else
|
|
queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, A.name), class)
|
|
else
|
|
queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, A.name), class)
|
|
if (viewalerts) ai_alerts()
|
|
return 1
|
|
|
|
/mob/living/silicon/ai/cancelAlarm(var/class, area/A as area, obj/origin)
|
|
var/list/L = alarms[class]
|
|
var/cleared = 0
|
|
for (var/I in L)
|
|
if (I == A.name)
|
|
var/list/alarm = L[I]
|
|
var/list/srcs = alarm[3]
|
|
if (origin in srcs)
|
|
srcs -= origin
|
|
if (srcs.len == 0)
|
|
cleared = 1
|
|
L -= I
|
|
if (cleared)
|
|
queueAlarm(text("--- [] alarm in [] has been cleared.", class, A.name), class, 0)
|
|
if (viewalerts) ai_alerts()
|
|
return !cleared
|
|
|
|
/mob/living/silicon/ai/cancel_camera()
|
|
src.view_core()
|
|
|
|
|
|
//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 = "Jump To Network"
|
|
unset_machine()
|
|
src.cameraFollow = null
|
|
var/cameralist[0]
|
|
|
|
if(usr.stat == 2)
|
|
usr << "You can't change your camera network because you are dead!"
|
|
return
|
|
|
|
var/mob/living/silicon/ai/U = usr
|
|
|
|
for (var/obj/machinery/camera/C in cameranet.cameras)
|
|
if(!C.can_use())
|
|
continue
|
|
|
|
var/list/tempnetwork = difflist(C.network,RESTRICTED_CAMERA_NETWORKS,1)
|
|
if(tempnetwork.len)
|
|
for(var/i in tempnetwork)
|
|
cameralist[i] = i
|
|
var/old_network = network
|
|
network = input(U, "Which network would you like to view?") as null|anything in cameralist
|
|
|
|
if(!U.eyeobj)
|
|
U.view_core()
|
|
return
|
|
|
|
if(isnull(network))
|
|
network = old_network // If nothing is selected
|
|
else
|
|
for(var/obj/machinery/camera/C in cameranet.cameras)
|
|
if(!C.can_use())
|
|
continue
|
|
if(network in C.network)
|
|
U.eyeobj.setLoc(get_turf(C))
|
|
break
|
|
src << "\blue Switched to [network] camera network."
|
|
//End of code by Mord_Sith
|
|
|
|
|
|
/mob/living/silicon/ai/proc/choose_modules()
|
|
set category = "Malfunction"
|
|
set name = "Choose Module"
|
|
|
|
malf_picker.use(src)
|
|
|
|
/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/M in machines) //change status
|
|
if(istype(M, /obj/machinery/ai_status_display))
|
|
var/obj/machinery/ai_status_display/AISD = M
|
|
AISD.emotion = emote
|
|
//if Friend Computer, change ALL displays
|
|
else if(istype(M, /obj/machinery/status_display))
|
|
|
|
var/obj/machinery/status_display/SD = M
|
|
if(emote=="Friend Computer")
|
|
SD.friendc = 1
|
|
else
|
|
SD.friendc = 0
|
|
return
|
|
|
|
//I am the icon meister. Bow fefore me. //>fefore
|
|
/mob/living/silicon/ai/proc/ai_hologram_change()
|
|
set name = "Change Hologram"
|
|
set desc = "Change the default hologram available to AI to something else."
|
|
set category = "AI Commands"
|
|
|
|
var/input
|
|
if(alert("Would you like to select a hologram based on a crew member or switch to unique avatar?",,"Crew Member","Unique")=="Crew Member")
|
|
|
|
var/personnel_list[] = list()
|
|
|
|
for(var/datum/data/record/t in data_core.locked)//Look in data core locked.
|
|
personnel_list["[t.fields["name"]]: [t.fields["rank"]]"] = t.fields["image"]//Pull names, rank, and image.
|
|
|
|
if(personnel_list.len)
|
|
input = input("Select a crew member:") as null|anything in personnel_list
|
|
var/icon/character_icon = personnel_list[input]
|
|
if(character_icon)
|
|
del(holo_icon)//Clear old icon so we're not storing it in memory.
|
|
holo_icon = getHologramIcon(icon(character_icon))
|
|
else
|
|
alert("No suitable records found. Aborting.")
|
|
|
|
else
|
|
var/icon_list[] = list(
|
|
"Default",
|
|
"Floating face",
|
|
"Cortano",
|
|
"Spoopy",
|
|
"343",
|
|
"Auto",
|
|
"Four-Leaf",
|
|
"Yotsuba",
|
|
"Girl",
|
|
"Boy",
|
|
"SHODAN"
|
|
)
|
|
input = input("Please select a hologram:") as null|anything in icon_list
|
|
if(input)
|
|
del(holo_icon)
|
|
switch(input)
|
|
if("Default")
|
|
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1"))
|
|
if("Floating face")
|
|
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo2"))
|
|
if("Cortano")
|
|
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo3"))
|
|
if("Spoopy")
|
|
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo4"))
|
|
if("343")
|
|
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo5"))
|
|
if("Auto")
|
|
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo6"))
|
|
if("Four-Leaf")
|
|
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo7"))
|
|
if("Yotsuba")
|
|
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo8"))
|
|
if("Girl")
|
|
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo9"))
|
|
if("Boy")
|
|
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo10"))
|
|
if("SHODAN")
|
|
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo11"))
|
|
|
|
return
|
|
|
|
/mob/living/silicon/ai/proc/corereturn()
|
|
set category = "Malfunction"
|
|
set name = "Return to Main Core"
|
|
|
|
var/obj/machinery/power/apc/apc = src.loc
|
|
if(!istype(apc))
|
|
src << "\blue You are already in your Main Core."
|
|
return
|
|
apc.malfvacate()
|
|
|
|
//Toggles the luminosity and applies it by re-entereing the camera.
|
|
/mob/living/silicon/ai/proc/toggle_camera_light()
|
|
if(stat != CONSCIOUS)
|
|
return
|
|
|
|
camera_light_on = !camera_light_on
|
|
|
|
if (!camera_light_on)
|
|
src << "Camera lights deactivated."
|
|
|
|
for (var/obj/machinery/camera/C in lit_cameras)
|
|
C.SetLuminosity(0)
|
|
lit_cameras = list()
|
|
|
|
return
|
|
|
|
light_cameras()
|
|
|
|
src << "Camera lights activated."
|
|
return
|
|
|
|
//AI_CAMERA_LUMINOSITY
|
|
|
|
/mob/living/silicon/ai/proc/light_cameras()
|
|
var/list/obj/machinery/camera/add = list()
|
|
var/list/obj/machinery/camera/remove = list()
|
|
var/list/obj/machinery/camera/visible = list()
|
|
for (var/datum/camerachunk/CC in eyeobj.visibleCameraChunks)
|
|
for (var/obj/machinery/camera/C in CC.cameras)
|
|
if (!C.can_use() || C.light_disabled || get_dist(C, eyeobj) > 7)
|
|
continue
|
|
visible |= C
|
|
|
|
add = visible - lit_cameras
|
|
remove = lit_cameras - visible
|
|
|
|
for (var/obj/machinery/camera/C in remove)
|
|
C.SetLuminosity(0)
|
|
lit_cameras -= C
|
|
for (var/obj/machinery/camera/C in add)
|
|
C.SetLuminosity(AI_CAMERA_LUMINOSITY)
|
|
lit_cameras |= C
|
|
|
|
|
|
/mob/living/silicon/ai/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
|
if(istype(W, /obj/item/weapon/wrench))
|
|
if(anchored)
|
|
user.visible_message("\blue \The [user] starts to unbolt \the [src] from the plating...")
|
|
if(!do_after(user,40))
|
|
user.visible_message("\blue \The [user] decides not to unbolt \the [src].")
|
|
return
|
|
user.visible_message("\blue \The [user] finishes unfastening \the [src]!")
|
|
anchored = 0
|
|
return
|
|
else
|
|
user.visible_message("\blue \The [user] starts to bolt \the [src] to the plating...")
|
|
if(!do_after(user,40))
|
|
user.visible_message("\blue \The [user] decides not to bolt \the [src].")
|
|
return
|
|
user.visible_message("\blue \The [user] finishes fastening down \the [src]!")
|
|
anchored = 1
|
|
return
|
|
else
|
|
return ..()
|
|
|
|
|
|
/mob/living/silicon/ai/get_multitool(var/active_only=0)
|
|
return aiMulti
|
|
|
|
// An AI doesn't become inoperable until -100% (or whatever config.health_threshold_dead is set to)
|
|
/mob/living/silicon/ai/system_integrity()
|
|
return (health - config.health_threshold_dead) / 2
|