This commit is contained in:
Dmitry
2025-02-20 14:26:02 +03:00
159 changed files with 2163 additions and 1081 deletions
+1 -1
View File
@@ -1007,7 +1007,7 @@
log_admin("[key_name(usr)] stuffed [frommob.key] into [tomob.name].")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Ghost Drag Control")
tomob.ckey = frommob.ckey
tomob.key = frommob.key
qdel(frommob)
return TRUE
+1 -2
View File
@@ -2081,8 +2081,7 @@
if(!ismob(M))
to_chat(usr, "This can only be used on instances of type /mob.")
return
var/datum/language_holder/H = M.get_language_holder()
H.open_language_menu(usr)
M.get_language_holder().open_language_menu(usr)
else if(href_list["traitor"])
if(!check_rights(R_ADMIN))
+2 -2
View File
@@ -135,9 +135,9 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
/obj/effect/statclick/ticket_list
var/current_state
/obj/effect/statclick/ticket_list/New(loc, name, state)
/obj/effect/statclick/ticket_list/Initialize(mapload, name, state)
. = ..()
current_state = state
..()
/obj/effect/statclick/ticket_list/Click()
GLOB.ahelp_tickets.BrowseTickets(current_state)
@@ -63,6 +63,13 @@ GLOBAL_DATUM_INIT(pluto, /atom/movable, new /atom/movable(null))
return FALSE
if(var_name == NAMEOF(src, realized_underlays))
return FALSE
#if (MIN_COMPILER_VERSION >= 515 && MIN_COMPILER_BUILD >= 1643)
#warn X/Y/Z and contents are now fully unviewable on our supported versions, remove the below check
#endif
// lummy removed these from the the MA/image type
#if (DM_VERSION <= 515 && DM_BUILD < 1643)
// Filtering out the stuff I know we don't care about
if(var_name == NAMEOF(src, x))
return FALSE
@@ -70,13 +77,14 @@ GLOBAL_DATUM_INIT(pluto, /atom/movable, new /atom/movable(null))
return FALSE
if(var_name == NAMEOF(src, z))
return FALSE
// Could make an argument for these but I think they will just confuse people, so yeeet
#ifndef SPACEMAN_DMM // Spaceman doesn't believe in contents on appearances, sorry lads
#ifndef SPACEMAN_DMM // Spaceman doesn't believe in contents on appearances, sorry lads
if(var_name == NAMEOF(src, contents))
return FALSE
#endif
#endif
if(var_name == NAMEOF(src, loc))
return FALSE
#endif
// Could make an argument for this but I think they will just confuse people, so yeeet
if(var_name == NAMEOF(src, vis_contents))
return FALSE
return ..()
@@ -10,12 +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, TRUE, TRUE, LANGUAGE_GLAND)
owner.grant_language(/datum/language/slime, source = 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)
owner.remove_language(/datum/language/slime, source = LANGUAGE_GLAND)
/obj/item/organ/heart/gland/slime/activate()
to_chat(owner, "<span class='warning'>You feel nauseated!</span>")
@@ -210,7 +210,7 @@
// Physiology
CheckVampOrgans() // Heart, Eyes
// Language
owner.current.grant_language(/datum/language/vampiric, TRUE, TRUE, LANGUAGE_BLOODSUCKER)
owner.current.grant_language(/datum/language/vampiric, source = 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
@@ -48,7 +48,7 @@
objectives += vassal_objective
objectives_given += vassal_objective
give_thrall_eyes()
owner.current.grant_language(/datum/language/vampiric, TRUE, TRUE, LANGUAGE_VASSAL)
owner.current.grant_language(/datum/language/vampiric, source = LANGUAGE_VASSAL)
// Add Antag HUD
update_vassal_icons_added(owner.current, "vassal")
. = ..()
@@ -84,7 +84,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.
owner.current.get_language_holder().omnitongue = TRUE
remove_clownmut()
. = ..()
@@ -96,7 +96,7 @@
current = mob_override
GLOB.all_clockwork_mobs += current
current.faction |= "ratvar"
current.grant_language(/datum/language/ratvar, TRUE, TRUE, LANGUAGE_CLOCKIE)
current.grant_language(/datum/language/ratvar, source = 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
+2 -2
View File
@@ -121,7 +121,7 @@
if(mob_override)
current = mob_override
current.faction |= "cult"
current.grant_language(/datum/language/narsie, TRUE, TRUE, LANGUAGE_CULTIST)
current.grant_language(/datum/language/narsie, source = LANGUAGE_CULTIST)
if(!cult_team?.cult_master)
vote.Grant(current)
communion.Grant(current)
@@ -139,7 +139,7 @@
if(mob_override)
current = mob_override
current.faction -= "cult"
current.remove_language(/datum/language/narsie, TRUE, TRUE, LANGUAGE_CULTIST)
current.remove_language(/datum/language/narsie, source = LANGUAGE_CULTIST)
vote.Remove(current)
communion.Remove(current)
magic.Remove(current)
+1 -2
View File
@@ -182,9 +182,8 @@
add_antag_hud(antag_hud_type, antag_hud_name, M)
if(M.hud_used)
var/datum/hud/H = M.hud_used
var/atom/movable/screen/wanted/giving_wanted_lvl = new /atom/movable/screen/wanted()
var/atom/movable/screen/wanted/giving_wanted_lvl = new /atom/movable/screen/wanted(null, H)
H.wanted_lvl = giving_wanted_lvl
giving_wanted_lvl.hud = H
H.infodisplay += giving_wanted_lvl
H.mymob.client.screen += giving_wanted_lvl
+1 -2
View File
@@ -113,9 +113,8 @@
add_antag_hud(antag_hud_type, antag_hud_name, M)
if(M.hud_used)
var/datum/hud/H = M.hud_used
var/atom/movable/screen/wanted/giving_wanted_lvl = new /atom/movable/screen/wanted()
var/atom/movable/screen/wanted/giving_wanted_lvl = new /atom/movable/screen/wanted(null, H)
H.wanted_lvl = giving_wanted_lvl
giving_wanted_lvl.hud = H
H.infodisplay += giving_wanted_lvl
H.mymob.client.screen += giving_wanted_lvl
@@ -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, TRUE, TRUE, LANGUAGE_MALF)
T.owner.current.grant_language(/datum/language/codespeak, source = LANGUAGE_MALF)
return FALSE
@@ -41,13 +41,13 @@
var/spawn_amt_left = 20
var/spawn_fast = 0
/obj/effect/rend/New(loc, var/spawn_type, var/spawn_amt, var/desc, var/spawn_fast)
/obj/effect/rend/Initialize(mapload, spawn_type, spawn_amt, desc, spawn_fast)
. = ..()
src.spawn_path = spawn_type
src.spawn_amt_left = spawn_amt
src.desc = desc
src.spawn_fast = spawn_fast
START_PROCESSING(SSobj, src)
return
/obj/effect/rend/process()
if(!spawn_fast)
@@ -287,9 +287,7 @@
S.real_name = "Shade of [T.real_name]"
T.transfer_ckey(S)
S.original_mind = T.mind
S.copy_languages(T, LANGUAGE_MIND)//Copies the old mobs languages into the new mob holder.
S.update_atom_languages()
grant_all_languages(FALSE, FALSE, TRUE) //Grants omnitongue
S.get_language_holder().omnitongue = TRUE //Grants omnitongue
if(user)
S.faction |= "[REF(user)]" //Add the master as a faction, allowing inter-mob cooperation
if(user && iscultist(user))
@@ -186,6 +186,6 @@ GLOBAL_DATUM_INIT(gas_data, /datum/auxgm, new)
appearance_flags = TILE_BOUND
vis_flags = NONE
/obj/effect/overlay/gas/New(state)
/obj/effect/overlay/gas/Initialize(mapload, state)
. = ..()
icon_state = state
+1
View File
@@ -1,5 +1,6 @@
/atom/movable/screen/buildmode
icon = 'icons/misc/buildmode.dmi'
mouse_over_pointer = MOUSE_HAND_POINTER
var/datum/buildmode/bd
// If we don't do this, we get occluded by item action buttons
layer = ABOVE_HUD_LAYER
+9
View File
@@ -169,6 +169,15 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
to_chat(src, "Become a BYOND member to access member-perks and features, as well as support the engine that makes this game possible. Only 10 bucks for 3 months! <a href=\"https://secure.byond.com/membership\">Click Here to find out more</a>.")
return FALSE
return TRUE
/client/proc/is_localhost()
var/static/localhost_addresses = list(
"127.0.0.1",
"::1",
null,
)
return address in localhost_addresses
/*
* Call back proc that should be checked in all paths where a client can send messages
*
+1 -1
View File
@@ -3837,7 +3837,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/language_entry = GLOB.roundstart_languages[additional_language]
if(language_entry)
character.additional_language = language_entry
character.grant_language(language_entry, TRUE, TRUE)
character.grant_language(language_entry)
character.set_bark(bark_id)
character.vocal_speed = bark_speed
+1 -1
View File
@@ -55,7 +55,7 @@
SG.transfer_ckey(SA, FALSE)
SA.grant_all_languages(TRUE, FALSE, FALSE)
SA.grant_all_languages(UNDERSTOOD_LANGUAGE, grant_omnitongue = FALSE, source = LANGUAGE_ATOM)
SA.sentience_act()
+2 -1
View File
@@ -50,4 +50,5 @@
if(visualsOnly)
return
H.grant_all_languages(TRUE, TRUE, TRUE, LANGUAGE_CURATOR)
H.grant_all_languages(source = LANGUAGE_CURATOR)
H.remove_blocked_language(GLOB.all_languages, source=LANGUAGE_ALL)
+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, TRUE, TRUE, LANGUAGE_MIND)
user.grant_language(/datum/language/codespeak, source = 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, TRUE, TRUE, LANGUAGE_MIND)
M.grant_language(/datum/language/codespeak, source = LANGUAGE_MIND)
use_charge(user)
/obj/item/codespeak_manual/proc/use_charge(mob/user)
+133 -97
View File
@@ -1,23 +1,28 @@
/*!Language holders will either exist in an atom/movable or a mind. Creation of language holders happens
/*!Language holders will either exist in an atom/movable. 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)
@@ -28,83 +33,86 @@ Key procs
* [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.
/// Lazyassoclist of all understood languages
var/list/understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM))
/// Lazyassoclist 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.
/// Lazyassoclist of blocked languages.
/// Used to prevent understanding and speaking certain languages, ie for certain mobs, mutations etc.
var/list/blocked_languages
/// If true, overrides tongue aforementioned 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
var/atom/movable/owner
/// 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)
update_atom_languages(M.current)
get_selected_language()
/datum/language_holder/New(atom/new_owner)
if(new_owner)
if(QDELETED(new_owner))
CRASH("Langauge holder added to a qdeleting thing, what the fuck [text_ref(new_owner)]")
if(!ismovable(new_owner))
CRASH("Language holder being added to a non-movable thing, this is invalid (was: [new_owner] / [new_owner.type])")
owner = new_owner
// If we have an owner, we'll set a default selected language
if(owner)
get_selected_language()
/datum/language_holder/Destroy()
QDEL_NULL(language_menu)
owner = null
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
/datum/language_holder/proc/grant_language(language, language_flags = ALL, source = LANGUAGE_MIND)
if(language_flags & UNDERSTOOD_LANGUAGE)
LAZYORASSOCLIST(understood_languages, language, source)
. = TRUE
if(spoken)
if(!spoken_languages[language])
spoken_languages[language] = list()
spoken_languages[language] |= source
if(language_flags & SPOKEN_LANGUAGE)
LAZYORASSOCLIST(spoken_languages, language, source)
. = TRUE
return .
/// 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)
/datum/language_holder/proc/grant_all_languages(language_flags = ALL, 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.
grant_language(language, language_flags, 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])
/datum/language_holder/proc/remove_language(language, language_flags = ALL, source = LANGUAGE_ALL)
if(language_flags & UNDERSTOOD_LANGUAGE)
if(source == LANGUAGE_ALL)
understood_languages -= language
LAZYREMOVE(understood_languages, language)
else
understood_languages[language] -= source
if(!length(understood_languages[language]))
understood_languages -= language
LAZYREMOVEASSOC(understood_languages, language, source)
. = TRUE
if(spoken && spoken_languages[language])
if(language_flags & SPOKEN_LANGUAGE)
if(source == LANGUAGE_ALL)
spoken_languages -= language
LAZYREMOVE(spoken_languages, language)
else
spoken_languages[language] -= source
if(!length(spoken_languages[language]))
spoken_languages -= language
LAZYREMOVEASSOC(spoken_languages, language, source)
. = TRUE
return .
/// 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)
remove_language(language, ALL, source)
if(remove_omnitongue)
omnitongue = FALSE
return TRUE
@@ -113,41 +121,41 @@ Key procs
/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
LAZYORASSOCLIST(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
if(source == LANGUAGE_ALL)
LAZYREMOVE(blocked_languages, language)
else
LAZYREMOVEASSOC(blocked_languages, language, source)
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)
/// Checks if you have the language passed.
/datum/language_holder/proc/has_language(language, flag_to_check = UNDERSTOOD_LANGUAGE)
if(language in blocked_languages)
return FALSE
if(spoken)
return language in spoken_languages
return language in understood_languages
var/list/langs_to_check = list()
if(flag_to_check & SPOKEN_LANGUAGE)
langs_to_check |= spoken_languages
if(flag_to_check & UNDERSTOOD_LANGUAGE)
langs_to_check |= understood_languages
return language in langs_to_check
/// 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
var/can_speak_language_path = omnitongue || owner.could_speak_language(language)
return (can_speak_language_path && has_language(language, SPOKEN_LANGUAGE))
/// 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()
@@ -172,59 +180,79 @@ Key procs
/datum/language_holder/proc/get_random_spoken_language()
return pick(spoken_languages)
/// Gets a random spoken language, trying to get a non-common language.
/datum/language_holder/proc/get_random_spoken_uncommon_language()
var/list/languages_minus_common = assoc_to_keys(spoken_languages) - /datum/language/common
// They have a language other than common
if(length(languages_minus_common))
return pick(languages_minus_common)
// They can only speak common, oh well.
else
return /datum/language/common
/// 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.
/datum/language_holder/proc/copy_languages(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)
grant_language(language, UNDERSTOOD_LANGUAGE, source_override)
for(var/language in from_holder.spoken_languages)
grant_language(language, FALSE, TRUE, source_override)
grant_language(language, SPOKEN_LANGUAGE, source_override)
else
for(var/language in from_holder.understood_languages)
grant_language(language, TRUE, FALSE, from_holder.understood_languages[language])
grant_language(language, UNDERSTOOD_LANGUAGE, from_holder.understood_languages[language])
for(var/language in from_holder.spoken_languages)
grant_language(language, FALSE, TRUE, from_holder.spoken_languages[language])
grant_language(language, SPOKEN_LANGUAGE, from_holder.spoken_languages[language])
for(var/language in from_holder.blocked_languages)
add_blocked_language(language, from_holder.blocked_languages[language])
return TRUE
/// Transfers all mind languages to the supplied language holder.
/datum/language_holder/proc/transfer_mind_languages(datum/language_holder/to_holder)
for(var/language in understood_languages)
if(LANGUAGE_MIND in understood_languages[language])
remove_language(language, UNDERSTOOD_LANGUAGE, LANGUAGE_MIND)
to_holder.grant_language(language, UNDERSTOOD_LANGUAGE, LANGUAGE_MIND)
for(var/language in spoken_languages)
if(LANGUAGE_MIND in spoken_languages[language])
remove_language(language, SPOKEN_LANGUAGE, LANGUAGE_MIND)
to_holder.grant_language(language, SPOKEN_LANGUAGE, LANGUAGE_MIND)
for(var/language in blocked_languages)
if(LANGUAGE_MIND in blocked_languages[language])
remove_blocked_language(language, LANGUAGE_MIND)
to_holder.add_blocked_language(language, LANGUAGE_MIND)
//************************************************
//* Specific language holders *
//* Use atom language sources only. *
//************************************************/
if(owner)
get_selected_language()
if(to_holder.owner)
to_holder.get_selected_language()
/// A global assoc list containing prototypes of all language holders
/// [Language holder typepath] to [language holder instance]
/// Used for easy reference of what can speak what without needing to constantly recreate language holders.
GLOBAL_LIST_INIT(prototype_language_holders, init_language_holder_prototypes())
/// Inits the global list of language holder prototypes.
/proc/init_language_holder_prototypes()
var/list/prototypes = list()
for(var/holdertype in typesof(/datum/language_holder))
prototypes[holdertype] = new holdertype()
return prototypes
/*
* Specific language holders presets
*
* Prefer to use [LANGUGAE_ATOM]. Atom languages will stick through species changes but not mindswaps.
*/
/datum/language_holder/alien
@@ -252,6 +280,10 @@ Key procs
/datum/language_holder/drone/syndicate
blocked_languages = null
/datum/language_holder/human_basic
understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM))
spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM))
/datum/language_holder/dwarf
understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/dwarf = list(LANGUAGE_ATOM))
@@ -339,8 +371,12 @@ Key procs
/datum/language/arachnid = list(LANGUAGE_ATOM))
/datum/language_holder/empty
understood_languages = list()
spoken_languages = list()
understood_languages = null
spoken_languages = null
/datum/language_holder/universal
understood_languages = null
spoken_languages = null
/datum/language_holder/universal/New()
..()
+59 -60
View File
@@ -20,109 +20,108 @@
/datum/language_menu/ui_data(mob/user)
var/list/data = list()
var/atom/movable/AM = language_holder.get_atom()
if(isliving(AM))
data["is_living"] = TRUE
else
data["is_living"] = FALSE
var/atom/movable/speaker = language_holder.owner
data["is_living"] = isliving(speaker)
data["languages"] = list()
for(var/lang in GLOB.all_languages)
var/result = language_holder.has_language(lang) || language_holder.has_language(lang, TRUE)
for(var/datum/language/language as anything in GLOB.all_languages)
var/result = language_holder.has_language(language) || language_holder.has_language(language, SPOKEN_LANGUAGE)
if(!result)
continue
var/datum/language/language = lang
var/list/L = list()
var/list/lang_data = list()
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_language(language)
L["can_understand"] = AM.has_language(language)
lang_data["name"] = initial(language.name)
lang_data["desc"] = initial(language.desc)
lang_data["key"] = initial(language.key)
lang_data["is_default"] = (language == language_holder.selected_language)
if(speaker)
lang_data["can_speak"] = speaker.can_speak_language(language)
lang_data["can_understand"] = speaker.has_language(language)
data["languages"] += list(L)
UNTYPED_LIST_ADD(data["languages"], lang_data)
if(check_rights_for(user.client, R_ADMIN) || isobserver(AM))
if(check_rights_for(user.client, R_ADMIN) || isobserver(speaker))
data["admin_mode"] = TRUE
data["omnitongue"] = language_holder.omnitongue
data["unknown_languages"] = list()
for(var/lang in GLOB.all_languages)
if(language_holder.has_language(lang) || language_holder.has_language(lang, TRUE))
for(var/datum/language/language as anything in GLOB.all_languages)
if(language_holder.has_language(language) || language_holder.has_language(language, SPOKEN_LANGUAGE))
continue
var/datum/language/language = lang
var/list/L = list()
var/list/lang_data = list()
L["name"] = initial(language.name)
L["desc"] = initial(language.desc)
L["key"] = initial(language.key)
lang_data["name"] = initial(language.name)
lang_data["desc"] = initial(language.desc)
lang_data["key"] = initial(language.key)
UNTYPED_LIST_ADD(data["unknown_languages"], lang_data)
data["unknown_languages"] += list(L)
return data
/datum/language_menu/ui_act(action, params)
if(..())
. = ..()
if(.)
return
var/mob/user = usr
var/atom/movable/AM = language_holder.get_atom()
var/atom/movable/speaker = language_holder.owner
var/is_admin = check_rights_for(user.client, R_ADMIN)
var/language_name = params["language_name"]
var/datum/language/language_datum
for(var/lang in GLOB.all_languages)
var/datum/language/language = lang
for(var/datum/language/language as anything in GLOB.all_languages)
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_language(language_datum))
if(language_datum && speaker.can_speak_language(language_datum))
language_holder.selected_language = language_datum
. = TRUE
if("grant_language")
if((is_admin || isobserver(AM)) && language_datum)
if((is_admin || isobserver(speaker)) && 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
var/choice = tgui_input_list(user, "How do you want to add this language?", "[language_datum]", choices)
if(isnull(choice))
return
var/adding_flags = NONE
switch(choice)
if("Only Spoken")
spoken = TRUE
adding_flags |= SPOKEN_LANGUAGE
if("Only Understood")
understood = TRUE
adding_flags |= UNDERSTOOD_LANGUAGE
if("Both")
spoken = TRUE
understood = TRUE
language_holder.grant_language(language_datum, understood, spoken)
adding_flags |= ALL
if(LAZYACCESS(language_holder.blocked_languages, language_datum))
choice = tgui_alert(user, "Do you want to lift the blockage that's also preventing the language to be spoken or understood?", "[language_datum]", list("Yes", "No"))
if(choice == "Yes")
language_holder.remove_blocked_language(language_datum, LANGUAGE_ALL)
language_holder.grant_language(language_datum, adding_flags)
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)].")
message_admins("[key_name_admin(user)] granted the [language_name] language to [key_name_admin(speaker)].")
log_admin("[key_name(user)] granted the language [language_name] to [key_name(speaker)].")
. = TRUE
if("remove_language")
if((is_admin || isobserver(AM)) && language_datum)
if((is_admin || isobserver(speaker)) && 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
var/choice = tgui_input_list(user, "Which part do you wish to remove?", "[language_datum]", choices)
if(isnull(choice))
return
var/removing_flags = NONE
switch(choice)
if("Only Spoken")
spoken = TRUE
removing_flags |= SPOKEN_LANGUAGE
if("Only Understood")
understood = TRUE
removing_flags |= UNDERSTOOD_LANGUAGE
if("Both")
spoken = TRUE
understood = TRUE
language_holder.remove_language(language_datum, understood, spoken)
removing_flags |= ALL
language_holder.remove_language(language_datum, removing_flags)
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)].")
message_admins("[key_name_admin(user)] removed the [language_name] language to [key_name_admin(speaker)].")
log_admin("[key_name(user)] removed the language [language_name] to [key_name(speaker)].")
. = TRUE
if("toggle_omnitongue")
if(is_admin || isobserver(AM))
if(is_admin || isobserver(speaker))
language_holder.omnitongue = !language_holder.omnitongue
if(is_admin)
message_admins("[key_name_admin(user)] [language_holder.omnitongue ? "enabled" : "disabled"] the ability to speak all languages (that they know) of [key_name_admin(AM)].")
log_admin("[key_name(user)] [language_holder.omnitongue ? "enabled" : "disabled"] the ability to speak all languages (that_they know) of [key_name(AM)].")
message_admins("[key_name_admin(user)] [language_holder.omnitongue ? "enabled" : "disabled"] the ability to speak all languages (that they know) of [key_name_admin(speaker)].")
log_admin("[key_name(user)] [language_holder.omnitongue ? "enabled" : "disabled"] the ability to speak all languages (that_they know) of [key_name(speaker)].")
. = TRUE
@@ -730,6 +730,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()
user.remove_blocked_language(GLOB.all_languages, source = LANGUAGE_ALL)
new /obj/effect/decal/cleanable/ash(get_turf(user))
qdel(src)
+6 -6
View File
@@ -89,20 +89,20 @@ INITIALIZE_IMMEDIATE(/mob/dead)
if(alert(src, "Jump to server [pick] ([addr])?", "Server Hop", "Yes", "No") != "Yes")
return
var/client/C = client
to_chat(C, "<span class='notice'>Sending you to [pick].</span>")
new /atom/movable/screen/splash(C)
var/client/hopper = client
to_chat(hopper, "<span class='notice'>Sending you to [pick].</span>")
new /atom/movable/screen/splash(null, src, hopper, FALSE)
mob_transforming = TRUE
sleep(29) //let the animation play
sleep(2.9 SECONDS) //let the animation play
mob_transforming = FALSE
if(!C)
if(!hopper)
return
winset(src, null, "command=.options") //other wise the user never knows if byond is downloading resources
C << link("[addr]")
hopper << link("[addr]")
/mob/dead/proc/update_z(new_z) // 1+ to register, null to unregister
if (registered_z != new_z)
@@ -41,7 +41,3 @@
else
postfix = "soon"
to_chat(src, "Please set up your character and select \"Ready\". The game will start [postfix].")
var/datum/hud/new_player/NH = hud_used
if(istype(NH))
NH.populate_buttons(src)
@@ -27,7 +27,7 @@
/mob/dead/new_player/Initialize(mapload)
if(client && SSticker.state == GAME_STATE_STARTUP)
var/atom/movable/screen/splash/S = new(client, TRUE, TRUE)
var/atom/movable/screen/splash/S = new(null, null, client, TRUE)
S.Fade(TRUE)
if(length(GLOB.newplayer_start))
@@ -491,7 +491,7 @@
if(job && !job.override_latejoin_spawn(character))
SSjob.SendToLateJoin(character)
if(!arrivals_docked)
var/atom/movable/screen/splash/Spl = new(character.client, TRUE)
var/atom/movable/screen/splash/Spl = new(null, character, character.client, TRUE)
Spl.Fade(TRUE)
character.playsound_local(get_turf(character), 'GainStation13/sound/voice/Approaching.ogg', 25) //GS13 - "now approaching, general station 13"
+1 -1
View File
@@ -180,5 +180,5 @@
client.view_size.resetToDefault()
var/mob/dead/new_player/M = new /mob/dead/new_player
M.ckey = ckey
M.key = key
return M
-4
View File
@@ -793,10 +793,6 @@
else
hud_used.healths.icon_state = "health7"
/mob/living/carbon/proc/update_internals_hud_icon(internal_state = 0)
if(hud_used && hud_used.internals)
hud_used.internals.icon_state = "internal[internal_state]"
/mob/living/carbon/update_stat()
if(status_flags & GODMODE)
return
@@ -6,6 +6,7 @@
can_buckle = TRUE
buckle_lying = FALSE
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
initial_language_holder = /datum/language_holder/empty // We get stuff from our species
/// Enable stamina combat
combat_flags = COMBAT_FLAGS_STAMINA_COMBAT | COMBAT_FLAG_UNARMED_PARRY
status_flags = CANSTUN|CANKNOCKDOWN|CANUNCONSCIOUS|CANPUSH|CANSTAGGER
@@ -285,12 +285,9 @@ GLOBAL_LIST_INIT(strippable_human_items, create_strippable_list(list(
if(carbon_source.internal)
carbon_source.internal = null
// This isn't meant to be FALSE, it correlates to the icon's name.
carbon_source.update_internals_hud_icon(0)
else if (!QDELETED(item))
if(internals || carbon_source.getorganslot(ORGAN_SLOT_BREATHING_TUBE))
carbon_source.internal = item
carbon_source.update_internals_hud_icon(1)
carbon_source.visible_message(
span_danger("[user] [isnull(carbon_source.internal) ? "closes": "opens"] the valve on [source]'s [item.name]."),
@@ -253,7 +253,6 @@
if((C.flags_inv & (HIDEHAIR|HIDEFACIALHAIR)) || (initial(C.flags_inv) & (HIDEHAIR|HIDEFACIALHAIR)))
update_hair()
if(toggle_off && internal && !getorganslot(ORGAN_SLOT_BREATHING_TUBE))
update_internals_hud_icon(0)
internal = null
if(C.flags_inv & HIDEEYES)
update_inv_glasses()
@@ -86,8 +86,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
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!"
///Affects the speech message, for example: Motharula flutters, "My speech message is flutters!"
var/say_mod = "says"
///What languages this species can understand and say. Use a [language holder datum][/datum/language_holder] in this var.
var/species_language_holder = /datum/language_holder
/// What languages this species can understand and say.
/// Use a [language holder datum][/datum/language_holder] typepath in this var.
/// Should never be null.
var/datum/language_holder/species_language_holder = /datum/language_holder/human_basic
/**
* Visible CURRENT bodyparts that are unique to a species.
* DO NOT USE THIS AS A LIST OF ALL POSSIBLE BODYPARTS AS IT WILL FUCK
@@ -544,6 +546,16 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
for(var/obj/item/bodypart/B in C.bodyparts)
B.change_bodypart_status(BODYPART_HYBRID, FALSE, TRUE) // Makes all Bodyparts 'robotic'.
// All languages associated with this language holder are added with source [LANGUAGE_SPECIES]
// rather than source [LANGUAGE_ATOM], so we can track what to remove if our species changes again
var/datum/language_holder/gaining_holder = GLOB.prototype_language_holders[species_language_holder]
for(var/language in gaining_holder.understood_languages)
C.grant_language(language, UNDERSTOOD_LANGUAGE, LANGUAGE_SPECIES)
for(var/language in gaining_holder.spoken_languages)
C.grant_language(language, SPOKEN_LANGUAGE, LANGUAGE_SPECIES)
for(var/language in gaining_holder.blocked_languages)
C.add_blocked_language(language, LANGUAGE_SPECIES)
SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species)
/datum/species/proc/update_species_slowdown(mob/living/carbon/human/H)
@@ -69,7 +69,6 @@
H.equipOutfit(O, visualsOnly)
H.internal = H.get_item_for_held_index(2)
H.update_internals_hud_icon(1)
return FALSE
/datum/species/plasmaman/random_name(gender,unique,lastname)
@@ -34,11 +34,11 @@
/mob/living/carbon/human/set_drugginess(amount)
..()
if(!amount)
remove_language(/datum/language/beachbum, TRUE, TRUE, LANGUAGE_HIGH)
remove_language(/datum/language/beachbum, source = LANGUAGE_HIGH)
/mob/living/carbon/human/adjust_drugginess(amount)
..()
if(druggy)
grant_language(/datum/language/beachbum, TRUE, TRUE, LANGUAGE_HIGH)
grant_language(/datum/language/beachbum, source = LANGUAGE_HIGH)
else
remove_language(/datum/language/beachbum, TRUE, TRUE, LANGUAGE_HIGH)
remove_language(/datum/language/beachbum, source = LANGUAGE_HIGH)
-3
View File
@@ -329,12 +329,9 @@
if(internal)
if(internal.loc != src)
internal = null
update_internals_hud_icon(0)
else if (!internals && !getorganslot(ORGAN_SLOT_BREATHING_TUBE))
internal = null
update_internals_hud_icon(0)
else
update_internals_hud_icon(1)
. = internal.remove_air_volume(volume_needed)
if(!.)
return FALSE //to differentiate between no internals and active, but empty internals
+1 -4
View File
@@ -187,10 +187,7 @@
else if(eye_blurry) //blurry eyes heal slowly
eye_blurry = max(eye_blurry-1, 0)
if(client)
if(!eye_blurry)
remove_eyeblur()
else
update_eyeblur()
update_eye_blur()
/mob/living/proc/update_damage_hud()
return
-5
View File
@@ -496,8 +496,3 @@ 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(get_minds = TRUE)
if(get_minds && mind)
return mind.get_language_holder()
. = ..()
@@ -139,13 +139,11 @@
var/datum/action/innate/pai/light/AL = new /datum/action/innate/pai/light
var/datum/action/innate/custom_holoform/custom_holoform = new /datum/action/innate/custom_holoform
var/datum/action/language_menu/ALM = new
SW.Grant(src)
AS.Grant(src)
AC.Grant(src)
AR.Grant(src)
AL.Grant(src)
ALM.Grant(src)
custom_holoform.Grant(src)
emitter_next_use = world.time + 10 SECONDS
@@ -268,7 +268,7 @@
encryptmod = TRUE
if("translator")
if(href_list["toggle"]) //This is permanent.
grant_all_languages(TRUE, TRUE, TRUE, LANGUAGE_SOFTWARE)
grant_all_languages(source = LANGUAGE_SOFTWARE)
if("doorjack")
if(href_list["jack"])
if(cable && cable.machine)
@@ -24,9 +24,9 @@
robot_modules_background.layer = HUD_LAYER //Objects that appear on screen are on layer ABOVE_HUD_LAYER, UI should be just below it.
robot_modules_background.plane = HUD_PLANE
inv1 = new /atom/movable/screen/robot/module1()
inv2 = new /atom/movable/screen/robot/module2()
inv3 = new /atom/movable/screen/robot/module3()
inv1 = new /atom/movable/screen/robot/module1(null, src)
inv2 = new /atom/movable/screen/robot/module2(null, src)
inv3 = new /atom/movable/screen/robot/module3(null, src)
ident = rand(1, 999)
+3 -4
View File
@@ -461,7 +461,7 @@
client.prefs.chat_toggles ^= CHAT_OOC
if (!(client.prefs.chat_toggles & CHAT_OOC) && isdead(new_mob))
client.prefs.chat_toggles ^= CHAT_OOC
new_mob.ckey = ckey
new_mob.key = key
if(send_signal)
SEND_SIGNAL(src, COMSIG_MOB_KEY_CHANGE, new_mob, src)
return TRUE
@@ -954,12 +954,11 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
//Do not do parent's actions, as we *usually* do this differently.
fully_replace_character_name(real_name, new_name)
/mob/verb/open_language_menu()
/mob/verb/open_language_menu_verb()
set name = "Open Language Menu"
set category = "IC"
var/datum/language_holder/H = get_language_holder()
H.open_language_menu(usr)
get_language_holder().open_language_menu(usr)
///Adjust the nutrition of a mob
/mob/proc/adjust_nutrition(change, max = INFINITY) //Honestly FUCK the oldcoders for putting nutrition on /mob someone else can move it up because holy hell I'd have to fix SO many typechecks
+10 -24
View File
@@ -66,42 +66,28 @@
/mob/proc/blur_eyes(amount)
if(amount>0)
eye_blurry = max(amount, eye_blurry)
update_eyeblur()
update_eye_blur()
/**
* Adjust the current blurriness of the mobs vision by amount
*/
/mob/proc/adjust_blurriness(amount)
eye_blurry = max(eye_blurry+amount, 0)
update_eyeblur()
update_eye_blur()
///Set the mobs blurriness of vision to an amount
/mob/proc/set_blurriness(amount)
eye_blurry = max(amount, 0)
update_eyeblur()
update_eye_blur()
/mob/proc/update_eyeblur()
remove_eyeblur()
/mob/proc/update_eye_blur()
if(!hud_used)
return
var/atom/movable/plane_master_controller/game_plane_master_controller = hud_used.plane_master_controllers[PLANE_MASTERS_GAME]
if(eye_blurry)
add_eyeblur()
/mob/proc/add_eyeblur()
if(!client)
return
var/list/screens = list(hud_used.plane_masters["[GAME_PLANE]"], hud_used.plane_masters["[FLOOR_PLANE]"],
hud_used.plane_masters["[WALL_PLANE]"], hud_used.plane_masters["[ABOVE_WALL_PLANE]"])
for(var/A in screens)
var/atom/movable/screen/plane_master/P = A
P.add_filter("blurry_eyes", 2, EYE_BLUR(clamp(eye_blurry*0.1,0.6,3)))
/mob/proc/remove_eyeblur()
if(!client)
return
var/list/screens = list(hud_used.plane_masters["[GAME_PLANE]"], hud_used.plane_masters["[FLOOR_PLANE]"],
hud_used.plane_masters["[WALL_PLANE]"], hud_used.plane_masters["[ABOVE_WALL_PLANE]"])
for(var/A in screens)
var/atom/movable/screen/plane_master/P = A
P.remove_filter("blurry_eyes")
game_plane_master_controller.add_filter("eye_blur", 1, gauss_blur_filter(clamp(eye_blurry * 0.1, 0.6, 3)))
else
game_plane_master_controller.remove_filter("eye_blur")
///Adjust the drugginess of a mob
/mob/proc/adjust_drugginess(amount)
-1
View File
@@ -436,7 +436,6 @@
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
@@ -786,26 +786,22 @@
value = REAGENT_VALUE_VERY_RARE
/datum/reagent/toxin/rotatium/on_mob_life(mob/living/carbon/M)
return ..() // until fixed - the rotations never stop
/*
if(M.hud_used)
if(current_cycle >= 20 && current_cycle%20 == 0)
var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"],
M.hud_used.plane_masters["[LIGHTING_PLANE]"], M.hud_used.plane_masters["[WALL_PLANE]"],
M.hud_used.plane_masters["[ABOVE_WALL_PLANE]"])
var/atom/movable/plane_master_controller/pm_controller = M.hud_used.plane_master_controllers[PLANE_MASTERS_GAME]
var/rotation = min(round(current_cycle/20), 89) // By this point the player is probably puking and quitting anyway
for(var/whole_screen in screens)
animate(whole_screen, transform = matrix(rotation, MATRIX_ROTATE), time = 5, easing = QUAD_EASING, loop = -1)
for(var/key in pm_controller.controlled_planes)
animate(pm_controller.controlled_planes[key], transform = matrix(rotation, MATRIX_ROTATE), time = 5, easing = QUAD_EASING, loop = -1)
animate(transform = matrix(-rotation, MATRIX_ROTATE), time = 5, easing = QUAD_EASING)
return ..()
/datum/reagent/toxin/rotatium/on_mob_end_metabolize(mob/living/M)
if(M && M.hud_used)
var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
for(var/whole_screen in screens)
animate(whole_screen, transform = matrix(), time = 5, easing = QUAD_EASING)
if(M?.hud_used)
var/atom/movable/plane_master_controller/pm_controller = M.hud_used.plane_master_controllers[PLANE_MASTERS_GAME]
for(var/key in pm_controller.controlled_planes)
animate(pm_controller.controlled_planes[key], transform = matrix(), time = 5, easing = QUAD_EASING)
..()
*/
/datum/reagent/toxin/skewium
name = "Skewium"
@@ -58,9 +58,9 @@
build_path = /obj/item/construction/rcd
category = list("hacked", "Construction")
/datum/design/rpd_autolathe //ORIGINAL /datum/design/rpd
/datum/design/rpd_autolathe
name = "Rapid Pipe Dispenser (RPD)"
id = "rpd_autolathe" // ORIGINAL id = "rpd"
id = "rpd_autolathe"
build_type = AUTOLATHE | NO_PUBLIC_LATHE
materials = list(/datum/material/iron = 75000, /datum/material/glass = 37500)
build_path = /obj/item/pipe_dispenser
@@ -980,7 +980,6 @@
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)
@@ -159,7 +159,7 @@
to_chat(user, "<span class='boldannounce'>You start skimming through [src], but you already know dronespeak.</span>")
else
to_chat(user, "<span class='boldannounce'>You start skimming through [src], and suddenly the drone chittering makes sense.</span>")
user.grant_language(/datum/language/drone, TRUE, TRUE)//, LANGUAGE_MIND)
user.grant_language(/datum/language/drone, source = LANGUAGE_MIND)
return
if(user.has_language(/datum/language/drone))
@@ -180,7 +180,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='hear'>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], chitters resonate in your mind.</span>", "<span class='hear'>You hear smacking.</span>")
M.grant_language(/datum/language/drone, TRUE, TRUE) //, LANGUAGE_MIND)
M.grant_language(/datum/language/drone, source = LANGUAGE_MIND)
return
/obj/structure/fluff/oldturret
+1
View File
@@ -69,6 +69,7 @@ All ShuttleMove procs go here
/turf/proc/afterShuttleMove(turf/oldT, rotation)
//Dealing with the turf we left behind
oldT.TransferComponents(src)
SEND_SIGNAL(oldT, COMSIG_TURF_AFTER_SHUTTLE_MOVE, src) //Mostly for decals
var/shuttle_boundary = baseturfs.Find(/turf/baseturf_skipover/shuttle)
if(shuttle_boundary)
oldT.ScrapeAway(baseturfs.len - shuttle_boundary + 1)
+2 -2
View File
@@ -14,6 +14,6 @@ GLOBAL_DATUM_INIT(language_menu_state, /datum/ui_state/language_menu, new)
if(check_rights_for(user.client, R_ADMIN))
. = UI_INTERACTIVE
else if(istype(src_object, /datum/language_menu))
var/datum/language_menu/LM = src_object
if(LM.language_holder.get_atom() == user)
var/datum/language_menu/my_languages = src_object
if(my_languages.language_holder.owner == user)
. = UI_INTERACTIVE
+1
View File
@@ -67,6 +67,7 @@
// #include "holidays.dm"
// #include "hydroponics_harvest.dm"
// #include "keybinding_init.dm"
// #include "language_transfer.dm"
#include "machine_disassembly.dm"
#include "medical_wounds.dm"
#include "merge_type.dm"
@@ -0,0 +1,191 @@
// Dedicated to testing language holders
/// Simply tests that swapping to a new species gives you the languages of that species and removes the languages of the old species
/datum/unit_test/language_species_swap_simple
/datum/unit_test/language_species_swap_simple/Run()
var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent)
var/datum/language_holder/holder = dummy.get_language_holder()
var/list/initial_spoken = holder.spoken_languages.Copy()
var/list/initial_understood = holder.understood_languages.Copy()
TEST_ASSERT(length(initial_spoken) == 1, \
"Dummy should only speak one language! Instead, it knew the following: [print_language_list(initial_spoken)]")
TEST_ASSERT(length(initial_understood) == 1, \
"Dummy should only understand one language! Instead, it knew the following: [print_language_list(initial_understood)]")
dummy.set_species(/datum/species/lizard)
TEST_ASSERT(length(holder.spoken_languages) == 2, \
"Dummy should speak two languages - Common and Draconic! Instead, it knew the following: [print_language_list(holder.spoken_languages)]")
TEST_ASSERT(length(holder.understood_languages) == 2, \
"Dummy should understand two languages - Common and Draconic! Instead, it knew the following: [print_language_list(holder.understood_languages)]")
dummy.set_species(/datum/species/human)
TEST_ASSERT(length(initial_spoken & holder.spoken_languages) == 1, \
"Dummy did not speak Common after returning to human! Instead, it knew the following: [print_language_list(holder.spoken_languages)]")
TEST_ASSERT(length(initial_understood & holder.understood_languages) == 1, \
"Dummy did not understand Common after returning to human! Instead, it knew the following: [print_language_list(holder.understood_languages)]")
/// Tests species changes which are more complex are functional (e.g. from a species which speaks common to one which does not)
/datum/unit_test/language_species_swap_complex
/datum/unit_test/language_species_swap_complex/Run()
var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent)
var/datum/language_holder/holder = dummy.get_language_holder()
dummy.set_species(/datum/species/lizard/silverscale)
TEST_ASSERT(!dummy.has_language(/datum/language/common, SPOKEN_LANGUAGE), \
"Changing a mob's species from one which speaks common to one which does not should remove the language!")
TEST_ASSERT(dummy.has_language(/datum/language/common, UNDERSTOOD_LANGUAGE), \
"Changing a mob's species from one which understands common another which does should not remove the language!")
TEST_ASSERT(length(holder.spoken_languages) == 2, \
"Dummy should speak two languages - Uncommon and Draconic! Instead, it knew the following: [print_language_list(holder.spoken_languages)]")
TEST_ASSERT(length(holder.understood_languages) == 3, \
"Dummy should understand two languages - Common, Uncommon and Draconic! Instead, it knew the following: [print_language_list(holder.understood_languages)]")
/// Test that other random languages known are not lost on species change
/datum/unit_test/language_species_change_other_known
/datum/unit_test/language_species_change_other_known/Run()
var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent)
dummy.grant_language(/datum/language/piratespeak, source = LANGUAGE_MIND)
dummy.grant_language(/datum/language/draconic, source = LANGUAGE_ATOM)
dummy.set_species(/datum/species/lizard)
TEST_ASSERT(dummy.has_language(/datum/language/piratespeak, SPOKEN_LANGUAGE), \
"Dummy should still speak Pirate after changing species, as it's a mind language!")
TEST_ASSERT(dummy.has_language(/datum/language/piratespeak, UNDERSTOOD_LANGUAGE), \
"Dummy should still understand Pirate after changing species, as it's a mind language!")
dummy.set_species(/datum/species/human)
TEST_ASSERT(dummy.has_language(/datum/language/draconic, SPOKEN_LANGUAGE), \
"Dummy should still speak Draconic after changing species, as it's an atom language!")
TEST_ASSERT(dummy.has_language(/datum/language/draconic, UNDERSTOOD_LANGUAGE), \
"Dummy should still understand Draconic after changing species, as it's an atom language!")
/// Tests that mind bound languages are not lost swapping into a new mob, but other languages are
/datum/unit_test/language_mind_transfer
/datum/unit_test/language_mind_transfer/Run()
var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent)
var/mob/living/basic/pet/dog/corgi/transfer_target = allocate(/mob/living/basic/pet/dog/corgi)
dummy.mind_initialize()
dummy.grant_language(/datum/language/piratespeak, source = LANGUAGE_MIND)
dummy.grant_language(/datum/language/draconic, source = LANGUAGE_ATOM)
dummy.set_species(/datum/species/lizard/silverscale)
dummy.mind.transfer_to(transfer_target)
// transfer_target should speak and understand pirate
TEST_ASSERT(!dummy.has_language(/datum/language/piratespeak, SPOKEN_LANGUAGE), \
"Dummy should no longer be speaking Pirate after losing their mind!")
TEST_ASSERT(transfer_target.has_language(/datum/language/piratespeak, SPOKEN_LANGUAGE), \
"Dummy's new mob should be capable of speaking Pirate!")
TEST_ASSERT(!dummy.has_language(/datum/language/piratespeak, UNDERSTOOD_LANGUAGE), \
"Dummy should no longer be understanding Pirate after losing their mind!")
TEST_ASSERT(transfer_target.has_language(/datum/language/piratespeak, UNDERSTOOD_LANGUAGE), \
"Dummy's new mob should be capable of understanding Pirate!")
// transfer_target should NOT speak and understand draconic
TEST_ASSERT(dummy.has_language(/datum/language/draconic, SPOKEN_LANGUAGE), \
"Dummy should still understand Draconic after losing their mind - it's an atom language!")
TEST_ASSERT(!transfer_target.has_language(/datum/language/draconic, SPOKEN_LANGUAGE), \
"Dummy's new mob should not understand Draconic - it's an atom language!")
TEST_ASSERT(dummy.has_language(/datum/language/draconic, UNDERSTOOD_LANGUAGE), \
"Dummy should still understand Draconic after losing their mind - it's an atom language!")
TEST_ASSERT(!transfer_target.has_language(/datum/language/draconic, UNDERSTOOD_LANGUAGE), \
"Dummy's new mob should not understand Draconic - it's an atom language!")
// transfer_target should NOT speak and understand uncommon
TEST_ASSERT(dummy.has_language(/datum/language/uncommon, SPOKEN_LANGUAGE), \
"Dummy should still understand Uncommon after losing their mind - it's a species language!")
TEST_ASSERT(!transfer_target.has_language(/datum/language/uncommon, SPOKEN_LANGUAGE), \
"Dummy's new mob should not understand Uncommon - it's a species language!")
TEST_ASSERT(dummy.has_language(/datum/language/uncommon, UNDERSTOOD_LANGUAGE), \
"Dummy should still understand Uncommon after losing their mind - it's a species language!")
TEST_ASSERT(!transfer_target.has_language(/datum/language/uncommon, UNDERSTOOD_LANGUAGE), \
"Dummy's new mob should not understand Uncommon - it's a species language!")
/// Tests that mind bound languages are not lost when swapping with another person (wiz mindswap)
/datum/unit_test/language_mind_swap
/datum/unit_test/language_mind_swap/Run()
var/mob/living/carbon/human/dummy_A = allocate(/mob/living/carbon/human/consistent)
var/mob/living/carbon/human/dummy_B = allocate(/mob/living/carbon/human/consistent)
dummy_A.mind_initialize()
dummy_B.mind_initialize()
var/datum/mind/dummy_A_mind = dummy_A.mind
var/datum/mind/dummy_B_mind = dummy_B.mind
dummy_A.set_species(/datum/species/lizard)
dummy_B.grant_language(/datum/language/piratespeak, source = LANGUAGE_MIND)
dummy_A_mind.transfer_to(dummy_B)
dummy_B_mind.transfer_to(dummy_A)
var/datum/language_holder/holder_A = dummy_A.get_language_holder()
var/datum/language_holder/holder_B = dummy_B.get_language_holder()
// Holder A is a lizard: starts with 2 languages (common, draconic)
// Holder B is a human with a mind language: starts with 2 language (common, pirate)
// Swap occurs
// Holder A is a lizard with 2 languages, but should now also have pirate: 3 languages (common, draconic, pirate)
// Holder B is a human with just 1 language left over (common)
TEST_ASSERT_EQUAL(length(holder_A.spoken_languages), 3, \
"Holder A / Dummy A / Dummy B mind should speak Common, Draconic, and Pirate! \
Instead, it knew the following: [print_language_list(holder_A.spoken_languages)]")
TEST_ASSERT_EQUAL(length(holder_A.understood_languages), 3, \
"Holder A / Dummy A / Dummy B mind should only understand Common, Draconic, and Pirate! \
Instead, it knew the following: [print_language_list(holder_A.understood_languages)]")
TEST_ASSERT_EQUAL(length(holder_B.spoken_languages), 1, \
"Holder B / Dummy B / Dummy A mind should only speak 1 language - Common! \
Instead, it knew the following: [print_language_list(holder_B.spoken_languages)]")
TEST_ASSERT_EQUAL(length(holder_B.understood_languages), 1, \
"Holder B / Dummy B / Dummy A mind only understand 1 language - Common! \
Instead, it knew the following: [print_language_list(holder_B.understood_languages)]")
/// Tests that the book of babel, and by extension grant_all_languages, works as intended
/datum/unit_test/book_of_babel
/datum/unit_test/book_of_babel/Run()
var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent)
var/obj/item/book_of_babel/book = allocate(/obj/item/book_of_babel)
var/datum/language_holder/holder = dummy.get_language_holder()
var/expected_amount = length(GLOB.all_languages)
book.attack_self(dummy)
TEST_ASSERT_EQUAL(length(holder.spoken_languages), expected_amount, "Book of Babel failed to give all languages out!")
dummy.set_species(/datum/species/lizard)
TEST_ASSERT_EQUAL(length(holder.spoken_languages), expected_amount, "Changing species after using the Book of Bable should not remove languages!")
/// Helper proc to print a list of languages in a human readable format
/proc/print_language_list(list/languages_to_print)
var/list/printed_languages = list()
for(var/datum/language/language as anything in languages_to_print)
printed_languages += initial(language.name)
return english_list(printed_languages)
+3
View File
@@ -100,6 +100,9 @@
if(iscarbon(prey) && prey.fatness_real)
var/fatness_to_add = (prey.fatness_real * 0.80)
gainer.adjust_fatness(fatness_to_add, FATTENING_TYPE_FOOD)
gainer.human_prey_digested += 1
gainer.prey_digested += 1
//GS13 edit end
//Send messages