April sync (#360)
* Maps and things no code/icons * helpers defines globalvars * Onclick world.dm orphaned_procs * subsystems Round vote and shuttle autocall done here too * datums * Game folder * Admin - chatter modules * clothing - mining * modular computers - zambies * client * mob level 1 * mob stage 2 + simple_animal * silicons n brains * mob stage 3 + Alien/Monkey * human mobs * icons updated * some sounds * emitter y u no commit * update tgstation.dme * compile fixes * travis fixes Also removes Fast digest mode, because reasons. * tweaks for travis Mentors are broke again Also fixes Sizeray guns * oxygen loss fix for vore code. * removes unused code * some code updates * bulk fixes * further fixes * outside things * whoops. * Maint bar ported * GLOBs.
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
#define CALL_BOT_COOLDOWN 900
|
||||
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)
|
||||
for(var/A in GLOB.ai_list)
|
||||
var/mob/living/silicon/ai/M = A
|
||||
if ((M.client && M.machine == subject))
|
||||
is_in_use = 1
|
||||
@@ -22,7 +21,6 @@ var/list/ai_list = list()
|
||||
canmove = 0
|
||||
status_flags = CANSTUN|CANPUSH
|
||||
a_intent = INTENT_HARM //so we always get pushed instead of trying to swap
|
||||
force_compose = 1 //This ensures that the AI always composes it's own hear message. Needed for hrefs and job display.
|
||||
sight = SEE_TURFS | SEE_MOBS | SEE_OBJS
|
||||
see_in_dark = 8
|
||||
med_hud = DATA_HUD_MEDICAL_BASIC
|
||||
@@ -84,6 +82,10 @@ var/list/ai_list = list()
|
||||
var/obj/machinery/camera/portable/builtInCamera
|
||||
|
||||
var/obj/structure/AIcore/deactivated/linked_core //For exosuit control
|
||||
var/mob/living/silicon/robot/deployed_shell = null //For shell control
|
||||
var/datum/action/innate/deploy_shell/deploy_action = new
|
||||
var/datum/action/innate/deploy_last_shell/redeploy_action = new
|
||||
var/chnotify = 0
|
||||
|
||||
/mob/living/silicon/ai/Initialize(mapload, datum/ai_laws/L, mob/target_ai)
|
||||
..()
|
||||
@@ -138,22 +140,24 @@ var/list/ai_list = list()
|
||||
radio = new /obj/item/device/radio/headset/ai(src)
|
||||
aicamera = new/obj/item/device/camera/siliconcam/ai_camera(src)
|
||||
|
||||
deploy_action.Grant(src)
|
||||
|
||||
if(isturf(loc))
|
||||
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/set_automatic_say_channel)
|
||||
|
||||
ai_list += src
|
||||
shuttle_caller_list += src
|
||||
GLOB.ai_list += src
|
||||
GLOB.shuttle_caller_list += src
|
||||
|
||||
builtInCamera = new /obj/machinery/camera/portable(src)
|
||||
builtInCamera.network = list("SS13")
|
||||
|
||||
|
||||
/mob/living/silicon/ai/Destroy()
|
||||
ai_list -= src
|
||||
shuttle_caller_list -= src
|
||||
GLOB.ai_list -= src
|
||||
GLOB.shuttle_caller_list -= src
|
||||
SSshuttle.autoEvac()
|
||||
qdel(eyeobj) // No AI, no Eye
|
||||
malfhack = null
|
||||
@@ -247,13 +251,16 @@ var/list/ai_list = list()
|
||||
for(var/mob/living/silicon/robot/R in connected_robots)
|
||||
borg_area = get_area(R)
|
||||
var/robot_status = "Nominal"
|
||||
if(R.stat || !R.client)
|
||||
if(R.shell)
|
||||
robot_status = "AI SHELL"
|
||||
else if(R.stat || !R.client)
|
||||
robot_status = "OFFLINE"
|
||||
else if(!R.cell || R.cell.charge <= 0)
|
||||
robot_status = "DEPOWERED"
|
||||
//Name, Health, Battery, Module, Area, and Status! Everything an AI wants to know about its borgies!
|
||||
stat(null, text("[R.name] | S.Integrity: [R.health]% | Cell: [R.cell ? "[R.cell.charge]/[R.cell.maxcharge]" : "Empty"] | \
|
||||
Module: [R.designation] | Loc: [borg_area.name] | Status: [robot_status]"))
|
||||
Module: [R.designation] | Loc: [borg_area.name] | Status: [robot_status]"))
|
||||
stat(null, text("AI shell beacons detected: [LAZYLEN(GLOB.available_ai_shells)]")) //Count of total AI shells
|
||||
else
|
||||
stat(null, text("Systems nonfunctional"))
|
||||
|
||||
@@ -293,7 +300,7 @@ var/list/ai_list = list()
|
||||
/mob/living/silicon/ai/proc/ai_roster()
|
||||
var/dat = "<html><head><title>Crew Roster</title></head><body><b>Crew Roster:</b><br><br>"
|
||||
|
||||
dat += data_core.get_manifest()
|
||||
dat += GLOB.data_core.get_manifest()
|
||||
dat += "</body></html>"
|
||||
|
||||
src << browse(dat, "window=airoster")
|
||||
@@ -315,7 +322,7 @@ var/list/ai_list = list()
|
||||
|
||||
// hack to display shuttle timer
|
||||
if(!EMERGENCY_IDLE_OR_RECALLED)
|
||||
var/obj/machinery/computer/communications/C = locate() in machines
|
||||
var/obj/machinery/computer/communications/C = locate() in GLOB.machines
|
||||
if(C)
|
||||
C.post_status("shuttle")
|
||||
|
||||
@@ -363,7 +370,7 @@ var/list/ai_list = list()
|
||||
unset_machine()
|
||||
src << browse(null, t1)
|
||||
if (href_list["switchcamera"])
|
||||
switchCamera(locate(href_list["switchcamera"])) in cameranet.cameras
|
||||
switchCamera(locate(href_list["switchcamera"])) in GLOB.cameranet.cameras
|
||||
if (href_list["showalerts"])
|
||||
ai_alerts()
|
||||
#ifdef AI_VOX
|
||||
@@ -403,14 +410,14 @@ var/list/ai_list = list()
|
||||
if(call_bot_cooldown > world.time)
|
||||
to_chat(src, "<span class='danger'>Error: Your last call bot command is still processing, please wait for the bot to finish calculating a route.</span>")
|
||||
return
|
||||
Bot = locate(href_list["callbot"]) in living_mob_list
|
||||
Bot = locate(href_list["callbot"]) in GLOB.living_mob_list
|
||||
if(!Bot || Bot.remote_disabled || src.control_disabled)
|
||||
return //True if there is no bot found, the bot is manually emagged, or the AI is carded with wireless off.
|
||||
waypoint_mode = 1
|
||||
to_chat(src, "<span class='notice'>Set your waypoint by clicking on a valid location free of obstructions.</span>")
|
||||
return
|
||||
if(href_list["interface"]) //Remotely connect to a bot!
|
||||
Bot = locate(href_list["interface"]) in living_mob_list
|
||||
Bot = locate(href_list["interface"]) in GLOB.living_mob_list
|
||||
if(!Bot || Bot.remote_disabled || src.control_disabled)
|
||||
return
|
||||
Bot.attack_ai(src)
|
||||
@@ -423,7 +430,7 @@ var/list/ai_list = list()
|
||||
if(controlled_mech)
|
||||
to_chat(src, "<span class='warning'>You are already loaded into an onboard computer!</span>")
|
||||
return
|
||||
if(!cameranet.checkCameraVis(M))
|
||||
if(!GLOB.cameranet.checkCameraVis(M))
|
||||
to_chat(src, "<span class='warning'>Exosuit is no longer near active cameras.</span>")
|
||||
return
|
||||
if(lacks_power())
|
||||
@@ -470,7 +477,7 @@ var/list/ai_list = list()
|
||||
d += "<A HREF=?src=\ref[src];botrefresh=1>Query network status</A><br>"
|
||||
d += "<table width='100%'><tr><td width='40%'><h3>Name</h3></td><td width='30%'><h3>Status</h3></td><td width='30%'><h3>Location</h3></td><td width='10%'><h3>Control</h3></td></tr>"
|
||||
|
||||
for (Bot in living_mob_list)
|
||||
for (Bot in GLOB.living_mob_list)
|
||||
if(Bot.z == ai_Zlevel && !Bot.remote_disabled) //Only non-emagged bots on the same Z-level are detected!
|
||||
bot_area = get_area(Bot)
|
||||
var/bot_mode = Bot.get_mode()
|
||||
@@ -492,7 +499,7 @@ var/list/ai_list = list()
|
||||
//The target must be in view of a camera or near the core.
|
||||
if(turf_check in range(get_turf(src)))
|
||||
call_bot(turf_check)
|
||||
else if(cameranet && cameranet.checkTurfVis(turf_check))
|
||||
else if(GLOB.cameranet && GLOB.cameranet.checkTurfVis(turf_check))
|
||||
call_bot(turf_check)
|
||||
else
|
||||
to_chat(src, "<span class='danger'>Selected location is not visible.</span>")
|
||||
@@ -582,7 +589,7 @@ var/list/ai_list = list()
|
||||
|
||||
var/mob/living/silicon/ai/U = usr
|
||||
|
||||
for (var/obj/machinery/camera/C in cameranet.cameras)
|
||||
for (var/obj/machinery/camera/C in GLOB.cameranet.cameras)
|
||||
if(!C.can_use())
|
||||
continue
|
||||
|
||||
@@ -601,7 +608,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.cameras)
|
||||
for(var/obj/machinery/camera/C in GLOB.cameranet.cameras)
|
||||
if(!C.can_use())
|
||||
continue
|
||||
if(network in C.network)
|
||||
@@ -625,7 +632,7 @@ var/list/ai_list = list()
|
||||
return //won't work if dead
|
||||
var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Sad", "BSOD", "Blank", "Problems?", "Awesome", "Facepalm", "Friend Computer", "Dorfy", "Blue Glow", "Red Glow")
|
||||
var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions
|
||||
for (var/obj/machinery/M in machines) //change status
|
||||
for (var/obj/machinery/M in GLOB.machines) //change status
|
||||
if(istype(M, /obj/machinery/ai_status_display))
|
||||
var/obj/machinery/ai_status_display/AISD = M
|
||||
AISD.emotion = emote
|
||||
@@ -652,7 +659,7 @@ var/list/ai_list = list()
|
||||
if("Crew Member")
|
||||
var/list/personnel_list = list()
|
||||
|
||||
for(var/datum/data/record/t in data_core.locked)//Look in data core locked.
|
||||
for(var/datum/data/record/t in GLOB.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)
|
||||
@@ -791,12 +798,13 @@ var/list/ai_list = list()
|
||||
if(!..())
|
||||
return
|
||||
if(interaction == AI_TRANS_TO_CARD)//The only possible interaction. Upload AI mob to a card.
|
||||
if(!mind)
|
||||
to_chat(user, "<span class='warning'>No intelligence patterns detected.</span>" )
|
||||
return
|
||||
if(!can_be_carded)
|
||||
to_chat(user, "<span class='boldwarning'>Transfer failed.</span>")
|
||||
return
|
||||
disconnect_shell() //If the AI is controlling a borg, force the player back to core!
|
||||
if(!mind)
|
||||
to_chat(user, "<span class='warning'>No intelligence patterns detected.</span>" )
|
||||
return
|
||||
ShutOffDoomsdayDevice()
|
||||
new /obj/structure/AIcore/deactivated(loc)//Spawns a deactivated terminal at AI location.
|
||||
ai_restore_power()//So the AI initially has power.
|
||||
@@ -818,12 +826,12 @@ var/list/ai_list = list()
|
||||
//stop AIs from leaving windows open and using then after they lose vision
|
||||
//apc_override is needed here because AIs use their own APC when powerless
|
||||
//get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera
|
||||
if(M && cameranet && !cameranet.checkTurfVis(get_turf_pixel(M)) && !apc_override)
|
||||
if(M && GLOB.cameranet && !GLOB.cameranet.checkTurfVis(get_turf_pixel(M)) && !apc_override)
|
||||
return
|
||||
return 1
|
||||
|
||||
/mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
|
||||
raw_message = lang_treat(speaker, message_langs, raw_message, spans)
|
||||
/mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
raw_message = lang_treat(speaker, message_language, raw_message, spans, message_mode)
|
||||
var/name_used = speaker.GetVoice()
|
||||
var/rendered = "<i><span class='game say'>Relayed Speech: <span class='name'>[name_used]</span> <span class='message'>[raw_message]</span></span></i>"
|
||||
show_message(rendered, 2)
|
||||
@@ -907,6 +915,69 @@ var/list/ai_list = list()
|
||||
to_chat(src, "Hack complete. \The [apc] is now under your exclusive control.")
|
||||
apc.update_icon()
|
||||
|
||||
/mob/living/silicon/ai/verb/deploy_to_shell(var/mob/living/silicon/robot/target)
|
||||
set category = "AI Commands"
|
||||
set name = "Deploy to Shell"
|
||||
|
||||
if(stat || lacks_power() || control_disabled)
|
||||
to_chat(src, "<span class='danger'>Wireless networking module is offline.</span>")
|
||||
return
|
||||
|
||||
var/list/possible = list()
|
||||
|
||||
for(var/borgie in GLOB.available_ai_shells)
|
||||
var/mob/living/silicon/robot/R = borgie
|
||||
if(R.shell && !R.deployed && (R.stat != DEAD) && (!R.connected_ai ||(R.connected_ai == src)))
|
||||
possible += R
|
||||
|
||||
if(!LAZYLEN(possible))
|
||||
to_chat(src, "No usable AI shell beacons detected.")
|
||||
|
||||
if(!target || !(target in possible)) //If the AI is looking for a new shell, or its pre-selected shell is no longer valid
|
||||
target = input(src, "Which body to control?") as null|anything in possible
|
||||
|
||||
if (!target || target.stat == DEAD || target.deployed || !(!target.connected_ai ||(target.connected_ai == src)))
|
||||
return
|
||||
|
||||
else if(mind)
|
||||
soullink(/datum/soullink/sharedbody, src, target)
|
||||
deployed_shell = target
|
||||
target.deploy_init(src)
|
||||
mind.transfer_to(target)
|
||||
diag_hud_set_deployed()
|
||||
|
||||
/datum/action/innate/deploy_shell
|
||||
name = "Deploy to AI Shell"
|
||||
desc = "Wirelessly control a specialized cyborg shell."
|
||||
button_icon_state = "ai_shell"
|
||||
|
||||
/datum/action/innate/deploy_shell/Trigger()
|
||||
var/mob/living/silicon/ai/AI = owner
|
||||
if(!AI)
|
||||
return
|
||||
AI.deploy_to_shell()
|
||||
|
||||
/datum/action/innate/deploy_last_shell
|
||||
name = "Reconnect to shell"
|
||||
desc = "Reconnect to the most recently used AI shell."
|
||||
button_icon_state = "ai_last_shell"
|
||||
var/mob/living/silicon/robot/last_used_shell
|
||||
|
||||
/datum/action/innate/deploy_last_shell/Trigger()
|
||||
if(!owner)
|
||||
return
|
||||
if(last_used_shell)
|
||||
var/mob/living/silicon/ai/AI = owner
|
||||
AI.deploy_to_shell(last_used_shell)
|
||||
else
|
||||
Remove(owner) //If the last shell is blown, destroy it.
|
||||
|
||||
/mob/living/silicon/ai/proc/disconnect_shell()
|
||||
if(deployed_shell) //Forcibly call back AI in event of things such as damage, EMP or power loss.
|
||||
to_chat(src, "<span class='danger'>Your remote connection has been reset!</span>")
|
||||
deployed_shell.undeploy()
|
||||
diag_hud_set_deployed()
|
||||
|
||||
/mob/living/silicon/ai/resist()
|
||||
return
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
|
||||
/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(!ticker || !ticker.mode)
|
||||
if(!SSticker || !SSticker.mode)
|
||||
to_chat(M, "You cannot attack people before the game has started.")
|
||||
return
|
||||
..()
|
||||
@@ -22,6 +22,7 @@
|
||||
return 0
|
||||
|
||||
/mob/living/silicon/ai/emp_act(severity)
|
||||
disconnect_shell()
|
||||
if (prob(30))
|
||||
switch(pick(1,2))
|
||||
if(1)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
if(eyeobj)
|
||||
eyeobj.setLoc(get_turf(src))
|
||||
|
||||
shuttle_caller_list -= src
|
||||
GLOB.shuttle_caller_list -= src
|
||||
SSshuttle.autoEvac()
|
||||
|
||||
ShutOffDoomsdayDevice()
|
||||
@@ -35,7 +35,7 @@
|
||||
if(nuking)
|
||||
set_security_level("red")
|
||||
nuking = FALSE
|
||||
for(var/obj/item/weapon/pinpointer/P in pinpointer_list)
|
||||
for(var/obj/item/weapon/pinpointer/P in GLOB.pinpointer_list)
|
||||
P.switch_mode_to(TRACK_NUKE_DISK) //Party's over, back to work, everyone
|
||||
P.nuke_warning = FALSE
|
||||
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/mob/living/silicon/ai/examine(mob/user)
|
||||
var/msg = "<span class='info'>*---------*\nThis is \icon[src] <EM>[src]</EM>!\n"
|
||||
if (src.stat == DEAD)
|
||||
if (stat == DEAD)
|
||||
msg += "<span class='deadsay'>It appears to be powered-down.</span>\n"
|
||||
else
|
||||
msg += "<span class='warning'>"
|
||||
if (src.getBruteLoss())
|
||||
if (src.getBruteLoss() < 30)
|
||||
if (getBruteLoss())
|
||||
if (getBruteLoss() < 30)
|
||||
msg += "It looks slightly dented.\n"
|
||||
else
|
||||
msg += "<B>It looks severely dented!</B>\n"
|
||||
if (src.getFireLoss())
|
||||
if (src.getFireLoss() < 30)
|
||||
if (getFireLoss())
|
||||
if (getFireLoss() < 30)
|
||||
msg += "It looks slightly charred.\n"
|
||||
else
|
||||
msg += "<B>Its casing is melted and heat-warped!</B>\n"
|
||||
msg += "</span>"
|
||||
if (shunted == 0 && !src.client)
|
||||
if(deployed_shell)
|
||||
msg += "The wireless networking light is blinking.\n"
|
||||
else if (!shunted && !client)
|
||||
msg += "[src]Core.exe has stopped responding! NTOS is searching for a solution to the problem...\n"
|
||||
msg += "*---------*</span>"
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
//
|
||||
// The datum containing all the chunks.
|
||||
|
||||
var/const/CHUNK_SIZE = 16 // Only chunk sizes that are to the power of 2. E.g: 2, 4, 8, 16, etc..
|
||||
#define CHUNK_SIZE 16 // Only chunk sizes that are to the power of 2. E.g: 2, 4, 8, 16, etc..
|
||||
|
||||
var/datum/cameranet/cameranet = new()
|
||||
GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
|
||||
|
||||
/datum/cameranet
|
||||
var/name = "Camera Net" // Name to show for VV and stat()
|
||||
@@ -66,7 +66,7 @@ var/datum/cameranet/cameranet = new()
|
||||
|
||||
/datum/cameranet/proc/updateVisibility(atom/A, opacity_check = 1)
|
||||
|
||||
if(!ticker || (opacity_check && !A.opacity))
|
||||
if(!SSticker || (opacity_check && !A.opacity))
|
||||
return
|
||||
majorChunkChange(A, 2)
|
||||
|
||||
@@ -151,7 +151,7 @@ var/datum/cameranet/cameranet = new()
|
||||
if(!statclick)
|
||||
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
|
||||
|
||||
stat(name, statclick.update("Cameras: [cameranet.cameras.len] | Chunks: [cameranet.chunks.len]"))
|
||||
stat(name, statclick.update("Cameras: [GLOB.cameranet.cameras.len] | Chunks: [GLOB.cameranet.chunks.len]"))
|
||||
|
||||
// Debug verb for VVing the chunk that the turf is in.
|
||||
/*
|
||||
|
||||
@@ -173,4 +173,5 @@
|
||||
t.obscured.plane = LIGHTING_PLANE+1
|
||||
obscured += t.obscured
|
||||
|
||||
#undef UPDATE_BUFFER
|
||||
#undef UPDATE_BUFFER
|
||||
#undef CHUNK_SIZE
|
||||
@@ -21,7 +21,7 @@
|
||||
return
|
||||
T = get_turf(T)
|
||||
loc = T
|
||||
cameranet.visibility(src)
|
||||
GLOB.cameranet.visibility(src)
|
||||
if(ai.client)
|
||||
ai.client.eye = src
|
||||
update_parallax_contents()
|
||||
@@ -104,6 +104,6 @@
|
||||
acceleration = !acceleration
|
||||
to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].")
|
||||
|
||||
/mob/camera/aiEye/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
|
||||
/mob/camera/aiEye/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
if(relay_speech && speaker && ai && !radio_freq && speaker != ai && near_camera(speaker))
|
||||
ai.relay_speech(message, speaker, message_langs, raw_message, radio_freq, spans)
|
||||
ai.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans)
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
health = maxHealth - getOxyLoss() - getToxLoss() - getBruteLoss() - getFireLoss()
|
||||
update_stat()
|
||||
diag_hud_set_health()
|
||||
disconnect_shell()
|
||||
|
||||
/mob/living/silicon/ai/update_stat()
|
||||
if(status_flags & GODMODE)
|
||||
@@ -90,6 +91,7 @@
|
||||
|
||||
if(see_override)
|
||||
see_invisible = see_override
|
||||
sync_lighting_plane_alpha()
|
||||
|
||||
|
||||
/mob/living/silicon/ai/proc/start_RestorePowerRoutine()
|
||||
@@ -146,7 +148,7 @@
|
||||
to_chat(src, "Receiving control information from APC.")
|
||||
sleep(2)
|
||||
apc_override = 1
|
||||
theAPC.ui_interact(src, state = conscious_state)
|
||||
theAPC.ui_interact(src, state = GLOB.conscious_state)
|
||||
apc_override = 0
|
||||
aiRestorePowerRoutine = POWER_RESTORATION_APC_FOUND
|
||||
sleep(50)
|
||||
@@ -163,6 +165,7 @@
|
||||
update_sight()
|
||||
|
||||
/mob/living/silicon/ai/proc/ai_lose_power()
|
||||
disconnect_shell()
|
||||
aiRestorePowerRoutine = POWER_RESTORATION_START
|
||||
blind_eyes(1)
|
||||
update_sight()
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
client.images += blood
|
||||
|
||||
if(stat != DEAD)
|
||||
for(var/obj/machinery/ai_status_display/O in machines) //change status
|
||||
for(var/obj/machinery/ai_status_display/O in GLOB.machines) //change status
|
||||
O.mode = 1
|
||||
O.emotion = "Neutral"
|
||||
view_core()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/mob/living/silicon/ai/say(message)
|
||||
/mob/living/silicon/ai/say(message, language)
|
||||
if(parent && istype(parent) && parent.stat != 2) //If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead.
|
||||
parent.say(message)
|
||||
parent.say(message, language)
|
||||
return
|
||||
..(message)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
/mob/living/silicon/ai/IsVocal()
|
||||
return !config.silent_ai
|
||||
|
||||
/mob/living/silicon/ai/radio(message, message_mode, list/spans)
|
||||
/mob/living/silicon/ai/radio(message, message_mode, list/spans, language)
|
||||
if(!radio_enabled || aiRestorePowerRoutine || stat) //AI cannot speak if radio is disabled (via intellicard) or depowered.
|
||||
to_chat(src, "<span class='danger'>Your radio transmitter is offline!</span>")
|
||||
return 0
|
||||
@@ -29,17 +29,17 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/ai/handle_inherent_channels(message, message_mode)
|
||||
/mob/living/silicon/ai/handle_inherent_channels(message, message_mode, language)
|
||||
. = ..()
|
||||
if(.)
|
||||
return .
|
||||
|
||||
if(message_mode == MODE_HOLOPAD)
|
||||
holopad_talk(message)
|
||||
holopad_talk(message, language)
|
||||
return 1
|
||||
|
||||
//For holopads only. Usable by AI.
|
||||
/mob/living/silicon/ai/proc/holopad_talk(message)
|
||||
/mob/living/silicon/ai/proc/holopad_talk(message, language)
|
||||
log_say("[key_name(src)] : [message]")
|
||||
|
||||
message = trim(message)
|
||||
@@ -49,20 +49,15 @@
|
||||
|
||||
var/obj/machinery/holopad/T = current
|
||||
if(istype(T) && T.masters[src])//If there is a hologram and its master is the user.
|
||||
send_speech(message, 7, T, "robot", get_spans())
|
||||
send_speech(message, 7, T, "robot", get_spans(), language)
|
||||
to_chat(src, "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> <span class='message robot'>\"[message]\"</span></span></i>")
|
||||
else
|
||||
to_chat(src, "No holopad connected.")
|
||||
return
|
||||
|
||||
|
||||
// Make sure that the code compiles with AI_VOX undefined
|
||||
#ifdef AI_VOX
|
||||
|
||||
var/announcing_vox = 0 // Stores the time of the last announcement
|
||||
var/const/VOX_CHANNEL = 200
|
||||
var/const/VOX_DELAY = 600
|
||||
|
||||
#define VOX_DELAY 600
|
||||
/mob/living/silicon/ai/verb/announcement_help()
|
||||
|
||||
set name = "Announcement Help"
|
||||
@@ -79,10 +74,10 @@ var/const/VOX_DELAY = 600
|
||||
<font class='bad'>WARNING:</font><BR>Misuse of the announcement system will get you job banned.<HR>"
|
||||
|
||||
var/index = 0
|
||||
for(var/word in vox_sounds)
|
||||
for(var/word in GLOB.vox_sounds)
|
||||
index++
|
||||
dat += "<A href='?src=\ref[src];say_word=[word]'>[capitalize(word)]</A>"
|
||||
if(index != vox_sounds.len)
|
||||
if(index != GLOB.vox_sounds.len)
|
||||
dat += " / "
|
||||
|
||||
var/datum/browser/popup = new(src, "announce_help", "Announcement Help", 500, 400)
|
||||
@@ -91,6 +86,7 @@ var/const/VOX_DELAY = 600
|
||||
|
||||
|
||||
/mob/living/silicon/ai/proc/announcement()
|
||||
var/static/announcing_vox = 0 // Stores the time of the last announcement
|
||||
if(announcing_vox > world.time)
|
||||
to_chat(src, "<span class='notice'>Please wait [round((announcing_vox - world.time) / 10)] seconds.</span>")
|
||||
return
|
||||
@@ -120,7 +116,7 @@ var/const/VOX_DELAY = 600
|
||||
if(!word)
|
||||
words -= word
|
||||
continue
|
||||
if(!vox_sounds[word])
|
||||
if(!GLOB.vox_sounds[word])
|
||||
incorrect_words += word
|
||||
|
||||
if(incorrect_words.len)
|
||||
@@ -147,16 +143,16 @@ var/const/VOX_DELAY = 600
|
||||
|
||||
word = lowertext(word)
|
||||
|
||||
if(vox_sounds[word])
|
||||
if(GLOB.vox_sounds[word])
|
||||
|
||||
var/sound_file = vox_sounds[word]
|
||||
var/sound/voice = sound(sound_file, wait = 1, channel = VOX_CHANNEL)
|
||||
var/sound_file = GLOB.vox_sounds[word]
|
||||
var/sound/voice = sound(sound_file, wait = 1, channel = CHANNEL_VOX)
|
||||
voice.status = SOUND_STREAM
|
||||
|
||||
// If there is no single listener, broadcast to everyone in the same z level
|
||||
if(!only_listener)
|
||||
// Play voice for all mobs in the z level
|
||||
for(var/mob/M in player_list)
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M.client && !M.ear_deaf && (M.client.prefs.toggles & SOUND_ANNOUNCEMENTS))
|
||||
var/turf/T = get_turf(M)
|
||||
if(T.z == z_level)
|
||||
@@ -167,3 +163,12 @@ var/const/VOX_DELAY = 600
|
||||
return 0
|
||||
|
||||
#endif
|
||||
|
||||
/mob/living/silicon/ai/can_speak_in_language(datum/language/dt)
|
||||
if(HAS_SECONDARY_FLAG(src, OMNITONGUE))
|
||||
. = has_language(dt)
|
||||
else if(is_servant_of_ratvar(src))
|
||||
// Ratvarian AIs can only speak Ratvarian
|
||||
. = ispath(dt, /datum/language/ratvar) && has_language(dt)
|
||||
else
|
||||
. = ..()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Dynamically loading it has bad results with sounds overtaking each other, even with the wait variable.
|
||||
#ifdef AI_VOX
|
||||
|
||||
var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg',
|
||||
GLOBAL_LIST_INIT(vox_sounds, list("," = 'sound/vox_fem/,.ogg',
|
||||
"." = 'sound/vox_fem/..ogg',
|
||||
"a" = 'sound/vox_fem/a.ogg',
|
||||
"abortions" = 'sound/vox_fem/abortions.ogg',
|
||||
@@ -713,6 +713,5 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg',
|
||||
"z" = 'sound/vox_fem/z.ogg',
|
||||
"zero" = 'sound/vox_fem/zero.ogg',
|
||||
"zone" = 'sound/vox_fem/zone.ogg',
|
||||
"zulu" = 'sound/vox_fem/zulu.ogg',
|
||||
)
|
||||
"zulu" = 'sound/vox_fem/zulu.ogg'))
|
||||
#endif
|
||||
Reference in New Issue
Block a user