mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-06-04 21:56:01 +01:00
8c1e35e1c0
## About The Pull Request This PR refactors mind language holders into non-existence As a result, `update_atom_languages` is no longer necessary Mind-bound languages are transferred via `/mind/proc/transfer_to` Species changing no longer deletes and re-creates the mob's language holder, allowing them to keep any languages they have. Species languages are sourced from `LANGUAGE_SPECIES` now, meaning they are removed when they change species. If the mob is not a human with a species datum, these are effectively just atom level languages. Makes a bunch of unit tests to ensure language transfer over certain events works as intended ## Why It's Good For The Game Mobs with minds having two independent language holders results in a good few bugs, and simply doesn't make sense when we have sources (`LANGUAGE_MIND`). Instead of tracking two language holders, we can simply use sources better and only track one. This means that the language holder you start with is your language holder, period. It doesn't get deleted or re-instantiated or whatever. ## Changelog 🆑 Melbert refactor: Refactored language holders, making species changes not delete all of your known languages /🆑
115 lines
4.5 KiB
Plaintext
115 lines
4.5 KiB
Plaintext
/obj/item/language_manual
|
|
icon = 'icons/obj/library.dmi'
|
|
icon_state = "book2"
|
|
/// Number of charges the book has, limits the number of times it can be used.
|
|
var/charges = 1
|
|
/// Path to a language datum that the book teaches.
|
|
var/datum/language/language = /datum/language/common
|
|
/// Flavour text to display when the language is successfully learned.
|
|
var/flavour_text = "suddenly your mind is filled with codewords and responses"
|
|
|
|
/obj/item/language_manual/attack_self(mob/living/user)
|
|
if(!isliving(user))
|
|
return
|
|
|
|
if(user.has_language(language))
|
|
to_chat(user, span_boldwarning("You start skimming through [src], but you already know [initial(language.name)]."))
|
|
return
|
|
|
|
to_chat(user, span_boldannounce("You start skimming through [src], and [flavour_text]."))
|
|
|
|
user.grant_language(language)
|
|
user.remove_blocked_language(language, source=LANGUAGE_ALL)
|
|
ADD_TRAIT(user.mind, TRAIT_TOWER_OF_BABEL, MAGIC_TRAIT) // this makes you immune to babel effects
|
|
|
|
use_charge(user)
|
|
|
|
/obj/item/language_manual/attack(mob/living/M, mob/living/user)
|
|
if(!istype(M) || !istype(user))
|
|
return
|
|
if(M == user)
|
|
attack_self(user)
|
|
return
|
|
|
|
playsound(loc, SFX_PUNCH, 25, TRUE, -1)
|
|
|
|
if(M.stat == DEAD)
|
|
M.visible_message(span_danger("[user] smacks [M]'s lifeless corpse with [src]."), span_userdanger("[user] smacks your lifeless corpse with [src]."), span_hear("You hear smacking."))
|
|
else if(M.has_language(language))
|
|
M.visible_message(span_danger("[user] beats [M] over the head with [src]!"), span_userdanger("[user] beats you over the head with [src]!"), span_hear("You hear smacking."))
|
|
else
|
|
M.visible_message(span_notice("[user] teaches [M] by beating [M.p_them()] over the head with [src]!"), span_boldnotice("As [user] hits you with [src], [flavour_text]."), span_hear("You hear smacking."))
|
|
M.grant_language(language, source = LANGUAGE_MIND)
|
|
use_charge(user)
|
|
|
|
/obj/item/language_manual/proc/use_charge(mob/user)
|
|
charges--
|
|
if(!charges)
|
|
var/turf/T = get_turf(src)
|
|
T.visible_message(span_warning("The cover and contents of [src] start shifting and changing! It slips out of your hands!"))
|
|
|
|
new /obj/item/book/manual/random(T)
|
|
qdel(src)
|
|
|
|
/obj/item/language_manual/codespeak_manual
|
|
name = "codespeak manual"
|
|
desc = "The book's cover reads: \"Codespeak(tm) - Secure your communication with metaphors so elaborate, they seem randomly generated!\""
|
|
language = /datum/language/codespeak
|
|
flavour_text = "suddenly your mind is filled with codewords and responses"
|
|
|
|
/obj/item/language_manual/codespeak_manual/unlimited
|
|
name = "deluxe codespeak manual"
|
|
charges = INFINITY
|
|
|
|
/obj/item/language_manual/roundstart_species
|
|
|
|
/obj/item/language_manual/roundstart_species/Initialize(mapload)
|
|
. = ..()
|
|
language = pick( \
|
|
/datum/language/voltaic, \
|
|
/datum/language/nekomimetic, \
|
|
/datum/language/draconic, \
|
|
/datum/language/moffic, \
|
|
/datum/language/calcic \
|
|
)
|
|
name = "[initial(language.name)] manual"
|
|
desc = "The book's cover reads: \"[initial(language.name)] for Xenos - Learn common galactic tongues in seconds.\""
|
|
flavour_text = "you feel empowered with a mastery over [initial(language.name)]"
|
|
|
|
/obj/item/language_manual/roundstart_species/unlimited
|
|
charges = INFINITY
|
|
|
|
/obj/item/language_manual/roundstart_species/unlimited/Initialize(mapload)
|
|
. = ..()
|
|
name = "deluxe [initial(language.name)] manual"
|
|
|
|
/obj/item/language_manual/roundstart_species/five
|
|
charges = 5
|
|
|
|
/obj/item/language_manual/roundstart_species/five/Initialize(mapload)
|
|
. = ..()
|
|
name = "extended [initial(language.name)] manual"
|
|
|
|
// So drones can teach borgs and AI dronespeak. For best effect, combine with mother drone lawset.
|
|
/obj/item/language_manual/dronespeak_manual
|
|
name = "dronespeak manual"
|
|
desc = "The book's cover reads: \"Understanding Dronespeak - An exercise in futility.\" The book is written entirely in binary, non-silicons probably won't understand it."
|
|
language = /datum/language/drone
|
|
flavour_text = "suddenly the drone chittering makes sense"
|
|
charges = INFINITY
|
|
|
|
/obj/item/language_manual/dronespeak_manual/attack(mob/living/M, mob/living/user)
|
|
// If they are not drone or silicon, we don't want them to learn this language.
|
|
if(!(isdrone(M) || issilicon(M)))
|
|
M.visible_message(span_danger("[user] beats [M] over the head with [src]!"), span_userdanger("[user] beats you over the head with [src]!"), span_hear("You hear smacking."))
|
|
return
|
|
|
|
return ..()
|
|
|
|
/obj/item/language_manual/dronespeak_manual/attack_self(mob/living/user)
|
|
if(!(isdrone(user) || issilicon(user)))
|
|
to_chat(user, span_danger("You beat yourself over the head with [src]!"))
|
|
return
|
|
|
|
return ..()
|