This commit is contained in:
Ghommie
2020-05-11 00:46:51 +02:00
74 changed files with 1049 additions and 596 deletions
+21 -2
View File
@@ -3,5 +3,24 @@
#define LANGUAGE_HIDE_ICON_IF_UNDERSTOOD 4
#define LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD 8
#define LANGUAGE_KNOWN "language_known"
#define LANGUAGE_SHADOWED "language_shadowed"
// LANGUAGE SOURCE DEFINES
#define LANGUAGE_ALL "all" // For use in full removal only.
#define LANGUAGE_ATOM "atom"
#define LANGUAGE_MIND "mind"
#define LANGUAGE_ABSORB "absorb"
#define LANGUAGE_APHASIA "aphasia"
#define LANGUAGE_BLOODSUCKER "bloodsucker"
#define LANGUAGE_CLOCKIE "clockie"
#define LANGUAGE_CULTIST "cultist"
#define LANGUAGE_CURATOR "curator"
#define LANGUAGE_DEVIL "devil"
#define LANGUAGE_GLAND "gland"
#define LANGUAGE_HAT "hat"
#define LANGUAGE_HIGH "high"
#define LANGUAGE_MALF "malf"
#define LANGUAGE_MASTER "master"
#define LANGUAGE_SOFTWARE "software"
#define LANGUAGE_STONER "stoner"
#define LANGUAGE_VASSAL "vassal"
#define LANGUAGE_VOICECHANGE "voicechange"
+10 -1
View File
@@ -255,6 +255,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
current_user = M.client
//Blank
menu_holder = image(icon='icons/effects/effects.dmi',loc=anchor,icon_state="nothing",layer = ABOVE_HUD_LAYER)
menu_holder.plane = ABOVE_HUD_PLANE
menu_holder.appearance_flags |= KEEP_APART
menu_holder.vis_contents += elements + close_button
current_user.images += menu_holder
@@ -285,13 +286,16 @@ GLOBAL_LIST_EMPTY(radial_menus)
Choices should be a list where list keys are movables or text used for element names and return value
and list values are movables/icons/images used for element icons
*/
/proc/show_radial_menu(mob/user, atom/anchor, list/choices, uniqueid, radius, datum/callback/custom_check, require_near = FALSE, tooltips = FALSE)
/proc/show_radial_menu(mob/user, atom/anchor, list/choices, uniqueid, radius, datum/callback/custom_check, require_near = FALSE, tooltips = FALSE, no_repeat_close = FALSE)
if(!user || !anchor || !length(choices))
return
if(!uniqueid)
uniqueid = "defmenu_[REF(user)]_[REF(anchor)]"
if(GLOB.radial_menus[uniqueid])
if(!no_repeat_close)
var/datum/radial_menu/menu = GLOB.radial_menus[uniqueid]
menu.finished = TRUE
return
var/datum/radial_menu/menu = new
@@ -308,4 +312,9 @@ GLOBAL_LIST_EMPTY(radial_menus)
var/answer = menu.selected_choice
qdel(menu)
GLOB.radial_menus -= uniqueid
if(require_near && !in_range(anchor, user))
return
if(istype(custom_check))
if(!custom_check.Invoke())
return
return answer
@@ -91,7 +91,6 @@
trauma = _trauma
owner = trauma.owner
copy_known_languages_from(owner, TRUE)
setup_friend()
+4 -10
View File
@@ -26,21 +26,15 @@
scan_desc = "extensive damage to the brain's language center"
gain_text = "<span class='warning'>You have trouble forming words in your head...</span>"
lose_text = "<span class='notice'>You suddenly remember how languages work.</span>"
var/datum/language_holder/prev_language
var/datum/language_holder/mob_language
/datum/brain_trauma/severe/aphasia/on_gain()
mob_language = owner.get_language_holder()
prev_language = mob_language.copy()
mob_language.remove_all_languages()
mob_language.grant_language(/datum/language/aphasia)
owner.add_blocked_language(subtypesof(/datum/language/) - /datum/language/aphasia, LANGUAGE_APHASIA)
owner.grant_language(/datum/language/aphasia, TRUE, TRUE, LANGUAGE_APHASIA)
..()
/datum/brain_trauma/severe/aphasia/on_lose()
mob_language.remove_language(/datum/language/aphasia)
mob_language.copy_known_languages_from(prev_language) //this will also preserve languages learned during the trauma
QDEL_NULL(prev_language)
mob_language = null
owner.remove_blocked_language(subtypesof(/datum/language/), LANGUAGE_APHASIA)
owner.remove_language(/datum/language/aphasia, TRUE, TRUE, LANGUAGE_APHASIA)
..()
/datum/brain_trauma/severe/blindness
@@ -30,7 +30,6 @@ Bonus
symptom_delay_max = 120
var/scramble_language = FALSE
var/datum/language/current_language
var/datum/language_holder/original_language
threshold_desc = list(
"Transmission 14" = "The host's language center of the brain is damaged, leading to complete inability to speak or understand any language.",
"Stage Speed 7" = "Changes voice more often.",
@@ -48,9 +47,6 @@ Bonus
symptom_delay_max = 85
if(A.properties["transmittable"] >= 14) //random language
scramble_language = TRUE
var/mob/living/M = A.affected_mob
var/datum/language_holder/mob_language = M.get_language_holder()
original_language = mob_language.copy()
/datum/symptom/voice_change/Activate(datum/disease/advance/A)
if(!..())
@@ -64,12 +60,10 @@ Bonus
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.SetSpecialVoice(H.dna.species.random_name(H.gender))
if(scramble_language)
H.remove_language(current_language)
if(scramble_language && !current_language) // Last part prevents rerolling language with small amounts of cure.
current_language = pick(subtypesof(/datum/language) - /datum/language/common)
H.grant_language(current_language)
var/datum/language_holder/mob_language = H.get_language_holder()
mob_language.only_speaks_language = current_language
H.add_blocked_language(subtypesof(/datum/language) - current_language, LANGUAGE_VOICECHANGE)
H.grant_language(current_language, TRUE, TRUE, LANGUAGE_VOICECHANGE)
/datum/symptom/voice_change/End(datum/disease/advance/A)
..()
@@ -77,7 +71,5 @@ Bonus
var/mob/living/carbon/human/H = A.affected_mob
H.UnsetSpecialVoice()
if(scramble_language)
var/mob/living/M = A.affected_mob
M.copy_known_languages_from(original_language, TRUE)
current_language = null
QDEL_NULL(original_language)
A.affected_mob.remove_blocked_language(subtypesof(/datum/language), LANGUAGE_VOICECHANGE)
A.affected_mob.remove_all_languages(LANGUAGE_VOICECHANGE) // In case someone managed to get more than one anyway.
+5
View File
@@ -355,6 +355,11 @@
var/datum/species/old_species = dna.species
dna.species = new_race
dna.species.on_species_gain(src, old_species, pref_load)
if(ishuman(src))
qdel(language_holder)
var/species_holder = initial(mrace.species_language_holder)
language_holder = new species_holder(src)
update_atom_languages()
/mob/living/carbon/human/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE)
..()
+2 -5
View File
@@ -85,8 +85,7 @@
/datum/mind/proc/get_language_holder()
if(!language_holder)
var/datum/language_holder/L = current.get_language_holder(shadow=FALSE)
language_holder = L.copy(src)
language_holder = new (src)
return language_holder
@@ -101,9 +100,6 @@
if(iscarbon(current))
var/mob/living/carbon/C = current
C.disable_intentional_combat_mode(TRUE)
if(!language_holder)
var/datum/language_holder/mob_holder = new_character.get_language_holder(shadow = FALSE)
language_holder = mob_holder.copy(src)
if(key)
if(new_character.key != key) //if we're transferring into a body with a key associated which is not ours
@@ -131,6 +127,7 @@
transfer_martial_arts(new_character)
if(active || force_key_move)
new_character.key = key //now transfer the key to link the client to our new body
current.update_atom_languages()
//CIT CHANGE - makes arousal update when transfering bodies
if(isliving(new_character)) //New humans and such are by default enabled arousal. Let's always use the new mind's prefs.
+4 -4
View File
@@ -277,10 +277,10 @@
/datum/mutation/human/stoner/on_acquiring(mob/living/carbon/human/owner)
..()
owner.grant_language(/datum/language/beachbum)
owner.remove_language(/datum/language/common)
owner.grant_language(/datum/language/beachbum, TRUE, TRUE, LANGUAGE_STONER)
owner.add_blocked_language(subtypesof(/datum/language) - /datum/language/beachbum, LANGUAGE_STONER)
/datum/mutation/human/stoner/on_losing(mob/living/carbon/human/owner)
..()
owner.grant_language(/datum/language/common)
owner.remove_language(/datum/language/beachbum)
owner.remove_language(/datum/language/beachbum, TRUE, TRUE, LANGUAGE_STONER)
owner.remove_blocked_language(subtypesof(/datum/language) - /datum/language/beachbum, LANGUAGE_STONER)
+79 -73
View File
@@ -11,7 +11,7 @@
var/throw_range = 7
var/mob/pulledby = null
var/initial_language_holder = /datum/language_holder
var/datum/language_holder/language_holder
var/datum/language_holder/language_holder // Mindless mobs and objects need language too, some times. Mind holder takes prescedence.
var/verb_say = "says"
var/verb_ask = "asks"
var/verb_exclaim = "exclaims"
@@ -502,88 +502,94 @@
animate(src, pixel_y = initial(pixel_y), time = 10)
setMovetype(movement_type & ~FLOATING)
/* Language procs */
/atom/movable/proc/get_language_holder(shadow=TRUE)
if(language_holder)
return language_holder
else
/* Language procs
* Unless you are doing something very specific, these are the ones you want to use.
*/
/// Gets or creates the relevant language holder. For mindless atoms, gets the local one. For atom with mind, gets the mind one.
/atom/movable/proc/get_language_holder(get_minds = TRUE)
if(!language_holder)
language_holder = new initial_language_holder(src)
return language_holder
return language_holder
/atom/movable/proc/grant_language(datum/language/dt, body = FALSE)
var/datum/language_holder/H = get_language_holder(!body)
H.grant_language(dt, body)
/// Grants the supplied language and sets omnitongue true.
/atom/movable/proc/grant_language(language, understood = TRUE, spoken = TRUE, source = LANGUAGE_ATOM)
var/datum/language_holder/LH = get_language_holder()
return LH.grant_language(language, understood, spoken, source)
/atom/movable/proc/grant_all_languages(omnitongue=FALSE)
var/datum/language_holder/H = get_language_holder()
H.grant_all_languages(omnitongue)
/// Grants every language.
/atom/movable/proc/grant_all_languages(understood = TRUE, spoken = TRUE, grant_omnitongue = TRUE, source = LANGUAGE_MIND)
var/datum/language_holder/LH = get_language_holder()
return LH.grant_all_languages(understood, spoken, grant_omnitongue, source)
/// Removes a single language.
/atom/movable/proc/remove_language(language, understood = TRUE, spoken = TRUE, source = LANGUAGE_ALL)
var/datum/language_holder/LH = get_language_holder()
return LH.remove_language(language, understood, spoken, source)
/// Removes every language and sets omnitongue false.
/atom/movable/proc/remove_all_languages(source = LANGUAGE_ALL, remove_omnitongue = FALSE)
var/datum/language_holder/LH = get_language_holder()
return LH.remove_all_languages(source, remove_omnitongue)
/// Adds a language to the blocked language list. Use this over remove_language in cases where you will give languages back later.
/atom/movable/proc/add_blocked_language(language, source = LANGUAGE_ATOM)
var/datum/language_holder/LH = get_language_holder()
return LH.add_blocked_language(language, source)
/// Removes a language from the blocked language list.
/atom/movable/proc/remove_blocked_language(language, source = LANGUAGE_ATOM)
var/datum/language_holder/LH = get_language_holder()
return LH.remove_blocked_language(language, source)
/// Checks if atom has the language. If spoken is true, only checks if atom can speak the language.
/atom/movable/proc/has_language(language, spoken = FALSE)
var/datum/language_holder/LH = get_language_holder()
return LH.has_language(language, spoken)
/// Checks if atom can speak the language.
/atom/movable/proc/can_speak_language(language)
var/datum/language_holder/LH = get_language_holder()
return LH.can_speak_language(language)
/// Returns the result of tongue specific limitations on spoken languages.
/atom/movable/proc/could_speak_language(language)
return TRUE
/// Returns selected language, if it can be spoken, or finds, sets and returns a new selected language if possible.
/atom/movable/proc/get_selected_language()
var/datum/language_holder/LH = get_language_holder()
return LH.get_selected_language()
/// Gets a random understood language, useful for hallucinations and such.
/atom/movable/proc/get_random_understood_language()
var/datum/language_holder/H = get_language_holder()
. = H.get_random_understood_language()
var/datum/language_holder/LH = get_language_holder()
return LH.get_random_understood_language()
/atom/movable/proc/remove_language(datum/language/dt, body = FALSE)
var/datum/language_holder/H = get_language_holder(!body)
H.remove_language(dt, body)
/// Gets a random spoken language, useful for forced speech and such.
/atom/movable/proc/get_random_spoken_language()
var/datum/language_holder/LH = get_language_holder()
return LH.get_random_spoken_language()
/atom/movable/proc/remove_all_languages()
var/datum/language_holder/H = get_language_holder()
H.remove_all_languages()
/// Copies all languages into the supplied atom/language holder. Source should be overridden when you
/// do not want the language overwritten by later atom updates or want to avoid blocked languages.
/atom/movable/proc/copy_languages(from_holder, source_override)
if(isatom(from_holder))
var/atom/movable/thing = from_holder
from_holder = thing.get_language_holder()
var/datum/language_holder/LH = get_language_holder()
return LH.copy_languages(from_holder, source_override)
/atom/movable/proc/has_language(datum/language/dt)
var/datum/language_holder/H = get_language_holder()
. = H.has_language(dt)
/atom/movable/proc/copy_known_languages_from(thing, replace=FALSE)
var/datum/language_holder/H = get_language_holder()
. = H.copy_known_languages_from(thing, replace)
// Whether an AM can speak in a language or not, independent of whether
// it KNOWS the language
/atom/movable/proc/could_speak_in_language(datum/language/dt)
. = TRUE
/atom/movable/proc/can_speak_in_language(datum/language/dt)
var/datum/language_holder/H = get_language_holder()
if(!H.has_language(dt))
return FALSE
else if(H.omnitongue)
return TRUE
else if(could_speak_in_language(dt) && (!H.only_speaks_language || H.only_speaks_language == dt))
return TRUE
else
return FALSE
/atom/movable/proc/get_default_language()
// if no language is specified, and we want to say() something, which
// language do we use?
var/datum/language_holder/H = get_language_holder()
if(H.selected_default_language)
if(can_speak_in_language(H.selected_default_language))
return H.selected_default_language
else
H.selected_default_language = null
var/datum/language/chosen_langtype
var/highest_priority
for(var/lt in H.languages)
var/datum/language/langtype = lt
if(!can_speak_in_language(langtype))
continue
var/pri = initial(langtype.default_priority)
if(!highest_priority || (pri > highest_priority))
chosen_langtype = langtype
highest_priority = pri
H.selected_default_language = .
. = chosen_langtype
/// Empties out the atom specific languages and updates them according to the current atoms language holder.
/// As a side effect, it also creates missing language holders in the process.
/atom/movable/proc/update_atom_languages()
var/datum/language_holder/LH = get_language_holder()
return LH.update_atom_languages(src)
/* End language procs */
/atom/movable/proc/ConveyorMove(movedir)
set waitfor = FALSE
if(!anchored && has_gravity())
+3 -4
View File
@@ -396,7 +396,6 @@ GLOBAL_LIST_EMPTY(network_holopads)
Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY)
Hologram.Impersonation = user
Hologram.copy_known_languages_from(user,replace = TRUE)
Hologram.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it.
Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
Hologram.setAnchored(TRUE)//So space wind cannot drag it.
@@ -555,9 +554,8 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
Hologram.alpha = 170
Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY)
Hologram.dir = SOUTH //for now
Hologram.grant_all_languages(omnitongue=TRUE)
var/datum/language_holder/holder = Hologram.get_language_holder()
holder.selected_default_language = record.language
holder.selected_language = record.language
Hologram.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it.
Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
Hologram.setAnchored(TRUE)//So space wind cannot drag it.
@@ -649,7 +647,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
return
if(HOLORECORD_LANGUAGE)
var/datum/language_holder/holder = replay_holo.get_language_holder()
holder.selected_default_language = entry[2]
holder.selected_language = entry[2]
if(HOLORECORD_PRESET)
var/preset_type = entry[2]
var/datum/preset_holoimage/H = new preset_type
@@ -672,6 +670,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
updateDialog()
/obj/effect/overlay/holo_pad_hologram
initial_language_holder = /datum/language_holder/universal
var/mob/living/Impersonation
var/datum/holocall/HC
@@ -100,7 +100,7 @@
obj/source, // the originating radio
frequency, // the frequency the signal is taking place on
atom/movable/virtualspeaker/speaker, // representation of the method's speaker
datum/language/language, // the langauge of the message
datum/language/language, // the language of the message
message, // the text content of the message
spans // the list of spans applied to the message
)
+74 -24
View File
@@ -6,17 +6,42 @@
icon_state = "cutout_basic"
w_class = WEIGHT_CLASS_BULKY
resistance_flags = FLAMMABLE
// Possible restyles for the cutout;
// add an entry in change_appearance() if you add to here
var/list/possible_appearances = list("Assistant", "Clown", "Mime",
"Traitor", "Nuke Op", "Cultist", "Brass Cultist", "Clockwork Cultist",
"Revolutionary", "Wizard", "Shadowling", "Xenomorph", "Xenomorph Maid", "Swarmer",
"Ash Walker", "Deathsquad Officer", "Ian", "Slaughter Demon",
"Laughter Demon", "Private Security Officer", "Securitron", "Gondola", "Monkey")
var/pushed_over = FALSE //If the cutout is pushed over and has to be righted
var/deceptive = FALSE //If the cutout actually appears as what it portray and not a discolored version
/// Possible restyles for the cutout, add an entry in change_appearance() if you add to here
var/static/list/possible_appearances
/// If the cutout is pushed over and has to be righted
var/pushed_over = FALSE
/// If the cutout actually appears as what it portray and not a discolored version
var/deceptive = FALSE
var/lastattacker = null
/obj/item/cardboard_cutout/Initialize()
. = ..()
if(possible_appearances)
return
possible_appearances = sortList(list(
"Assistant" = image(icon = src.icon, icon_state = "cutout_greytide"),
"Clown" = image(icon = src.icon, icon_state = "cutout_clown"),
"Mime" = image(icon = src.icon, icon_state = "cutout_mime"),
"Traitor" = image(icon = src.icon, icon_state = "cutout_traitor"),
"Nuke Op" = image(icon = src.icon, icon_state = "cutout_fluke"),
"Cultist" = image(icon = src.icon, icon_state = "cutout_cultist"),
"Brass Cultist" = image(icon = src.icon, icon_state = "cutout_servant"),
"Clockwork Cultist" = image(icon = src.icon, icon_state = "cutout_new_servant"),
"Revolutionary" = image(icon = src.icon, icon_state = "cutout_viva"),
"Wizard" = image(icon = src.icon, icon_state = "cutout_wizard"),
"Shadowling" = image(icon = src.icon, icon_state = "cutout_shadowling"),
"Xenomorph" = image(icon = src.icon, icon_state = "cutout_fukken_xeno"),
"Xenomorph Maid" = image(icon = src.icon, icon_state = "cutout_lusty"),
"Swarmer" = image(icon = src.icon, icon_state = "cutout_swarmer"),
"Ash Walker" = image(icon = src.icon, icon_state = "cutout_free_antag"),
"Deathsquad Officer" = image(icon = src.icon, icon_state = "cutout_deathsquad"),
"Ian" = image(icon = src.icon, icon_state = "cutout_ian"),
"Slaughter Demon" = image(icon = 'icons/mob/mob.dmi', icon_state = "daemon"),
"Laughter Demon" = image(icon = 'icons/mob/mob.dmi', icon_state = "bowmon"),
"Private Security Officer" = image(icon = src.icon, icon_state = "cutout_ntsec"),
"Securitron" = image(icon = src.icon, icon_state = "cutout_law"),
"Gondola" = image(icon = src.icon, icon_state = "cutout_gondola"),
"Monkey" = image(icon = src.icon, icon_state = "cutout_monky"),
))
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/cardboard_cutout/attack_hand(mob/living/user)
@@ -76,22 +101,21 @@
push_over()
return BULLET_ACT_HIT
/**
* change_appearance: Changes a skin of the cardboard cutout based on a user's choice
*
* Arguments:
* * crayon The crayon used to change and recolor the cardboard cutout
* * user The mob choosing a skin of the cardboard cutout
*/
/obj/item/cardboard_cutout/proc/change_appearance(obj/item/toy/crayon/crayon, mob/living/user)
if(!crayon || !user)
return
if(pushed_over)
to_chat(user, "<span class='warning'>Right [src] first!</span>")
return
if(crayon.check_empty(user))
return
if(crayon.is_capped)
to_chat(user, "<span class='warning'>Take the cap off first!</span>")
return
var/new_appearance = input(user, "Choose a new appearance for [src].", "26th Century Deception") as null|anything in possible_appearances
if(!new_appearance || !crayon || !user.canUseTopic(src))
var/new_appearance = show_radial_menu(user, src, possible_appearances, custom_check = CALLBACK(src, .proc/check_menu, user, crayon), radius = 36, require_near = TRUE)
if(!new_appearance)
return
if(!do_after(user, 10, FALSE, src, TRUE))
return
return FALSE
if(!check_menu(user, crayon))
return FALSE
user.visible_message("<span class='notice'>[user] gives [src] a new look.</span>", "<span class='notice'>Voila! You give [src] a new look.</span>")
crayon.use_charges(1)
crayon.check_empty(user)
@@ -196,7 +220,33 @@
name = "monkey ([rand(1, 999)])"
desc = "A cardboard cutout of a monkey."
icon_state = "cutout_monky"
return 1
else
return FALSE
return TRUE
/**
* check_menu: Checks if we are allowed to interact with a radial menu
*
* Arguments:
* * user The mob interacting with a menu
* * crayon The crayon used to interact with a menu
*/
/obj/item/cardboard_cutout/proc/check_menu(mob/living/user, obj/item/toy/crayon/crayon)
if(!istype(user))
return FALSE
if(user.incapacitated())
return FALSE
if(pushed_over)
to_chat(user, "<span class='warning'>Right [src] first!</span>")
return FALSE
if(!crayon || !user.is_holding(crayon))
return FALSE
if(crayon.check_empty(user))
return FALSE
if(crayon.is_capped)
to_chat(user, "<span class='warning'>Take the cap off first!</span>")
return FALSE
return TRUE
/obj/item/cardboard_cutout/setDir(newdir)
dir = SOUTH
@@ -199,7 +199,7 @@
if(!spans)
spans = list(M.speech_span)
if(!language)
language = M.get_default_language()
language = M.get_selected_language()
INVOKE_ASYNC(src, .proc/talk_into_impl, M, message, channel, spans.Copy(), language)
return ITALICS | REDUCE_RANGE
+3 -1
View File
@@ -519,7 +519,9 @@
S.name = name
S.ckey = C.ckey
S.status_flags |= GODMODE
S.language_holder = user.language_holder.copy(S)
S.copy_languages(user, LANGUAGE_MASTER) //Make sure the sword can understand and communicate with the user.
S.update_atom_languages()
grant_all_languages(FALSE, FALSE, TRUE) //Grants omnitongue
S.AddElement(/datum/element/ghost_role_eligibility,penalize_on_ghost = TRUE)
START_PROCESSING(SSprocessing,src)
var/input = stripped_input(S,"What are you named?", ,"", MAX_NAME_LEN)
+51 -37
View File
@@ -850,12 +850,6 @@
#define NODESIGN "None"
#define NANOTRASEN "NanotrasenStandard"
#define SYNDI "SyndiSnacks"
#define HEART "Heart"
#define SMILEY "SmileyFace"
/obj/item/storage/box/papersack
name = "paper sack"
desc = "A sack neatly crafted out of paper."
@@ -863,7 +857,18 @@
item_state = "paperbag_None"
resistance_flags = FLAMMABLE
foldable = null
var/design = NODESIGN
/// A list of all available papersack reskins
var/list/papersack_designs = list()
/obj/item/storage/box/papersack/Initialize(mapload)
. = ..()
papersack_designs = sortList(list(
"None" = image(icon = src.icon, icon_state = "paperbag_None"),
"NanotrasenStandard" = image(icon = src.icon, icon_state = "paperbag_NanotrasenStandard"),
"SyndiSnacks" = image(icon = src.icon, icon_state = "paperbag_SyndiSnacks"),
"Heart" = image(icon = src.icon, icon_state = "paperbag_Heart"),
"SmileyFace" = image(icon = src.icon, icon_state = "paperbag_SmileyFace")
))
/obj/item/storage/box/papersack/update_icon_state()
if(contents.len == 0)
@@ -871,55 +876,64 @@
else
icon_state = "[item_state]_closed"
/obj/item/storage/box/papersack/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/pen))
//if a pen is used on the sack, dialogue to change its design appears
if(contents.len)
to_chat(user, "<span class='warning'>You can't modify [src] with items still inside!</span>")
return
var/list/designs = list(NODESIGN, NANOTRASEN, SYNDI, HEART, SMILEY, "Cancel")
var/switchDesign = input("Select a Design:", "Paper Sack Design", designs[1]) in designs
if(get_dist(usr, src) > 1)
to_chat(usr, "<span class='warning'>You have moved too far away!</span>")
return
var/choice = designs.Find(switchDesign)
if(design == designs[choice] || designs[choice] == "Cancel")
return 0
to_chat(usr, "<span class='notice'>You make some modifications to [src] using your pen.</span>")
design = designs[choice]
icon_state = "paperbag_[design]"
item_state = "paperbag_[design]"
switch(designs[choice])
if(NODESIGN)
var/choice = show_radial_menu(user, src , papersack_designs, custom_check = CALLBACK(src, .proc/check_menu, user, W), radius = 36, require_near = TRUE)
if(!choice)
return FALSE
if(icon_state == "paperbag_[choice]")
return FALSE
switch(choice)
if("None")
desc = "A sack neatly crafted out of paper."
if(NANOTRASEN)
if("NanotrasenStandard")
desc = "A standard Nanotrasen paper lunch sack for loyal employees on the go."
if(SYNDI)
if("SyndiSnacks")
desc = "The design on this paper sack is a remnant of the notorious 'SyndieSnacks' program."
if(HEART)
if("Heart")
desc = "A paper sack with a heart etched onto the side."
if(SMILEY)
if("SmileyFace")
desc = "A paper sack with a crude smile etched onto the side."
return 0
else
return FALSE
to_chat(user, "<span class='notice'>You make some modifications to [src] using your pen.</span>")
icon_state = "paperbag_[choice]"
item_state = "paperbag_[choice]"
return FALSE
else if(W.get_sharpness())
if(!contents.len)
if(item_state == "paperbag_None")
user.show_message("<span class='notice'>You cut eyeholes into [src].</span>", MSG_VISUAL)
new /obj/item/clothing/head/papersack(user.loc)
qdel(src)
return 0
return FALSE
else if(item_state == "paperbag_SmileyFace")
user.show_message("<span class='notice'>You cut eyeholes into [src] and modify the design.</span>", MSG_VISUAL)
new /obj/item/clothing/head/papersack/smiley(user.loc)
qdel(src)
return 0
return FALSE
return ..()
#undef NODESIGN
#undef NANOTRASEN
#undef SYNDI
#undef HEART
#undef SMILEY
/**
* check_menu: Checks if we are allowed to interact with a radial menu
*
* Arguments:
* * user The mob interacting with a menu
* * P The pen used to interact with a menu
*/
/obj/item/storage/box/papersack/proc/check_menu(mob/user, obj/item/pen/P)
if(!istype(user))
return FALSE
if(user.incapacitated())
return FALSE
if(contents.len)
to_chat(user, "<span class='warning'>You can't modify [src] with items still inside!</span>")
return FALSE
if(!P || !user.is_holding(P))
to_chat(user, "<span class='warning'>You need a pen to modify [src]!</span>")
return FALSE
return TRUE
/obj/item/storage/box/ingredients //This box is for the randomly chosen version the chef spawns with, it shouldn't actually exist.
name = "ingredients box"
+57 -54
View File
@@ -902,79 +902,57 @@
name = "hand of cards"
desc = "A number of cards not in a deck, customarily held in ones hand."
icon = 'icons/obj/toy.dmi'
icon_state = "nanotrasen_hand2"
icon_state = "none"
w_class = WEIGHT_CLASS_TINY
var/list/currenthand = list()
var/choice = null
/obj/item/toy/cards/cardhand/attack_self(mob/user)
user.set_machine(src)
var/list/handradial = list()
interact(user)
/obj/item/toy/cards/cardhand/ui_interact(mob/user)
. = ..()
var/dat = "You have:<BR>"
for(var/t in currenthand)
dat += "<A href='?src=[REF(src)];pick=[t]'>A [t].</A><BR>"
dat += "Which card will you remove next?"
var/datum/browser/popup = new(user, "cardhand", "Hand of Cards", 400, 240)
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.set_content(dat)
popup.open()
handradial[t] = image(icon = src.icon, icon_state = "sc_[t]_[deckstyle]")
/obj/item/toy/cards/cardhand/Topic(href, href_list)
if(..())
return
if(usr.stat || !ishuman(usr))
return
var/mob/living/carbon/human/cardUser = usr
var/O = src
if(href_list["pick"])
if (cardUser.is_holding(src))
var/choice = href_list["pick"]
var/obj/item/toy/cards/singlecard/C = new/obj/item/toy/cards/singlecard(cardUser.loc)
src.currenthand -= choice
C.parentdeck = src.parentdeck
C.cardname = choice
C.apply_card_vars(C,O)
C.pickup(cardUser)
cardUser.put_in_hands(C)
cardUser.visible_message("<span class='notice'>[cardUser] draws a card from [cardUser.p_their()] hand.</span>", "<span class='notice'>You take the [C.cardname] from your hand.</span>")
interact(cardUser)
if(src.currenthand.len < 3)
src.icon_state = "[deckstyle]_hand2"
else if(src.currenthand.len < 4)
src.icon_state = "[deckstyle]_hand3"
else if(src.currenthand.len < 5)
src.icon_state = "[deckstyle]_hand4"
if(src.currenthand.len == 1)
var/obj/item/toy/cards/singlecard/N = new/obj/item/toy/cards/singlecard(src.loc)
N.parentdeck = src.parentdeck
N.cardname = src.currenthand[1]
N.apply_card_vars(N,O)
qdel(src)
N.pickup(cardUser)
cardUser.put_in_hands(N)
to_chat(cardUser, "<span class='notice'>You also take [currenthand[1]] and hold it.</span>")
cardUser << browse(null, "window=cardhand")
if(!(cardUser.mobility_flags & MOBILITY_USE))
return
var/O = src
var/choice = show_radial_menu(usr,src, handradial, custom_check = CALLBACK(src, .proc/check_menu, user), radius = 36, require_near = TRUE)
if(!choice)
return FALSE
var/obj/item/toy/cards/singlecard/C = new/obj/item/toy/cards/singlecard(cardUser.loc)
currenthand -= choice
handradial -= choice
C.parentdeck = parentdeck
C.cardname = choice
C.apply_card_vars(C,O)
C.pickup(cardUser)
cardUser.put_in_hands(C)
cardUser.visible_message("<span class='notice'>[cardUser] draws a card from [cardUser.p_their()] hand.</span>", "<span class='notice'>You take the [C.cardname] from your hand.</span>")
interact(cardUser)
update_sprite()
if(length(currenthand) == 1)
var/obj/item/toy/cards/singlecard/N = new/obj/item/toy/cards/singlecard(loc)
N.parentdeck = parentdeck
N.cardname = currenthand[1]
N.apply_card_vars(N,O)
qdel(src)
N.pickup(cardUser)
cardUser.put_in_hands(N)
to_chat(cardUser, "<span class='notice'>You also take [currenthand[1]] and hold it.</span>")
/obj/item/toy/cards/cardhand/attackby(obj/item/toy/cards/singlecard/C, mob/living/user, params)
if(istype(C))
if(C.parentdeck == src.parentdeck)
src.currenthand += C.cardname
user.visible_message("[user] adds a card to [user.p_their()] hand.", "<span class='notice'>You add the [C.cardname] to your hand.</span>")
user.visible_message("<span class='notice'>[user] adds a card to [user.p_their()] hand.</span>", "<span class='notice'>You add the [C.cardname] to your hand.</span>")
qdel(C)
interact(user)
if(currenthand.len > 4)
src.icon_state = "[deckstyle]_hand5"
else if(currenthand.len > 3)
src.icon_state = "[deckstyle]_hand4"
else if(currenthand.len > 2)
src.icon_state = "[deckstyle]_hand3"
update_sprite(src)
else
to_chat(user, "<span class='warning'>You can't mix cards from other decks!</span>")
else
@@ -983,7 +961,7 @@
/obj/item/toy/cards/cardhand/apply_card_vars(obj/item/toy/cards/newobj,obj/item/toy/cards/sourceobj)
..()
newobj.deckstyle = sourceobj.deckstyle
newobj.icon_state = "[deckstyle]_hand2" // Another dumb hack, without this the hand is invisible (or has the default deckstyle) until another card is added.
update_sprite()
newobj.card_hitsound = sourceobj.card_hitsound
newobj.card_force = sourceobj.card_force
newobj.card_throwforce = sourceobj.card_throwforce
@@ -992,6 +970,31 @@
newobj.card_attack_verb = sourceobj.card_attack_verb
newobj.resistance_flags = sourceobj.resistance_flags
/**
* check_menu: Checks if we are allowed to interact with a radial menu
*
* Arguments:
* * user The mob interacting with a menu
*/
/obj/item/toy/cards/cardhand/proc/check_menu(mob/living/user)
if(!istype(user))
return FALSE
if(user.incapacitated())
return FALSE
return TRUE
/**
* This proc updates the sprite for when you create a hand of cards
*/
/obj/item/toy/cards/cardhand/proc/update_sprite()
cut_overlays()
var/overlay_cards = currenthand.len
var/k = overlay_cards == 2 ? 1 : overlay_cards - 2
for(var/i = k; i <= overlay_cards; i++)
var/card_overlay = image(icon=src.icon,icon_state="sc_[currenthand[i]]_[deckstyle]",pixel_x=(1-i+k)*3,pixel_y=(1-i+k)*3)
add_overlay(card_overlay)
/obj/item/toy/cards/singlecard
name = "card"
desc = "a card"
@@ -32,6 +32,7 @@
new_spawn.undershirt = "Nude" //changing underwear/shirt/socks doesn't seem to function correctly right now because of some bug elsewhere?
new_spawn.socks = "Nude"
new_spawn.update_body(TRUE)
new_spawn.language_holder.selected_language = /datum/language/sylvan
//Ash walker eggs: Spawns in ash walker dens in lavaland. Ghosts become unbreathing lizards that worship the Necropolis and are advised to retrieve corpses to create more ash walkers.
@@ -63,10 +64,6 @@
else
to_chat(new_spawn, "<span class='userdanger'>You have been born outside of your natural home! Whether you decide to return home, or make due with your new home is your own decision.</span>")
new_spawn.grant_language(/datum/language/draconic)
var/datum/language_holder/holder = new_spawn.get_language_holder()
holder.selected_default_language = /datum/language/draconic
//Ash walkers on birth understand how to make bone bows, bone arrows and ashen arrows
new_spawn.mind.teach_crafting_recipe(/datum/crafting_recipe/bone_arrow)
+50 -39
View File
@@ -32,7 +32,6 @@
/obj/structure/janitorialcart/proc/put_in_cart(obj/item/I, mob/user)
if(!user.transferItemToLoc(I, src))
return
updateUsrDialog()
to_chat(user, "<span class='notice'>You put [I] into [src].</span>")
return
@@ -96,70 +95,82 @@
. = ..()
if(.)
return
user.set_machine(src)
var/dat
var/list/items = list()
if(mybag)
dat += "<a href='?src=[REF(src)];garbage=1'>[mybag.name]</a><br>"
items += list("Trash bag" = image(icon = mybag.icon, icon_state = mybag.icon_state))
if(mymop)
dat += "<a href='?src=[REF(src)];mop=1'>[mymop.name]</a><br>"
items += list("Mop" = image(icon = mymop.icon, icon_state = mymop.icon_state))
if(mybroom)
dat += "<a href='?src=[REF(src)];broom=1'>[mybroom.name]</a><br>"
items += list("Broom" = image(icon = mybroom.icon, icon_state = mybroom.icon_state))
if(myspray)
dat += "<a href='?src=[REF(src)];spray=1'>[myspray.name]</a><br>"
items += list("Spray bottle" = image(icon = myspray.icon, icon_state = myspray.icon_state))
if(myreplacer)
dat += "<a href='?src=[REF(src)];replacer=1'>[myreplacer.name]</a><br>"
if(signs)
dat += "<a href='?src=[REF(src)];sign=1'>[signs] sign\s</a><br>"
var/datum/browser/popup = new(user, "janicart", name, 240, 160)
popup.set_content(dat)
popup.open()
items += list("Light replacer" = image(icon = myreplacer.icon, icon_state = myreplacer.icon_state))
var/obj/item/caution/sign = locate() in src
if(sign)
items += list("Sign" = image(icon = sign.icon, icon_state = sign.icon_state))
/obj/structure/janitorialcart/Topic(href, href_list)
if(!in_range(src, usr))
if(!length(items))
return
if(!isliving(usr))
items = sortList(items)
var/pick = show_radial_menu(user, src, items, custom_check = CALLBACK(src, .proc/check_menu, user), radius = 38, require_near = TRUE)
if(!pick)
return
var/mob/living/user = usr
if(href_list["garbage"])
if(mybag)
switch(pick)
if("Trash bag")
if(!mybag)
return
user.put_in_hands(mybag)
to_chat(user, "<span class='notice'>You take [mybag] from [src].</span>")
mybag = null
if(href_list["mop"])
if(mymop)
if("Mop")
if(!mymop)
return
user.put_in_hands(mymop)
to_chat(user, "<span class='notice'>You take [mymop] from [src].</span>")
mymop = null
if(href_list["broom"])
if(mybroom)
if("Broom")
if(!mybroom)
return
user.put_in_hands(mybroom)
to_chat(user, "<span class='notice'>You take [mybroom] from [src].</span>")
mybroom = null
if(href_list["spray"])
if(myspray)
if("Spray bottle")
if(!myspray)
return
user.put_in_hands(myspray)
to_chat(user, "<span class='notice'>You take [myspray] from [src].</span>")
myspray = null
if(href_list["replacer"])
if(myreplacer)
if("Light replacer")
if(!myreplacer)
return
user.put_in_hands(myreplacer)
to_chat(user, "<span class='notice'>You take [myreplacer] from [src].</span>")
myreplacer = null
if(href_list["sign"])
if(signs)
var/obj/item/caution/Sign = locate() in src
if(Sign)
user.put_in_hands(Sign)
to_chat(user, "<span class='notice'>You take \a [Sign] from [src].</span>")
signs--
else
WARNING("Signs ([signs]) didn't match contents")
signs = 0
if("Sign")
if(signs <= 0)
return
user.put_in_hands(sign)
to_chat(user, "<span class='notice'>You take \a [sign] from [src].</span>")
signs--
else
return
update_icon()
updateUsrDialog()
/**
* check_menu: Checks if we are allowed to interact with a radial menu
*
* Arguments:
* * user The mob interacting with a menu
*/
/obj/structure/janitorialcart/proc/check_menu(mob/living/user)
if(!istype(user))
return FALSE
if(user.incapacitated())
return FALSE
return TRUE
/obj/structure/janitorialcart/update_overlays()
. = ..()
+11 -1
View File
@@ -91,8 +91,13 @@
if (!is_ghost && !in_range(src, user))
return
var/list/tool_list = list(
"Up" = image(icon = 'icons/testing/turf_analysis.dmi', icon_state = "red_arrow", dir = NORTH),
"Down" = image(icon = 'icons/testing/turf_analysis.dmi', icon_state = "red_arrow", dir = SOUTH)
)
if (up && down)
var/result = alert("Go up or down [src]?", "Ladder", "Up", "Down", "Cancel")
var/result = show_radial_menu(user, src, tool_list, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE, tooltips = TRUE)
if (!is_ghost && !in_range(src, user))
return // nice try
switch(result)
@@ -112,6 +117,11 @@
if(!is_ghost)
add_fingerprint(user)
/obj/structure/ladder/proc/check_menu(mob/user)
if(user.incapacitated() || !user.Adjacent(src))
return FALSE
return TRUE
/obj/structure/ladder/attack_hand(mob/user)
. = ..()
if(.)
+1 -1
View File
@@ -25,7 +25,7 @@ GLOBAL_LIST_INIT(freqtospan, list(
return
spans |= speech_span
if(!language)
language = get_default_language()
language = get_selected_language()
send_speech(message, 7, src, , spans, message_language=language)
/atom/movable/proc/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
@@ -10,7 +10,12 @@
/obj/item/organ/heart/gland/slime/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
owner.faction |= "slime"
owner.grant_language(/datum/language/slime)
owner.grant_language(/datum/language/slime, TRUE, TRUE, LANGUAGE_GLAND)
/obj/item/organ/heart/gland/slime/Remove(mob/living/carbon/M, special = 0)
..()
owner.faction -= "slime"
owner.remove_language(/datum/language/slime, TRUE, TRUE, LANGUAGE_GLAND)
/obj/item/organ/heart/gland/slime/activate()
to_chat(owner, "<span class='warning'>You feel nauseated!</span>")
@@ -20,7 +20,7 @@
var/poweron_feed = FALSE // Am I feeding?
var/poweron_masquerade = FALSE
// STATS
var/bloodsucker_level
var/bloodsucker_level
var/bloodsucker_level_unspent = 1
var/regen_rate = 0.3 // How fast do I regenerate?
var/additional_regen // How much additional blood regen we gain from bonuses such as high blood.
@@ -209,7 +209,7 @@
// Physiology
CheckVampOrgans() // Heart, Eyes
// Language
owner.current.grant_language(/datum/language/vampiric)
owner.current.grant_language(/datum/language/vampiric, TRUE, TRUE, LANGUAGE_BLOODSUCKER)
owner.hasSoul = FALSE // If false, renders the character unable to sell their soul.
owner.isholy = FALSE // is this person a chaplain or admin role allowed to use bibles
// Disabilities
@@ -246,7 +246,7 @@
// Update Health
owner.current.setMaxHealth(100)
// Language
owner.current.remove_language(/datum/language/vampiric)
owner.current.remove_language(/datum/language/vampiric, TRUE, TRUE, LANGUAGE_BLOODSUCKER)
// Soul
if (owner.soulOwner == owner) // Return soul, if *I* own it.
owner.hasSoul = TRUE
@@ -649,10 +649,10 @@
return TRUE
// Check 3) If I am a BLOODSUCKER, then are they my Vassal?
if (mob_B && atom_V && (atom_V in mob_B.vassals))
return TRUE
return TRUE
// Check 4) If we are both VASSAL, then do we have the same master?
if (atom_V && mob_V && atom_V.master == mob_V.master)
return TRUE
return TRUE
return FALSE
@@ -710,7 +710,7 @@
invisibility = INVISIBILITY_ABSTRACT
/obj/screen/bloodsucker/proc/update_counter(value, valuecolor)
invisibility = 0
invisibility = 0
/obj/screen/bloodsucker/blood_counter
icon = 'icons/mob/actions/bloodsucker.dmi'
@@ -758,7 +758,7 @@
/obj/screen/bloodsucker/sunlight_counter/update_counter(value, valuecolor)
..()
maptext = "<div align='center' valign='bottom' style='position:relative; top:0px; left:6px'><font color='[valuecolor]'>[value]</font></div>"
maptext = "<div align='center' valign='bottom' style='position:relative; top:0px; left:6px'><font color='[valuecolor]'>[value]</font></div>"
/datum/antagonist/bloodsucker/proc/count_vassals(datum/mind/master)
var/datum/antagonist/bloodsucker/B = master.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
@@ -48,7 +48,7 @@
objectives += vassal_objective
objectives_given += vassal_objective
give_thrall_eyes()
owner.current.grant_language(/datum/language/vampiric)
owner.current.grant_language(/datum/language/vampiric, TRUE, TRUE, LANGUAGE_VASSAL)
// Add Antag HUD
update_vassal_icons_added(owner.current, "vassal")
. = ..()
@@ -81,7 +81,7 @@
qdel(O)
objectives_given = list()
remove_thrall_eyes()
owner.current.remove_language(/datum/language/vampiric)
owner.current.remove_language(/datum/language/vampiric, TRUE, TRUE, LANGUAGE_VASSAL)
// Clear Antag HUD
update_vassal_icons_removed(owner.current)
@@ -78,6 +78,7 @@
create_initial_profile()
if(give_objectives)
forge_objectives()
owner.current.grant_all_languages(FALSE, FALSE, TRUE) //Grants omnitongue. We are able to transform our body after all.
remove_clownmut()
. = ..()
@@ -61,10 +61,10 @@
if(user.nutrition < NUTRITION_LEVEL_WELL_FED)
user.nutrition = min((user.nutrition + target.nutrition), NUTRITION_LEVEL_WELL_FED)
if(target.mind)//if the victim has got a mind
// Absorb a lizard, speak Draconic.
user.copy_known_languages_from(target)
// Absorb a lizard, speak Draconic.
user.copy_languages(target, LANGUAGE_ABSORB)
if(target.mind && user.mind)//if the victim and user have minds
target.mind.show_memory(user, 0) //I can read your mind, kekeke. Output all their notes.
//Some of target's recent speech, so the changeling can attempt to imitate them better.
@@ -31,6 +31,7 @@
laws = new /datum/ai_laws/ratvar()
braintype = picked_name
GLOB.all_clockwork_objects += src
brainmob.add_blocked_language(subtypesof(/datum/language) - /datum/language/ratvar, LANGUAGE_CLOCKIE)
/obj/item/mmi/posibrain/soul_vessel/Destroy()
GLOB.all_clockwork_objects -= src
@@ -91,7 +91,7 @@
current = mob_override
GLOB.all_clockwork_mobs += current
current.faction |= "ratvar"
current.grant_language(/datum/language/ratvar)
current.grant_language(/datum/language/ratvar, TRUE, TRUE, LANGUAGE_CLOCKIE)
current.update_action_buttons_icon() //because a few clockcult things are action buttons and we may be wearing/holding them for whatever reason, we need to update buttons
if(issilicon(current))
var/mob/living/silicon/S = current
@@ -102,6 +102,7 @@
R.module.rebuild_modules()
else if(isAI(S))
var/mob/living/silicon/ai/A = S
A.add_blocked_language(subtypesof(/datum/language) - /datum/language/ratvar, LANGUAGE_CLOCKIE)
A.can_be_carded = FALSE
A.requires_power = POWER_REQ_CLOCKCULT
var/list/AI_frame = list(mutable_appearance('icons/mob/clockwork_mobs.dmi', "aiframe")) //make the AI's cool frame
@@ -142,7 +143,7 @@
current = mob_override
GLOB.all_clockwork_mobs -= current
current.faction -= "ratvar"
current.remove_language(/datum/language/ratvar)
current.remove_language(/datum/language/ratvar, TRUE, TRUE, LANGUAGE_CLOCKIE)
current.clear_alert("clockinfo")
for(var/datum/action/innate/clockwork_armaments/C in owner.current.actions) //Removes any bound clockwork armor
qdel(C)
@@ -152,6 +153,7 @@
var/mob/living/silicon/S = current
if(isAI(S))
var/mob/living/silicon/ai/A = S
A.remove_blocked_language(subtypesof(/datum/language) - /datum/language/ratvar, LANGUAGE_CLOCKIE)
A.can_be_carded = initial(A.can_be_carded)
A.requires_power = initial(A.requires_power)
A.cut_overlays()
+2 -2
View File
@@ -116,7 +116,7 @@
if(mob_override)
current = mob_override
current.faction |= "cult"
current.grant_language(/datum/language/narsie)
current.grant_language(/datum/language/narsie, TRUE, TRUE, LANGUAGE_CULTIST)
if(!cult_team?.cult_master)
vote.Grant(current)
communion.Grant(current)
@@ -134,7 +134,7 @@
if(mob_override)
current = mob_override
current.faction -= "cult"
current.remove_language(/datum/language/narsie)
current.remove_language(/datum/language/narsie, TRUE, TRUE, LANGUAGE_CULTIST)
vote.Remove(current)
communion.Remove(current)
magic.Remove(current)
+2 -1
View File
@@ -527,7 +527,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
/datum/antagonist/devil/apply_innate_effects(mob/living/mob_override)
give_appropriate_spells()
owner.current.grant_all_languages(TRUE)
owner.current.grant_all_languages(TRUE, TRUE, TRUE, LANGUAGE_DEVIL)
update_hud()
.=..()
@@ -536,6 +536,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
var/obj/effect/proc_holder/spell/S = X
if(is_type_in_typecache(S, devil_spells))
owner.RemoveSpell(S)
owner.current.remove_all_languages(LANGUAGE_DEVIL)
.=..()
/datum/antagonist/devil/proc/printdevilinfo()
@@ -29,7 +29,7 @@
/mob/living/carbon/true_devil/Initialize()
create_bodyparts() //initialize bodyparts
create_internal_organs()
grant_all_languages(omnitongue=TRUE)
grant_all_languages()
..()
/mob/living/carbon/true_devil/create_internal_organs()
@@ -65,5 +65,5 @@
/datum/traitor_class/ai/finalize_traitor(datum/antagonist/traitor/T)
T.add_law_zero()
T.owner.current.playsound_local(get_turf(T.owner.current), 'sound/ambience/antag/malf.ogg', 100, FALSE, pressure_affected = FALSE)
T.owner.current.grant_language(/datum/language/codespeak)
T.owner.current.grant_language(/datum/language/codespeak, TRUE, TRUE, LANGUAGE_MALF)
return FALSE
@@ -233,7 +233,7 @@
newstruct.cancel_camera()
/obj/item/soulstone/proc/init_shade(mob/living/carbon/human/T, mob/U, vic = 0)
/obj/item/soulstone/proc/init_shade(mob/living/carbon/human/T, mob/user, vic = 0)
new /obj/effect/decal/remains/human(T.loc) //Spawns a skeleton
T.stop_sound_channel(CHANNEL_HEARTBEAT)
T.invisibility = INVISIBILITY_ABSTRACT
@@ -245,20 +245,23 @@
S.name = "Shade of [T.real_name]"
S.real_name = "Shade of [T.real_name]"
T.transfer_ckey(S)
S.language_holder = U.language_holder.copy(S)
if(U)
S.faction |= "[REF(U)]" //Add the master as a faction, allowing inter-mob cooperation
if(U && iscultist(U))
S.copy_languages(T, LANGUAGE_MIND)//Copies the old mobs languages into the new mob holder.
S.copy_languages(user, LANGUAGE_MASTER)
S.update_atom_languages()
grant_all_languages(FALSE, FALSE, TRUE) //Grants omnitongue
if(user)
S.faction |= "[REF(user)]" //Add the master as a faction, allowing inter-mob cooperation
if(user && iscultist(user))
SSticker.mode.add_cultist(S.mind, 0)
S.cancel_camera()
name = "soulstone: Shade of [T.real_name]"
icon_state = "soulstone2"
if(U && (iswizard(U) || usability))
to_chat(S, "Your soul has been captured! You are now bound to [U.real_name]'s will. Help [U.p_them()] succeed in [U.p_their()] goals at all costs.")
else if(U && iscultist(U))
if(user && (iswizard(user) || usability))
to_chat(S, "Your soul has been captured! You are now bound to [user.real_name]'s will. Help [user.p_them()] succeed in [user.p_their()] goals at all costs.")
else if(user && iscultist(user))
to_chat(S, "Your soul has been captured! You are now bound to the cult's will. Help them succeed in their goals at all costs.")
if(vic && U)
to_chat(U, "<span class='info'><b>Capture successful!</b>:</span> [T.real_name]'s soul has been ripped from [T.p_their()] body and stored within the soul stone.")
if(vic && user)
to_chat(user, "<span class='info'><b>Capture successful!</b>:</span> [T.real_name]'s soul has been ripped from [T.p_their()] body and stored within the soul stone.")
/obj/item/soulstone/proc/getCultGhost(mob/living/carbon/human/T, mob/U)
+43 -21
View File
@@ -73,18 +73,26 @@
resistance_flags = FLAMMABLE
actions_types = list(/datum/action/item_action/adjust)
dog_fashion = /datum/dog_fashion/head/clown
var/list/clownmask_designs = list()
/obj/item/clothing/mask/gas/clown_hat/Initialize(mapload)
.=..()
clownmask_designs = list(
"True Form" = image(icon = src.icon, icon_state = "clown"),
"The Feminist" = image(icon = src.icon, icon_state = "sexyclown"),
"The Jester" = image(icon = src.icon, icon_state = "chaos"),
"The Madman" = image(icon = src.icon, icon_state = "joker"),
"The Rainbow Color" = image(icon = src.icon, icon_state = "rainbow")
)
/obj/item/clothing/mask/gas/clown_hat/ui_action_click(mob/user)
if(!istype(user) || user.incapacitated())
return
var/list/options = list()
options["True Form"] = "clown"
options["The Feminist"] = "sexyclown"
options["The Madman"] = "joker"
options["The Rainbow Color"] ="rainbow"
var/static/list/options = list("True Form" = "clown", "The Feminist" = "sexyclown", "The Madman" = "joker",
"The Rainbow Color" ="rainbow", "The Jester" = "chaos")
var/choice = input(user,"To what form do you wish to Morph this mask?","Morph Mask") in options
var/choice = show_radial_menu(user,src, clownmask_designs, custom_check = FALSE, radius = 36, require_near = TRUE)
if(src && choice && !user.incapacitated() && in_range(user,src))
icon_state = options[choice]
@@ -93,7 +101,7 @@
var/datum/action/A = X
A.UpdateButtonIcon()
to_chat(user, "<span class='notice'>Your Clown Mask has now morphed into [choice], all praise the Honkmother!</span>")
return 1
return TRUE
/obj/item/clothing/mask/gas/sexyclown
name = "sexy-clown wig and mask"
@@ -113,19 +121,26 @@
flags_cover = MASKCOVERSEYES
resistance_flags = FLAMMABLE
actions_types = list(/datum/action/item_action/adjust)
var/list/mimemask_designs = list()
/obj/item/clothing/mask/gas/mime/Initialize(mapload)
.=..()
mimemask_designs = list(
"Blanc" = image(icon = src.icon, icon_state = "mime"),
"Excité" = image(icon = src.icon, icon_state = "sexymime"),
"Triste" = image(icon = src.icon, icon_state = "sadmime"),
"Effrayé" = image(icon = src.icon, icon_state = "scaredmime")
)
/obj/item/clothing/mask/gas/mime/ui_action_click(mob/user)
if(!istype(user) || user.incapacitated())
return
var/list/options = list()
options["Blanc"] = "mime"
options["Triste"] = "sadmime"
options["Effrayé"] = "scaredmime"
options["Excité"] ="sexymime"
var/static/list/options = list("Blanc" = "mime", "Triste" = "sadmime", "Effrayé" = "scaredmime", "Excité" ="sexymime")
var/choice = input(user,"To what form do you wish to Morph this mask?","Morph Mask") in options
var/choice = show_radial_menu(user,src, mimemask_designs, custom_check = FALSE, radius = 36, require_near = TRUE)
if(src && choice && !user.incapacitated() && in_range(user,src))
icon_state = options[choice]
@@ -134,7 +149,7 @@
var/datum/action/A = X
A.UpdateButtonIcon()
to_chat(user, "<span class='notice'>Your Mime Mask has now morphed into [choice]!</span>")
return 1
return TRUE
/obj/item/clothing/mask/gas/monkeymask
name = "monkey mask"
@@ -187,18 +202,25 @@
max_integrity = 100
actions_types = list(/datum/action/item_action/adjust)
dog_fashion = null
var/list/tikimask_designs = list()
/obj/item/clothing/mask/gas/tiki_mask/Initialize(mapload)
.=..()
tikimask_designs = list(
"Original Tiki" = image(icon = src.icon, icon_state = "tiki_eyebrow"),
"Happy Tiki" = image(icon = src.icon, icon_state = "tiki_happy"),
"Confused Tiki" = image(icon = src.icon, icon_state = "tiki_confused"),
"Angry Tiki" = image(icon = src.icon, icon_state = "tiki_angry")
)
/obj/item/clothing/mask/gas/tiki_mask/ui_action_click(mob/user)
var/mob/M = usr
var/list/options = list()
options["Original Tiki"] = "tiki_eyebrow"
options["Happy Tiki"] = "tiki_happy"
options["Confused Tiki"] = "tiki_confused"
options["Angry Tiki"] ="tiki_angry"
var/static/list/options = list("Original Tiki" = "tiki_eyebrow", "Happy Tiki" = "tiki_happy", "Confused Tiki" = "tiki_confused",
"Angry Tiki" = "tiki_angry")
var/choice = input(M,"To what form do you wish to change this mask?","Morph Mask") in options
var/choice = show_radial_menu(user,src, tikimask_designs, custom_check = FALSE, radius = 36, require_near = TRUE)
if(src && choice && !M.stat && in_range(M,src))
icon_state = options[choice]
@@ -207,4 +229,4 @@
var/datum/action/A = X
A.UpdateButtonIcon()
to_chat(M, "The Tiki Mask has now changed into the [choice] Mask!")
return 1
return TRUE
+27 -17
View File
@@ -351,30 +351,40 @@
resistance_flags = FLAMMABLE
max_integrity = 100
actions_types = list(/datum/action/item_action/adjust)
var/list/papermask_designs = list()
/obj/item/clothing/mask/paper/Initialize(mapload)
.=..()
papermask_designs = list(
"Blank" = image(icon = src.icon, icon_state = "plainmask"),
"Neutral" = image(icon = src.icon, icon_state = "neutralmask"),
"Eyes" = image(icon = src.icon, icon_state = "eyemask"),
"Sleeping" = image(icon = src.icon, icon_state = "sleepingmask"),
"Heart" = image(icon = src.icon, icon_state = "heartmask"),
"Core" = image(icon = src.icon, icon_state = "coremask"),
"Plus" = image(icon = src.icon, icon_state = "plusmask"),
"Square" = image(icon = src.icon, icon_state = "squaremask"),
"Bullseye" = image(icon = src.icon, icon_state = "bullseyemask"),
"Vertical" = image(icon = src.icon, icon_state = "verticalmask"),
"Horizontal" = image(icon = src.icon, icon_state = "horizontalmask"),
"X" = image(icon = src.icon, icon_state = "xmask"),
"Bugeyes" = image(icon = src.icon, icon_state = "bugmask"),
"Double" = image(icon = src.icon, icon_state = "doublemask"),
"Mark" = image(icon = src.icon, icon_state = "markmask")
)
/obj/item/clothing/mask/paper/ui_action_click(mob/user)
if(!istype(user) || user.incapacitated())
return
var/list/options = list()
options["Blank"] = "plainmask"
options["Neutral"] = "neutralmask"
options["Eyes"] = "eyemask"
options["Sleeping"] ="sleepingmask"
options["Heart"] = "heartmask"
options["Core"] = "coremask"
options["Plus"] = "plusmask"
options["Square"] ="squaremask"
options["Bullseye"] = "bullseyemask"
options["Vertical"] = "verticalmask"
options["Horizontal"] = "horizontalmask"
options["X"] ="xmask"
options["Bugeyes"] = "bugmask"
options["Double"] = "doublemask"
options["Mark"] = "markmask"
var/static/list/options = list("Blank" = "plainmask", "Neutral" = "neutralmask", "Eyes" = "eyemask",
"Sleeping" ="sleepingmask", "Heart" = "heartmask", "Core" = "coremask",
"Plus" = "plusmask", "Square" ="squaremask", "Bullseye" = "bullseyemask",
"Vertical" = "verticalmask", "Horizontal" = "horizontalmask", "X" ="xmask",
"Bugeyes" = "bugmask", "Double" = "doublemask", "Mark" = "markmask")
var/choice = input(user,"What symbol would you want on this mask?","Morph Mask") in options
var/choice = show_radial_menu(user,src, papermask_designs, custom_check = FALSE, radius = 36, require_near = TRUE)
if(src && choice && !user.incapacitated() && in_range(user,src))
icon_state = options[choice]
+2 -2
View File
@@ -9,7 +9,7 @@
role_name = "random animal"
var/animals = 1
var/one = "one"
/// Blacklisted mob_biotypes - Hey can we like, not have player controlled megafauna?
/// Blacklisted mob_biotypes - Hey can we like, not have player controlled megafauna?
var/blacklisted_biotypes = MOB_EPIC
fakeable = TRUE
@@ -54,7 +54,7 @@
SG.transfer_ckey(SA, FALSE)
SA.grant_all_languages(TRUE)
SA.grant_all_languages(TRUE, FALSE, FALSE)
SA.sentience_act()
@@ -865,7 +865,7 @@
var/translated = FALSE
if(speaker && message)
if(raw_message)
if(message_langs != get_default_language())
if(message_langs != get_selected_language())
translated = TRUE
set_pin_data(IC_OUTPUT, 1, speaker.GetVoice())
set_pin_data(IC_OUTPUT, 2, raw_message)
+1 -1
View File
@@ -41,4 +41,4 @@
if(visualsOnly)
return
H.grant_all_languages(omnitongue=TRUE)
H.grant_all_languages(TRUE, TRUE, TRUE, LANGUAGE_CURATOR)
+2 -2
View File
@@ -46,7 +46,7 @@
return
to_chat(user, "<span class='boldannounce'>You start skimming through [src], and suddenly your mind is filled with codewords and responses.</span>")
user.grant_language(/datum/language/codespeak)
user.grant_language(/datum/language/codespeak, TRUE, TRUE, LANGUAGE_MIND)
use_charge(user)
@@ -65,7 +65,7 @@
M.visible_message("<span class='danger'>[user] beats [M] over the head with [src]!</span>", "<span class='userdanger'>[user] beats you over the head with [src]!</span>", "<span class='italics'>You hear smacking.</span>")
else
M.visible_message("<span class='notice'>[user] teaches [M] by beating [M.p_them()] over the head with [src]!</span>", "<span class='boldnotice'>As [user] hits you with [src], codewords and responses flow through your mind.</span>", "<span class='italics'>You hear smacking.</span>")
M.grant_language(/datum/language/codespeak)
M.grant_language(/datum/language/codespeak, TRUE, TRUE, LANGUAGE_MIND)
use_charge(user)
/obj/item/codespeak_manual/proc/use_charge(mob/user)
+304 -121
View File
@@ -1,149 +1,332 @@
/datum/language_holder
var/list/languages = list(/datum/language/common)
var/list/shadow_languages = list()
var/only_speaks_language = null
var/selected_default_language = null
var/datum/language_menu/language_menu
/*!Language holders will either exist in an atom/movable or a mind. Creation of language holders happens
automatically when they are needed, for example when something tries to speak.
Where a mind is available, the mind language holder will be the one "in charge". The mind holder
will update its languages based on the atom holder, and will get updated as part of
transformations and other events that cause new languages to become available.
Every language holder has three lists of languages (and sources for each of them):
- understood_languages
- spoken_languages
- blocked_languages
Understood languages let you understand them, spoken languages lets you speak them
(if your tongue is compatible), and blocked languages will let you do neither no matter
what the source of the language is.
Language holders are designed to mostly only ever require the use the helpers in atom/movable
to achieve your goals, but it is also possible to work on them directly if needed. Any adding
and removing of languages and sources should only happen through the procs, as directly changing
these will mess something up somewhere down the line.
All atom movables have the initial_language_holder var which allows you to set the default language
holder to create. For example, /datum/language_holder/alien will give you xenocommon and a block for
galactic common. Human species also have a default language holder var that will be updated on
species change, initial_species_holder.
Key procs
* [grant_language](atom/movable.html#proc/grant_language)
* [remove_language](atom/movable.html#proc/remove_language)
* [add_blocked_language](atom/movable.html#proc/add_blocked_language)
* [remove_blocked_language](atom/movable.html#proc/remove_blocked_language)
* [grant_all_languages](atom/movable.html#proc/grant_all_languages)
* [remove_all_languages](atom/movable.html#proc/remove_all_languages)
* [has_language](atom/movable.html#proc/has_language)
* [can_speak_language](atom/movable.html#proc/can_speak_language)
* [get_selected_language](atom/movable.html#proc/get_selected_language)
* [update_atom_languages](atom/movable.html#proc/update_atom_languages)
*/
/datum/language_holder
/// Understood languages.
var/list/understood_languages = list(/datum/language/common = list(LANGUAGE_MIND))
/// A list of languages that can be spoken. Tongue organ may also set limits beyond this list.
var/list/spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM))
/// A list of blocked languages. Used to prevent understanding and speaking certain languages, ie for certain mobs, mutations etc.
var/list/blocked_languages = list()
/// If true, overrides tongue limitations.
var/omnitongue = FALSE
/// Handles displaying the language menu UI.
var/datum/language_menu/language_menu
/// Currently spoken language
var/selected_language
/// Tracks the entity that owns the holder.
var/owner
/datum/language_holder/New(owner)
src.owner = owner
languages = typecacheof(languages)
shadow_languages = typecacheof(shadow_languages)
/datum/language_holder/Destroy()
owner = null
QDEL_NULL(language_menu)
languages.Cut()
shadow_languages.Cut()
return ..()
/datum/language_holder/proc/copy(newowner)
var/datum/language_holder/copy = new(newowner)
copy.languages = src.languages.Copy()
// shadow languages are not copied.
copy.only_speaks_language = src.only_speaks_language
copy.selected_default_language = src.selected_default_language
// language menu is not copied, that's tied to the holder.
copy.omnitongue = src.omnitongue
return copy
/datum/language_holder/proc/grant_language(datum/language/dt, shadow = FALSE)
if(shadow)
shadow_languages[dt] = TRUE
else
languages[dt] = TRUE
/datum/language_holder/proc/grant_all_languages(omnitongue=FALSE)
for(var/la in GLOB.all_languages)
grant_language(la)
if(omnitongue)
src.omnitongue = TRUE
/datum/language_holder/proc/get_random_understood_language()
var/list/possible = list()
for(var/dt in languages)
possible += dt
. = safepick(possible)
/datum/language_holder/proc/remove_language(datum/language/dt, shadow = FALSE)
if(shadow)
shadow_languages -= dt
else
languages -= dt
/datum/language_holder/proc/remove_all_languages()
languages.Cut()
/datum/language_holder/proc/has_language(datum/language/dt)
if(is_type_in_typecache(dt, languages))
return LANGUAGE_KNOWN
else
var/atom/movable/AM = get_atom()
var/datum/language_holder/L = AM.get_language_holder(shadow=FALSE)
if(L != src)
if(is_type_in_typecache(dt, L.shadow_languages))
return LANGUAGE_SHADOWED
return FALSE
/datum/language_holder/proc/copy_known_languages_from(thing, replace=FALSE)
var/datum/language_holder/other
if(istype(thing, /datum/language_holder))
other = thing
else if(ismovable(thing))
var/atom/movable/AM = thing
other = AM.get_language_holder()
else if(istype(thing, /datum/mind))
var/datum/mind/M = thing
other = M.get_language_holder()
if(replace)
src.remove_all_languages()
for(var/l in other.languages)
src.grant_language(l)
/datum/language_holder/proc/open_language_menu(mob/user)
if(!language_menu)
language_menu = new(src)
language_menu.ui_interact(user)
/datum/language_holder/proc/get_atom()
if(ismovable(owner))
. = owner
else if(istype(owner, /datum/mind))
/// Initializes, and copies in the languages from the current atom if available.
/datum/language_holder/New(_owner)
owner = _owner
if(istype(owner, /datum/mind))
var/datum/mind/M = owner
if(M.current)
. = M.current
update_atom_languages(M.current)
get_selected_language()
/datum/language_holder/Destroy()
QDEL_NULL(language_menu)
return ..()
/// Grants the supplied language.
/datum/language_holder/proc/grant_language(language, understood = TRUE, spoken = TRUE, source = LANGUAGE_MIND)
if(understood)
if(!understood_languages[language])
understood_languages[language] = list()
understood_languages[language] |= source
. = TRUE
if(spoken)
if(!spoken_languages[language])
spoken_languages[language] = list()
spoken_languages[language] |= source
. = TRUE
/// Grants every language to understood and spoken, and gives omnitongue.
/datum/language_holder/proc/grant_all_languages(understood = TRUE, spoken = TRUE, grant_omnitongue = TRUE, source = LANGUAGE_MIND)
for(var/language in GLOB.all_languages)
grant_language(language, understood, spoken, source)
if(grant_omnitongue) // Overrides tongue limitations.
omnitongue = TRUE
return TRUE
/// Removes a single language or source, removing all sources returns the pre-removal state of the language.
/datum/language_holder/proc/remove_language(language, understood = TRUE, spoken = TRUE, source = LANGUAGE_ALL)
if(understood && understood_languages[language])
if(source == LANGUAGE_ALL)
understood_languages -= language
else
understood_languages[language] -= source
if(!length(understood_languages[language]))
understood_languages -= language
. = TRUE
if(spoken && spoken_languages[language])
if(source == LANGUAGE_ALL)
spoken_languages -= language
else
spoken_languages[language] -= source
if(!length(spoken_languages[language]))
spoken_languages -= language
. = TRUE
/// Removes every language and optionally sets omnitongue false. If a non default source is supplied, only removes that source.
/datum/language_holder/proc/remove_all_languages(source = LANGUAGE_ALL, remove_omnitongue = FALSE)
for(var/language in GLOB.all_languages)
remove_language(language, TRUE, TRUE, source)
if(remove_omnitongue)
omnitongue = FALSE
return TRUE
/// Adds a single language or list of languages to the blocked language list.
/datum/language_holder/proc/add_blocked_language(languages, source = LANGUAGE_MIND)
if(!islist(languages))
languages = list(languages)
for(var/language in languages)
if(!blocked_languages[language])
blocked_languages[language] = list()
blocked_languages[language] |= source
return TRUE
/// Removes a single language or list of languages from the blocked language list.
/datum/language_holder/proc/remove_blocked_language(languages, source = LANGUAGE_MIND)
if(!islist(languages))
languages = list(languages)
for(var/language in languages)
if(blocked_languages[language])
if(source == LANGUAGE_ALL)
blocked_languages -= language
else
blocked_languages[language] -= source
if(!length(blocked_languages[language]))
blocked_languages -= language
return TRUE
/// Checks if you have the language. If spoken is true, only checks if you can speak the language.
/datum/language_holder/proc/has_language(language, spoken = FALSE)
if(language in blocked_languages)
return FALSE
if(spoken)
return language in spoken_languages
return language in understood_languages
/// Checks if you can speak the language. Tongue limitations should be supplied as an argument.
/datum/language_holder/proc/can_speak_language(language)
var/atom/movable/ouratom = get_atom()
var/tongue = ouratom.could_speak_language(language)
if((omnitongue || tongue) && has_language(language, TRUE))
return TRUE
return FALSE
/// Returns selected language if it can be spoken, or decides, sets and returns a new selected language if possible.
/datum/language_holder/proc/get_selected_language()
if(selected_language && can_speak_language(selected_language))
return selected_language
selected_language = null
var/highest_priority
for(var/lang in spoken_languages)
var/datum/language/language = lang
var/priority = initial(language.default_priority)
if((!highest_priority || (priority > highest_priority)) && !(language in blocked_languages))
if(can_speak_language(language))
selected_language = language
highest_priority = priority
return selected_language
/// Gets a random understood language, useful for hallucinations and such.
/datum/language_holder/proc/get_random_understood_language()
return pick(understood_languages)
/// Gets a random spoken language, useful for forced speech and such.
/datum/language_holder/proc/get_random_spoken_language()
return pick(spoken_languages)
/// Opens a language menu reading from the language holder.
/datum/language_holder/proc/open_language_menu(mob/user)
if(!language_menu)
language_menu = new (src)
language_menu.ui_interact(user)
/// Gets the atom, since we some times need to check if the tongue has limitations.
/datum/language_holder/proc/get_atom()
if(owner)
if(istype(owner, /datum/mind))
var/datum/mind/M = owner
return M.current
return owner
return FALSE
/// Empties out the atom specific languages and updates them according to the supplied atoms language holder.
/datum/language_holder/proc/update_atom_languages(atom/movable/thing)
var/datum/language_holder/from_atom = thing.get_language_holder(FALSE) //Gets the atoms language holder
if(from_atom == src) //This could happen if called on an atom without a mind.
return FALSE
for(var/language in understood_languages)
remove_language(language, TRUE, FALSE, LANGUAGE_ATOM)
for(var/language in spoken_languages)
remove_language(language, FALSE, TRUE, LANGUAGE_ATOM)
for(var/language in blocked_languages)
remove_blocked_language(language, LANGUAGE_ATOM)
copy_languages(from_atom)
get_selected_language()
return TRUE
/// Copies all languages from the supplied atom/language holder. Source should be overridden when you
/// do not want the language overwritten by later atom updates or want to avoid blocked languages.
/datum/language_holder/proc/copy_languages(var/datum/language_holder/from_holder, source_override)
if(source_override) //No blocked languages here, for now only used by ling absorb.
for(var/language in from_holder.understood_languages)
grant_language(language, TRUE, FALSE, source_override)
for(var/language in from_holder.spoken_languages)
grant_language(language, FALSE, TRUE, source_override)
else
for(var/language in from_holder.understood_languages)
grant_language(language, TRUE, FALSE, from_holder.understood_languages[language])
for(var/language in from_holder.spoken_languages)
grant_language(language, FALSE, TRUE, from_holder.spoken_languages[language])
for(var/language in from_holder.blocked_languages)
add_blocked_language(language, from_holder.blocked_languages[language])
return TRUE
//************************************************
//* Specific language holders *
//* Use atom language sources only. *
//************************************************/
/datum/language_holder/alien
languages = list(/datum/language/xenocommon)
/datum/language_holder/monkey
languages = list(/datum/language/monkey)
/datum/language_holder/swarmer
languages = list(/datum/language/swarmer)
understood_languages = list(/datum/language/xenocommon = list(LANGUAGE_ATOM))
spoken_languages = list(/datum/language/xenocommon = list(LANGUAGE_ATOM))
blocked_languages = list(/datum/language/common = list(LANGUAGE_ATOM))
/datum/language_holder/clockmob
languages = list(/datum/language/common, /datum/language/ratvar)
only_speaks_language = /datum/language/ratvar
understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/ratvar = list(LANGUAGE_ATOM))
spoken_languages = list(/datum/language/ratvar = list(LANGUAGE_ATOM))
/datum/language_holder/construct
languages = list(/datum/language/common, /datum/language/narsie)
understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/narsie = list(LANGUAGE_ATOM))
spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/narsie = list(LANGUAGE_ATOM))
/datum/language_holder/drone
languages = list(/datum/language/common, /datum/language/drone, /datum/language/machine)
only_speaks_language = /datum/language/drone
understood_languages = list(/datum/language/drone = list(LANGUAGE_ATOM),
/datum/language/machine = list(LANGUAGE_ATOM))
spoken_languages = list(/datum/language/drone = list(LANGUAGE_ATOM))
blocked_languages = list(/datum/language/common = list(LANGUAGE_ATOM))
/datum/language_holder/drone/syndicate
only_speaks_language = null
blocked_languages = null
/datum/language_holder/dwarf
languages = list(/datum/language/common, /datum/language/dwarf)
only_speaks_language = /datum/language/dwarf
understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/dwarf = list(LANGUAGE_ATOM))
spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/dwarf = list(LANGUAGE_ATOM))
/datum/language_holder/slime
languages = list(/datum/language/common, /datum/language/slime)
only_speaks_language = /datum/language/slime
/datum/language_holder/jelly
understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/slime = list(LANGUAGE_ATOM))
spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/slime = list(LANGUAGE_ATOM))
/datum/language_holder/lightbringer
// TODO change to a lightbringer specific sign language
languages = list(/datum/language/slime)
understood_languages = list(/datum/language/slime = list(LANGUAGE_ATOM))
spoken_languages = list(/datum/language/slime = list(LANGUAGE_ATOM))
blocked_languages = list(/datum/language/common = list(LANGUAGE_ATOM))
/datum/language_holder/lizard
understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/draconic = list(LANGUAGE_ATOM))
spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/draconic = list(LANGUAGE_ATOM))
/datum/language_holder/lizard/ash
selected_language = /datum/language/draconic
/datum/language_holder/monkey
understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/monkey = list(LANGUAGE_ATOM))
spoken_languages = list(/datum/language/monkey = list(LANGUAGE_ATOM))
/datum/language_holder/mushroom
understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/mushroom = list(LANGUAGE_ATOM))
spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/mushroom = list(LANGUAGE_ATOM))
/datum/language_holder/slime
understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/slime = list(LANGUAGE_ATOM))
spoken_languages = list(/datum/language/slime = list(LANGUAGE_ATOM))
/datum/language_holder/swarmer
understood_languages = list(/datum/language/swarmer = list(LANGUAGE_ATOM))
spoken_languages = list(/datum/language/swarmer = list(LANGUAGE_ATOM))
blocked_languages = list(/datum/language/common = list(LANGUAGE_ATOM))
/datum/language_holder/sylvan
understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/sylvan = list(LANGUAGE_ATOM))
spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/sylvan = list(LANGUAGE_ATOM))
/datum/language_holder/synthetic
languages = list(/datum/language/common)
shadow_languages = list(/datum/language/common, /datum/language/machine, /datum/language/draconic, /datum/language/slime, /datum/language/dwarf)
understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/machine = list(LANGUAGE_ATOM),
/datum/language/draconic = list(LANGUAGE_ATOM),
/datum/language/slime = list(LANGUAGE_ATOM),
/datum/language/dwarf = list(LANGUAGE_ATOM))
spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/machine = list(LANGUAGE_ATOM),
/datum/language/draconic = list(LANGUAGE_ATOM),
/datum/language/slime = list(LANGUAGE_ATOM),
/datum/language/dwarf = list(LANGUAGE_ATOM))
/datum/language_holder/venus
understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/sylvan = list(LANGUAGE_ATOM))
spoken_languages = list(/datum/language/sylvan = list(LANGUAGE_ATOM))
/datum/language_holder/empty
languages = list()
shadow_languages = list()
understood_languages = list()
spoken_languages = list()
/datum/language_holder/universal/New()
..()
grant_all_languages(omnitongue=TRUE)
grant_all_languages()
+49 -26
View File
@@ -1,8 +1,8 @@
/datum/language_menu
var/datum/language_holder/language_holder
/datum/language_menu/New(language_holder)
src.language_holder = language_holder
/datum/language_menu/New(_language_holder)
language_holder = _language_holder
/datum/language_menu/Destroy()
language_holder = null
@@ -24,21 +24,20 @@
data["is_living"] = FALSE
data["languages"] = list()
for(var/ld in GLOB.all_languages)
var/result = language_holder.has_language(ld)
for(var/lang in GLOB.all_languages)
var/result = language_holder.has_language(lang) || language_holder.has_language(lang, TRUE)
if(!result)
continue
var/shadow = result == LANGUAGE_SHADOWED
var/datum/language/LD = ld
var/datum/language/language = lang
var/list/L = list()
L["name"] = initial(LD.name)
L["desc"] = initial(LD.desc)
L["key"] = initial(LD.key)
L["is_default"] = (LD == language_holder.selected_default_language)
L["shadow"] = shadow
L["name"] = initial(language.name)
L["desc"] = initial(language.desc)
L["key"] = initial(language.key)
L["is_default"] = (language == language_holder.selected_language)
if(AM)
L["can_speak"] = AM.can_speak_in_language(LD)
L["can_speak"] = AM.can_speak_language(language)
L["can_understand"] = AM.has_language(language)
data["languages"] += list(L)
@@ -47,15 +46,15 @@
data["omnitongue"] = language_holder.omnitongue
data["unknown_languages"] = list()
for(var/ld in GLOB.all_languages)
if(language_holder.has_language(ld))
for(var/lang in GLOB.all_languages)
if(language_holder.has_language(lang) || language_holder.has_language(lang, TRUE))
continue
var/datum/language/LD = ld
var/datum/language/language = lang
var/list/L = list()
L["name"] = initial(LD.name)
L["desc"] = initial(LD.desc)
L["key"] = initial(LD.key)
L["name"] = initial(language.name)
L["desc"] = initial(language.desc)
L["key"] = initial(language.key)
data["unknown_languages"] += list(L)
return data
@@ -68,27 +67,51 @@
var/language_name = params["language_name"]
var/datum/language/language_datum
for(var/ld in GLOB.all_languages)
var/datum/language/LD = ld
if(language_name == initial(LD.name))
language_datum = LD
for(var/lang in GLOB.all_languages)
var/datum/language/language = lang
if(language_name == initial(language.name))
language_datum = language
var/is_admin = check_rights_for(user.client, R_ADMIN)
switch(action)
if("select_default")
if(language_datum && AM.can_speak_in_language(language_datum))
language_holder.selected_default_language = language_datum
if(language_datum && AM.can_speak_language(language_datum))
language_holder.selected_language = language_datum
. = TRUE
if("grant_language")
if((is_admin || isobserver(AM)) && language_datum)
language_holder.grant_language(language_datum)
var/list/choices = list("Only Spoken", "Only Understood", "Both")
var/choice = input(user,"How do you want to add this language?","[language_datum]",null) as null|anything in choices
var/spoken = FALSE
var/understood = FALSE
switch(choice)
if("Only Spoken")
spoken = TRUE
if("Only Understood")
understood = TRUE
if("Both")
spoken = TRUE
understood = TRUE
language_holder.grant_language(language_datum, understood, spoken)
if(is_admin)
message_admins("[key_name_admin(user)] granted the [language_name] language to [key_name_admin(AM)].")
log_admin("[key_name(user)] granted the language [language_name] to [key_name(AM)].")
. = TRUE
if("remove_language")
if((is_admin || isobserver(AM)) && language_datum)
language_holder.remove_language(language_datum)
var/list/choices = list("Only Spoken", "Only Understood", "Both")
var/choice = input(user,"Which part do you wish to remove?","[language_datum]",null) as null|anything in choices
var/spoken = FALSE
var/understood = FALSE
switch(choice)
if("Only Spoken")
spoken = TRUE
if("Only Understood")
understood = TRUE
if("Both")
spoken = TRUE
understood = TRUE
language_holder.remove_language(language_datum, understood, spoken)
if(is_admin)
message_admins("[key_name_admin(user)] removed the [language_name] language to [key_name_admin(AM)].")
log_admin("[key_name(user)] removed the language [language_name] to [key_name(AM)].")
+18
View File
@@ -0,0 +1,18 @@
// The language of the vinebings. Yes, it's a shameless ripoff of elvish.
/datum/language/sylvan
name = "Sylvan"
desc = "A complicated, ancient language spoken by vine like beings."
speech_verb = "expresses"
ask_verb = "inquires"
exclaim_verb = "declares"
key = "h"
space_chance = 20
syllables = list(
"fii", "sii", "rii", "rel", "maa", "ala", "san", "tol", "tok", "dia", "eres",
"fal", "tis", "bis", "qel", "aras", "losk", "rasa", "eob", "hil", "tanl", "aere",
"fer", "bal", "pii", "dala", "ban", "foe", "doa", "cii", "uis", "mel", "wex",
"incas", "int", "elc", "ent", "aws", "qip", "nas", "vil", "jens", "dila", "fa",
"la", "re", "do", "ji", "ae", "so", "qe", "ce", "na", "mo", "ha", "yu"
)
icon_state = "plant"
default_priority = 90
@@ -564,7 +564,7 @@
/obj/item/book_of_babel/attack_self(mob/user)
to_chat(user, "You flip through the pages of the book, quickly and conveniently learning every language in existence. Somewhat less conveniently, the aging book crumbles to dust in the process. Whoops.")
user.grant_all_languages(omnitongue=TRUE)
user.grant_all_languages()
new /obj/effect/decal/cleanable/ash(get_turf(user))
qdel(src)
-7
View File
@@ -25,10 +25,3 @@
/mob/living/brain/treat_message(message)
message = capitalize(message)
return message
/mob/living/brain/could_speak_in_language(datum/language/dt)
if(istype(container, /obj/item/mmi/posibrain/soul_vessel))
// soul vessels can only speak ratvarian.
. = ispath(dt, /datum/language/ratvar)
else
. = ..()
@@ -1059,6 +1059,9 @@
if(health_deficiency >= 40)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown, TRUE, (health_deficiency-39) / 75)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying, TRUE, (health_deficiency-39) / 25)
else
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown)
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
else
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown)
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
@@ -49,6 +49,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/blacklisted = 0 //Flag to exclude from green slime core species.
var/dangerous_existence //A flag for transformation spells that tells them "hey if you turn a person into one of these without preperation, they'll probably die!"
var/say_mod = "says" // affects the speech message
var/species_language_holder = /datum/language_holder
var/list/mutant_bodyparts = list() // Visible CURRENT bodyparts that are unique to a species. Changes to this list for non-species specific bodyparts (ie cat ears and tails) should be assigned at organ level if possible. Layer hiding is handled by handle_mutant_bodyparts() below.
var/list/mutant_organs = list() //Internal organs that are unique to this race.
var/speedmod = 0 // this affects the race's speed. positive numbers make it move slower, negative numbers make it move faster
@@ -9,6 +9,7 @@
gib_types = /obj/effect/gibspawner/robot
damage_overlay_type = "synth"
mutanttongue = /obj/item/organ/tongue/robot
species_language_holder = /datum/language_holder/synthetic
limbs_id = "synth"
/datum/species/android/on_species_gain(mob/living/carbon/C)
@@ -17,6 +17,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
disliked_food = JUNKFOOD | FRIED //Dwarves hate foods that have no nutrition other than alcohol.
mutant_organs = list(/obj/item/organ/dwarfgland) //Dwarven alcohol gland, literal gland warrior
mutantliver = /obj/item/organ/liver/dwarf //Dwarven super liver (Otherwise they r doomed)
species_language_holder = /datum/language_holder/dwarf
/mob/living/carbon/human/species/dwarf //species admin spawn path
race = /datum/species/dwarf //and the race the path is set to.
@@ -30,7 +31,6 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
. = ..()
var/dwarf_hair = pick("Beard (Dwarf)", "Beard (Very Long)", "Beard (Long)") //beard roullette
var/mob/living/carbon/human/H = C
H.grant_language(/datum/language/dwarf)
H.facial_hair_style = dwarf_hair
H.update_hair()
H.transform = H.transform.Scale(1, 0.8) //We use scale, and yeah. Dwarves can become gnomes with DWARFISM.
@@ -40,7 +40,6 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
. = ..()
H.transform = H.transform.Scale(1, 1.25) //And we undo it.
UnregisterSignal(H, COMSIG_MOB_SAY) //We register handle_speech is not being used.
H.remove_language(/datum/language/dwarf)
//Dwarf Name stuff
/proc/dwarf_name() //hello caller: my name is urist mcuristurister
@@ -21,20 +21,19 @@
coldmod = 6 // = 3x cold damage
heatmod = 0.5 // = 1/4x heat damage
burnmod = 0.5 // = 1/2x generic burn damage
species_language_holder = /datum/language_holder/jelly
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
if(regenerate_limbs)
regenerate_limbs.Remove(C)
if(slime_change) //CIT CHANGE
slime_change.Remove(C) //CIT CHANGE
C.remove_language(/datum/language/slime)
C.faction -= "slime"
..()
C.faction -= "slime"
/datum/species/jelly/on_species_gain(mob/living/carbon/C, datum/species/old_species)
..()
C.grant_language(/datum/language/slime)
if(ishuman(C))
regenerate_limbs = new
regenerate_limbs.Grant(C)
@@ -24,9 +24,7 @@
disliked_food = GRAIN | DAIRY
liked_food = GROSS | MEAT
inert_mutation = FIREBREATH
/datum/species/lizard/after_equip_job(datum/job/J, mob/living/carbon/human/H)
H.grant_language(/datum/language/draconic)
species_language_holder = /datum/language_holder/lizard
/datum/species/lizard/random_name(gender,unique,lastname)
if(unique)
@@ -86,6 +84,7 @@
mutantlungs = /obj/item/organ/lungs/ashwalker
burnmod = 0.9
brutemod = 0.9
species_language_holder = /datum/language_holder/lizard/ash
/datum/species/lizard/ashwalker/on_species_gain(mob/living/carbon/human/C, datum/species/old_species)
if((C.dna.features["spines"] != "None" ) && (C.dna.features["tail_lizard"] == "None")) //tbh, it's kinda ugly for them not to have a tail yet have floating spines
@@ -23,9 +23,7 @@
mutanteyes = /obj/item/organ/eyes/night_vision/mushroom
var/datum/martial_art/mushpunch/mush
/datum/species/mush/after_equip_job(datum/job/J, mob/living/carbon/human/H)
H.grant_language(/datum/language/mushroom) //pomf pomf
species_language_holder = /datum/language_holder/mushroom
/datum/species/mush/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
@@ -12,6 +12,7 @@
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/plant
disliked_food = MEAT | DAIRY
liked_food = VEGETABLES | FRUIT | GRAIN
species_language_holder = /datum/language_holder/sylvan
var/light_nutrition_gain_factor = 10
var/light_toxheal = 1
var/light_oxyheal = 1
@@ -16,6 +16,7 @@
var/list/initial_inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOLIMBDISABLE,TRAIT_NOHUNGER,TRAIT_NOBREATH)
var/disguise_fail_health = 75 //When their health gets to this level their synthflesh partially falls off
var/datum/species/fake_species = null //a species to do most of our work for us, unless we're damaged
species_language_holder = /datum/language_holder/synthetic
/datum/species/synth/military
name = "Military Synth"
@@ -34,12 +34,11 @@
/mob/living/carbon/human/set_drugginess(amount)
..()
if(!amount)
remove_language(/datum/language/beachbum)
remove_language(/datum/language/beachbum, TRUE, TRUE, LANGUAGE_HIGH)
/mob/living/carbon/human/adjust_drugginess(amount)
..()
if(!dna.check_mutation(STONER))
if(druggy)
grant_language(/datum/language/beachbum)
else
remove_language(/datum/language/beachbum)
if(druggy)
grant_language(/datum/language/beachbum, TRUE, TRUE, LANGUAGE_HIGH)
else
remove_language(/datum/language/beachbum, TRUE, TRUE, LANGUAGE_HIGH)
+3 -3
View File
@@ -12,9 +12,9 @@
return 0
return ..()
/mob/living/carbon/could_speak_in_language(datum/language/dt)
/mob/living/carbon/could_speak_language(datum/language/language)
var/obj/item/organ/tongue/T = getorganslot(ORGAN_SLOT_TONGUE)
if(T)
. = T.could_speak_in_language(dt)
return T.could_speak_language(language)
else
. = initial(dt.flags) & TONGUELESS_SPEECH
return initial(language.flags) & TONGUELESS_SPEECH
@@ -98,8 +98,6 @@
var/datum/riding/riding_datum
var/datum/language/selected_default_language
var/last_words //used for database logging
var/list/obj/effect/proc_holder/abilities = list()
+5 -9
View File
@@ -133,7 +133,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
var/datum/language/message_language = get_message_language(message)
if(message_language)
// No, you cannot speak in xenocommon just because you know the key
if(can_speak_in_language(message_language))
if(can_speak_language(message_language))
language = message_language
message = copytext_char(message, 3)
@@ -141,7 +141,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
message = trim_left(message)
if(!language)
language = get_default_language()
language = get_selected_language()
// Detection of language needs to be before inherent channels, because
// AIs use inherent channels for the holopad. Most inherent channels
@@ -415,11 +415,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
/mob/living/whisper(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
say("#[message]", bubble_type, spans, sanitize, language, ignore_spam, forced)
/mob/living/get_language_holder(shadow=TRUE)
if(mind && shadow)
// Mind language holders shadow mob holders.
. = mind.get_language_holder()
if(.)
return .
/mob/living/get_language_holder(get_minds = TRUE)
if(get_minds && mind)
return mind.get_language_holder()
. = ..()
@@ -171,10 +171,3 @@
#undef VOX_DELAY
#endif
/mob/living/silicon/ai/could_speak_in_language(datum/language/dt)
if(is_servant_of_ratvar(src))
// Ratvarian AIs can only speak Ratvarian
. = ispath(dt, /datum/language/ratvar)
else
. = ..()
@@ -267,9 +267,8 @@
if(href_list["toggle"])
encryptmod = TRUE
if("translator")
if(href_list["toggle"])
grant_all_languages(TRUE)
// this is PERMAMENT.
if(href_list["toggle"]) //This is permanent.
grant_all_languages(TRUE, TRUE, TRUE, LANGUAGE_SOFTWARE)
if("doorjack")
if(href_list["jack"])
if(cable && cable.machine)
@@ -276,6 +276,19 @@
R.hud_used.update_robot_modules_display()
SSblackbox.record_feedback("tally", "cyborg_modules", 1, R.module)
/**
* check_menu: Checks if we are allowed to interact with a radial menu
*
* Arguments:
* * user The mob interacting with a menu
*/
/obj/item/robot_module/proc/check_menu(mob/user)
if(!istype(user))
return FALSE
if(user.incapacitated() || !user.Adjacent(src))
return FALSE
return TRUE
/obj/item/robot_module/standard
name = "Standard"
basic_modules = list(
@@ -337,13 +350,28 @@
/obj/item/robot_module/medical/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/medmodels = list("Default", "Heavy", "Sleek", "Marina", "Droid", "Eyebot", "Medihound", "Medihound Dark", "Vale")
if(R.client && (R.client.ckey in list("nezuli")))
medmodels += "Alina"
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in medmodels
if(!borg_icon)
return FALSE
switch(borg_icon)
var/static/list/med_icons
if(!med_icons)
med_icons = list(
"Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "medical"),
"Droid" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "medical"),
"Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekmed"),
"Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinamed"),
"Eyebot" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "eyebotmed"),
"Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymed")
)
var/list/L = list("Medihound" = "medihound", "Medihound Dark" = "medihounddark", "Vale" = "valemed")
for(var/a in L)
var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
wide.pixel_x = -16
med_icons[a] = wide
if(R.client && R.client.ckey == "nezuli")
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)
var/med_borg_icon = show_radial_menu(R, R , med_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(med_borg_icon)
if("Default")
cyborg_base_icon = "medical"
if("Droid")
@@ -391,6 +419,8 @@
moduleselect_icon = "medihound"
moduleselect_alternate_icon = 'modular_citadel/icons/ui/screen_cyborg.dmi'
dogborg = TRUE
else
return FALSE
return ..()
/obj/item/robot_module/engineering
@@ -434,13 +464,31 @@
/obj/item/robot_module/engineering/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/list/engymodels = list("Default", "Default - Treads", "Heavy", "Sleek", "Marina", "Can", "Spider", "Loader","Handy", "Pup Dozer", "Vale")
if(R.client && (R.client.ckey in list("nezuli")))
engymodels += "Alina"
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in engymodels
if(!borg_icon)
return FALSE
switch(borg_icon)
var/static/list/engi_icons
if(!engi_icons)
engi_icons = list(
"Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "engineer"),
"Default - Treads" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "engi-tread"),
"Loader" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "loaderborg"),
"Handy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "handyeng"),
"Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekeng"),
"Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "caneng"),
"Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinaeng"),
"Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "spidereng"),
"Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyeng")
)
var/list/L = list("Pup Dozer" = "pupdozer", "Vale" = "valeeng")
for(var/a in L)
var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
wide.pixel_x = -16
engi_icons[a] = wide
if(R.client && R.client.ckey == "nezuli")
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)
var/engi_borg_icon = show_radial_menu(R, R , engi_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(engi_borg_icon)
if("Default")
cyborg_base_icon = "engineer"
if("Default - Treads")
@@ -485,6 +533,8 @@
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
sleeper_overlay = "alinasleeper"
dogborg = TRUE
else
return FALSE
return ..()
/obj/item/robot_module/security
@@ -512,13 +562,29 @@
/obj/item/robot_module/security/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/list/secmodels = list("Default", "Default - Treads", "Heavy", "Sleek", "Can", "Marina", "Spider", "K9", "K9 Dark", "Vale")
if(R.client && (R.client.ckey in list("nezuli")))
secmodels += "Alina"
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in secmodels
if(!borg_icon)
return FALSE
switch(borg_icon)
var/static/list/sec_icons
if(!sec_icons)
sec_icons = list(
"Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "sec"),
"Default - Treads" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sec-tread"),
"Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleeksec"),
"Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "cansec"),
"Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinasec"),
"Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "spidersec"),
"Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavysec")
)
var/list/L = list("K9" = "k9", "Vale" = "valesec", "K9 Dark" = "k9dark")
for(var/a in L)
var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
wide.pixel_x = -16
sec_icons[a] = wide
if(R.client && R.client.ckey == "nezuli")
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)
var/sec_borg_icon = show_radial_menu(R, R , sec_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(sec_borg_icon)
if("Default")
cyborg_base_icon = "sec"
if("Default - Treads")
@@ -561,6 +627,8 @@
sleeper_overlay = "valesecsleeper"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
dogborg = TRUE
else
return FALSE
return ..()
/obj/item/robot_module/security/Initialize()
@@ -599,10 +667,13 @@
/obj/item/robot_module/peacekeeper/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Default", "Spider", "Borgi")
if(!borg_icon)
return FALSE
switch(borg_icon)
var/static/list/peace_icons = sortList(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")
))
var/peace_borg_icon = show_radial_menu(R, R , peace_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(peace_borg_icon)
if("Default")
cyborg_base_icon = "peace"
if("Spider")
@@ -615,6 +686,8 @@
hat_offset = INFINITY
cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi'
has_snowflake_deadsprite = TRUE
else
return FALSE
return ..()
//Janitor module combined with Service module
@@ -738,10 +811,35 @@
/obj/item/robot_module/butler/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("(Service) Waitress", "(Service) Heavy", "(Service) Sleek", "(Service) Butler", "(Service) Tophat", "(Service) Can", "(Service) Bro", "(Service) DarkK9", "(Service) Vale", "(Service) ValeDark", "(Janitor) Default", "(Janitor) Sleek", "(Janitor) Marina", "(Janitor) Can", "(Janitor) Heavy", "(Janitor) Scrubpuppy")
if(!borg_icon)
return FALSE
switch(borg_icon)
var/static/list/service_icons
if(!service_icons)
service_icons = list(
"(Service) Waitress" = image(icon = 'icons/mob/robots.dmi', icon_state = "service_f"),
"(Service) Butler" = image(icon = 'icons/mob/robots.dmi', icon_state = "service_m"),
"(Service) Bro" = image(icon = 'icons/mob/robots.dmi', icon_state = "brobot"),
"(Service) Can" = image(icon = 'icons/mob/robots.dmi', icon_state = "kent"),
"(Service) Tophat" = image(icon = 'icons/mob/robots.dmi', icon_state = "tophat"),
"(Service) Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekserv"),
"(Service) Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyserv"),
"(Janitor) Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "janitor"),
"(Janitor) Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinajan"),
"(Janitor) Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekjan"),
"(Janitor) Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "canjan"),
"(Janitor) Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyjan"),
)
var/list/L = list("(Service) DarkK9" = "k50", "(Service) Vale" = "valeserv", "(Service) ValeDark" = "valeservdark",
"(Janitor) Scrubpuppy" = "scrubpup")
for(var/a in L)
var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
wide.pixel_x = -16
service_icons[a] = wide
if(R.client && R.client.ckey == "nezuli")
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)
var/service_robot_icon = show_radial_menu(R, R , service_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(service_robot_icon)
if("(Service) Waitress")
cyborg_base_icon = "service_f"
special_light_key = "service"
@@ -799,6 +897,8 @@
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
sleeper_overlay = "jsleeper"
dogborg = TRUE
else
return FALSE
return ..()
/obj/item/robot_module/miner
@@ -833,10 +933,25 @@
/obj/item/robot_module/miner/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Lavaland", "Heavy", "Sleek", "Marina", "Can", "Spider", "Asteroid", "Droid", "Blade", "Vale")
if(!borg_icon)
return FALSE
switch(borg_icon)
var/static/list/mining_icons
if(!mining_icons)
mining_icons = list(
"Lavaland" = image(icon = 'icons/mob/robots.dmi', icon_state = "miner"),
"Asteroid" = image(icon = 'icons/mob/robots.dmi', icon_state = "minerOLD"),
"Droid" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "miner"),
"Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekmin"),
"Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinamin"),
"Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "canmin"),
"Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymin"),
)
var/list/L = list("Blade" = "blade", "Vale" = "valemine")
for(var/a in L)
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)
var/mining_borg_icon = show_radial_menu(R, R , mining_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(mining_borg_icon)
if("Lavaland")
cyborg_base_icon = "miner"
if("Asteroid")
@@ -871,6 +986,8 @@
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
sleeper_overlay = "valeminesleeper"
dogborg = TRUE
else
return FALSE
return ..()
/obj/item/robot_module/syndicate
@@ -911,7 +911,6 @@ Pass a positive integer as an argument to override a bot's default speed.
bot_name = name
name = paicard.pai.name
faction = user.faction.Copy()
language_holder = paicard.pai.language_holder.copy(src)
log_combat(user, paicard.pai, "uploaded to [bot_name],")
return TRUE
else
+1
View File
@@ -425,6 +425,7 @@
mind.transfer_to(new_xeno)
else
transfer_ckey(new_xeno)
update_atom_languages()
to_chat(new_xeno, "<B>You are now an alien.</B>")
. = new_xeno
@@ -249,7 +249,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
add_overlay(causality_field, TRUE)
var/speaking = "[emergency_alert] The supermatter has reached critical integrity failure. Emergency causality destabilization field has been activated."
radio.talk_into(src, speaking, common_channel, language = get_default_language())
radio.talk_into(src, speaking, common_channel, language = get_selected_language())
for(var/i in SUPERMATTER_COUNTDOWN_TIME to 0 step -10)
if(damage < explosion_point) // Cutting it a bit close there engineers
radio.talk_into(src, "[safe_alert] Failsafe has been disengaged.", common_channel)
@@ -228,7 +228,6 @@
if(!new_mob)
return
new_mob.grant_language(/datum/language/common)
// Some forms can still wear some items
for(var/obj/item/W in contents)
@@ -959,9 +959,10 @@ datum/status_effect/stabilized/blue/on_remove()
familiar = new linked.mob_type(get_turf(owner.loc))
familiar.name = linked.mob_name
familiar.del_on_death = TRUE
familiar.copy_known_languages_from(owner, FALSE)
familiar.copy_languages(owner, LANGUAGE_MASTER)
if(linked.saved_mind)
linked.saved_mind.transfer_to(familiar)
familiar.update_atom_languages()
familiar.ckey = linked.saved_mind.key
else
if(familiar.mind)
@@ -684,7 +684,7 @@
if(SM.flags_1 & HOLOGRAM_1) //Check to see if it's a holodeck creature
to_chat(SM, "<span class='userdanger'>You also become depressingly aware that you are not a real creature, but instead a holoform. Your existence is limited to the parameters of the holodeck.</span>")
to_chat(user, "<span class='notice'>[SM] accepts [src] and suddenly becomes attentive and aware. It worked!</span>")
SM.copy_known_languages_from(user, FALSE)
SM.copy_languages(user)
after_success(user, SM)
qdel(src)
else
+1 -1
View File
@@ -133,7 +133,7 @@
assignedrole = "Lavaland Syndicate"
/obj/effect/mob_spawn/human/lavaland_syndicate/special(mob/living/new_spawn)
new_spawn.grant_language(/datum/language/codespeak)
new_spawn.grant_language(/datum/language/codespeak, TRUE, TRUE, LANGUAGE_MIND)
/datum/outfit/lavaland_syndicate
name = "Lavaland Syndicate Agent"
+4 -4
View File
@@ -64,8 +64,8 @@
owner.RegisterSignal(owner, COMSIG_MOB_SAY, /mob/living/carbon/.proc/handle_tongueless_speech)
return ..()
/obj/item/organ/tongue/could_speak_in_language(datum/language/dt)
return is_type_in_typecache(dt, languages_possible)
/obj/item/organ/tongue/could_speak_language(language)
return is_type_in_typecache(language, languages_possible)
/obj/item/organ/tongue/lizard
name = "forked tongue"
@@ -141,7 +141,7 @@
/obj/item/organ/tongue/abductor/handle_speech(datum/source, list/speech_args)
//Hacks
var/message = speech_args[SPEECH_MESSAGE]
var/mob/living/carbon/human/user = usr
var/mob/living/carbon/human/user = source
var/rendered = "<span class='abductor'><b>[user.name]:</b> [message]</span>"
user.log_talk(message, LOG_SAY, tag="abductor")
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
@@ -260,7 +260,7 @@
maxHealth = 100 //RoboTongue!
var/electronics_magic = TRUE
/obj/item/organ/tongue/robot/can_speak_in_language(datum/language/dt)
/obj/item/organ/tongue/robot/could_speak_language(language)
return ..() || electronics_magic
/obj/item/organ/tongue/robot/handle_speech(datum/source, list/speech_args)