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
|
||||
@@ -1,6 +1,6 @@
|
||||
/mob/living/silicon/Login()
|
||||
if(mind && ticker && ticker.mode)
|
||||
ticker.mode.remove_cultist(mind, 0, 0)
|
||||
ticker.mode.remove_revolutionary(mind, 0)
|
||||
ticker.mode.remove_gangster(mind, remove_bosses=1)
|
||||
if(mind && SSticker && SSticker.mode)
|
||||
SSticker.mode.remove_cultist(mind, 0, 0)
|
||||
SSticker.mode.remove_revolutionary(mind, 0)
|
||||
SSticker.mode.remove_gangster(mind, remove_bosses=1)
|
||||
..()
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
stat = DEAD
|
||||
canmove = 0
|
||||
card.removePersonality()
|
||||
if(holoform)
|
||||
card.forceMove(loc)
|
||||
update_sight()
|
||||
clear_fullscreens()
|
||||
|
||||
//New pAI's get a brand new mind to prevent meta stuff from their previous life. This new mind causes problems down the line if it's not deleted here.
|
||||
living_mob_list -= src
|
||||
GLOB.living_mob_list -= src
|
||||
ghostize()
|
||||
qdel(src)
|
||||
@@ -78,13 +78,13 @@
|
||||
. += slowdown
|
||||
|
||||
/mob/living/silicon/pai/Destroy()
|
||||
pai_list -= src
|
||||
GLOB.pai_list -= src
|
||||
..()
|
||||
|
||||
/mob/living/silicon/pai/Initialize()
|
||||
var/obj/item/device/paicard/P = loc
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
pai_list += src
|
||||
GLOB.pai_list += src
|
||||
make_laws()
|
||||
canmove = 0
|
||||
if(!istype(P)) //when manually spawning a pai, we create a card to put it into.
|
||||
@@ -110,10 +110,13 @@
|
||||
var/datum/action/innate/pai/chassis/AC = new /datum/action/innate/pai/chassis
|
||||
var/datum/action/innate/pai/rest/AR = new /datum/action/innate/pai/rest
|
||||
var/datum/action/innate/pai/light/AL = new /datum/action/innate/pai/light
|
||||
|
||||
var/datum/action/language_menu/ALM = new
|
||||
AS.Grant(src)
|
||||
AC.Grant(src)
|
||||
AR.Grant(src)
|
||||
AL.Grant(src)
|
||||
ALM.Grant(src)
|
||||
emittersemicd = TRUE
|
||||
addtimer(CALLBACK(src, .proc/emittercool), 600)
|
||||
|
||||
|
||||
@@ -102,4 +102,4 @@
|
||||
|
||||
/mob/living/silicon/pai/movement_delay()
|
||||
. = ..()
|
||||
. += 1 //A bit slower than humans, so they're easier to smash
|
||||
. += 1 //A bit slower than humans, so they're easier to smash
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
if(temp)
|
||||
left_part = temp
|
||||
else if(src.stat == 2) // Show some flavor text if the pAI is dead
|
||||
left_part = "<b><font color=red>ÈRrÖR Ða†Ä ÇÖRrÚþ†Ìoñ</font></b>"
|
||||
left_part = "<b><font color=red>�Rr�R �a�� ��Rr����o�</font></b>"
|
||||
right_part = "<pre>Program index hash not found</pre>"
|
||||
|
||||
else
|
||||
@@ -220,18 +220,18 @@
|
||||
// Accessing medical records
|
||||
if("medicalrecord")
|
||||
if(subscreen == 1)
|
||||
medicalActive1 = find_record("id", href_list["med_rec"], data_core.general)
|
||||
medicalActive1 = find_record("id", href_list["med_rec"], GLOB.data_core.general)
|
||||
if(medicalActive1)
|
||||
medicalActive2 = find_record("id", href_list["med_rec"], data_core.medical)
|
||||
medicalActive2 = find_record("id", href_list["med_rec"], GLOB.data_core.medical)
|
||||
if(!medicalActive2)
|
||||
medicalActive1 = null
|
||||
temp = "Unable to locate requested security record. Record may have been deleted, or never have existed."
|
||||
|
||||
if("securityrecord")
|
||||
if(subscreen == 1)
|
||||
securityActive1 = find_record("id", href_list["sec_rec"], data_core.general)
|
||||
securityActive1 = find_record("id", href_list["sec_rec"], GLOB.data_core.general)
|
||||
if(securityActive1)
|
||||
securityActive2 = find_record("id", href_list["sec_rec"], data_core.security)
|
||||
securityActive2 = find_record("id", href_list["sec_rec"], GLOB.data_core.security)
|
||||
if(!securityActive2)
|
||||
securityActive1 = null
|
||||
temp = "Unable to locate requested security record. Record may have been deleted, or never have existed."
|
||||
@@ -241,7 +241,7 @@
|
||||
if(secHUD)
|
||||
add_sec_hud()
|
||||
else
|
||||
var/datum/atom_hud/sec = huds[sec_hud]
|
||||
var/datum/atom_hud/sec = GLOB.huds[sec_hud]
|
||||
sec.remove_hud_from(src)
|
||||
if("medicalhud")
|
||||
if(href_list["toggle"])
|
||||
@@ -249,13 +249,13 @@
|
||||
if(medHUD)
|
||||
add_med_hud()
|
||||
else
|
||||
var/datum/atom_hud/med = huds[med_hud]
|
||||
var/datum/atom_hud/med = GLOB.huds[med_hud]
|
||||
med.remove_hud_from(src)
|
||||
if("translator")
|
||||
if(href_list["toggle"])
|
||||
var/on_already = ((languages_understood == ALL) && (languages_spoken == ALL))
|
||||
languages_spoken = on_already ? (HUMAN | ROBOT) : ALL
|
||||
languages_understood = on_already ? (HUMAN | ROBOT) : ALL
|
||||
if(!HAS_SECONDARY_FLAG(src, OMNITONGUE))
|
||||
grant_all_languages(TRUE)
|
||||
// this is PERMAMENT.
|
||||
if("doorjack")
|
||||
if(href_list["jack"])
|
||||
if(src.cable && src.cable.machine)
|
||||
@@ -313,7 +313,8 @@
|
||||
if(s == "medical HUD")
|
||||
dat += "<a href='byond://?src=\ref[src];software=medicalhud;sub=0'>Medical Analysis Suite</a>[(src.medHUD) ? "<font color=#55FF55> On</font>" : "<font color=#FF5555> Off</font>"] <br>"
|
||||
if(s == "universal translator")
|
||||
dat += "<a href='byond://?src=\ref[src];software=translator;sub=0'>Universal Translator</a>[((languages_spoken == ALL) && (languages_understood == ALL)) ? "<font color=#55FF55> On</font>" : "<font color=#FF5555> Off</font>"] <br>"
|
||||
var/translator_on = HAS_SECONDARY_FLAG(src, OMNITONGUE)
|
||||
dat += "<a href='byond://?src=\ref[src];software=translator;sub=0'>Universal Translator</a>[translator_on ? "<font color=#55FF55> On</font>" : "<font color=#FF5555> Off</font>"] <br>"
|
||||
if(s == "projection array")
|
||||
dat += "<a href='byond://?src=\ref[src];software=projectionarray;sub=0'>Projection Array</a> <br>"
|
||||
if(s == "camera jack")
|
||||
@@ -413,8 +414,8 @@
|
||||
// Crew Manifest
|
||||
/mob/living/silicon/pai/proc/softwareManifest()
|
||||
. += "<h2>Crew Manifest</h2><br><br>"
|
||||
if(data_core.general)
|
||||
for(var/datum/data/record/t in sortRecord(data_core.general))
|
||||
if(GLOB.data_core.general)
|
||||
for(var/datum/data/record/t in sortRecord(GLOB.data_core.general))
|
||||
. += "[t.fields["name"]] - [t.fields["rank"]]<BR>"
|
||||
. += "</body></html>"
|
||||
return .
|
||||
@@ -424,16 +425,16 @@
|
||||
switch(subscreen)
|
||||
if(0)
|
||||
. += "<h3>Medical Records</h3><HR>"
|
||||
if(data_core.general)
|
||||
for(var/datum/data/record/R in sortRecord(data_core.general))
|
||||
if(GLOB.data_core.general)
|
||||
for(var/datum/data/record/R in sortRecord(GLOB.data_core.general))
|
||||
. += "<A href='?src=\ref[src];med_rec=[R.fields["id"]];software=medicalrecord;sub=1'>[R.fields["id"]]: [R.fields["name"]]<BR>"
|
||||
if(1)
|
||||
. += "<CENTER><B>Medical Record</B></CENTER><BR>"
|
||||
if(medicalActive1 in data_core.general)
|
||||
if(medicalActive1 in GLOB.data_core.general)
|
||||
. += "Name: [medicalActive1.fields["name"]] ID: [medicalActive1.fields["id"]]<BR>\nSex: [medicalActive1.fields["sex"]]<BR>\nAge: [medicalActive1.fields["age"]]<BR>\nFingerprint: [medicalActive1.fields["fingerprint"]]<BR>\nPhysical Status: [medicalActive1.fields["p_stat"]]<BR>\nMental Status: [medicalActive1.fields["m_stat"]]<BR>"
|
||||
else
|
||||
. += "<pre>Requested medical record not found.</pre><BR>"
|
||||
if(medicalActive2 in data_core.medical)
|
||||
if(medicalActive2 in GLOB.data_core.medical)
|
||||
. += "<BR>\n<CENTER><B>Medical Data</B></CENTER><BR>\nBlood Type: <A href='?src=\ref[src];field=blood_type'>[medicalActive2.fields["blood_type"]]</A><BR>\nDNA: <A href='?src=\ref[src];field=b_dna'>[medicalActive2.fields["b_dna"]]</A><BR>\n<BR>\nMinor Disabilities: <A href='?src=\ref[src];field=mi_dis'>[medicalActive2.fields["mi_dis"]]</A><BR>\nDetails: <A href='?src=\ref[src];field=mi_dis_d'>[medicalActive2.fields["mi_dis_d"]]</A><BR>\n<BR>\nMajor Disabilities: <A href='?src=\ref[src];field=ma_dis'>[medicalActive2.fields["ma_dis"]]</A><BR>\nDetails: <A href='?src=\ref[src];field=ma_dis_d'>[medicalActive2.fields["ma_dis_d"]]</A><BR>\n<BR>\nAllergies: <A href='?src=\ref[src];field=alg'>[medicalActive2.fields["alg"]]</A><BR>\nDetails: <A href='?src=\ref[src];field=alg_d'>[medicalActive2.fields["alg_d"]]</A><BR>\n<BR>\nCurrent Diseases: <A href='?src=\ref[src];field=cdi'>[medicalActive2.fields["cdi"]]</A> (per disease info placed in log/comment section)<BR>\nDetails: <A href='?src=\ref[src];field=cdi_d'>[medicalActive2.fields["cdi_d"]]</A><BR>\n<BR>\nImportant Notes:<BR>\n\t<A href='?src=\ref[src];field=notes'>[medicalActive2.fields["notes"]]</A><BR>\n<BR>\n<CENTER><B>Comments/Log</B></CENTER><BR>"
|
||||
else
|
||||
. += "<pre>Requested medical record not found.</pre><BR>"
|
||||
@@ -446,16 +447,16 @@
|
||||
switch(subscreen)
|
||||
if(0)
|
||||
. += "<h3>Security Records</h3><HR>"
|
||||
if(data_core.general)
|
||||
for(var/datum/data/record/R in sortRecord(data_core.general))
|
||||
if(GLOB.data_core.general)
|
||||
for(var/datum/data/record/R in sortRecord(GLOB.data_core.general))
|
||||
. += "<A href='?src=\ref[src];sec_rec=[R.fields["id"]];software=securityrecord;sub=1'>[R.fields["id"]]: [R.fields["name"]]<BR>"
|
||||
if(1)
|
||||
. += "<h3>Security Record</h3>"
|
||||
if(securityActive1 in data_core.general)
|
||||
if(securityActive1 in GLOB.data_core.general)
|
||||
. += "Name: <A href='?src=\ref[src];field=name'>[securityActive1.fields["name"]]</A> ID: <A href='?src=\ref[src];field=id'>[securityActive1.fields["id"]]</A><BR>\nSex: <A href='?src=\ref[src];field=sex'>[securityActive1.fields["sex"]]</A><BR>\nAge: <A href='?src=\ref[src];field=age'>[securityActive1.fields["age"]]</A><BR>\nRank: <A href='?src=\ref[src];field=rank'>[securityActive1.fields["rank"]]</A><BR>\nFingerprint: <A href='?src=\ref[src];field=fingerprint'>[securityActive1.fields["fingerprint"]]</A><BR>\nPhysical Status: [securityActive1.fields["p_stat"]]<BR>\nMental Status: [securityActive1.fields["m_stat"]]<BR>"
|
||||
else
|
||||
. += "<pre>Requested security record not found,</pre><BR>"
|
||||
if(securityActive2 in data_core.security)
|
||||
if(securityActive2 in GLOB.data_core.security)
|
||||
. += "<BR>\nSecurity Data<BR>\nCriminal Status: [securityActive2.fields["criminal"]]<BR>\n<BR>\nMinor Crimes: <A href='?src=\ref[src];field=mi_crim'>[securityActive2.fields["mi_crim"]]</A><BR>\nDetails: <A href='?src=\ref[src];field=mi_crim_d'>[securityActive2.fields["mi_crim_d"]]</A><BR>\n<BR>\nMajor Crimes: <A href='?src=\ref[src];field=ma_crim'>[securityActive2.fields["ma_crim"]]</A><BR>\nDetails: <A href='?src=\ref[src];field=ma_crim_d'>[securityActive2.fields["ma_crim_d"]]</A><BR>\n<BR>\nImportant Notes:<BR>\n\t<A href='?src=\ref[src];field=notes'>[securityActive2.fields["notes"]]</A><BR>\n<BR>\n<CENTER><B>Comments/Log</B></CENTER><BR>"
|
||||
else
|
||||
. += "<pre>Requested security record not found,</pre><BR>"
|
||||
@@ -464,11 +465,10 @@
|
||||
|
||||
// Universal Translator
|
||||
/mob/living/silicon/pai/proc/softwareTranslator()
|
||||
var/translator_on = HAS_SECONDARY_FLAG(src, OMNITONGUE)
|
||||
. = {"<h3>Universal Translator</h3><br>
|
||||
When enabled, this device will automatically convert all spoken and written language into a format that any known recipient can understand.<br><br>
|
||||
The device is currently [ ((languages_spoken == ALL) && (languages_understood == ALL)) ? "<font color=#55FF55>en" : "<font color=#FF5555>dis" ]abled.</font><br>
|
||||
<a href='byond://?src=\ref[src];software=translator;sub=0;toggle=1'>Toggle Device</a><br>
|
||||
"}
|
||||
When enabled, this device will permamently be able to speak and understand all known forms of communication.<br><br>
|
||||
The device is currently [translator_on ? "<font color=#55FF55>en" : "<font color=#FF5555>dis" ]abled.</font><br>[translator_on ? "" : "<a href='byond://?src=\ref[src];software=translator;sub=0;toggle=1'>Activate Translation Module</a><br>"]"}
|
||||
return .
|
||||
|
||||
// Security HUD
|
||||
@@ -599,7 +599,7 @@
|
||||
// Door Jack - supporting proc
|
||||
/mob/living/silicon/pai/proc/hackloop()
|
||||
var/turf/T = get_turf(src.loc)
|
||||
for(var/mob/living/silicon/ai/AI in player_list)
|
||||
for(var/mob/living/silicon/ai/AI in GLOB.player_list)
|
||||
if(T.loc)
|
||||
to_chat(AI, "<font color = red><b>Network Alert: Brute-force encryption crack in progress in [T.loc].</b></font>")
|
||||
else
|
||||
|
||||
@@ -36,9 +36,11 @@
|
||||
if(is_servant_of_ratvar(src) && user.Adjacent(src) && !stat) //To counter pseudo-stealth by using headlamps
|
||||
msg += "<span class='warning'>Its eyes are glowing a blazing yellow!</span>\n"
|
||||
|
||||
switch(src.stat)
|
||||
switch(stat)
|
||||
if(CONSCIOUS)
|
||||
if(!src.client)
|
||||
if(shell)
|
||||
msg += "It appears to be an [deployed ? "active" : "empty"] AI shell.\n"
|
||||
else if(!client)
|
||||
msg += "It appears to be in stand-by mode.\n" //afk
|
||||
if(UNCONSCIOUS)
|
||||
msg += "<span class='warning'>It doesn't seem to be responding.</span>\n"
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
|
||||
to_chat(who, "<b>Obey these laws:</b>")
|
||||
laws.show_laws(who)
|
||||
if (is_special_character(src) && connected_ai)
|
||||
if (shell) //AI shell
|
||||
to_chat(who, "<b>Remember, you are an AI remotely controlling your shell, other AIs can be ignored.</b>")
|
||||
else if (is_special_character(src) && connected_ai)
|
||||
to_chat(who, "<b>Remember, [connected_ai.name] is technically your master, but your objective comes first.</b>")
|
||||
else if (connected_ai)
|
||||
to_chat(who, "<b>Remember, [connected_ai.name] is your master, other AIs can be ignored.</b>")
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
update_cell_hud_icon()
|
||||
|
||||
if(syndicate)
|
||||
if(ticker.mode.name == "traitor")
|
||||
for(var/datum/mind/tra in ticker.mode.traitors)
|
||||
if(SSticker.mode.name == "traitor")
|
||||
for(var/datum/mind/tra in SSticker.mode.traitors)
|
||||
if(tra.current)
|
||||
var/I = image('icons/mob/mob.dmi', loc = tra.current, icon_state = "traitor") //no traitor sprite in that dmi!
|
||||
src.client.images += I
|
||||
@@ -48,7 +48,7 @@
|
||||
if(mind)
|
||||
if(!mind.special_role)
|
||||
mind.special_role = "traitor"
|
||||
ticker.mode.traitors += mind
|
||||
SSticker.mode.traitors += mind
|
||||
|
||||
|
||||
/mob/living/silicon/robot/update_health_hud()
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
regenerate_icons()
|
||||
show_laws(0)
|
||||
if(mind)
|
||||
ticker.mode.remove_revolutionary(mind)
|
||||
ticker.mode.remove_gangster(mind,1,remove_bosses=1)
|
||||
SSticker.mode.remove_revolutionary(mind)
|
||||
SSticker.mode.remove_gangster(mind,1,remove_bosses=1)
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
var/obj/item/robot_suit/robot_suit = null //Used for deconstruction to remember what the borg was constructed out of..
|
||||
var/obj/item/device/mmi/mmi = null
|
||||
|
||||
var/shell = FALSE
|
||||
var/deployed = FALSE
|
||||
var/mob/living/silicon/ai/mainframe = null
|
||||
var/datum/action/innate/undeployment/undeployment_action = new
|
||||
|
||||
//Hud stuff
|
||||
|
||||
@@ -47,7 +51,7 @@
|
||||
|
||||
var/ident = 0
|
||||
var/locked = 1
|
||||
var/list/req_access = list(access_robotics)
|
||||
var/list/req_access = list(GLOB.access_robotics)
|
||||
|
||||
var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list(), "Burglar"=list())
|
||||
|
||||
@@ -73,7 +77,7 @@
|
||||
|
||||
var/sight_mode = 0
|
||||
var/updating = 0 //portable camera camerachunk update
|
||||
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD)
|
||||
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_TRACK_HUD)
|
||||
|
||||
var/list/upgrades = list()
|
||||
|
||||
@@ -129,8 +133,12 @@
|
||||
update_icons()
|
||||
..()
|
||||
|
||||
//If this body is meant to be a borg controlled by the AI player
|
||||
if(shell)
|
||||
make_shell()
|
||||
|
||||
//MMI stuff. Held togheter by magic. ~Miauw
|
||||
if(!mmi || !mmi.brainmob)
|
||||
else if(!mmi || !mmi.brainmob)
|
||||
mmi = new (src)
|
||||
mmi.brain = new /obj/item/organ/brain(mmi)
|
||||
mmi.brain.name = "[real_name]'s brain"
|
||||
@@ -159,8 +167,8 @@
|
||||
if(mmi.brainmob)
|
||||
if(mmi.brainmob.stat == DEAD)
|
||||
mmi.brainmob.stat = CONSCIOUS
|
||||
dead_mob_list -= mmi.brainmob
|
||||
living_mob_list += mmi.brainmob
|
||||
GLOB.dead_mob_list -= mmi.brainmob
|
||||
GLOB.living_mob_list += mmi.brainmob
|
||||
mind.transfer_to(mmi.brainmob)
|
||||
mmi.update_icon()
|
||||
else
|
||||
@@ -170,6 +178,8 @@
|
||||
mmi = null
|
||||
if(connected_ai)
|
||||
connected_ai.connected_robots -= src
|
||||
if(shell)
|
||||
GLOB.available_ai_shells -= src
|
||||
qdel(wires)
|
||||
qdel(module)
|
||||
qdel(eye_lights)
|
||||
@@ -204,6 +214,8 @@
|
||||
|
||||
|
||||
/mob/living/silicon/robot/proc/updatename()
|
||||
if(shell)
|
||||
return
|
||||
var/changed_name = ""
|
||||
if(custom_name)
|
||||
changed_name = custom_name
|
||||
@@ -424,7 +436,9 @@
|
||||
update_icons()
|
||||
|
||||
else if(istype(W, /obj/item/weapon/screwdriver) && opened && cell) // radio
|
||||
if(radio)
|
||||
if(shell)
|
||||
to_chat(user, "You cannot seem to open the radio compartment") //Prevent AI radio key theft
|
||||
else if(radio)
|
||||
radio.attackby(W,user)//Push it to the radio to let it handle everything
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Unable to locate a radio!</span>")
|
||||
@@ -453,6 +467,9 @@
|
||||
if(!cell)
|
||||
to_chat(user, "<span class='warning'>You need to install a power cell to do that!</span>")
|
||||
return
|
||||
if(shell) //AI shells always have the laws of the AI
|
||||
to_chat(user, "<span class='warning'>[src] is controlled remotely! You cannot upload new laws this way!</span>")
|
||||
return
|
||||
if(emagged || (connected_ai && lawupdate)) //Can't be sure which, metagamers
|
||||
emote("buzz-[user.name]")
|
||||
return
|
||||
@@ -594,7 +611,7 @@
|
||||
|
||||
/mob/living/silicon/robot/proc/do_camera_update(oldLoc)
|
||||
if(oldLoc != src.loc)
|
||||
cameranet.updatePortableCamera(src.camera)
|
||||
GLOB.cameranet.updatePortableCamera(src.camera)
|
||||
updating = 0
|
||||
|
||||
/mob/living/silicon/robot/Move(a, b, flag)
|
||||
@@ -606,36 +623,6 @@
|
||||
updating = 1
|
||||
addtimer(CALLBACK(src, .proc/do_camera_update, oldLoc), BORG_CAMERA_BUFFER)
|
||||
if(module)
|
||||
if(istype(module, /obj/item/weapon/robot_module/janitor))
|
||||
var/turf/tile = loc
|
||||
if(isturf(tile))
|
||||
tile.clean_blood()
|
||||
for(var/A in tile)
|
||||
if(is_cleanable(A))
|
||||
qdel(A)
|
||||
else if(istype(A, /obj/item))
|
||||
var/obj/item/cleaned_item = A
|
||||
cleaned_item.clean_blood()
|
||||
else if(ishuman(A))
|
||||
var/mob/living/carbon/human/cleaned_human = A
|
||||
if(cleaned_human.lying)
|
||||
if(cleaned_human.head)
|
||||
cleaned_human.head.clean_blood()
|
||||
cleaned_human.update_inv_head()
|
||||
if(cleaned_human.wear_suit)
|
||||
cleaned_human.wear_suit.clean_blood()
|
||||
cleaned_human.update_inv_wear_suit()
|
||||
else if(cleaned_human.w_uniform)
|
||||
cleaned_human.w_uniform.clean_blood()
|
||||
cleaned_human.update_inv_w_uniform()
|
||||
if(cleaned_human.shoes)
|
||||
cleaned_human.shoes.clean_blood()
|
||||
cleaned_human.update_inv_shoes()
|
||||
cleaned_human.clean_blood()
|
||||
cleaned_human.wash_cream()
|
||||
to_chat(cleaned_human, "<span class='danger'>[src] cleans your face!</span>")
|
||||
return
|
||||
|
||||
if(istype(module, /obj/item/weapon/robot_module/miner))
|
||||
if(istype(loc, /turf/open/floor/plating/asteroid))
|
||||
for(var/obj/item/I in held_items)
|
||||
@@ -806,7 +793,7 @@
|
||||
icon_state = "syndie_bloodhound"
|
||||
faction = list("syndicate")
|
||||
bubble_icon = "syndibot"
|
||||
req_access = list(access_syndicate)
|
||||
req_access = list(GLOB.access_syndicate)
|
||||
lawupdate = FALSE
|
||||
scrambledcodes = TRUE // These are rogue borgs.
|
||||
ionpulse = TRUE
|
||||
@@ -829,6 +816,9 @@
|
||||
if(playstyle_string)
|
||||
to_chat(src, playstyle_string)
|
||||
|
||||
/mob/living/silicon/robot/syndicate/ResetModule()
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/syndicate/medical
|
||||
icon_state = "syndi-medi"
|
||||
playstyle_string = "<span class='userdanger'>You are a Syndicate medical cyborg!</span><br>\
|
||||
@@ -843,12 +833,14 @@
|
||||
if(!connected_ai)
|
||||
return
|
||||
switch(notifytype)
|
||||
if(1) //New Cyborg
|
||||
if(NEW_BORG) //New Cyborg
|
||||
to_chat(connected_ai, "<br><br><span class='notice'>NOTICE - New cyborg connection detected: <a href='?src=\ref[connected_ai];track=[html_encode(name)]'>[name]</a></span><br>")
|
||||
if(2) //New Module
|
||||
if(NEW_MODULE) //New Module
|
||||
to_chat(connected_ai, "<br><br><span class='notice'>NOTICE - Cyborg module change detected: [name] has loaded the [designation] module.</span><br>")
|
||||
if(3) //New Name
|
||||
if(RENAME) //New Name
|
||||
to_chat(connected_ai, "<br><br><span class='notice'>NOTICE - Cyborg reclassification detected: [oldname] is now designated as [newname].</span><br>")
|
||||
if(AI_SHELL) //New Shell
|
||||
to_chat(connected_ai, "<br><br><span class='notice'>NOTICE - New cyborg shell detected: <a href='?src=\ref[connected_ai];track=[html_encode(name)]'>[name]</a></span><br>")
|
||||
|
||||
/mob/living/silicon/robot/canUseTopic(atom/movable/M, be_close = 0)
|
||||
if(stat || lockcharge || low_power_mode)
|
||||
@@ -889,12 +881,12 @@
|
||||
|
||||
if(sight_mode & BORGMESON)
|
||||
sight |= SEE_TURFS
|
||||
see_invisible = min(see_invisible, SEE_INVISIBLE_MINIMUM)
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
|
||||
see_in_dark = 1
|
||||
|
||||
if(sight_mode & BORGMATERIAL)
|
||||
sight |= SEE_OBJS
|
||||
see_invisible = min(see_invisible, SEE_INVISIBLE_MINIMUM)
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
see_in_dark = 1
|
||||
|
||||
if(sight_mode & BORGXRAY)
|
||||
@@ -909,6 +901,7 @@
|
||||
|
||||
if(see_override)
|
||||
see_invisible = see_override
|
||||
sync_lighting_plane_alpha()
|
||||
|
||||
/mob/living/silicon/robot/update_stat()
|
||||
if(status_flags & GODMODE)
|
||||
@@ -931,6 +924,7 @@
|
||||
update_headlamp()
|
||||
diag_hud_set_status()
|
||||
diag_hud_set_health()
|
||||
diag_hud_set_aishell()
|
||||
update_health_hud()
|
||||
|
||||
/mob/living/silicon/robot/revive(full_heal = 0, admin_revive = 0)
|
||||
@@ -940,13 +934,13 @@
|
||||
update_headlamp()
|
||||
if(admin_revive)
|
||||
locked = 1
|
||||
notify_ai(1)
|
||||
notify_ai(NEW_BORG)
|
||||
. = 1
|
||||
|
||||
/mob/living/silicon/robot/fully_replace_character_name(oldname, newname)
|
||||
..()
|
||||
if(oldname != real_name)
|
||||
notify_ai(3, oldname, newname)
|
||||
notify_ai(RENAME, oldname, newname)
|
||||
if(camera)
|
||||
camera.c_tag = real_name
|
||||
custom_name = newname
|
||||
@@ -967,6 +961,7 @@
|
||||
|
||||
speed = 0
|
||||
ionpulse = FALSE
|
||||
revert_shell()
|
||||
|
||||
return 1
|
||||
|
||||
@@ -985,6 +980,11 @@
|
||||
else
|
||||
status_flags &= ~CANPUSH
|
||||
|
||||
if(module.clean_on_move)
|
||||
flags |= CLEAN_ON_MOVE
|
||||
else
|
||||
flags &= ~CLEAN_ON_MOVE
|
||||
|
||||
hat_offset = module.hat_offset
|
||||
|
||||
magpulse = module.magpulsing
|
||||
@@ -998,6 +998,97 @@
|
||||
new_hat.forceMove(src)
|
||||
update_icons()
|
||||
|
||||
/mob/living/silicon/robot/proc/make_shell(var/obj/item/borg/upgrade/ai/board)
|
||||
if(!board)
|
||||
upgrades |= new /obj/item/borg/upgrade/ai(src)
|
||||
shell = TRUE
|
||||
braintype = "AI Shell"
|
||||
name = "[designation] AI Shell [rand(100,999)]"
|
||||
real_name = name
|
||||
GLOB.available_ai_shells |= src
|
||||
if(camera)
|
||||
camera.c_tag = real_name //update the camera name too
|
||||
diag_hud_set_aishell()
|
||||
notify_ai(AI_SHELL)
|
||||
|
||||
/mob/living/silicon/robot/proc/revert_shell()
|
||||
if(!shell)
|
||||
return
|
||||
undeploy()
|
||||
for(var/obj/item/borg/upgrade/ai/boris in src)
|
||||
//A player forced reset of a borg would drop the module before this is called, so this is for catching edge cases
|
||||
qdel(boris)
|
||||
shell = FALSE
|
||||
GLOB.available_ai_shells -= src
|
||||
name = "Unformatted Cyborg [rand(100,999)]"
|
||||
real_name = name
|
||||
if(camera)
|
||||
camera.c_tag = real_name
|
||||
diag_hud_set_aishell()
|
||||
|
||||
/mob/living/silicon/robot/proc/deploy_init(var/mob/living/silicon/ai/AI)
|
||||
real_name = "[AI.real_name] shell [rand(100, 999)] - [designation]" //Randomizing the name so it shows up seperately in the shells list
|
||||
name = real_name
|
||||
if(camera)
|
||||
camera.c_tag = real_name //update the camera name too
|
||||
mainframe = AI
|
||||
deployed = TRUE
|
||||
connected_ai = mainframe
|
||||
mainframe.connected_robots |= src
|
||||
lawupdate = TRUE
|
||||
lawsync()
|
||||
if(radio && AI.radio) //AI keeps all channels, including Syndie if it is a Traitor
|
||||
if(AI.radio.syndie)
|
||||
radio.make_syndie()
|
||||
radio.subspace_transmission = TRUE
|
||||
radio.channels = AI.radio.channels
|
||||
for(var/chan in radio.channels)
|
||||
radio.secure_radio_connections[chan] = add_radio(radio, GLOB.radiochannels[chan])
|
||||
|
||||
diag_hud_set_aishell()
|
||||
undeployment_action.Grant(src)
|
||||
|
||||
/datum/action/innate/undeployment
|
||||
name = "Disconnect from shell"
|
||||
desc = "Stop controlling your shell and resume normal core operations."
|
||||
button_icon_state = "ai_core"
|
||||
|
||||
/datum/action/innate/undeployment/Trigger()
|
||||
if(!..())
|
||||
return FALSE
|
||||
var/mob/living/silicon/robot/R = owner
|
||||
|
||||
R.undeploy()
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/living/silicon/robot/proc/undeploy()
|
||||
|
||||
if(!deployed || !mind || !mainframe)
|
||||
return
|
||||
mainframe.redeploy_action.Grant(mainframe)
|
||||
mainframe.redeploy_action.last_used_shell = src
|
||||
mind.transfer_to(mainframe)
|
||||
deployed = FALSE
|
||||
mainframe.deployed_shell = null
|
||||
undeployment_action.Remove(src)
|
||||
if(radio) //Return radio to normal
|
||||
radio.recalculateChannels()
|
||||
if(camera)
|
||||
camera.c_tag = real_name //update the camera name too
|
||||
diag_hud_set_aishell()
|
||||
mainframe.diag_hud_set_deployed()
|
||||
mainframe.show_laws() //Always remind the AI when switching
|
||||
mainframe = null
|
||||
|
||||
/mob/living/silicon/robot/attack_ai(mob/user)
|
||||
if(shell && (!connected_ai || connected_ai == user))
|
||||
var/mob/living/silicon/ai/AI = user
|
||||
AI.deploy_to_shell(src)
|
||||
|
||||
/mob/living/silicon/robot/shell
|
||||
shell = TRUE
|
||||
|
||||
/mob/living/silicon/robot/MouseDrop_T(mob/living/M, mob/living/user)
|
||||
. = ..()
|
||||
if(!(M in buckled_mobs) && isliving(M))
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
if (M.a_intent == INTENT_DISARM)
|
||||
if(!(lying))
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
|
||||
if(get_active_held_item())
|
||||
var/obj/item/I = get_active_held_item()
|
||||
if(I)
|
||||
uneq_active()
|
||||
visible_message("<span class='danger'>[M] disarmed [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has disabled [src]'s active module!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
add_logs(M, src, "disarmed")
|
||||
add_logs(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
|
||||
else
|
||||
Stun(2)
|
||||
step(src,get_dir(M,src))
|
||||
@@ -92,6 +93,8 @@
|
||||
if(locked)
|
||||
to_chat(user, "<span class='notice'>You emag the cover lock.</span>")
|
||||
locked = 0
|
||||
if(shell) //A warning to Traitors who may not know that emagging AI shells does not slave them.
|
||||
to_chat(user, "<span class='boldwarning'>[src] seems to be controlled remotely! Emagging the interface may not work as expected.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The cover is already unlocked!</span>")
|
||||
return
|
||||
@@ -125,6 +128,12 @@
|
||||
log_game("[key_name(user)] attempted to emag cyborg [key_name(src)], but they were slaved to traitor AI [connected_ai].")
|
||||
return
|
||||
|
||||
if(shell) //AI shells cannot be emagged, so we try to make it look like a standard reset. Smart players may see through this, however.
|
||||
to_chat(user, "<span class='danger'>[src] is remotely controlled! Your emag attempt has triggered a system reset instead!</span>")
|
||||
log_game("[key_name(user)] attempted to emag an AI shell belonging to [key_name(src) ? key_name(src) : connected_ai]. The shell has been reset as a result.")
|
||||
ResetModule()
|
||||
return
|
||||
|
||||
SetEmagged(1)
|
||||
SetStunned(3) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown
|
||||
lawupdate = 0
|
||||
@@ -132,7 +141,7 @@
|
||||
message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.")
|
||||
log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.")
|
||||
var/time = time2text(world.realtime,"hh:mm:ss")
|
||||
lawchanges.Add("[time] <B>:</B> [user.name]([user.key]) emagged [name]([key])")
|
||||
GLOB.lawchanges.Add("[time] <B>:</B> [user.name]([user.key]) emagged [name]([key])")
|
||||
to_chat(src, "<span class='danger'>ALERT: Foreign software detected.</span>")
|
||||
sleep(5)
|
||||
to_chat(src, "<span class='danger'>Initiating diagnostics...</span>")
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
var/can_be_pushed = TRUE
|
||||
var/magpulsing = FALSE
|
||||
var/clean_on_move = FALSE
|
||||
|
||||
var/did_feedback = FALSE
|
||||
var/feedback_key
|
||||
@@ -217,7 +218,7 @@
|
||||
R.SetLockdown(0)
|
||||
R.anchored = FALSE
|
||||
R.notransform = FALSE
|
||||
R.notify_ai(2)
|
||||
R.notify_ai(NEW_MODULE)
|
||||
if(R.hud_used)
|
||||
R.hud_used.update_robot_modules_display()
|
||||
if(feedback_key && !did_feedback)
|
||||
@@ -228,8 +229,17 @@
|
||||
basic_modules = list(
|
||||
/obj/item/device/assembly/flash/cyborg,
|
||||
/obj/item/weapon/reagent_containers/borghypo/epi,
|
||||
/obj/item/device/healthanalyzer,
|
||||
/obj/item/weapon/weldingtool/largetank/cyborg,
|
||||
/obj/item/weapon/wrench/cyborg,
|
||||
/obj/item/weapon/crowbar/cyborg,
|
||||
/obj/item/stack/sheet/metal/cyborg,
|
||||
/obj/item/stack/rods/cyborg,
|
||||
/obj/item/stack/tile/plasteel/cyborg,
|
||||
/obj/item/weapon/extinguisher,
|
||||
/obj/item/weapon/pickaxe,
|
||||
/obj/item/device/t_scanner/adv_mining_scanner,
|
||||
/obj/item/weapon/restraints/handcuffs/cable/zipties/cyborg,
|
||||
/obj/item/weapon/soap/nanotrasen,
|
||||
/obj/item/borg/cyborghug)
|
||||
emag_modules = list(/obj/item/weapon/melee/energy/sword/cyborg)
|
||||
@@ -382,6 +392,7 @@
|
||||
moduleselect_icon = "janitor"
|
||||
feedback_key = "cyborg_janitor"
|
||||
hat_offset = -5
|
||||
clean_on_move = TRUE
|
||||
|
||||
/obj/item/weapon/reagent_containers/spray/cyborg_drying
|
||||
name = "drying agent spray"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
desig = trim_left(S.designation + " " + S.job)
|
||||
var/message_a = say_quote(message, get_spans())
|
||||
var/rendered = "<i><span class='game say'>Robotic Talk, <span class='name'>[name]</span> <span class='message'>[message_a]</span></span></i>"
|
||||
for(var/mob/M in player_list)
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M.binarycheck())
|
||||
if(isAI(M))
|
||||
var/renderedAI = "<i><span class='game say'>Robotic Talk, <a href='?src=\ref[M];track=[html_encode(name)]'><span class='name'>[name] ([desig])</span></a> <span class='message'>[message_a]</span></span></i>"
|
||||
@@ -33,19 +33,19 @@
|
||||
/mob/living/silicon/lingcheck()
|
||||
return 0 //Borged or AI'd lings can't speak on the ling channel.
|
||||
|
||||
/mob/living/silicon/radio(message, message_mode, list/spans)
|
||||
/mob/living/silicon/radio(message, message_mode, list/spans, language)
|
||||
. = ..()
|
||||
if(. != 0)
|
||||
return .
|
||||
|
||||
if(message_mode == "robot")
|
||||
if (radio)
|
||||
radio.talk_into(src, message, , spans)
|
||||
radio.talk_into(src, message, , spans, language)
|
||||
return REDUCE_RANGE
|
||||
|
||||
else if(message_mode in radiochannels)
|
||||
else if(message_mode in GLOB.radiochannels)
|
||||
if(radio)
|
||||
radio.talk_into(src, message, message_mode, spans)
|
||||
radio.talk_into(src, message, message_mode, spans, language)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
|
||||
return 0
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
/mob/living/silicon
|
||||
gender = NEUTER
|
||||
voice_name = "synthesized voice"
|
||||
languages_spoken = ROBOT | HUMAN
|
||||
languages_understood = ROBOT | HUMAN
|
||||
has_unlimited_silicon_privilege = 1
|
||||
verb_say = "states"
|
||||
verb_ask = "queries"
|
||||
verb_exclaim = "declares"
|
||||
verb_yell = "alarms"
|
||||
initial_languages = list(/datum/language/common, /datum/language/machine)
|
||||
see_in_dark = 8
|
||||
bubble_icon = "machine"
|
||||
weather_immunities = list("ash")
|
||||
@@ -21,8 +20,7 @@
|
||||
var/designation = ""
|
||||
var/radiomod = "" //Radio character used before state laws/arrivals announce to allow department transmissions, default, or none at all.
|
||||
var/obj/item/device/camera/siliconcam/aicamera = null //photography
|
||||
//hud_possible = list(DIAG_STAT_HUD, DIAG_HUD, ANTAG_HUD)
|
||||
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD)
|
||||
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_TRACK_HUD)
|
||||
|
||||
var/obj/item/device/radio/borg/radio = null //AIs dont use this but this is at the silicon level to advoid copypasta in say()
|
||||
|
||||
@@ -41,8 +39,8 @@
|
||||
|
||||
/mob/living/silicon/Initialize()
|
||||
..()
|
||||
silicon_mobs += src
|
||||
var/datum/atom_hud/data/diagnostic/diag_hud = huds[DATA_HUD_DIAGNOSTIC]
|
||||
GLOB.silicon_mobs += src
|
||||
var/datum/atom_hud/data/diagnostic/diag_hud = GLOB.huds[DATA_HUD_DIAGNOSTIC]
|
||||
diag_hud.add_to_hud(src)
|
||||
diag_hud_set_status()
|
||||
diag_hud_set_health()
|
||||
@@ -56,7 +54,7 @@
|
||||
/mob/living/silicon/Destroy()
|
||||
radio = null
|
||||
aicamera = null
|
||||
silicon_mobs -= src
|
||||
GLOB.silicon_mobs -= src
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/contents_explosion(severity, target)
|
||||
@@ -307,8 +305,8 @@
|
||||
else if(Autochan == "None") //Prevents use of the radio for automatic annoucements.
|
||||
radiomod = ""
|
||||
else //For department channels, if any, given by the internal radio.
|
||||
for(var/key in department_radio_keys)
|
||||
if(department_radio_keys[key] == Autochan)
|
||||
for(var/key in GLOB.department_radio_keys)
|
||||
if(GLOB.department_radio_keys[key] == Autochan)
|
||||
radiomod = key
|
||||
break
|
||||
|
||||
@@ -327,23 +325,23 @@
|
||||
return -10
|
||||
|
||||
/mob/living/silicon/proc/remove_med_sec_hud()
|
||||
var/datum/atom_hud/secsensor = huds[sec_hud]
|
||||
var/datum/atom_hud/medsensor = huds[med_hud]
|
||||
var/datum/atom_hud/diagsensor = huds[d_hud]
|
||||
var/datum/atom_hud/secsensor = GLOB.huds[sec_hud]
|
||||
var/datum/atom_hud/medsensor = GLOB.huds[med_hud]
|
||||
var/datum/atom_hud/diagsensor = GLOB.huds[d_hud]
|
||||
secsensor.remove_hud_from(src)
|
||||
medsensor.remove_hud_from(src)
|
||||
diagsensor.remove_hud_from(src)
|
||||
|
||||
/mob/living/silicon/proc/add_sec_hud()
|
||||
var/datum/atom_hud/secsensor = huds[sec_hud]
|
||||
var/datum/atom_hud/secsensor = GLOB.huds[sec_hud]
|
||||
secsensor.add_hud_to(src)
|
||||
|
||||
/mob/living/silicon/proc/add_med_hud()
|
||||
var/datum/atom_hud/medsensor = huds[med_hud]
|
||||
var/datum/atom_hud/medsensor = GLOB.huds[med_hud]
|
||||
medsensor.add_hud_to(src)
|
||||
|
||||
/mob/living/silicon/proc/add_diag_hud()
|
||||
var/datum/atom_hud/diagsensor = huds[d_hud]
|
||||
var/datum/atom_hud/diagsensor = GLOB.huds[d_hud]
|
||||
diagsensor.add_hud_to(src)
|
||||
|
||||
/mob/living/silicon/proc/sensor_mode()
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
"<span class='userdanger'>[M] took a swipe at [src]!</span>")
|
||||
|
||||
/mob/living/silicon/attack_animal(mob/living/simple_animal/M)
|
||||
if(..())
|
||||
. = ..()
|
||||
if(.)
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
if(prob(damage))
|
||||
for(var/mob/living/N in buckled_mobs)
|
||||
@@ -44,7 +45,6 @@
|
||||
adjustCloneLoss(damage)
|
||||
if(STAMINA)
|
||||
adjustStaminaLoss(damage)
|
||||
updatehealth()
|
||||
|
||||
/mob/living/silicon/attack_paw(mob/living/user)
|
||||
return attack_hand(user)
|
||||
|
||||
Reference in New Issue
Block a user