mirror of
https://github.com/evilew/GS13-Citadel.git
synced 2026-08-24 21:58:09 +01:00
Merge branch 'master' of https://github.com/Hekto61/GS13-Citadel
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user