/mob/living/silicon // Speaking gender = NEUTER voice_name = "Synthesized Voice" accent = ACCENT_TTS /// Which languages can be vocalized by the speech synthesizer var/list/speech_synthesizer_langs = list() var/speak_statement = "states" var/speak_exclamation = "declares" var/speak_query = "queries" // Description var/pose // Bad Guy Stuff var/syndicate = FALSE // Laws var/datum/ai_laws/laws var/law_channel = DEFAULT_LAW_CHANNEL var/list/additional_law_channels = list("State" = "") /// Channels laws are currently being stated on var/list/stating_laws = list() /// Used to determine default channels var/obj/item/radio/common_radio // Hud Stuff var/list/hud_list[10] var/sensor_mode = 0 //Determines the current HUD. // Alarms var/register_alarms = TRUE var/next_alarm_notice var/list/datum/alarm/queued_alarms = new() // Internal Computer var/obj/item/modular_computer/silicon/computer var/list/silicon_subsystems = list( /mob/living/silicon/verb/computer_interact, /mob/living/silicon/verb/silicon_mimic_accent ) // Utility var/obj/item/camera/siliconcam/ai_camera //photography // ID and Access var/list/access_rights var/obj/item/card/id/id_card var/id_card_type = /obj/item/card/id/synthetic /// ACCENT_ALL_IPC with the added consideration that this selection can be used by the ship AI itself, and should not look bad for the SCC. No dregs, Himeans, Trinarists, etc. var/list/possible_accents = list(ACCENT_CETI, ACCENT_TTS, ACCENT_XANU, ACCENT_COC, ACCENT_ELYRA, ACCENT_ERIDANI, ACCENT_SOL, ACCENT_SILVERSUN_EXPATRIATE, ACCENT_SILVERSUN_ORIGINAL, ACCENT_PHONG, ACCENT_MARTIAN, ACCENT_KONYAN, ACCENT_LUNA, ACCENT_GIBSON_OVAN, ACCENT_GIBSON_UNDIR, ACCENT_VYSOKA, ACCENT_VENUS, ACCENT_VENUSJIN, ACCENT_JUPITER, ACCENT_CALLISTO, ACCENT_EUROPA, ACCENT_EARTH, ACCENT_ASSUNZIONE, ACCENT_VISEGRAD, ACCENT_SANCOLETTE, ACCENT_VALKYRIE, ACCENT_MICTLAN, ACCENT_PERSEPOLIS, ACCENT_MEDINA, ACCENT_NEWSUEZ, ACCENT_AEMAQ, ACCENT_DAMASCUS) var/can_hear_hivenet = TRUE // Misc mob_thinks = FALSE var/can_speak_basic = TRUE /mob/living/silicon/Initialize() GLOB.silicon_mob_list |= src . = ..() add_language(LANGUAGE_TCB, can_speak_basic) init_id() var/datum/language/L = locate(/datum/language/common) in languages default_language = L init_subsystems() /mob/living/silicon/Destroy() GLOB.silicon_mob_list -= src QDEL_NULL(computer) QDEL_NULL(computer) QDEL_NULL(id_card) QDEL_NULL(common_radio) for(var/datum/alarm_handler/AH in SSalarm.all_handlers) AH.unregister_alarm(src) QDEL_LIST_ASSOC_VAL(hud_list) return ..() /mob/living/silicon/proc/init_id() if(id_card) return id_card = new id_card_type(src) set_id_info(id_card) /mob/living/silicon/proc/SetName(pickedName as text) real_name = pickedName name = real_name if(istype(id_card)) if(!istype(id_card.chat_user)) id_card.InitializeChatUser() id_card.chat_user.username = real_name /mob/living/silicon/proc/show_laws() return /mob/living/silicon/drop_item() return /mob/living/silicon/emp_act(severity) . = ..() switch(severity) if(EMP_HEAVY) src.take_organ_damage(0, 20, emp = TRUE) Stun(rand(5, 10)) if(EMP_LIGHT) src.take_organ_damage(0, 10, emp = TRUE) Stun(rand(1, 5)) flash_act(affect_silicon = TRUE) to_chat(src, SPAN_DANGER("BZZZT")) to_chat(src, SPAN_WARNING("Warning: Electromagnetic pulse detected.")) /mob/living/silicon/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone, var/used_weapon, var/damage_flags) return //immune /mob/living/silicon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0, var/def_zone = null, tesla_shock = FALSE, ground_zero) if(istype(source, /obj/machinery/containment_field)) spark(loc, 5, GLOB.alldirs) shock_damage *= 0.75 //take reduced damage take_overall_damage(0, shock_damage) visible_message(SPAN_WARNING("\The [src] was shocked by \the [source]!"), \ SPAN_DANGER("Energy pulse detected, system damaged!"), \ SPAN_WARNING("You hear an electrical crack.")) if(prob(20)) Stun(2) return /mob/living/silicon/proc/damage_mob(var/brute = 0, var/fire = 0, var/tox = 0) return /mob/living/silicon/IsAdvancedToolUser() return TRUE /mob/living/silicon/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit) SHOULD_CALL_PARENT(FALSE) //More shitcode if(hitting_projectile.damage > 0) switch(hitting_projectile.damage_type) if(DAMAGE_BRUTE) adjustBruteLoss(hitting_projectile.damage) if(DAMAGE_BURN) adjustFireLoss(hitting_projectile.damage) hitting_projectile.on_hit(src, 100) updatehealth() return BULLET_ACT_HIT /mob/living/silicon/apply_effect(var/effect = 0,var/effecttype = STUN, var/blocked = 0) return FALSE /proc/islinked(var/mob/living/silicon/robot/bot, var/mob/living/silicon/ai/ai) if(!istype(bot) || !istype(ai)) return FALSE if(bot.connected_ai == ai) return TRUE return FALSE /// This is a pure virtual function, it should be overwritten by all subclasses /mob/living/silicon/proc/show_malf_ai() return FALSE /// This function displays the shuttles ETA in the status panel if the shuttle has been called /mob/living/silicon/proc/show_emergency_shuttle_eta() if(GLOB.evacuation_controller) var/eta_status = GLOB.evacuation_controller.get_status_panel_eta() if(eta_status) stat(null, eta_status) /// This adds the basic clock, shuttle recall timer, and malf_ai info to all silicon lifeforms /mob/living/silicon/get_status_tab_items() . = ..() var/area/A = get_area(src) var/area_name = get_area_display_name(A) . += "[area_name]" . += "" if(A.area_blurb) . += "[A.area_blurb]" . += "" if(!stat) . += "System Integrity: [round((health/maxHealth)*100)]%" else . += "System Integrity: NON-FUNCTIONAL" show_malf_ai() /// can't inject synths /mob/living/silicon/can_inject(mob/user, error_msg) if(error_msg) to_chat(user, SPAN_ALERT("The armored plating is too tough.")) return 0 // Silicon mob language procs /mob/living/silicon/can_speak(datum/language/speaking) return universal_speak || (speaking in src.speech_synthesizer_langs) //need speech synthesizer support to vocalize a language /mob/living/silicon/add_language(var/language, var/can_speak=1) var/datum/language/added_language = GLOB.all_languages[language] if(!added_language) return . = ..(language) if(can_speak && (added_language in languages) && !(added_language in speech_synthesizer_langs)) speech_synthesizer_langs += added_language return TRUE /mob/living/silicon/remove_language(var/rem_language) var/datum/language/removed_language = GLOB.all_languages[rem_language] if(!removed_language) return ..(rem_language) speech_synthesizer_langs -= removed_language /mob/living/silicon/check_languages() set name = "Check Known Languages" set category = "IC.Language" set src = usr var/dat = "Known Languages

" if(default_language) dat += "Current default language: [default_language] - reset

" for(var/datum/language/L in languages) if(!(L.flags & NONGLOBAL)) var/default_str if(L == default_language) default_str = " - default - reset" else default_str = " - set default" var/synth = (L in speech_synthesizer_langs) dat += "[L.name] ([get_language_prefix()][L.key])[synth ? default_str : null]
Speech Synthesizer: [synth ? "YES" : "NOT SUPPORTED"]
[L.desc]

" src << browse(HTML_SKELETON(dat), "window=checklanguage") return /// Prompts the silicon mob which HUD to choose from, changes `sensor_mode` depending on choice /mob/living/silicon/proc/toggle_sensor_mode() var/sensor_type = tgui_input_list(src, "Please select sensor type.", "Sensor Integration", list("Security", "Medical", "Disable")) switch(sensor_type) if("Security") sensor_mode = SEC_HUD to_chat(src, SPAN_NOTICE("Security records overlay enabled.")) if("Medical") sensor_mode = MED_HUD to_chat(src, SPAN_NOTICE("Life signs monitor overlay enabled.")) if("Disable") sensor_mode = NO_HUD to_chat(src, SPAN_NOTICE("Sensor augmentations disabled.")) /mob/living/silicon/verb/pose() set name = "Set Pose" set desc = "Sets a description which will be shown when someone examines you." set category = "IC" pose = sanitize(input(usr, "This is [src]. It...", "Pose", null) as text) /mob/living/silicon/verb/set_flavor() set name = "Set Flavour Text" set desc = "Sets an extended description of your character's features." set category = "IC" flavor_text = sanitize(input(usr, "Please enter your new flavour text.", "Flavour text", null) as text) /mob/living/silicon/binarycheck() return TRUE /mob/living/silicon/ex_act(severity) if(!blinded) flash_act(affect_silicon = TRUE) var/brute var/burn switch(severity) if(1.0) brute = 400 burn = 100 if(2.0) brute = 60 burn = 60 if(3.0) brute = 30 apply_damage(brute, DAMAGE_BRUTE, damage_flags = DAMAGE_FLAG_EXPLODE) apply_damage(burn, DAMAGE_BURN, damage_flags = DAMAGE_FLAG_EXPLODE) /mob/living/silicon/proc/receive_alarm(var/datum/alarm_handler/alarm_handler, var/datum/alarm/alarm, was_raised) if(!next_alarm_notice) next_alarm_notice = world.time + SecondsToTicks(10) var/list/alarms = queued_alarms[alarm_handler] if(was_raised) // Raised alarms are always set alarms[alarm] = 1 else // Alarms that were raised but then cleared before the next notice are instead removed if(alarm in alarms) alarms -= alarm // And alarms that have only been cleared thus far are set as such else alarms[alarm] = -1 /mob/living/silicon/proc/process_queued_alarms() if(next_alarm_notice && (world.time > next_alarm_notice)) next_alarm_notice = 0 for(var/datum/alarm_handler/AH in queued_alarms) var/list/alarms = queued_alarms[AH] var/reported = FALSE for(var/datum/alarm/A in alarms) if(alarms[A] == 1) if(!reported) reported = TRUE to_chat(src, SPAN_WARNING("--- [AH.category] Detected ---")) raised_alarm(A) for(var/datum/alarm_handler/AH in queued_alarms) var/list/alarms = queued_alarms[AH] var/reported = FALSE for(var/datum/alarm/A in alarms) if(alarms[A] == -1) if(!reported) reported = TRUE to_chat(src, SPAN_NOTICE("--- [AH.category] Cleared ---")) to_chat(src, "\The [A.alarm_name()].") for(var/datum/alarm_handler/AH in queued_alarms) var/list/alarms = queued_alarms[AH] alarms.Cut() /mob/living/silicon/proc/raised_alarm(var/datum/alarm/A) to_chat(src, "[A.alarm_name()]!") /mob/living/silicon/ai/raised_alarm(var/datum/alarm/A) var/cameratext = "" for(var/obj/machinery/camera/C in A.cameras()) cameratext += "[(cameratext == "")? "" : "|"][C.c_tag]" to_chat(src, "[A.alarm_name()]! ([(cameratext)? cameratext : "No Camera"])") /mob/living/silicon/proc/is_traitor() return mind && (mind in GLOB.traitors.current_antagonists) /mob/living/silicon/proc/is_malf() return mind && (mind in GLOB.malf.current_antagonists) /mob/living/silicon/proc/is_malf_or_traitor() return is_traitor() || is_malf() /mob/living/silicon/flash_act(intensity = FLASH_PROTECTION_MODERATE, override_blindness_check = FALSE, affect_silicon = FALSE, ignore_inherent = FALSE, type = /atom/movable/screen/fullscreen/flash, length = 2.5 SECONDS) if(affect_silicon) return ..() /mob/living/silicon/is_blind() return FALSE /mob/living/silicon/adjustEarDamage() return /mob/living/silicon/setEarDamage() return /mob/living/silicon/reset_view() ..() if(cameraFollow) cameraFollow = null /mob/living/silicon/seizure() flash_act(affect_silicon = TRUE) /mob/living/silicon/Move(newloc, direct) . = ..() if(underdoor) underdoor = FALSE if((layer == UNDERDOOR))//if this is false, then we must have used hide, or had our layer changed by something else. We wont do anymore checks for this move proc for(var/obj/machinery/door/D in loc) if(D.hashatch) underdoor = TRUE break if(!underdoor) layer = initial(layer) /mob/living/silicon/get_bullet_impact_effect_type(var/def_zone) return BULLET_IMPACT_METAL /mob/living/silicon/get_radio() return common_radio /mob/living/silicon/get_speech_bubble_state_modifier() return "robot"