mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2026-08-21 18:16:37 +01:00
188 lines
7.3 KiB
Plaintext
188 lines
7.3 KiB
Plaintext
//Universal translator
|
|
/obj/item/universal_translator
|
|
name = "handheld translator"
|
|
desc = "This handy device appears to translate the languages it hears into onscreen text for a user."
|
|
icon = 'icons/obj/device.dmi'
|
|
icon_state = "translator"
|
|
w_class = WEIGHT_CLASS_NORMAL
|
|
origin_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3)
|
|
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
|
|
/// our translation context; set to path to start as path
|
|
var/datum/translation_context/context = /datum/translation_context/simple/universal_translator
|
|
|
|
var/mult_icons = 1 //Changes sprite when it translates
|
|
var/visual = 1 //If you need to see to get the message
|
|
var/audio = 0 //If you need to hear to get the message
|
|
var/listening = 0
|
|
var/datum/prototype/language/langset
|
|
/// allow us to translate tapes
|
|
var/cassette_translation = TRUE
|
|
/// allow knowledge transfering
|
|
var/allow_knowledge_transfer = TRUE
|
|
|
|
/obj/item/universal_translator/Initialize(mapload)
|
|
. = ..()
|
|
if(ispath(context))
|
|
set_context(context)
|
|
|
|
/obj/item/universal_translator/Destroy()
|
|
if(context && !ispath(context))
|
|
QDEL_NULL(context)
|
|
return ..()
|
|
|
|
/obj/item/universal_translator/proc/set_context(datum/translation_context/context_or_path)
|
|
if(istype(context, /datum/translation_context/variable/learning))
|
|
var/datum/translation_context/variable/learning/CTX = context
|
|
CTX.on_train = null
|
|
if(ispath(context_or_path))
|
|
context_or_path = new context_or_path
|
|
context = context_or_path
|
|
if(istype(context, /datum/translation_context/variable/learning))
|
|
var/datum/translation_context/variable/learning/CTX = context
|
|
CTX.on_train = CALLBACK(src, PROC_REF(on_learn))
|
|
|
|
/obj/item/universal_translator/proc/on_learn(datum/translation_context/context, datum/prototype/language/L, old_efficiency)
|
|
if(old_efficiency)
|
|
return
|
|
if(!ismob(loc))
|
|
return
|
|
to_chat(loc, SPAN_NOTICE("New language detected. Beginning translation network training."))
|
|
|
|
/obj/item/universal_translator/examine(mob/user, dist)
|
|
. = ..()
|
|
if(cassette_translation)
|
|
. += SPAN_NOTICE("Use a cassette tape on this to translate the tape's contents where possible.")
|
|
|
|
/obj/item/universal_translator/attackby(obj/item/I, mob/user)
|
|
if(istype(I, /obj/item/cassette_tape))
|
|
if(TIMER_COOLDOWN_CHECK(src, CD_INDEX_TAPE_TRANSLATION))
|
|
user.action_feedback(SPAN_WARNING("[src] cannot translate tapes that fast."), src)
|
|
return CLICKCHAIN_DO_NOT_PROPAGATE
|
|
var/obj/item/cassette_tape/T = I
|
|
var/datum/cassette_tape_iterator/translator/iter = T.lock_for_translation()
|
|
if(!iter)
|
|
user.action_feedback(SPAN_WARNING("Could not lock [T] for translation."), src)
|
|
return CLICKCHAIN_DO_NOT_PROPAGATE
|
|
var/amt = iter.translate(context)
|
|
user.action_feedback(SPAN_NOTICE("Translated [amt] lines on [T]. Processor cooling down for 10 seconds."), src)
|
|
TIMER_COOLDOWN_START(src, CD_INDEX_TAPE_TRANSLATION, 10 SECONDS)
|
|
return CLICKCHAIN_DO_NOT_PROPAGATE
|
|
return ..()
|
|
|
|
/obj/item/universal_translator/legacy_mob_melee_hook(mob/target, mob/user, clickchain_flags, list/params, mult, target_zone, intent)
|
|
if(user.a_intent == INTENT_HARM)
|
|
return ..()
|
|
if(!isrobot(target))
|
|
return ..()
|
|
. = CLICKCHAIN_DO_NOT_PROPAGATE
|
|
if(!istype(context, /datum/translation_context/variable))
|
|
user.action_feedback(SPAN_WARNING("[src] does not have a variable translation matrix."), src)
|
|
return
|
|
if(!allow_knowledge_transfer)
|
|
user.action_feedback(SPAN_WARNING("[src] doesn't have a data port."), src)
|
|
return
|
|
var/mob/living/silicon/robot/R = target
|
|
var/datum/translation_context/variable/theirs = R.translation_context
|
|
if(!istype(theirs))
|
|
user.action_feedback(SPAN_WARNING("[R] does not have a variable translation matrix."), src)
|
|
return
|
|
var/datum/translation_context/variable/ours = context
|
|
ours.copy_knowledge(theirs)
|
|
|
|
/obj/item/universal_translator/attack_self(mob/user, datum/event_args/actor/actor)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
if(!listening) //Turning ON
|
|
var/list/allowed = list()
|
|
for(var/datum/prototype/language/L in user.languages)
|
|
if(L.language_flags & (LANGUAGE_NONVERBAL | LANGUAGE_HIVEMIND))
|
|
continue
|
|
if(!context.can_translate(L))
|
|
continue
|
|
allowed += L
|
|
if(!length(allowed))
|
|
to_chat(user, SPAN_WARNING("There's no language you know that this can translate to."))
|
|
return
|
|
langset = input(user,"Translate to which of your languages?","Language Selection") as null|anything in allowed
|
|
if(!langset)
|
|
return
|
|
listening = 1
|
|
listening_objects |= src
|
|
if(mult_icons)
|
|
icon_state = "[initial(icon_state)]1"
|
|
to_chat(user, "<span class='notice'>You enable \the [src], translating into [langset.name].</span>")
|
|
else //Turning OFF
|
|
listening = 0
|
|
listening_objects -= src
|
|
langset = null
|
|
icon_state = "[initial(icon_state)]"
|
|
to_chat(user, "<span class='notice'>You disable \the [src].</span>")
|
|
|
|
/obj/item/universal_translator/hear_talk(var/mob/speaker, var/message, var/vrb, var/datum/prototype/language/language)
|
|
if(!listening || !istype(speaker))
|
|
return
|
|
|
|
//Show the "I heard something" animation.
|
|
if(mult_icons)
|
|
flick("[initial(icon_state)]2",src)
|
|
|
|
//Handheld or pocket only.
|
|
if(!isliving(loc))
|
|
return
|
|
|
|
var/mob/living/L = loc
|
|
|
|
if(!language)
|
|
return //Borgs were causing runtimes when passing language=null
|
|
|
|
if (language && (language.language_flags & LANGUAGE_NONVERBAL))
|
|
return //Not gonna translate sign language
|
|
|
|
if (visual && L.has_status_effect(/datum/status_effect/sight/blindness))
|
|
return //Can't see the screen, don't get the message
|
|
|
|
var/is_deaf = (L.sdisabilities & SDISABILITY_DEAF) || L.ear_deaf
|
|
|
|
if (audio && is_deaf)
|
|
return //Can't hear the translation, don't get the message
|
|
|
|
//Only translate if they can't understand, otherwise pointlessly spammy
|
|
//I'll just assume they don't look at the screen in that case
|
|
|
|
//They don't understand the spoken language we're translating FROM
|
|
if(!L.say_understands(speaker, language) || (visual && is_deaf))
|
|
//They understand the output language
|
|
if(L.say_understands(null,langset))
|
|
to_chat(L, "<i><b>[src]</b> translates, </i>\"<span class='[langset.colour]'>[context.attempt_translation(language, speaker, message)]</span>\"")
|
|
|
|
//Let's try an ear-worn version
|
|
/obj/item/universal_translator/ear
|
|
name = "translator earpiece"
|
|
desc = "This handy device appears to translate the languages it hears into another language for a user."
|
|
icon_state = "earpiece"
|
|
w_class = WEIGHT_CLASS_TINY
|
|
slot_flags = SLOT_EARS
|
|
visual = 0
|
|
audio = 1
|
|
context = /datum/translation_context/simple/universal_translator
|
|
|
|
/obj/item/universal_translator/adaptive
|
|
name = "handheld adaptive translator"
|
|
desc = "This handheld translator has been upgraded with a positronic accelerator, allowing it to \
|
|
slowly learn certain languages that wasn't originally included."
|
|
context = /datum/translation_context/variable/learning/universal_translator
|
|
|
|
/obj/item/universal_translator/ear/adaptive
|
|
name = "omni-translator earpiece"
|
|
desc = "This earpiece translator has been upgraded with a positronic accelerator, allowing it to \
|
|
slowly learn certain languages that wasn't originally included."
|
|
context = /datum/translation_context/variable/learning/universal_translator
|
|
|
|
/datum/translation_context/simple/universal_translator
|
|
translation_class = TRANSLATION_CLASSES_STANDARD_TRANSLATE
|
|
|
|
/datum/translation_context/variable/learning/universal_translator
|
|
translation_class = TRANSLATION_CLASSES_STANDARD_TRANSLATE
|
|
translation_class_learn = TRANSLATION_CLASSES_STANDARD_ADAPTIVE
|