Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into proc-define-shit
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
d_hud = DATA_HUD_DIAGNOSTIC_ADVANCED
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
has_field_of_vision = FALSE //Vision through cameras.
|
||||
var/battery = 200 //emergency power if the AI's APC is off
|
||||
var/list/network = list("ss13")
|
||||
var/obj/machinery/camera/current
|
||||
var/list/connected_robots = list()
|
||||
@@ -46,7 +47,7 @@
|
||||
var/obj/item/multitool/aiMulti
|
||||
var/mob/living/simple_animal/bot/Bot
|
||||
var/tracking = FALSE //this is 1 if the AI is currently tracking somebody, but the track has not yet been completed.
|
||||
var/datum/effect_system/spark_spread/spark_system//So they can initialize sparks whenever/N
|
||||
var/datum/effect_system/spark_spread/spark_system //So they can initialize sparks whenever/N
|
||||
var/obj/machinery/status_display/controlled_display
|
||||
|
||||
//MALFUNCTION
|
||||
@@ -83,7 +84,7 @@
|
||||
var/cooldown = 0
|
||||
var/acceleration = 1
|
||||
|
||||
var/obj/structure/AIcore/deactivated/linked_core //For exosuit control
|
||||
var/obj/structure/ai_core/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
|
||||
@@ -105,11 +106,17 @@
|
||||
///remember AI's last location
|
||||
var/atom/lastloc
|
||||
interaction_range = INFINITY
|
||||
///whether its mmi is a posibrain or regular mmi when going ai mob to ai core structure
|
||||
var/posibrain_inside = TRUE
|
||||
///whether its cover is opened, so you can wirecut it for deconstruction
|
||||
var/opened = FALSE
|
||||
///whether AI is anchored or not, used for checks
|
||||
var/is_anchored = TRUE
|
||||
|
||||
/mob/living/silicon/ai/Initialize(mapload, datum/ai_laws/L, mob/target_ai)
|
||||
. = ..()
|
||||
if(!target_ai) //If there is no player/brain inside.
|
||||
new/obj/structure/AIcore/deactivated(loc) //New empty terminal.
|
||||
new/obj/structure/ai_core/deactivated(loc) //New empty terminal.
|
||||
return INITIALIZE_HINT_QDEL //Delete AI.
|
||||
|
||||
ADD_TRAIT(src, TRAIT_NO_TELEPORT, src)
|
||||
@@ -125,6 +132,8 @@
|
||||
mind.store_memory("As an AI, you must obey your silicon laws above all else. Your objectives will consider you to be dead.")
|
||||
to_chat(src, "<span class='userdanger'>You have been installed as an AI! </span>")
|
||||
to_chat(src, "<span class='danger'>You must obey your silicon laws above all else. Your objectives will consider you to be dead.</span>")
|
||||
if(!mind.has_ever_been_ai)
|
||||
mind.has_ever_been_ai = TRUE
|
||||
|
||||
to_chat(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>")
|
||||
to_chat(src, "<B>To look at other parts of the station, click on yourself to get a camera menu.</B>")
|
||||
@@ -237,6 +246,8 @@
|
||||
. += text("Systems nonfunctional")
|
||||
return
|
||||
. += text("System integrity: [(health + 100) * 0.5]%")
|
||||
if(isturf(loc)) //only show if we're "in" a core
|
||||
. += "Backup Power: [battery * 0.5]%"
|
||||
. += text("Connected cyborgs: [length(connected_robots)]")
|
||||
for(var/r in connected_robots)
|
||||
var/mob/living/silicon/robot/connected_robot = r
|
||||
@@ -333,18 +344,64 @@
|
||||
if(!isturf(loc)) // if their location isn't a turf
|
||||
return // stop
|
||||
if(incapacitated())
|
||||
return
|
||||
var/is_anchored = FALSE
|
||||
if(move_resist == MOVE_FORCE_OVERPOWERING)
|
||||
if(battery < 50)
|
||||
to_chat(src, span_warning("Insufficient backup power!"))
|
||||
return
|
||||
battery = battery - 50
|
||||
to_chat(src, span_notice("You route power from your backup battery to move the bolts."))
|
||||
flip_anchored()
|
||||
to_chat(src, "<b>You are now [is_anchored ? "" : "un"]anchored.</b>")
|
||||
|
||||
/mob/living/silicon/ai/proc/flip_anchored()
|
||||
if(is_anchored)
|
||||
is_anchored = !is_anchored
|
||||
move_resist = MOVE_FORCE_NORMAL
|
||||
status_flags |= CANPUSH
|
||||
REMOVE_TRAIT(src, TRAIT_NO_TELEPORT, src)
|
||||
else
|
||||
is_anchored = TRUE
|
||||
is_anchored = !is_anchored
|
||||
move_resist = MOVE_FORCE_OVERPOWERING
|
||||
status_flags &= ~CANPUSH
|
||||
ADD_TRAIT(src, TRAIT_NO_TELEPORT, src)
|
||||
|
||||
to_chat(src, "<b>You are now [is_anchored ? "" : "un"]anchored.</b>")
|
||||
// the message in the [] will change depending whether or not the AI is anchored
|
||||
/mob/living/silicon/ai/proc/ai_mob_to_structure()
|
||||
disconnect_shell()
|
||||
ShutOffDoomsdayDevice()
|
||||
var/obj/structure/ai_core/deactivated/ai_core = new(get_turf(src), /* skip_mmi_creation = */ TRUE)
|
||||
if(make_mmi_drop_and_transfer(ai_core.core_mmi, the_core = ai_core))
|
||||
qdel(src)
|
||||
return ai_core
|
||||
|
||||
/mob/living/silicon/ai/proc/make_mmi_drop_and_transfer(obj/item/mmi/the_mmi, the_core)
|
||||
var/mmi_type
|
||||
if(posibrain_inside)
|
||||
mmi_type = new/obj/item/mmi/posibrain(src, /* autoping = */ FALSE)
|
||||
else
|
||||
mmi_type = new/obj/item/mmi(src)
|
||||
if(hack_software)
|
||||
new/obj/item/malf_upgrade(get_turf(src))
|
||||
the_mmi = mmi_type
|
||||
the_mmi.brain = new /obj/item/organ/brain(the_mmi)
|
||||
the_mmi.brain.organ_flags |= ORGAN_FROZEN
|
||||
the_mmi.brain.name = "[real_name]'s brain"
|
||||
the_mmi.name = "[initial(the_mmi.name)]: [real_name]"
|
||||
the_mmi.brainmob = new /mob/living/brain(the_mmi)
|
||||
the_mmi.brainmob.name = src.real_name
|
||||
the_mmi.brainmob.real_name = src.real_name
|
||||
the_mmi.brainmob.container = the_mmi
|
||||
the_mmi.brainmob.suiciding = suiciding
|
||||
if(the_core)
|
||||
var/obj/structure/ai_core/core = the_core
|
||||
core.core_mmi = the_mmi
|
||||
the_mmi.forceMove(the_core)
|
||||
else
|
||||
the_mmi.forceMove(get_turf(src))
|
||||
if(the_mmi.brainmob.stat == DEAD && !suiciding)
|
||||
the_mmi.brainmob.stat = CONSCIOUS
|
||||
if(mind)
|
||||
mind.transfer_to(the_mmi.brainmob)
|
||||
the_mmi.update_appearance()
|
||||
return TRUE
|
||||
|
||||
// AIs are immobile
|
||||
/mob/living/silicon/ai/update_mobility()
|
||||
@@ -427,18 +484,30 @@
|
||||
return
|
||||
|
||||
if (href_list["ai_take_control"]) //Mech domination
|
||||
var/obj/vehicle/sealed/mecha/M = locate(href_list["ai_take_control"])
|
||||
var/obj/vehicle/sealed/mecha/M = locate(href_list["ai_take_control"]) in GLOB.mechas_list
|
||||
if (!M)
|
||||
return
|
||||
|
||||
var/mech_has_controlbeacon = FALSE
|
||||
for(var/obj/item/mecha_parts/mecha_tracking/ai_control/A in M.trackers)
|
||||
mech_has_controlbeacon = TRUE
|
||||
break
|
||||
if(!can_dominate_mechs && !mech_has_controlbeacon)
|
||||
message_admins("Warning: possible href exploit by [key_name(usr)] - attempted control of a mecha without can_dominate_mechs or a control beacon in the mech.")
|
||||
usr.log_message("possibly attempting href exploit - attempted control of a mecha without can_dominate_mechs or a control beacon in the mech.", LOG_ADMIN)
|
||||
return
|
||||
|
||||
if(controlled_equipment)
|
||||
to_chat(src, "<span class='warning'>You are already loaded into an onboard computer!</span>")
|
||||
to_chat(src, span_warning("You are already loaded into an onboard computer!"))
|
||||
return
|
||||
if(!GLOB.cameranet.checkCameraVis(M))
|
||||
to_chat(src, "<span class='warning'>Exosuit is no longer near active cameras.</span>")
|
||||
to_chat(src, span_warning("Exosuit is no longer near active cameras."))
|
||||
return
|
||||
if(!isturf(loc))
|
||||
to_chat(src, "<span class='warning'>You aren't in your core!</span>")
|
||||
to_chat(src, span_warning("You aren't in your core!"))
|
||||
return
|
||||
if(M)
|
||||
M.transfer_ai(AI_MECH_HACK,src, usr) //Called om the mech itself.
|
||||
M.transfer_ai(AI_MECH_HACK, src, usr) //Called on the mech itself.
|
||||
|
||||
|
||||
/mob/living/silicon/ai/proc/switchCamera(obj/machinery/camera/C)
|
||||
@@ -549,7 +618,7 @@
|
||||
queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, home.name), class)
|
||||
if (viewalerts)
|
||||
ai_alerts()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/mob/living/silicon/ai/freeCamera(area/home, obj/machinery/camera/cam)
|
||||
for(var/class in alarms)
|
||||
@@ -825,17 +894,19 @@
|
||||
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.
|
||||
var/obj/structure/ai_core/new_core = new /obj/structure/ai_core/deactivated(loc, posibrain_inside)//Spawns a deactivated terminal at AI location.
|
||||
new_core.circuit.battery = battery
|
||||
ai_restore_power()//So the AI initially has power.
|
||||
control_disabled = 1//Can't control things remotely if you're stuck in a card!
|
||||
radio_enabled = 0 //No talking on the built-in radio for you either!
|
||||
control_disabled = TRUE //Can't control things remotely if you're stuck in a card!
|
||||
interaction_range = 0
|
||||
radio_enabled = FALSE //No talking on the built-in radio for you either!
|
||||
forceMove(card)
|
||||
card.AI = src
|
||||
to_chat(src, "You have been downloaded to a mobile storage device. Remote device connection severed.")
|
||||
to_chat(user, "<span class='boldnotice'>Transfer successful</span>: [name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory.")
|
||||
|
||||
/mob/living/silicon/ai/can_buckle()
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/mob/living/silicon/ai/incapacitated(ignore_restraints, ignore_grab)
|
||||
if(aiRestorePowerRoutine)
|
||||
@@ -1063,7 +1134,7 @@
|
||||
// Sends an announcement the AI has cryoed.
|
||||
var/obj/machinery/announcement_system/announcer = pick(GLOB.announcement_systems)
|
||||
announcer.announce("CRYOSTORAGE", src.real_name, announce_rank, list())
|
||||
new /obj/structure/AIcore/latejoin_inactive(loc)
|
||||
new /obj/structure/ai_core/latejoin_inactive(loc)
|
||||
if(src.mind)
|
||||
//Handle job slot/tater cleanup.
|
||||
if(src.mind.assigned_role == "AI")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(I.force && I.damtype != STAMINA && stat != DEAD) //only sparks if real damage is dealt.
|
||||
if(I.force && I.damtype != STAMINA && stat != DEAD && !QDELETED(src)) //only sparks if real damage is dealt.
|
||||
spark_system.start()
|
||||
|
||||
/mob/living/silicon/ai/attack_slime(mob/living/simple_animal/slime/user)
|
||||
@@ -12,8 +12,8 @@
|
||||
if (stat != DEAD)
|
||||
adjustBruteLoss(60)
|
||||
updatehealth()
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/silicon/ai/emp_act(severity)
|
||||
. = ..()
|
||||
@@ -48,3 +48,105 @@
|
||||
|
||||
/mob/living/silicon/ai/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
|
||||
return // no eyes, no flashing
|
||||
|
||||
/mob/living/silicon/ai/emag_act(mob/user, obj/item/card/emag/emag_card) ///emags access panel lock, so you can crowbar it without robotics access or consent
|
||||
. = ..()
|
||||
if(emagged)
|
||||
balloon_alert(user, "access panel lock already shorted!")
|
||||
return
|
||||
balloon_alert(user, "access panel lock shorted")
|
||||
var/message = (user ? "[user] shorts out your access panel lock!" : "Your access panel lock was short circuited!")
|
||||
to_chat(src, span_warning(message))
|
||||
do_sparks(3, FALSE, src) // just a bit of extra "oh shit" to the ai - might grab its attention
|
||||
emagged = TRUE
|
||||
return TRUE
|
||||
|
||||
/mob/living/silicon/ai/wrench_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return
|
||||
balloon_alert(user, "[!is_anchored ? "tightening" : "loosening"] bolts...")
|
||||
balloon_alert(src, "bolts being [!is_anchored ? "tightened" : "loosened"]...")
|
||||
if(!tool.use_tool(src, user, 4 SECONDS))
|
||||
return TRUE
|
||||
flip_anchored()
|
||||
balloon_alert(user, "bolts [is_anchored ? "tightened" : "loosened"]")
|
||||
balloon_alert(src, "bolts [is_anchored ? "tightened" : "loosened"]")
|
||||
return TRUE
|
||||
|
||||
/mob/living/silicon/ai/crowbar_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return
|
||||
if(!is_anchored)
|
||||
balloon_alert(user, "bolt it down first!")
|
||||
return TRUE
|
||||
if(opened)
|
||||
if(emagged)
|
||||
balloon_alert(user, "access panel lock damaged!")
|
||||
return TRUE
|
||||
balloon_alert(user, "closing access panel...")
|
||||
balloon_alert(src, "access panel being closed...")
|
||||
if(!tool.use_tool(src, user, 5 SECONDS))
|
||||
return TRUE
|
||||
balloon_alert(src, "access panel closed")
|
||||
balloon_alert(user, "access panel closed")
|
||||
opened = FALSE
|
||||
return TRUE
|
||||
if(stat == DEAD)
|
||||
to_chat(user, span_warning("The access panel looks damaged, you try dislodging the cover."))
|
||||
else
|
||||
var/consent
|
||||
var/consent_override = FALSE
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
if(human_user.wear_id)
|
||||
var/list/access = human_user.wear_id.GetAccess()
|
||||
if(ACCESS_ROBOTICS in access)
|
||||
consent_override = TRUE
|
||||
if(mind)
|
||||
consent = tgui_alert(src, "[user] is attempting to open your access panel, unlock the cover?", "AI Access Panel", list("Yes", "No"))
|
||||
if(consent == "No" && !consent_override && !emagged)
|
||||
to_chat(user, span_notice("[src] refuses to unlock its access panel."))
|
||||
return TRUE
|
||||
if(consent != "Yes" && (consent_override || emagged))
|
||||
to_chat(user, span_warning("[src] refuses to unlock its access panel...so you[!emagged ? " swipe your ID and " : " "]open it anyway!"))
|
||||
else
|
||||
if(!consent_override && !emagged)
|
||||
to_chat(user, span_notice("[src] did not respond to your request to unlock its access panel cover lock."))
|
||||
return TRUE
|
||||
else
|
||||
to_chat(user, span_notice("[src] did not respond to your request to unlock its access panel cover lock. You[!emagged ? " swipe your ID and " : " "]open it anyway."))
|
||||
|
||||
balloon_alert(user, "prying open access panel...")
|
||||
balloon_alert(src, "access panel being pried open...")
|
||||
if(!tool.use_tool(src, user, (stat == DEAD ? 40 SECONDS : 5 SECONDS)))
|
||||
return TRUE
|
||||
balloon_alert(src, "access panel opened")
|
||||
balloon_alert(user, "access panel opened")
|
||||
opened = TRUE
|
||||
return TRUE
|
||||
|
||||
/mob/living/silicon/ai/wirecutter_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return
|
||||
if(!is_anchored)
|
||||
balloon_alert(user, "bolt it down first!")
|
||||
return TRUE
|
||||
if(!opened)
|
||||
balloon_alert(user, "open the access panel first!")
|
||||
return TRUE
|
||||
balloon_alert(src, "neural network being disconnected...")
|
||||
balloon_alert(user, "disconnecting neural network...")
|
||||
if(!tool.use_tool(src, user, (stat == DEAD ? 40 SECONDS : 5 SECONDS)))
|
||||
return TRUE
|
||||
if(IS_MALF_AI(src))
|
||||
to_chat(user, span_userdanger("The voltage inside the wires rises dramatically!"))
|
||||
user.electrocute_act(120, src)
|
||||
opened = FALSE
|
||||
return TRUE
|
||||
to_chat(src, span_danger("You feel incredibly confused and disorientated."))
|
||||
var/atom/ai_structure = ai_mob_to_structure()
|
||||
ai_structure.balloon_alert(user, "disconnected neural network")
|
||||
return TRUE
|
||||
|
||||
@@ -177,8 +177,8 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
|
||||
if(chunk.changed)
|
||||
chunk.hasChanged(1) // Update now, no matter if it's visible or not.
|
||||
if(chunk.visibleTurfs[position])
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/cameranet/proc/stat_entry()
|
||||
if(!statclick)
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
return TRUE
|
||||
|
||||
/mob/camera/aiEye/Move()
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/mob/camera/aiEye/proc/GetViewerClient()
|
||||
if(ai)
|
||||
|
||||
@@ -28,11 +28,15 @@
|
||||
// Handle power damage (oxy)
|
||||
if(aiRestorePowerRoutine)
|
||||
// Lost power
|
||||
adjustOxyLoss(1)
|
||||
if (!battery)
|
||||
to_chat(src, span_warning("Your backup battery's output drops below usable levels. It takes only a moment longer for your systems to fail, corrupted and unusable."))
|
||||
adjustOxyLoss(200)
|
||||
else
|
||||
battery--
|
||||
else
|
||||
// Gain Power
|
||||
if(getOxyLoss())
|
||||
adjustOxyLoss(-1)
|
||||
if (battery < 200)
|
||||
battery++
|
||||
|
||||
if(!lacks_power())
|
||||
var/area/home = get_area(src)
|
||||
|
||||
@@ -187,8 +187,8 @@
|
||||
SEND_SOUND(M, voice)
|
||||
else
|
||||
SEND_SOUND(only_listener, voice)
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
#undef VOX_DELAY
|
||||
#endif
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE)
|
||||
var/hit_percent = (100-blocked)/100
|
||||
if(!damage || (!forced && hit_percent <= 0))
|
||||
return 0
|
||||
return FALSE
|
||||
var/damage_amount = forced ? damage : damage * hit_percent
|
||||
switch(damagetype)
|
||||
if(BRUTE)
|
||||
adjustBruteLoss(damage_amount, forced = forced)
|
||||
if(BURN)
|
||||
adjustFireLoss(damage_amount, forced = forced)
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/living/silicon/apply_effect(effect = 0,effecttype = EFFECT_STUN, blocked = FALSE)
|
||||
|
||||
@@ -230,7 +230,7 @@
|
||||
|
||||
/datum/action/innate/pai/Trigger()
|
||||
if(!ispAI(owner))
|
||||
return 0
|
||||
return FALSE
|
||||
P = owner
|
||||
|
||||
/datum/action/innate/pai/software
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
/datum/paiCandidate/proc/savefile_save(mob/user)
|
||||
if(IsGuestKey(user.key))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
var/savefile/F = new /savefile(src.savefile_path(user))
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
WRITE_FILE(F["version"], 1)
|
||||
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
// loads the savefile corresponding to the mob's ckey
|
||||
// if silent=true, report incompatible savefiles
|
||||
@@ -33,12 +33,12 @@
|
||||
|
||||
/datum/paiCandidate/proc/savefile_load(mob/user, silent = TRUE)
|
||||
if (IsGuestKey(user.key))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
var/path = savefile_path(user)
|
||||
|
||||
if (!fexists(path))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
var/savefile/F = new /savefile(path)
|
||||
|
||||
@@ -52,10 +52,10 @@
|
||||
fdel(path)
|
||||
if (!silent)
|
||||
alert(user, "Your savefile was incompatible with this version and was deleted.")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
F["name"] >> src.name
|
||||
F["description"] >> src.description
|
||||
F["role"] >> src.role
|
||||
F["comments"] >> src.comments
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
@@ -206,12 +206,12 @@
|
||||
var/count = 0
|
||||
while(!isliving(M))
|
||||
if(!M || !M.loc)
|
||||
return 0 //For a runtime where M ends up in nullspace (similar to bluespace but less colourful)
|
||||
return FALSE //For a runtime where M ends up in nullspace (similar to bluespace but less colourful)
|
||||
M = M.loc
|
||||
count++
|
||||
if(count >= 6)
|
||||
to_chat(src, "You are not being carried by anyone!")
|
||||
return 0
|
||||
return FALSE
|
||||
spawn CheckDNA(M, src)
|
||||
|
||||
if("pdamessage")
|
||||
|
||||
@@ -351,7 +351,7 @@
|
||||
if(module_active)
|
||||
return held_items.Find(module_active)
|
||||
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Selects the module in the slot module_num.
|
||||
|
||||
@@ -28,11 +28,13 @@
|
||||
inv2 = new /atom/movable/screen/robot/module2()
|
||||
inv3 = new /atom/movable/screen/robot/module3()
|
||||
|
||||
ident = rand(1, 999)
|
||||
|
||||
if(!shell)
|
||||
aiPDA = new/obj/item/pda/ai(src)
|
||||
aiPDA.owner = real_name
|
||||
aiPDA.ownjob = "Cyborg"
|
||||
aiPDA.name = real_name + " (" + aiPDA.ownjob + ")"
|
||||
aiPDA.name = real_name + " ([aiPDA.ownjob])"
|
||||
|
||||
previous_health = health
|
||||
|
||||
@@ -59,26 +61,29 @@
|
||||
update_icons()
|
||||
. = ..()
|
||||
|
||||
//If this body is meant to be a borg controlled by the AI player
|
||||
//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
|
||||
else if(!mmi || !mmi.brainmob)
|
||||
mmi = new (src)
|
||||
mmi.brain = new /obj/item/organ/brain(mmi)
|
||||
mmi.brain.organ_flags |= ORGAN_FROZEN
|
||||
mmi.brain.name = "[real_name]'s brain"
|
||||
mmi.icon_state = "mmi_full"
|
||||
mmi.name = "Man-Machine Interface: [real_name]"
|
||||
mmi.brainmob = new(mmi)
|
||||
mmi.brainmob.name = src.real_name
|
||||
mmi.brainmob.real_name = src.real_name
|
||||
mmi.brainmob.container = mmi
|
||||
var/obj/item/borg/upgrade/ai/board = new(src)
|
||||
make_shell(board)
|
||||
add_to_upgrades(board)
|
||||
else
|
||||
//MMI stuff. Held togheter by magic. ~Miauw
|
||||
if(!mmi?.brainmob)
|
||||
mmi = new (src)
|
||||
mmi.brain = new /obj/item/organ/brain(mmi)
|
||||
mmi.brain.organ_flags |= ORGAN_FROZEN
|
||||
mmi.brain.name = "[real_name]'s brain"
|
||||
mmi.icon_state = "mmi_full"
|
||||
mmi.name = "[initial(mmi.name)]: [real_name]"
|
||||
mmi.brainmob = new(mmi)
|
||||
mmi.brainmob.name = src.real_name
|
||||
mmi.brainmob.real_name = src.real_name
|
||||
mmi.brainmob.container = mmi
|
||||
mmi.update_appearance()
|
||||
|
||||
INVOKE_ASYNC(src, .proc/updatename)
|
||||
|
||||
playsound(loc, 'sound/voice/liveagain.ogg', 75, TRUE)
|
||||
aicamera = new/obj/item/camera/siliconcam/robot_camera(src)
|
||||
toner = tonermax
|
||||
diag_hud_set_borgcell()
|
||||
@@ -157,7 +162,7 @@
|
||||
if(BORG_SEC_AVAILABLE)
|
||||
modulelist["Security"] = /obj/item/robot_module/security
|
||||
|
||||
var/input_module = input("Please, select a module!", "Robot", null, null) as null|anything in sortList(modulelist)
|
||||
var/input_module = input("Please, select a module!", "Robot", null, null) as null|anything in sort_list(modulelist)
|
||||
if(!input_module || module.type != /obj/item/robot_module)
|
||||
return
|
||||
|
||||
@@ -266,7 +271,7 @@
|
||||
if(source.z != z)
|
||||
return
|
||||
if(stat == DEAD)
|
||||
return 1
|
||||
return TRUE
|
||||
var/list/our_sort = alarms[class]
|
||||
for(var/areaname in our_sort)
|
||||
if (areaname == home.name)
|
||||
@@ -274,7 +279,7 @@
|
||||
var/list/sources = alarm[3]
|
||||
if (!(source in sources))
|
||||
sources += source
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
var/obj/machinery/camera/cam = null
|
||||
var/list/our_cams = null
|
||||
@@ -330,194 +335,145 @@
|
||||
return FALSE
|
||||
return ISINRANGE(T1.x, T0.x - interaction_range, T0.x + interaction_range) && ISINRANGE(T1.y, T0.y - interaction_range, T0.y + interaction_range)
|
||||
|
||||
/mob/living/silicon/robot/proc/attempt_welder_repair(obj/item/W, mob/user)
|
||||
if(!W.tool_behaviour == TOOL_WELDER)
|
||||
return
|
||||
if(!getBruteLoss())
|
||||
to_chat(user, "<span class='warning'>[src] is already in good condition!</span>")
|
||||
return
|
||||
if(!W.tool_start_check(user, amount=0)) //The welder has 1u of fuel consumed by it's afterattack, so we don't need to worry about taking any away.
|
||||
return
|
||||
user.DelayNextAction(CLICK_CD_MELEE)
|
||||
if(src == user)
|
||||
to_chat(user, "<span class='notice'>You start fixing yourself...</span>")
|
||||
if(!W.use_tool(src, user, 50))
|
||||
return
|
||||
adjustBruteLoss(-10)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You start fixing [src]...</span>")
|
||||
if(!do_after(user, 30, target = src))
|
||||
return
|
||||
adjustBruteLoss(-30)
|
||||
updatehealth()
|
||||
add_fingerprint(user)
|
||||
visible_message("<span class='notice'>[user] has fixed some of the dents on [src].</span>")
|
||||
|
||||
/mob/living/silicon/robot/proc/attempt_cable_repair(obj/item/stack/cable_coil/W, mob/user)
|
||||
if (getFireLoss() > 0 || getToxLoss() > 0)
|
||||
user.DelayNextAction(CLICK_CD_MELEE)
|
||||
if(src == user)
|
||||
to_chat(user, "<span class='notice'>You start fixing yourself...</span>")
|
||||
if(!W.use_tool(src, user, 50, 1, skill_gain_mult = TRIVIAL_USE_TOOL_MULT))
|
||||
to_chat(user, "<span class='warning'>You need more cable to repair [src]!</span>")
|
||||
return
|
||||
adjustFireLoss(-10)
|
||||
adjustToxLoss(-10)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You start fixing [src]...</span>")
|
||||
if(!W.use_tool(src, user, 30, 1))
|
||||
to_chat(user, "<span class='warning'>You need more cable to repair [src]!</span>")
|
||||
return
|
||||
adjustFireLoss(-30)
|
||||
adjustToxLoss(-30)
|
||||
updatehealth()
|
||||
user.visible_message("[user] has fixed some of the burnt wires on [src].", "<span class='notice'>You fix some of the burnt wires on [src].</span>")
|
||||
else
|
||||
to_chat(user, "The wires seem fine, there's no need to fix them.")
|
||||
|
||||
/mob/living/silicon/robot/attackby(obj/item/W, mob/user, params)
|
||||
if(W.tool_behaviour == TOOL_WELDER && (user.a_intent != INTENT_HARM || user == src))
|
||||
INVOKE_ASYNC(src, .proc/attempt_welder_repair, W, user)
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/stack/cable_coil) && wiresexposed)
|
||||
INVOKE_ASYNC(src, .proc/attempt_cable_repair, W, user)
|
||||
return
|
||||
|
||||
else if(W.tool_behaviour == TOOL_CROWBAR) // crowbar means open or close the cover
|
||||
if(opened)
|
||||
to_chat(user, "<span class='notice'>You close the cover.</span>")
|
||||
opened = 0
|
||||
update_icons()
|
||||
else
|
||||
if(locked)
|
||||
to_chat(user, "<span class='warning'>The cover is locked and cannot be opened!</span>")
|
||||
if(istype(W, /obj/item/stack/cable_coil) && wiresexposed)
|
||||
user.DelayNextAction(CLICK_CD_MELEE)
|
||||
if (getFireLoss() > 0 || getToxLoss() > 0)
|
||||
if(src == user)
|
||||
to_chat(user, span_notice("You start fixing yourself..."))
|
||||
if(!W.use_tool(src, user, 5 SECONDS, 1, skill_gain_mult = TRIVIAL_USE_TOOL_MULT))
|
||||
to_chat(user, span_warning("You need more cable to repair [src]!"))
|
||||
return
|
||||
adjustFireLoss(-10)
|
||||
adjustToxLoss(-10)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You open the cover.</span>")
|
||||
opened = 1
|
||||
update_icons()
|
||||
to_chat(user, span_notice("You start fixing [src]..."))
|
||||
if(!W.use_tool(src, user, 3 SECONDS, 1))
|
||||
to_chat(user, span_warning("You need more cable to repair [src]!"))
|
||||
adjustFireLoss(-30)
|
||||
adjustToxLoss(-30)
|
||||
updatehealth()
|
||||
user.visible_message(span_notice("[user] has fixed some of the burnt wires on [src]."), span_notice("You fix some of the burnt wires on [src]."))
|
||||
else
|
||||
to_chat(user, span_warning("The wires seem fine, there's no need to fix them."))
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/stock_parts/cell) && opened) // trying to put a cell inside
|
||||
if(istype(W, /obj/item/stock_parts/cell) && opened) // trying to put a cell inside
|
||||
if(wiresexposed)
|
||||
to_chat(user, "<span class='warning'>Close the cover first!</span>")
|
||||
to_chat(user, span_warning("Close the cover first!"))
|
||||
else if(cell)
|
||||
to_chat(user, "<span class='warning'>There is a power cell already installed!</span>")
|
||||
to_chat(user, span_warning("There is a power cell already installed!"))
|
||||
else
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return
|
||||
cell = W
|
||||
to_chat(user, "<span class='notice'>You insert the power cell.</span>")
|
||||
to_chat(user, span_notice("You insert the power cell."))
|
||||
update_icons()
|
||||
diag_hud_set_borgcell()
|
||||
return
|
||||
|
||||
else if(is_wire_tool(W))
|
||||
if(is_wire_tool(W))
|
||||
if (wiresexposed)
|
||||
wires.interact(user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You can't reach the wiring!</span>")
|
||||
to_chat(user, span_warning("You can't reach the wiring!"))
|
||||
return
|
||||
|
||||
else if(W.tool_behaviour == TOOL_SCREWDRIVER && opened && !cell) // haxing
|
||||
wiresexposed = !wiresexposed
|
||||
to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"]")
|
||||
update_icons()
|
||||
|
||||
else if((W.tool_behaviour == TOOL_SCREWDRIVER) && opened && cell) // 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>")
|
||||
update_icons()
|
||||
|
||||
else if(W.tool_behaviour == TOOL_WRENCH && opened && !cell) //Deconstruction. The flashes break from the fall, to prevent this from being a ghetto reset module.
|
||||
if(!locked_down)
|
||||
to_chat(user, "<span class='boldannounce'>[src]'s bolts spark! Maybe you should lock them down first!</span>")
|
||||
spark_system.start()
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You start to unfasten [src]'s securing bolts...</span>")
|
||||
if(W.use_tool(src, user, 50, volume=50) && !cell)
|
||||
user.visible_message("[user] deconstructs [src]!", "<span class='notice'>You unfasten the securing bolts, and [src] falls to pieces!</span>")
|
||||
deconstruct()
|
||||
|
||||
else if(istype(W, /obj/item/aiModule))
|
||||
var/obj/item/aiModule/MOD = W
|
||||
if(istype(W, /obj/item/ai_module))
|
||||
var/obj/item/ai_module/MOD = W
|
||||
if(!opened)
|
||||
to_chat(user, "<span class='warning'>You need access to the robot's insides to do that!</span>")
|
||||
to_chat(user, span_warning("You need access to the robot's insides to do that!"))
|
||||
return
|
||||
if(wiresexposed)
|
||||
to_chat(user, "<span class='warning'>You need to close the wire panel to do that!</span>")
|
||||
to_chat(user, span_warning("You need to close the wire panel to do that!"))
|
||||
return
|
||||
if(!cell)
|
||||
to_chat(user, "<span class='warning'>You need to install a power cell to do that!</span>")
|
||||
to_chat(user, span_warning("You need to install a power cell to do that!"))
|
||||
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>")
|
||||
to_chat(user, span_warning("[src] is controlled remotely! You cannot upload new laws this way!"))
|
||||
return
|
||||
if(emagged || (connected_ai && lawupdate)) //Can't be sure which, metagamers
|
||||
emote("buzz-[user.name]")
|
||||
if(connected_ai && lawupdate)
|
||||
to_chat(user, span_warning("[src] is receiving laws remotely from a synced AI!"))
|
||||
return
|
||||
if(emagged)
|
||||
to_chat(user, span_warning("The law interface glitches out!"))
|
||||
emote("buzz")
|
||||
return
|
||||
if(!mind) //A player mind is required for law procs to run antag checks.
|
||||
to_chat(user, "<span class='warning'>[src] is entirely unresponsive!</span>")
|
||||
to_chat(user, span_warning("[src] is entirely unresponsive!"))
|
||||
return
|
||||
MOD.install(laws, user) //Proc includes a success mesage so we don't need another one
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/encryptionkey/) && opened)
|
||||
if(istype(W, /obj/item/encryptionkey) && opened)
|
||||
if(radio)//sanityyyyyy
|
||||
radio.attackby(W,user)//GTFO, you have your own procs
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Unable to locate a radio!</span>")
|
||||
to_chat(user, span_warning("Unable to locate a radio!"))
|
||||
return
|
||||
|
||||
else if (istype(W, /obj/item/card/id)||istype(W, /obj/item/pda)) // trying to unlock the interface with an ID card
|
||||
if(emagged)//still allow them to open the cover
|
||||
to_chat(user, "<span class='notice'>The interface seems slightly damaged.</span>")
|
||||
if (W.GetID()) // trying to unlock the interface with an ID card
|
||||
if(opened)
|
||||
to_chat(user, "<span class='warning'>You must close the cover to swipe an ID card!</span>")
|
||||
to_chat(user, span_warning("You must close the cover to swipe an ID card!"))
|
||||
else
|
||||
if(allowed(usr))
|
||||
locked = !locked
|
||||
to_chat(user, "<span class='notice'>You [ locked ? "lock" : "unlock"] [src]'s cover.</span>")
|
||||
to_chat(user, span_notice("You [ locked ? "lock" : "unlock"] [src]'s cover."))
|
||||
update_icons()
|
||||
if(emagged)
|
||||
to_chat(user, span_notice("The cover interface glitches out for a split second."))
|
||||
logevent("ChÃ¥vÃis cover lock has been [locked ? "engaged" : "released"]") //ChÃ¥vÃis: see above line
|
||||
else
|
||||
logevent("Chassis cover lock has been [locked ? "engaged" : "released"]")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Access denied.</span>")
|
||||
to_chat(user, span_danger("Access denied."))
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/borg/upgrade/))
|
||||
if(istype(W, /obj/item/borg/upgrade))
|
||||
var/obj/item/borg/upgrade/U = W
|
||||
if(!opened)
|
||||
to_chat(user, "<span class='warning'>You must access the borg's internals!</span>")
|
||||
else if(!src.module && U.require_module)
|
||||
to_chat(user, "<span class='warning'>The borg must choose a module before it can be upgraded!</span>")
|
||||
else if(U.locked)
|
||||
to_chat(user, "<span class='warning'>The upgrade is locked and cannot be used yet!</span>")
|
||||
else
|
||||
if(!user.temporarilyRemoveItemFromInventory(U))
|
||||
return
|
||||
if(U.action(src))
|
||||
to_chat(user, "<span class='notice'>You apply the upgrade to [src].</span>")
|
||||
if(U.one_use)
|
||||
U.afterInstall(src)
|
||||
qdel(U)
|
||||
else
|
||||
U.forceMove(src)
|
||||
upgrades += U
|
||||
U.afterInstall(src)
|
||||
else
|
||||
to_chat(user, "<span class='danger'>Upgrade error.</span>")
|
||||
U.forceMove(drop_location())
|
||||
to_chat(user, span_warning("You must access the cyborg's internals!"))
|
||||
return
|
||||
if(!module && U.require_module)
|
||||
to_chat(user, span_warning("The cyborg must choose a model before it can be upgraded!"))
|
||||
return
|
||||
if(U.locked)
|
||||
to_chat(user, span_warning("The upgrade is locked and cannot be used yet!"))
|
||||
return
|
||||
if(!user.canUnEquip(U))
|
||||
to_chat(user, span_warning("The upgrade is stuck to you and you can't seem to let go of it!"))
|
||||
return
|
||||
apply_upgrade(U, user)
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/toner))
|
||||
if(istype(W, /obj/item/toner))
|
||||
if(toner >= tonermax)
|
||||
to_chat(user, "<span class='warning'>The toner level of [src] is at its highest level possible!</span>")
|
||||
else
|
||||
if(!user.temporarilyRemoveItemFromInventory(W))
|
||||
return
|
||||
toner = tonermax
|
||||
qdel(W)
|
||||
to_chat(user, "<span class='notice'>You fill the toner level of [src] to its max capacity.</span>")
|
||||
else
|
||||
return ..()
|
||||
to_chat(user, span_warning("The toner level of [src] is at its highest level possible!"))
|
||||
return
|
||||
if(!user.temporarilyRemoveItemFromInventory(W))
|
||||
return
|
||||
toner = tonermax
|
||||
qdel(W)
|
||||
to_chat(user, span_notice("You fill the toner level of [src] to its max capacity."))
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/flashlight))
|
||||
if(!opened)
|
||||
to_chat(user, span_warning("You need to open the panel to repair the headlamp!"))
|
||||
return
|
||||
if(lamp_functional)
|
||||
to_chat(user, span_warning("The headlamp is already functional!"))
|
||||
return
|
||||
if(!user.temporarilyRemoveItemFromInventory(W))
|
||||
to_chat(user, span_warning("[W] seems to be stuck to your hand. You'll have to find a different light."))
|
||||
return
|
||||
lamp_functional = TRUE
|
||||
qdel(W)
|
||||
to_chat(user, span_notice("You replace the headlamp bulbs."))
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/crowbar_act(mob/living/user, obj/item/I) //TODO: make fucking everything up there in that attackby() proc use the proper tool_act() procs. But honestly, who has time for that? 'cause I know for sure that you, the person reading this, sure as hell doesn't.
|
||||
var/validbreakout = FALSE
|
||||
@@ -1023,7 +979,7 @@
|
||||
ionpulse = FALSE
|
||||
revert_shell()
|
||||
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/mob/living/silicon/robot/proc/has_module()
|
||||
if(!module || module.type == /obj/item/robot_module)
|
||||
@@ -1064,29 +1020,45 @@
|
||||
*Checking Exited() to detect if a hat gets up and walks off.
|
||||
*Drones and pAIs might do this, after all.
|
||||
*/
|
||||
/mob/living/silicon/robot/Exited(atom/A)
|
||||
if(hat && hat == A)
|
||||
/mob/living/silicon/robot/Exited(atom/movable/gone)
|
||||
. = ..()
|
||||
if(hat == gone)
|
||||
hat = null
|
||||
if(!QDELETED(src)) //Don't update icons if we are deleted.
|
||||
update_icons()
|
||||
return ..()
|
||||
|
||||
///Use this to add upgrades to robots. It'll register signals for when the upgrade is moved or deleted, if not single use.
|
||||
/mob/living/silicon/robot/proc/add_to_upgrades(obj/item/borg/upgrade/new_upgrade, mob/user)
|
||||
if(gone == cell)
|
||||
cell = null
|
||||
|
||||
if(gone == mmi)
|
||||
mmi = null
|
||||
|
||||
///Called when a mob uses an upgrade on an open borg. Checks to make sure the upgrade can be applied
|
||||
/mob/living/silicon/robot/proc/apply_upgrade(obj/item/borg/upgrade/new_upgrade, mob/user, admin_added)
|
||||
if(!admin_added && isnull(user))
|
||||
return FALSE
|
||||
if(new_upgrade in upgrades)
|
||||
return FALSE
|
||||
if(!user.temporarilyRemoveItemFromInventory(new_upgrade)) //calling the upgrade's dropped() proc /before/ we add action buttons
|
||||
if(!admin_added && !user.temporarilyRemoveItemFromInventory(new_upgrade)) //calling the upgrade's dropped() proc /before/ we add action buttons
|
||||
return FALSE
|
||||
if(!new_upgrade.action(src, user))
|
||||
to_chat(user, "<span class='danger'>Upgrade error.</span>")
|
||||
new_upgrade.forceMove(loc) //gets lost otherwise
|
||||
to_chat(user, span_danger("Upgrade error."))
|
||||
if(admin_added)
|
||||
qdel(new_upgrade)
|
||||
else
|
||||
new_upgrade.forceMove(loc) //gets lost otherwise
|
||||
return FALSE
|
||||
to_chat(user, "<span class='notice'>You apply the upgrade to [src].</span>")
|
||||
to_chat(user, span_notice("You apply the upgrade to [src]."))
|
||||
add_to_upgrades(new_upgrade)
|
||||
return TRUE
|
||||
|
||||
///Moves the upgrade inside the robot and registers relevant signals.
|
||||
/mob/living/silicon/robot/proc/add_to_upgrades(obj/item/borg/upgrade/new_upgrade)
|
||||
to_chat(src, "----------------\nNew hardware detected...Identified as \"<b>[new_upgrade]</b>\"...Setup complete.\n----------------")
|
||||
if(new_upgrade.one_use)
|
||||
logevent("Firmware [new_upgrade] run successfully.")
|
||||
qdel(new_upgrade)
|
||||
return FALSE
|
||||
return
|
||||
upgrades += new_upgrade
|
||||
new_upgrade.forceMove(src)
|
||||
RegisterSignal(new_upgrade, COMSIG_MOVABLE_MOVED, PROC_REF(remove_from_upgrades))
|
||||
@@ -1117,15 +1089,17 @@
|
||||
* * board - B.O.R.I.S. module board used for transforming the cyborg into AI shell
|
||||
*/
|
||||
/mob/living/silicon/robot/proc/make_shell(obj/item/borg/upgrade/ai/board)
|
||||
if(!board)
|
||||
upgrades |= new /obj/item/borg/upgrade/ai(src)
|
||||
if(isnull(board))
|
||||
stack_trace("make_shell was called without a board argument! This is never supposed to happen!")
|
||||
return FALSE
|
||||
|
||||
shell = TRUE
|
||||
braintype = "AI Shell"
|
||||
name = "Empty AI Shell-[ident]"
|
||||
real_name = name
|
||||
GLOB.available_ai_shells |= src
|
||||
if(!QDELETED(builtInCamera))
|
||||
builtInCamera.c_tag = real_name //update the camera name too
|
||||
builtInCamera.c_tag = real_name //update the camera name too
|
||||
diag_hud_set_aishell()
|
||||
notify_ai(AI_SHELL)
|
||||
|
||||
@@ -1328,7 +1302,7 @@
|
||||
switch(choice)
|
||||
if("Resting")
|
||||
update_icons()
|
||||
return 0
|
||||
return FALSE
|
||||
if("Sitting")
|
||||
sitting = 1
|
||||
if("Belly up")
|
||||
|
||||
@@ -94,6 +94,76 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real
|
||||
apply_status_effect(/datum/status_effect/vtec_disabled, time)
|
||||
update_movespeed()
|
||||
|
||||
/mob/living/silicon/robot/welder_act(mob/living/user, obj/item/tool)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return FALSE
|
||||
. = TRUE
|
||||
if (!getBruteLoss())
|
||||
to_chat(user, span_warning("[src] is already in good condition!"))
|
||||
return
|
||||
if (!tool.tool_start_check(user, amount=0)) //The welder has 1u of fuel consumed by it's afterattack, so we don't need to worry about taking any away.
|
||||
return
|
||||
user.DelayNextAction(CLICK_CD_MELEE)
|
||||
if(src == user)
|
||||
to_chat(user, span_notice("You start fixing yourself..."))
|
||||
if(!tool.use_tool(src, user, 50))
|
||||
return
|
||||
adjustBruteLoss(-10)
|
||||
else
|
||||
to_chat(user, span_notice("You start fixing [src]..."))
|
||||
if(!do_after(user, 3 SECONDS, target = src))
|
||||
return
|
||||
adjustBruteLoss(-30)
|
||||
updatehealth()
|
||||
add_fingerprint(user)
|
||||
visible_message(span_notice("[user] has fixed some of the dents on [src]."))
|
||||
|
||||
/mob/living/silicon/robot/crowbar_act(mob/living/user, obj/item/tool)
|
||||
. = TRUE
|
||||
if(opened)
|
||||
to_chat(user, span_notice("You close the cover."))
|
||||
opened = FALSE
|
||||
update_icons()
|
||||
else
|
||||
if(locked)
|
||||
to_chat(user, span_warning("The cover is locked and cannot be opened!"))
|
||||
else
|
||||
to_chat(user, span_notice("You open the cover."))
|
||||
opened = TRUE
|
||||
update_icons()
|
||||
|
||||
return TRUE
|
||||
|
||||
/mob/living/silicon/robot/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
if(!opened)
|
||||
return FALSE
|
||||
. = TRUE
|
||||
if(!cell) // haxing
|
||||
wiresexposed = !wiresexposed
|
||||
to_chat(user, span_notice("The wires have been [wiresexposed ? "exposed" : "unexposed"]."))
|
||||
else // radio
|
||||
if(shell)
|
||||
to_chat(user, span_warning("You cannot seem to open the radio compartment!")) //Prevent AI radio key theft
|
||||
else if(radio)
|
||||
radio.screwdriver_act(user, tool) // Push it to the radio to let it handle everything
|
||||
else
|
||||
to_chat(user, span_warning("Unable to locate a radio!"))
|
||||
update_icons()
|
||||
|
||||
/mob/living/silicon/robot/wrench_act(mob/living/user, obj/item/tool)
|
||||
if(!(opened && !cell)) // Deconstruction. The flashes break from the fall, to prevent this from being a ghetto reset module.
|
||||
return FALSE
|
||||
. = TRUE
|
||||
if(!locked_down)
|
||||
to_chat(user, span_boldannounce("[src]'s bolts spark! Maybe you should lock them down first!"))
|
||||
spark_system.start()
|
||||
return
|
||||
to_chat(user, span_notice("You start to unfasten [src]'s securing bolts..."))
|
||||
if(tool.use_tool(src, user, 5 SECONDS, volume = 50) && !cell)
|
||||
user.visible_message(span_notice("[user] deconstructs [src]!"), span_notice("You unfasten the securing bolts, and [src] falls to pieces!"))
|
||||
deconstruct()
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/fire_act()
|
||||
if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them
|
||||
IgniteMob()
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
var/obj/item/stock_parts/cell/cell = /obj/item/stock_parts/cell/high ///If this is a path, this gets created as an object in Initialize.
|
||||
|
||||
var/opened = FALSE
|
||||
var/emagged = FALSE
|
||||
var/emag_cooldown = 0
|
||||
var/wiresexposed = FALSE
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
if(!(m in R.held_items))
|
||||
. += m
|
||||
|
||||
/obj/item/robot_module/proc/get_or_create_estorage(var/storage_type)
|
||||
/obj/item/robot_module/proc/get_or_create_estorage(storage_type)
|
||||
for(var/datum/robot_energy_storage/S in storages)
|
||||
if(istype(S, storage_type))
|
||||
return S
|
||||
@@ -95,42 +95,9 @@
|
||||
|
||||
/obj/item/robot_module/proc/add_module(obj/item/I, nonstandard, requires_rebuild)
|
||||
rad_flags |= RAD_NO_CONTAMINATE
|
||||
if(istype(I, /obj/item/stack))
|
||||
var/obj/item/stack/S = I
|
||||
|
||||
if(is_type_in_list(S, list(/obj/item/stack/sheet/metal, /obj/item/stack/rods, /obj/item/stack/tile/plasteel)))
|
||||
if(S.custom_materials?.len && S.custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)])
|
||||
S.cost = S.custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)] * 0.25
|
||||
S.source = get_or_create_estorage(/datum/robot_energy_storage/metal)
|
||||
|
||||
else if(istype(S, /obj/item/stack/sheet/glass))
|
||||
S.cost = 500
|
||||
S.source = get_or_create_estorage(/datum/robot_energy_storage/glass)
|
||||
|
||||
else if(istype(S, /obj/item/stack/sheet/rglass/cyborg))
|
||||
var/obj/item/stack/sheet/rglass/cyborg/G = S
|
||||
G.source = get_or_create_estorage(/datum/robot_energy_storage/metal)
|
||||
G.glasource = get_or_create_estorage(/datum/robot_energy_storage/glass)
|
||||
|
||||
else if(istype(S, /obj/item/stack/medical))
|
||||
S.cost = 250
|
||||
S.source = get_or_create_estorage(/datum/robot_energy_storage/medical)
|
||||
|
||||
else if(istype(S, /obj/item/stack/cable_coil))
|
||||
S.cost = 1
|
||||
S.source = get_or_create_estorage(/datum/robot_energy_storage/wire)
|
||||
|
||||
else if(istype(S, /obj/item/stack/marker_beacon))
|
||||
S.cost = 1
|
||||
S.source = get_or_create_estorage(/datum/robot_energy_storage/beacon)
|
||||
|
||||
else if(istype(S, /obj/item/stack/packageWrap))
|
||||
S.cost = 1
|
||||
S.source = get_or_create_estorage(/datum/robot_energy_storage/wrapping_paper)
|
||||
|
||||
if(S && S.source)
|
||||
S.set_custom_materials(null)
|
||||
S.is_cyborg = 1
|
||||
var/obj/item/stack/S = I
|
||||
if(istype(I, /obj/item/stack) && !S.is_cyborg) // Now handled in the type itself
|
||||
stack_trace("Non-cyborg variant of /obj/item/stack added to a cyborg's modules.")
|
||||
|
||||
if(I.loc != src)
|
||||
I.forceMove(src)
|
||||
@@ -380,7 +347,7 @@
|
||||
var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-med")
|
||||
bad_snowflake.pixel_x = -16
|
||||
med_icons["Alina"] = bad_snowflake
|
||||
med_icons = sortList(med_icons)
|
||||
med_icons = sort_list(med_icons)
|
||||
var/med_borg_icon = show_radial_menu(R, R , med_icons, custom_check = CALLBACK(src, PROC_REF(check_menu), R), radius = 42, require_near = TRUE)
|
||||
switch(med_borg_icon)
|
||||
if("Default")
|
||||
@@ -498,7 +465,7 @@
|
||||
var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-eng")
|
||||
bad_snowflake.pixel_x = -16
|
||||
engi_icons["Alina"] = bad_snowflake
|
||||
engi_icons = sortList(engi_icons)
|
||||
engi_icons = sort_list(engi_icons)
|
||||
var/engi_borg_icon = show_radial_menu(R, R , engi_icons, custom_check = CALLBACK(src, PROC_REF(check_menu), R), radius = 42, require_near = TRUE)
|
||||
switch(engi_borg_icon)
|
||||
if("Default")
|
||||
@@ -595,7 +562,7 @@
|
||||
var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-sec")
|
||||
bad_snowflake.pixel_x = -16
|
||||
sec_icons["Alina"] = bad_snowflake
|
||||
sec_icons = sortList(sec_icons)
|
||||
sec_icons = sort_list(sec_icons)
|
||||
var/sec_borg_icon = show_radial_menu(R, R , sec_icons, custom_check = CALLBACK(src, PROC_REF(check_menu), R), radius = 42, require_near = TRUE)
|
||||
switch(sec_borg_icon)
|
||||
if("Default")
|
||||
@@ -681,7 +648,7 @@
|
||||
|
||||
/obj/item/robot_module/peacekeeper/be_transformed_to(obj/item/robot_module/old_module)
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
var/static/list/peace_icons = sortList(list(
|
||||
var/static/list/peace_icons = sort_list(list(
|
||||
"Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "peace"),
|
||||
"Borgi" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "borgi"),
|
||||
"Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "whitespider")
|
||||
@@ -852,7 +819,7 @@
|
||||
var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-sec")
|
||||
bad_snowflake.pixel_x = -16
|
||||
service_icons["Alina"] = bad_snowflake
|
||||
service_icons = sortList(service_icons)
|
||||
service_icons = sort_list(service_icons)
|
||||
var/service_robot_icon = show_radial_menu(R, R , service_icons, custom_check = CALLBACK(src, PROC_REF(check_menu), R), radius = 42, require_near = TRUE)
|
||||
switch(service_robot_icon)
|
||||
if("(Service) Waitress")
|
||||
@@ -935,9 +902,9 @@
|
||||
/obj/item/gps/cyborg,
|
||||
/obj/item/gripper/mining,
|
||||
/obj/item/cyborg_clamp,
|
||||
/obj/item/stack/marker_beacon,
|
||||
/obj/item/stack/marker_beacon/cyborg,
|
||||
/obj/item/destTagger,
|
||||
/obj/item/stack/packageWrap,
|
||||
/obj/item/stack/packageWrap/cyborg,
|
||||
/obj/item/card/id/miningborg)
|
||||
emag_modules = list(/obj/item/borg/stun)
|
||||
ratvar_modules = list(
|
||||
@@ -966,7 +933,7 @@
|
||||
var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
|
||||
wide.pixel_x = -16
|
||||
mining_icons[a] = wide
|
||||
mining_icons = sortList(mining_icons)
|
||||
mining_icons = sort_list(mining_icons)
|
||||
var/mining_borg_icon = show_radial_menu(R, R , mining_icons, custom_check = CALLBACK(src, PROC_REF(check_menu), R), radius = 42, require_near = TRUE)
|
||||
switch(mining_borg_icon)
|
||||
if("Lavaland")
|
||||
@@ -1056,7 +1023,7 @@
|
||||
/obj/item/surgicaldrill,
|
||||
/obj/item/scalpel,
|
||||
/obj/item/bonesetter,
|
||||
/obj/item/stack/medical/bone_gel,
|
||||
/obj/item/stack/medical/bone_gel/cyborg,
|
||||
/obj/item/melee/transforming/energy/sword/cyborg/saw,
|
||||
/obj/item/roller/robo,
|
||||
/obj/item/card/emag,
|
||||
@@ -1128,10 +1095,10 @@
|
||||
if (energy >= amount)
|
||||
energy -= amount
|
||||
if (energy == 0)
|
||||
return 1
|
||||
return TRUE
|
||||
return 2
|
||||
else
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/datum/robot_energy_storage/proc/add_charge(amount)
|
||||
energy = min(energy + amount, max_energy)
|
||||
@@ -1191,7 +1158,7 @@
|
||||
/obj/item/surgicaldrill,
|
||||
/obj/item/scalpel,
|
||||
/obj/item/bonesetter,
|
||||
/obj/item/stack/medical/bone_gel,
|
||||
/obj/item/stack/medical/bone_gel/cyborg,
|
||||
/obj/item/melee/transforming/energy/sword/cyborg/saw,
|
||||
/obj/item/roller/robo,
|
||||
/obj/item/stack/medical/gauze/cyborg,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/mob/living/silicon/robot/Process_Spacemove(movement_dir = 0)
|
||||
if(ionpulse())
|
||||
return 1
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/mob_negates_gravity()
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
to_chat(M, "<span class='binarysay'>[link] [rendered]</span>")
|
||||
|
||||
/mob/living/silicon/binarycheck()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/mob/living/silicon/lingcheck()
|
||||
return 0 //Borged or AI'd lings can't speak on the ling channel.
|
||||
return FALSE //Borged or AI'd lings can't speak on the ling channel.
|
||||
|
||||
/mob/living/silicon/radio(message, message_mode, list/spans, language)
|
||||
. = ..()
|
||||
@@ -44,7 +44,7 @@
|
||||
radio.talk_into(src, message, message_mode, spans, language)
|
||||
return ITALICS | REDUCE_RANGE
|
||||
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/mob/living/silicon/get_message_mode(message)
|
||||
. = ..()
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
var/obj/machinery/camera/builtInCamera = null
|
||||
var/updating = FALSE //portable camera camerachunk update
|
||||
|
||||
///Whether we have been emagged
|
||||
var/emagged = FALSE
|
||||
var/hack_software = FALSE //Will be able to use hacking actions
|
||||
var/interaction_range = 7 //wireless control range
|
||||
|
||||
@@ -362,12 +364,12 @@
|
||||
to_chat(src, "<span class='notice'>Automatic announcements [Autochan == "None" ? "will not use the radio." : "set to [Autochan]."]</span>")
|
||||
|
||||
/mob/living/silicon/put_in_hand_check() // This check is for borgs being able to receive items, not put them in others' hands.
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
// The src mob is trying to place an item on someone
|
||||
// But the src mob is a silicon!! Disable.
|
||||
/mob/living/silicon/stripPanelEquip(obj/item/what, mob/who, slot)
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
|
||||
/mob/living/silicon/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null) //Secbots won't hunt silicon units
|
||||
@@ -432,7 +434,7 @@
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/is_literate()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/mob/living/silicon/get_inactive_held_item()
|
||||
return FALSE
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
for(var/mob/living/M in buckled_mobs)
|
||||
unbuckle_mob(M)
|
||||
M.electrocute_act(shock_damage/100, source, siemens_coeff, flags) //Hard metal shell conducts!
|
||||
return 0 //So borgs they don't die trying to fix wiring
|
||||
return FALSE //So borgs they don't die trying to fix wiring
|
||||
|
||||
/mob/living/silicon/emp_act(severity)
|
||||
. = ..()
|
||||
|
||||
Reference in New Issue
Block a user