mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-24 13:38:41 +01:00
Adds silicon access and built-in radio to AI Uplink Brain (only when controlled by AI) (#90112)
## About The Pull Request - adds silicon access to body controlled by an AI. This is done just by adding a trait - adds internal headset with same channels as AI has in its core (including syndicate and special channels for special AIs) - binary channel required some additional code to work properly for carbons without binary key so I decided to also fix big bold text for borg shells and for big brother. They all have big texts in binary. This is done by adding new `TRAIT_LOUD_BINARY` - turns out borg shells also lack loud mode for regular radio, so it is added too - ai also locks bodies for themselves the same way as they do with shells, for consistency ## Why It's Good For The Game While AIs losing their ability to listen radio when inside uplink brain can provide so much needed human VS ai conflict (because AI ignored open door request from that one assistant), it feels a bit unjustified. Same reason for AI lacking its innate all-access while in carbon body. You can still open doors for yourself by juggling between uplink brain and your core so why bother people with additional clicks. It brings carbon shell on par with silicon shells (and makes them superior cough cough) ## Changelog 🆑 balance: AI uplink brain now comes with built-in radio and free silicon access for the AI to use balance: AI entering uplink brain now locks it for themselves. You can reinsert that brain to reset its controlling AI fix: fixed AI borg shells and big brother not having loud binary. Now they do. /🆑
This commit is contained in:
@@ -1185,6 +1185,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
///The entity has AI 'access', so is either an AI, has an access wand, or is an admin ghost AI. Used to block off regular Silicons from things.
|
||||
///This is put on the mob, it is used on the client for Admins but they are the exception as they use `isAdminGhostAI`.
|
||||
#define TRAIT_AI_ACCESS "ai_access_trait"
|
||||
///The entity should have `SPAN_COMMAND` in binary the same way as AI does.
|
||||
#define TRAIT_LOUD_BINARY "loud_binary_trait"
|
||||
///The entity is able to receive a tracking button in chat
|
||||
#define TRAIT_CAN_GET_AI_TRACKING_MESSAGE "can_get_ai_tracking_message"
|
||||
|
||||
|
||||
@@ -342,6 +342,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_LIMBATTACHMENT" = TRAIT_LIMBATTACHMENT,
|
||||
"TRAIT_LITERATE" = TRAIT_LITERATE,
|
||||
"TRAIT_LIVERLESS_METABOLISM" = TRAIT_LIVERLESS_METABOLISM,
|
||||
"TRAIT_LOUD_BINARY" = TRAIT_LOUD_BINARY,
|
||||
"TRAIT_MADNESS_IMMUNE" = TRAIT_MADNESS_IMMUNE,
|
||||
"TRAIT_MAFIAINITIATE" = TRAIT_MAFIAINITIATE,
|
||||
"TRAIT_MAGICALLY_GIFTED" = TRAIT_MAGICALLY_GIFTED,
|
||||
|
||||
@@ -411,6 +411,14 @@ GLOBAL_LIST_INIT(channel_tokens, list(
|
||||
keyslot2 = new /obj/item/encryptionkey/ai_with_binary
|
||||
command = TRUE
|
||||
|
||||
/obj/item/radio/headset/silicon/human_ai/equipped(mob/user, slot, initial)
|
||||
. = ..()
|
||||
ADD_TRAIT(user, TRAIT_LOUD_BINARY, REF(src))
|
||||
|
||||
/obj/item/radio/headset/silicon/human_ai/dropped(mob/user, slot, initial)
|
||||
. = ..()
|
||||
REMOVE_TRAIT(user, TRAIT_LOUD_BINARY, REF(src))
|
||||
|
||||
/obj/item/radio/headset/silicon/ai/evil
|
||||
name = "\proper Evil Integrated Subspace Transceiver"
|
||||
keyslot2 = new /obj/item/encryptionkey/ai/evil
|
||||
|
||||
@@ -18,8 +18,12 @@
|
||||
can_smoothen_out = FALSE
|
||||
/// if connected, our AI
|
||||
var/mob/living/silicon/ai/mainframe
|
||||
/// owner AI of this body (resets in on_mob_remove)
|
||||
var/mob/living/silicon/ai/connected_ai
|
||||
/// action for undeployment
|
||||
var/datum/action/innate/brain_undeployment/undeployment_action = new
|
||||
/// Weakref to our imaginary brain radio implant
|
||||
var/datum/weakref/radio_weakref
|
||||
|
||||
/obj/item/organ/brain/cybernetic/ai/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -42,12 +46,21 @@
|
||||
RegisterSignals(brain_owner, list(COMSIG_QDELETING, COMSIG_LIVING_PRE_WABBAJACKED), PROC_REF(undeploy))
|
||||
RegisterSignal(brain_owner, COMSIG_CARBON_GAIN_ORGAN, PROC_REF(on_organ_gain))
|
||||
|
||||
var/obj/item/implant/radio/radio = new(owner)
|
||||
radio.implant(owner, null, TRUE, TRUE)
|
||||
radio_weakref = WEAKREF(radio)
|
||||
|
||||
/obj/item/organ/brain/cybernetic/ai/on_mob_remove(mob/living/carbon/organ_owner, special, movement_flags)
|
||||
undeploy()
|
||||
. = ..()
|
||||
organ_owner.remove_traits(list(HUMAN_SENSORS_VISIBLE_WITHOUT_SUIT, TRAIT_NO_MINDSWAP, TRAIT_CORPSELOCKED), REF(src))
|
||||
UnregisterSignal(organ_owner, list(COMSIG_LIVING_HEALTH_UPDATE, COMSIG_CLICK, COMSIG_MOB_GET_STATUS_TAB_ITEMS, COMSIG_MOB_MIND_BEFORE_MIDROUND_ROLL, COMSIG_QDELETING, COMSIG_LIVING_PRE_WABBAJACKED))
|
||||
|
||||
var/obj/item/implant/radio/radio = radio_weakref.resolve()
|
||||
if(radio)
|
||||
QDEL_NULL(radio)
|
||||
connected_ai = null
|
||||
|
||||
/obj/item/organ/brain/cybernetic/ai/proc/cancel_rolls(mob/living/source, datum/mind/mind, datum/antagonist/antagonist)
|
||||
SIGNAL_HANDLER
|
||||
if(ispath(antagonist, /datum/antagonist/malf_ai))
|
||||
@@ -88,6 +101,8 @@
|
||||
lines += "Estimated organic/inorganic integrity: [owner.health]"
|
||||
if(mainframe)
|
||||
lines += span_warning("Already occupied by another digital entity.")
|
||||
else if(connected_ai && connected_ai != user)
|
||||
lines += span_warning("Uplink is locked by another digital entity.")
|
||||
else if(!is_sufficiently_augmented())
|
||||
lines += span_warning("Organic organs detected. Robotic organs only, cannot take over.")
|
||||
else
|
||||
@@ -118,14 +133,27 @@
|
||||
ADD_TRAIT(AI.mind, TRAIT_UNCONVERTABLE, REF(src))
|
||||
ADD_TRAIT(AI, TRAIT_MIND_TEMPORARILY_GONE, REF(src))
|
||||
AI.mind.transfer_to(owner)
|
||||
to_chat(owner, span_boldbig("You are still considered a silicon/cyborg/AI. Follow your laws."))
|
||||
|
||||
/obj/item/organ/brain/cybernetic/ai/proc/deploy_init(mob/living/silicon/ai/AI)
|
||||
//todo camera maybe
|
||||
mainframe = AI
|
||||
connected_ai = AI
|
||||
RegisterSignal(AI, COMSIG_QDELETING, PROC_REF(ai_deleted))
|
||||
undeployment_action.Grant(owner)
|
||||
update_med_hud_status(owner)
|
||||
to_chat(owner, span_boldbig("You are still considered a silicon/cyborg/AI. Follow your laws."))
|
||||
|
||||
owner.add_traits(list(TRAIT_SILICON_ACCESS, TRAIT_LOUD_BINARY), REF(src))
|
||||
|
||||
var/obj/item/implant/radio/implant = radio_weakref.resolve()
|
||||
if(implant.radio && AI.radio)
|
||||
if((AI.radio.special_channels & RADIO_SPECIAL_SYNDIE))
|
||||
implant.radio.make_syndie()
|
||||
implant.radio.subspace_transmission = TRUE
|
||||
implant.radio.command = TRUE
|
||||
implant.radio.channels = AI.radio.channels
|
||||
for(var/channel in implant.radio.channels)
|
||||
implant.radio.secure_radio_connections[channel] = add_radio(implant.radio, GLOB.radiochannels[channel])
|
||||
|
||||
/obj/item/organ/brain/cybernetic/ai/proc/undeploy(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
@@ -144,6 +172,12 @@
|
||||
mainframe.eyeobj.setLoc(loc)
|
||||
REMOVE_TRAIT(mainframe.mind, TRAIT_UNCONVERTABLE, REF(src))
|
||||
REMOVE_TRAIT(mainframe, TRAIT_MIND_TEMPORARILY_GONE, REF(src))
|
||||
owner.remove_traits(list(TRAIT_SILICON_ACCESS, TRAIT_LOUD_BINARY), REF(src)) // we don't want randoms using our body as free AA, so we only have it when we active.
|
||||
|
||||
var/obj/item/implant/radio/implant = radio_weakref.resolve()
|
||||
if(implant)
|
||||
implant.radio.resetChannels()
|
||||
|
||||
mainframe = null
|
||||
update_med_hud_status(owner)
|
||||
|
||||
|
||||
@@ -65,15 +65,18 @@
|
||||
return special_voice
|
||||
|
||||
/mob/living/carbon/human/binarycheck()
|
||||
if(stat >= SOFT_CRIT || !ears)
|
||||
return FALSE
|
||||
var/obj/item/radio/headset/dongle = ears
|
||||
if(!istype(dongle))
|
||||
if(stat >= SOFT_CRIT)
|
||||
return FALSE
|
||||
var/area/our_area = get_area(src)
|
||||
if(our_area.area_flags & BINARY_JAMMING)
|
||||
return FALSE
|
||||
return (dongle.special_channels & RADIO_SPECIAL_BINARY)
|
||||
var/obj/item/organ/brain/cybernetic/ai/brain = get_organ_slot(ORGAN_SLOT_BRAIN)
|
||||
if(istype(brain))
|
||||
return TRUE
|
||||
var/obj/item/radio/headset/dongle = ears
|
||||
if(!istype(dongle))
|
||||
return FALSE
|
||||
return dongle.special_channels & RADIO_SPECIAL_BINARY
|
||||
|
||||
/mob/living/carbon/human/radio(message, list/message_mods = list(), list/spans, language) //Poly has a copy of this, lazy bastard
|
||||
. = ..()
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
RegisterSignal(ai_tracking_tool, COMSIG_TRACKABLE_TRACKING_TARGET, PROC_REF(on_track_target))
|
||||
RegisterSignal(ai_tracking_tool, COMSIG_TRACKABLE_GLIDE_CHANGED, PROC_REF(tracked_glidesize_changed))
|
||||
|
||||
add_traits(list(TRAIT_PULL_BLOCKED, TRAIT_AI_ACCESS, TRAIT_HANDS_BLOCKED, TRAIT_CAN_GET_AI_TRACKING_MESSAGE), INNATE_TRAIT)
|
||||
add_traits(list(TRAIT_PULL_BLOCKED, TRAIT_AI_ACCESS, TRAIT_HANDS_BLOCKED, TRAIT_CAN_GET_AI_TRACKING_MESSAGE, TRAIT_LOUD_BINARY), INNATE_TRAIT)
|
||||
|
||||
alert_control = new(src, list(ALARM_ATMOS, ALARM_FIRE, ALARM_POWER, ALARM_CAMERA, ALARM_BURGLAR, ALARM_MOTION), list(z), camera_view = TRUE)
|
||||
RegisterSignal(alert_control.listener, COMSIG_ALARM_LISTENER_TRIGGERED, PROC_REF(alarm_triggered))
|
||||
@@ -967,6 +967,7 @@
|
||||
deployed_shell = target
|
||||
target.deploy_init(src)
|
||||
mind.transfer_to(target)
|
||||
ADD_TRAIT(target, TRAIT_LOUD_BINARY, REF(src))
|
||||
diag_hud_set_deployed()
|
||||
|
||||
/datum/action/innate/deploy_shell
|
||||
|
||||
@@ -895,6 +895,7 @@
|
||||
if((AI.radio.special_channels & RADIO_SPECIAL_SYNDIE))
|
||||
radio.make_syndie()
|
||||
radio.subspace_transmission = TRUE
|
||||
radio.command = TRUE
|
||||
radio.channels = AI.radio.channels
|
||||
for(var/chan in radio.channels)
|
||||
radio.secure_radio_connections[chan] = add_radio(radio, GLOB.radiochannels[chan])
|
||||
@@ -927,6 +928,7 @@
|
||||
deployed = FALSE
|
||||
mainframe.deployed_shell = null
|
||||
undeployment_action.Remove(src)
|
||||
REMOVE_TRAIT(src, TRAIT_LOUD_BINARY, REF(mainframe))
|
||||
if(radio) //Return radio to normal
|
||||
radio.recalculateChannels()
|
||||
if(!QDELETED(builtInCamera))
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
if(HAS_TRAIT(mind, TRAIT_DISPLAY_JOB_IN_BINARY))
|
||||
designation = mind.assigned_role.title
|
||||
|
||||
if(isAI(src))
|
||||
if(HAS_TRAIT(src, TRAIT_LOUD_BINARY))
|
||||
// AIs are loud and ugly
|
||||
spans |= SPAN_COMMAND
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
if(iscarbon(src))
|
||||
namepart = GetVoice()
|
||||
|
||||
// AI in carbon body should still have its real name
|
||||
var/obj/item/organ/brain/cybernetic/ai/brain = get_organ_slot(ORGAN_SLOT_BRAIN)
|
||||
if(istype(brain))
|
||||
namepart = brain.mainframe.name
|
||||
designation = brain.mainframe.job
|
||||
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M.binarycheck())
|
||||
if(isAI(M))
|
||||
|
||||
Reference in New Issue
Block a user