mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-15 04:32:42 +00:00
771 lines
24 KiB
Plaintext
771 lines
24 KiB
Plaintext
#define AI_CHECK_WIRELESS 1
|
|
#define AI_CHECK_RADIO 2
|
|
|
|
var/list/ai_list = list()
|
|
var/list/ai_verbs_default = list(
|
|
/mob/living/silicon/ai/proc/ai_alerts,
|
|
/mob/living/silicon/ai/proc/ai_announcement,
|
|
/mob/living/silicon/ai/proc/ai_call_shuttle,
|
|
// /mob/living/silicon/ai/proc/ai_recall_shuttle,
|
|
/mob/living/silicon/ai/proc/ai_camera_track,
|
|
/mob/living/silicon/ai/proc/ai_camera_list,
|
|
/mob/living/silicon/ai/proc/ai_goto_location,
|
|
/mob/living/silicon/ai/proc/ai_remove_location,
|
|
/mob/living/silicon/ai/proc/ai_hologram_change,
|
|
/mob/living/silicon/ai/proc/ai_network_change,
|
|
/mob/living/silicon/ai/proc/ai_roster,
|
|
/mob/living/silicon/ai/proc/ai_statuschange,
|
|
/mob/living/silicon/ai/proc/ai_store_location,
|
|
/mob/living/silicon/ai/proc/ai_checklaws,
|
|
/mob/living/silicon/ai/proc/control_integrated_radio,
|
|
/mob/living/silicon/ai/proc/core,
|
|
/mob/living/silicon/ai/proc/pick_icon,
|
|
/mob/living/silicon/ai/proc/sensor_mode,
|
|
/mob/living/silicon/ai/proc/show_laws_verb,
|
|
/mob/living/silicon/ai/proc/toggle_acceleration,
|
|
/mob/living/silicon/ai/proc/toggle_camera_light
|
|
)
|
|
|
|
//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
|
|
shouldnt_see = list(/obj/effect/rune)
|
|
var/list/network = list("SS13")
|
|
var/obj/machinery/camera/camera = null
|
|
var/list/connected_robots = list()
|
|
var/aiRestorePowerRoutine = 0
|
|
var/viewalerts = 0
|
|
var/icon/holo_icon//Default is assigned when AI is created.
|
|
var/obj/item/device/pda/ai/aiPDA = null
|
|
var/obj/item/device/multitool/aiMulti = null
|
|
var/obj/item/device/radio/headset/heads/ai_integrated/aiRadio = null
|
|
var/custom_sprite = 0 //For our custom sprites
|
|
//Hud stuff
|
|
|
|
//MALFUNCTION
|
|
var/datum/AI_Module/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/apc_override = 0 //hack for letting the AI use its APC even when visionless
|
|
var/camera_light_on = 0 //Defines if the AI toggled the light on the camera it's looking through.
|
|
var/datum/trackable/track = null
|
|
var/last_announcement = ""
|
|
var/datum/announcement/priority/announcement
|
|
|
|
/mob/living/silicon/ai/proc/add_ai_verbs()
|
|
src.verbs |= ai_verbs_default
|
|
|
|
/mob/living/silicon/ai/proc/remove_ai_verbs()
|
|
src.verbs -= ai_verbs_default
|
|
|
|
/mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = 0)
|
|
announcement = new()
|
|
announcement.title = "A.I. Announcement"
|
|
announcement.announcement_type = "A.I. Announcement"
|
|
announcement.newscast = 1
|
|
|
|
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
|
|
|
|
aiPDA = new/obj/item/device/pda/ai(src)
|
|
SetName(pickedName)
|
|
anchored = 1
|
|
canmove = 0
|
|
density = 1
|
|
loc = loc
|
|
|
|
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1"))
|
|
|
|
proc_holder_list = new()
|
|
|
|
if(L)
|
|
if (istype(L, /datum/ai_laws))
|
|
laws = L
|
|
else
|
|
laws = new base_law_type
|
|
|
|
aiMulti = new(src)
|
|
aiRadio = new(src)
|
|
common_radio = aiRadio
|
|
aiRadio.myAi = src
|
|
additional_law_channels += "Binary"
|
|
additional_law_channels += "Holopad"
|
|
|
|
aiCamera = new/obj/item/device/camera/siliconcam/ai_camera(src)
|
|
|
|
if (istype(loc, /turf))
|
|
add_ai_verbs(src)
|
|
|
|
//Languages
|
|
add_language("Robot Talk", 1)
|
|
add_language("Galactic Common", 1)
|
|
add_language("Sol Common", 0)
|
|
add_language("Sinta'unathi", 0)
|
|
add_language("Siik'tajr", 0)
|
|
add_language("Skrellian", 0)
|
|
add_language("Tradeband", 1)
|
|
add_language("Gutter", 0)
|
|
|
|
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)
|
|
|
|
on_mob_init()
|
|
|
|
spawn(5)
|
|
new /obj/machinery/ai_powersupply(src)
|
|
|
|
|
|
hud_list[HEALTH_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
|
hud_list[STATUS_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
|
hud_list[ID_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
|
hud_list[WANTED_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
|
hud_list[IMPLOYAL_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
|
hud_list[IMPCHEM_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
|
hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
|
hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
|
|
|
ai_list += src
|
|
..()
|
|
return
|
|
|
|
/mob/living/silicon/ai/proc/on_mob_init()
|
|
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. Use say :h to speak from an active holopad."
|
|
src << "For department channels, use the following say commands:"
|
|
|
|
var/radio_text = ""
|
|
for(var/i = 1 to common_radio.channels.len)
|
|
var/channel = common_radio.channels[i]
|
|
var/key = get_radio_key_from_channel(channel)
|
|
radio_text += "[key] - [channel]"
|
|
if(i != common_radio.channels.len)
|
|
radio_text += ", "
|
|
|
|
src << radio_text
|
|
|
|
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"
|
|
|
|
/mob/living/silicon/ai/Del()
|
|
ai_list -= src
|
|
..()
|
|
|
|
/mob/living/silicon/ai/pointed(atom/A as mob|obj|turf in view())
|
|
set popup_menu = 0
|
|
set src = usr.contents
|
|
return 0
|
|
|
|
/mob/living/silicon/ai/proc/system_integrity()
|
|
return (health-config.health_threshold_dead)/2
|
|
|
|
// this function shows the health of the pAI in the Status panel
|
|
/mob/living/silicon/ai/show_system_integrity()
|
|
// An AI doesn't become inoperable until -100% (or whatever config.health_threshold_dead is set to)
|
|
if(!src.stat)
|
|
stat(null, text("System integrity: [system_integrity()]%"))
|
|
else
|
|
stat(null, text("Systems nonfunctional"))
|
|
|
|
/mob/living/silicon/ai/proc/SetName(pickedName as text)
|
|
real_name = pickedName
|
|
name = pickedName
|
|
announcement.announcer = pickedName
|
|
if(eyeobj)
|
|
eyeobj.name = "[pickedName] (AI Eye)"
|
|
|
|
// Set ai pda name
|
|
if(aiPDA)
|
|
aiPDA.ownjob = "AI"
|
|
aiPDA.owner = pickedName
|
|
aiPDA.name = pickedName + " (" + aiPDA.ownjob + ")"
|
|
|
|
/*
|
|
The AI Power supply is a dummy object used for powering the AI since only machinery should be using power.
|
|
The alternative was to rewrite a bunch of AI code instead here we are.
|
|
*/
|
|
/obj/machinery/ai_powersupply
|
|
name="Power Supply"
|
|
active_power_usage=50000 // Station AIs use significant amounts of power. This, when combined with charged SMES should mean AI lasts for 1hr without external power.
|
|
use_power = 2
|
|
power_channel = EQUIP
|
|
var/mob/living/silicon/ai/powered_ai = null
|
|
invisibility = 100
|
|
|
|
/obj/machinery/ai_powersupply/New(var/mob/living/silicon/ai/ai=null)
|
|
powered_ai = ai
|
|
if(isnull(powered_ai))
|
|
Del()
|
|
|
|
loc = powered_ai.loc
|
|
use_power(1) // Just incase we need to wake up the power system.
|
|
|
|
..()
|
|
|
|
/obj/machinery/ai_powersupply/process()
|
|
if(!powered_ai || powered_ai.stat & DEAD)
|
|
Del()
|
|
if(!powered_ai.anchored)
|
|
loc = powered_ai.loc
|
|
use_power = 0
|
|
if(powered_ai.anchored)
|
|
use_power = 2
|
|
|
|
/mob/living/silicon/ai/proc/pick_icon()
|
|
set category = "AI Commands"
|
|
set name = "Set AI Core Display"
|
|
if(stat || aiRestorePowerRoutine)
|
|
return
|
|
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 = ""
|
|
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", "Rainbow", "Blue", "Inverted", "Text", "Smiley", "Angry", "Dorf", "Matrix", "Bliss", "Firewall", "Green", "Red", "Static", "Triumvirate", "Triumvirate Static", "Soviet", "Trapped", "Heartline", "Chatterbox")
|
|
switch(icontype)
|
|
if("Custom") icon_state = "[src.ckey]-ai"
|
|
if("Rainbow") icon_state = "ai-clown"
|
|
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-red"
|
|
if("Static") 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("Soviet") icon_state = "ai-redoctober"
|
|
if("Trapped") icon_state = "ai-hades"
|
|
if("Heartline") icon_state = "ai-heartline"
|
|
if("Chatterbox") icon_state = "ai-president"
|
|
else icon_state = "ai"
|
|
//else
|
|
//usr <<"You can only change your display once!"
|
|
//return
|
|
|
|
/mob/living/silicon/ai/proc/is_malf()
|
|
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)
|
|
return malf
|
|
return 0
|
|
|
|
// displays the malf_ai information if the AI is the malf
|
|
/mob/living/silicon/ai/show_malf_ai()
|
|
var/datum/game_mode/malfunction/malf = is_malf()
|
|
if(malf && 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()
|
|
set category = "AI Commands"
|
|
set name = "Show Alerts"
|
|
|
|
var/dat = "<HEAD><TITLE>Current Station Alerts</TITLE><META HTTP-EQUIV='Refresh' CONTENT='10'></HEAD><BODY>\n"
|
|
dat += "<A HREF='?src=\ref[src];mach_close=aialerts'>Close</A><BR><BR>"
|
|
for (var/cat in alarms)
|
|
dat += text("<B>[]</B><BR>\n", cat)
|
|
var/list/alarmlist = alarms[cat]
|
|
if (alarmlist.len)
|
|
for (var/area_name in alarmlist)
|
|
var/datum/alarm/alarm = alarmlist[area_name]
|
|
dat += "<NOBR>"
|
|
|
|
var/cameratext = ""
|
|
if (alarm.cameras)
|
|
for (var/obj/machinery/camera/I in alarm.cameras)
|
|
cameratext += text("[]<A HREF=?src=\ref[];switchcamera=\ref[]>[]</A>", (cameratext=="") ? "" : " | ", src, I, I.c_tag)
|
|
dat += text("-- [] ([])", alarm.area.name, (cameratext)? cameratext : "No Camera")
|
|
|
|
if (alarm.sources.len > 1)
|
|
dat += text(" - [] sources", alarm.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()
|
|
set category = "AI Commands"
|
|
set name = "Show Crew Manifest"
|
|
show_station_manifest()
|
|
|
|
/mob/living/silicon/ai/var/message_cooldown = 0
|
|
/mob/living/silicon/ai/proc/ai_announcement()
|
|
set category = "AI Commands"
|
|
set name = "Make Station Announcement"
|
|
|
|
if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO))
|
|
return
|
|
|
|
if(message_cooldown)
|
|
src << "Please allow one minute to pass between announcements."
|
|
return
|
|
var/input = stripped_input(usr, "Please write a message to announce to the station crew.", "A.I. Announcement")
|
|
if(!input)
|
|
return
|
|
|
|
if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO))
|
|
return
|
|
|
|
announcement.Announce(input)
|
|
message_cooldown = 1
|
|
spawn(600)//One minute cooldown
|
|
message_cooldown = 0
|
|
|
|
/mob/living/silicon/ai/proc/ai_call_shuttle()
|
|
set category = "AI Commands"
|
|
set name = "Call Emergency Shuttle"
|
|
|
|
if(check_unable(AI_CHECK_WIRELESS))
|
|
return
|
|
|
|
var/confirm = alert("Are you sure you want to call the shuttle?", "Confirm Shuttle Call", "Yes", "No")
|
|
|
|
if(check_unable(AI_CHECK_WIRELESS))
|
|
return
|
|
|
|
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")
|
|
|
|
/mob/living/silicon/ai/proc/ai_recall_shuttle()
|
|
set category = "AI Commands"
|
|
set name = "Recall Emergency Shuttle"
|
|
|
|
if(check_unable(AI_CHECK_WIRELESS))
|
|
return
|
|
|
|
var/confirm = alert("Are you sure you want to recall the shuttle?", "Confirm Shuttle Recall", "Yes", "No")
|
|
if(check_unable(AI_CHECK_WIRELESS))
|
|
return
|
|
|
|
if(confirm == "Yes")
|
|
cancel_call_proc(src)
|
|
|
|
/mob/living/silicon/ai/check_eye(var/mob/user as mob)
|
|
if (!camera)
|
|
return null
|
|
user.reset_view(camera)
|
|
return 1
|
|
|
|
/mob/living/silicon/ai/restrained()
|
|
return 0
|
|
|
|
/mob/living/silicon/ai/emp_act(severity)
|
|
if (prob(30))
|
|
switch(pick(1,2))
|
|
if(1)
|
|
view_core()
|
|
if(2)
|
|
ai_call_shuttle()
|
|
..()
|
|
|
|
/mob/living/silicon/ai/Topic(href, href_list)
|
|
if(usr != src)
|
|
return
|
|
if(..())
|
|
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()
|
|
//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["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
|
|
|
|
if(target && (!istype(target, /mob/living/carbon/human) || html_decode(href_list["trackname"]) == target:get_face_name()))
|
|
ai_actual_track(target)
|
|
else
|
|
src << "\red System error. Cannot locate [html_decode(href_list["trackname"])]."
|
|
return
|
|
|
|
return
|
|
|
|
/mob/living/silicon/ai/meteorhit(obj/O as obj)
|
|
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/reset_view(atom/A)
|
|
if(camera)
|
|
camera.SetLuminosity(0)
|
|
if(istype(A,/obj/machinery/camera))
|
|
camera = A
|
|
..()
|
|
if(istype(A,/obj/machinery/camera))
|
|
if(camera_light_on) A.SetLuminosity(AI_CAMERA_LUMINOSITY)
|
|
else A.SetLuminosity(0)
|
|
|
|
|
|
/mob/living/silicon/ai/proc/switchCamera(var/obj/machinery/camera/C)
|
|
if (!C || stat == DEAD) //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, list/cameralist, var/source)
|
|
if (stat == 2)
|
|
return 1
|
|
|
|
..()
|
|
|
|
var/cameratext = ""
|
|
for (var/obj/machinery/camera/C in cameralist)
|
|
cameratext += "[(cameratext == "")? "" : "|"]<A HREF=?src=\ref[src];switchcamera=\ref[C]>[C.c_tag]</A>"
|
|
|
|
queueAlarm("--- [class] alarm detected in [A.name]! ([(cameratext)? cameratext : "No Camera"])", class)
|
|
|
|
if (viewalerts) ai_alerts()
|
|
|
|
/mob/living/silicon/ai/cancelAlarm(var/class, area/A as area, var/source)
|
|
var/has_alarm = ..()
|
|
|
|
if (!has_alarm)
|
|
queueAlarm(text("--- [] alarm in [] has been cleared.", class, A.name), class, 0)
|
|
if (viewalerts) ai_alerts()
|
|
|
|
return has_alarm
|
|
|
|
/mob/living/silicon/ai/cancel_camera()
|
|
set category = "AI Commands"
|
|
set name = "Cancel Camera View"
|
|
|
|
//src.cameraFollow = null
|
|
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()
|
|
var/cameralist[0]
|
|
|
|
if(check_unable())
|
|
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(check_unable(AI_CHECK_WIRELESS))
|
|
return
|
|
|
|
set_ai_status_displays(src)
|
|
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"
|
|
|
|
if(check_unable())
|
|
return
|
|
|
|
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",
|
|
"carp"
|
|
)
|
|
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("carp")
|
|
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo4"))
|
|
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()
|
|
set name = "Toggle Camera Light"
|
|
set desc = "Toggles the light on the camera the AI is looking through."
|
|
set category = "AI Commands"
|
|
|
|
if(check_unable())
|
|
return
|
|
|
|
camera_light_on = !camera_light_on
|
|
src << "Camera lights [camera_light_on ? "activated" : "deactivated"]."
|
|
if(!camera_light_on)
|
|
if(camera)
|
|
camera.SetLuminosity(0)
|
|
camera = null
|
|
else
|
|
lightNearbyCamera()
|
|
|
|
|
|
|
|
// Handled camera lighting, when toggled.
|
|
// It will get the nearest camera from the eyeobj, lighting it.
|
|
|
|
/mob/living/silicon/ai/proc/lightNearbyCamera()
|
|
if(camera_light_on && camera_light_on < world.timeofday)
|
|
if(src.camera)
|
|
var/obj/machinery/camera/camera = near_range_camera(src.eyeobj)
|
|
if(camera && src.camera != camera)
|
|
src.camera.SetLuminosity(0)
|
|
if(!camera.light_disabled)
|
|
src.camera = camera
|
|
src.camera.SetLuminosity(AI_CAMERA_LUMINOSITY)
|
|
else
|
|
src.camera = null
|
|
else if(isnull(camera))
|
|
src.camera.SetLuminosity(0)
|
|
src.camera = null
|
|
else
|
|
var/obj/machinery/camera/camera = near_range_camera(src.eyeobj)
|
|
if(camera && !camera.light_disabled)
|
|
src.camera = camera
|
|
src.camera.SetLuminosity(AI_CAMERA_LUMINOSITY)
|
|
camera_light_on = world.timeofday + 1 * 20 // Update the light every 2 seconds.
|
|
|
|
|
|
/mob/living/silicon/ai/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
|
if(istype(W, /obj/item/device/aicard))
|
|
|
|
var/obj/item/device/aicard/card = W
|
|
card.grab_ai(src, user)
|
|
|
|
else 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/proc/control_integrated_radio()
|
|
set name = "Radio Settings"
|
|
set desc = "Allows you to change settings of your radio."
|
|
set category = "AI Commands"
|
|
|
|
if(check_unable(AI_CHECK_RADIO))
|
|
return
|
|
|
|
src << "Accessing Subspace Transceiver control..."
|
|
if (src.aiRadio)
|
|
src.aiRadio.interact(src)
|
|
|
|
/mob/living/silicon/ai/proc/sensor_mode()
|
|
set name = "Set Sensor Augmentation"
|
|
set category = "AI Commands"
|
|
set desc = "Augment visual feed with internal sensor overlays"
|
|
toggle_sensor_mode()
|
|
|
|
/mob/living/silicon/ai/proc/check_unable(var/flags = 0)
|
|
if(stat == DEAD)
|
|
usr << "\red You are dead!"
|
|
return 1
|
|
|
|
if((flags & AI_CHECK_WIRELESS) && src.control_disabled)
|
|
usr << "\red Wireless control is disabled!"
|
|
return 1
|
|
if((flags & AI_CHECK_RADIO) && src.aiRadio.disabledAi)
|
|
src << "\red System Error - Transceiver Disabled!"
|
|
return 1
|
|
return 0
|
|
|
|
#undef AI_CHECK_WIRELESS
|
|
#undef AI_CHECK_RADIO
|