diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 65a3903b03f..8a7b9e65910 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -52,6 +52,10 @@
#define isitem(A) (istype(A, /obj/item))
+#define isIdCard(A) (istype(A, /obj/item/card/id))
+
+#define isWallet(A) (istype(A, /obj/item/storage/wallet))
+
#define isstack(A) (istype(A, /obj/item/stack))
#define isstorage(A) (istype(A, /obj/item/storage))
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index ccb7c665b23..bbdfc97f573 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -146,11 +146,13 @@ GLOBAL_VAR_INIT(record_id_num, 1001)
var/id = num2hex(GLOB.record_id_num++, 6)
+ //При создании рекордсов еще берется и голос, боже помилуй чтобы это ничего не сломало
//General Record
var/datum/data/record/G = new()
G.fields["id"] = id
G.fields["name"] = H.real_name
G.fields["real_rank"] = H.mind.assigned_role
+ G.fields["voice"] = H.GetVoice()
G.fields["rank"] = assignment
G.fields["age"] = H.age
G.fields["fingerprint"] = md5(H.dna.uni_identity)
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index a6de1c0034c..98339829044 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -36,7 +36,7 @@
var/assigned_role //assigned role is what job you're assigned to when you join the station.
var/playtime_role //if set, overrides your assigned_role for the purpose of playtime awards. Set by IDcomputer when your ID is changed.
- var/special_role //special roles are typically reserved for antags or roles like ERT. If you want to avoid a character being automatically announced by the AI, on arrival (becuase they're an off station character or something); ensure that special_role and assigned_role are equal.
+ var/special_role //special roles are typically reserved for antags or roles like ERP. If you want to avoid a character being automatically announced by the AI, on arrival (becuase they're an off station character or something); ensure that special_role and assigned_role are equal.
var/offstation_role = FALSE //set to true for ERT, deathsquad, abductors, etc, that can go from and to z2 at will and shouldn't be antag targets
var/list/restricted_roles = list()
diff --git a/code/datums/voice.dm b/code/datums/voice.dm
new file mode 100644
index 00000000000..2a3648f87db
--- /dev/null
+++ b/code/datums/voice.dm
@@ -0,0 +1,120 @@
+#define GENDER_NAME_UNKNOW list(MALE = "Незнакомец", FEMALE = "Незнакомка", NEUTER = "Неизвестный", PLURAL = "Неизвестный")
+
+//Новая система голоса
+/datum/voice_model
+ var/tts_seed_string = "Arthas"
+ var/voice_gender = MALE
+ var/voice_name = "Неизвестный"
+ var/real_voice_name = "Неизвестный"
+
+ var/list/famous_voices = list()
+ //var/list/famous_faces = list()
+
+/datum/voice_model/proc/CreateVoiceModel(var/atom/owner_voice)
+ var/datum/voice_model/result = new()
+
+ result.real_voice_name = owner_voice.GetVoice()
+ result.voice_name = owner_voice.GetVoice()
+ result.voice_gender = owner_voice.gender
+ result.famous_voices[voice_name] = owner_voice.name
+ result.tts_seed_string = owner_voice.tts_seed
+
+ return result
+
+/datum/voice_model/proc/VoiceUpdate(var/atom/owner_voice)
+ voice_name = owner_voice.GetVoice() //:badguy:
+
+/datum/voice_model/proc/get_gender_unknown_name(gender_string)
+ var/result = (GENDER_NAME_UNKNOW)?[gender_string]
+ if(result)
+ return result
+ return "Неизвестный"
+
+/datum/voice_model/proc/CopyInVoice(datum/voice_model/voice_to_copy)
+ tts_seed_string = voice_to_copy.tts_seed_string
+ voice_gender = voice_to_copy.voice_gender
+ voice_name = voice_to_copy.voice_name
+
+/datum/voice_model/proc/FullCopyInVoice(datum/voice_model/voice_to_copy)
+ CopyInVoice(voice_to_copy)
+ real_voice_name = voice_to_copy.real_voice_name
+ famous_voices = voice_to_copy.famous_voices
+
+//было две бутылки, словарь или два прока. Я сел на вторую
+/datum/voice_model/proc/GetManifestKnowVoice()
+ for(var/datum/data/record/t in GLOB.data_core.general)
+ if(t)
+ if(t.fields["voice"] == voice_name)
+ return t.fields["name"]
+ return "IDENTIFICATION VOICE ERROR"
+//Технически name это представление твоего ебала
+/* BYOND...
+/datum/voice_model/proc/GetManifestKnowFace(mob/face_target)
+ for(var/datum/data/record/t in GLOB.data_core.general)
+ if(t)
+ if(t.fields["name"] == face_target.name)
+ return t.fields["name"]
+ return "IDENTIFICATION FACE ERROR"
+*/
+
+/datum/voice_model/proc/TryStore(mob/target)
+ if(src == target.adv_voice)
+ return TRUE
+ . = FALSE
+ if(!ishuman(target)) //Нахуя мне знать как зовут мышей :badguy:
+ return target.name
+ var/mob/living/carbon/human/target_H = target
+ var/obj/item/card/id/prov_wear_id = null
+
+ if(isIdCard(target_H.wear_id)) //Fuck
+ prov_wear_id = target_H.wear_id
+ if(isWallet(target_H.wear_id)) //Мфпмфпф
+ var/obj/item/storage/wallet/prom = target_H.wear_id
+ prov_wear_id = prom.front_id
+
+ if(!((target_H.wear_mask?.flags_inv & HIDENAME) || (target_H.head?.flags_inv & HIDENAME)) && prov_wear_id)
+
+ //famous_faces[target_H.name] = prov_wear_id.registered_name //FUCK BYOND
+ famous_voices[target_H.adv_voice.voice_name] = prov_wear_id.registered_name
+ . = TRUE
+ else if(prov_wear_id)
+ famous_voices[target_H.adv_voice.voice_name] = prov_wear_id.registered_name
+ . = TRUE
+ return
+
+//For examie
+/* FUCKING BYOND
+/datum/voice_model/proc/TryRecollectFace(mob/target)
+ if(src == target.adv_voice)
+ return target.name
+ if(!ishuman(target)) //:Roflcat: Чтобы имена мышей знать сразу
+ return target.name
+ var/mob/living/carbon/human/target_H = target
+
+ if(!((target_H.wear_mask?.flags_inv & HIDENAME) || (target_H.head?.flags_inv & HIDENAME)))
+ . = famous_faces?[target_H.name]
+
+ if(.)
+ return
+
+ if((target_H.wear_suit?.flags_inv & HIDEJUMPSUIT) && (target_H.head?.flags_inv & HIDENAME))
+ . = get_gender_unknown_name(NEUTER)
+ else
+ . = get_gender_unknown_name(target_H.gender)
+ return
+*/
+//For hear
+/datum/voice_model/proc/TryRecollectVoice(mob/target)
+ if(src == target.adv_voice)
+ return target.adv_voice.voice_name
+ if(!ishuman(target))
+ return target.adv_voice.voice_name
+ var/mob/living/carbon/human/target_H = target
+
+ . = famous_voices?[target_H.name]
+ if(.)
+ return
+
+ return get_gender_unknown_name(target_H.adv_voice.voice_gender)
+
+#undef GENDER_NAME_UNKNOW
diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm
index 9afe767d2e9..be55ac09005 100644
--- a/code/modules/mob/hear_say.dm
+++ b/code/modules/mob/hear_say.dm
@@ -138,7 +138,7 @@
if(italics)
message = "[message]"
-
+ speaker_name = adv_voice.TryRecollectVoice(speaker)
var/track = null
if(isobserver(src))
if(speaker_name != speaker.real_name && speaker.real_name)
@@ -245,17 +245,15 @@
INVOKE_ASYNC(GLOBAL_PROC, /proc/tts_cast, src, src, message_tts, speaker.tts_seed, FALSE, effect, null, null, 'sound/effects/radio_chatter.ogg')
/mob/proc/handle_speaker_name(mob/speaker = null, vname, hard_to_hear)
- var/speaker_name = "unknown"
- if(speaker)
- speaker_name = speaker.name
-
- if(vname)
- speaker_name = vname
-
+ var/speaker_name = "Неизвестный"
if(hard_to_hear)
- speaker_name = "unknown"
+ return speaker_name
+ if(!(speaker))
+ return vname
+ if(!ishuman(speaker))
+ return speaker.adv_voice.voice_name
- return speaker_name
+ return adv_voice.TryRecollectVoice(speaker)
/mob/proc/handle_track(message, verb = "says", mob/speaker = null, speaker_name, atom/follow_target, hard_to_hear)
return
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 6152cecfe17..5065f44e66b 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -29,7 +29,8 @@
skipears |= wear_mask.flags_inv & HIDEHEADSETS
var/msg = "This is "
-
+ if(!user.adv_voice.TryStore(src))
+ to_chat(user, "Кажется вам не за что зацепится взглядом...")
if(!(skipjumpsuit && skipface) && icon) //big suits/masks/helmets make it hard to tell their gender
msg += "[bicon(icon(icon, dir=SOUTH))] " //fucking BYOND: this should stop dreamseeker crashing if we -somehow- examine somebody before their icon is generated
msg += "[name]"
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 63f34de85cc..5120eeb3125 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1,3 +1,6 @@
+#define ASK_VERB "!"
+#define
+
/mob/living/carbon/human/Initialize(mapload, datum/species/new_species = /datum/species/human)
icon = null // This is now handled by overlays -- we just keep an icon for the sake of the map editor.
create_dna()
@@ -391,9 +394,9 @@
if(name_override)
return name_override
if(wear_mask && (wear_mask.flags_inv & HIDENAME)) //Wearing a mask which hides our face, use id-name if possible
- return get_id_name("Unknown")
+ return get_id_name(adv_voice.get_gender_unknown_name(gender))
if(head && (head.flags_inv & HIDENAME))
- return get_id_name("Unknown") //Likewise for hats
+ return get_id_name(adv_voice.get_gender_unknown_name(gender)) //Likewise for hats
var/face_name = get_face_name()
var/id_name = get_id_name("")
if(add_id_name && id_name && (id_name != face_name))
@@ -404,7 +407,7 @@
/mob/living/carbon/human/proc/get_face_name()
var/obj/item/organ/external/head_organ = get_organ(BODY_ZONE_HEAD)
if(!head_organ || head_organ.is_disfigured() || cloneloss > 50 || !real_name || HAS_TRAIT(src, TRAIT_HUSK)) //disfigured. use id-name if possible
- return "Unknown"
+ return adv_voice.get_gender_unknown_name(gender)
return real_name
@@ -413,6 +416,7 @@
* Useful when player is being seen by other mobs.
*/
/mob/living/carbon/human/proc/get_id_name(if_no_id = "Unknown")
+ if_no_id = adv_voice.get_gender_unknown_name(gender)
var/obj/item/card/id/id = wear_id?.GetID()
if(istype(id))
return id.registered_name
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 3f08ff83a94..66770ca55e7 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -11,8 +11,9 @@
life_tick++
- voice = GetVoice()
- tts_seed = GetTTSVoice()
+ //Теперь это этажом ниже
+ //voice = GetVoice()
+ //tts_seed = GetTTSVoice()
if(.) //not dead
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 3d8ab5a1387..4c8fcea0edd 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -1,6 +1,12 @@
/mob/living/carbon/Life(seconds, times_fired)
set invisibility = 0
+ //:roflcat:
+ adv_voice.voice_gender = gender
+ adv_voice.voice_name = GetVoice()
+ adv_voice.tts_seed_string = GetTTSVoice()
+ tts_seed = adv_voice.tts_seed_string
+ voice_name = adv_voice.voice_name
if(HAS_TRAIT(src, TRAIT_NO_TRANSFORM))
return
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 06714b5a316..dfee50ffa16 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -59,6 +59,9 @@
/mob/living/silicon/med_hud_set_status()
return diag_hud_set_status() //we use a different hud
+/mob/living/silicon/handle_speaker_name(mob/speaker = null, vname, hard_to_hear)
+ return speaker.adv_voice.GetManifestKnowVoice()
+
/mob/living/silicon/Destroy()
UnregisterSignal(SSalarm, list(
COMSIG_TRIGGERED_ALARM,
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index d1020156e82..b2da523bce1 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -26,6 +26,13 @@
/mob/Initialize(mapload)
GLOB.mob_list += src
+
+ adv_voice = new /datum/voice_model()
+ adv_voice.real_voice_name = name
+ adv_voice.tts_seed_string = GetTTSVoice()
+ adv_voice.voice_gender = gender
+ adv_voice.voice_name = GetVoice()
+
if(stat == DEAD)
GLOB.dead_mob_list += src
else
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index a76ad7796fa..e817066d7cf 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -154,7 +154,9 @@
//see: setup.dm for list of mutations
+ var/liberated_name = "Неизвестный" //Долой гнет бульена!!
var/voice_name = "неизвестный голос"
+ var/datum/voice_model/adv_voice = null
var/list/faction = list("neutral") //Used for checking whether hostile simple animals will attack you, possibly more stuff later
diff --git a/paradise.dme b/paradise.dme
index 30b22704ec1..9306314b226 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -39,7 +39,6 @@
#include "code\__DEFINES\blob.dm"
#include "code\__DEFINES\borer.dm"
#include "code\__DEFINES\bots.dm"
-#include "code\__DEFINES\rituals.dm"
#include "code\__DEFINES\byond_tracy.dm"
#include "code\__DEFINES\callbacks.dm"
#include "code\__DEFINES\cargo_quests.dm"
@@ -115,6 +114,7 @@
#include "code\__DEFINES\RCD.dm"
#include "code\__DEFINES\reagents.dm"
#include "code\__DEFINES\request.dm"
+#include "code\__DEFINES\rituals.dm"
#include "code\__DEFINES\role_preferences.dm"
#include "code\__DEFINES\rolebans.dm"
#include "code\__DEFINES\rust_g.dm"
@@ -368,7 +368,6 @@
#include "code\controllers\subsystem\tickets\mentor_tickets.dm"
#include "code\controllers\subsystem\tickets\tickets.dm"
#include "code\datums\action.dm"
-#include "code\datums\rituals.dm"
#include "code\datums\ai_law_sets.dm"
#include "code\datums\ai_laws.dm"
#include "code\datums\armor.dm"
@@ -404,6 +403,7 @@
#include "code\datums\radio.dm"
#include "code\datums\recipe.dm"
#include "code\datums\revision.dm"
+#include "code\datums\rituals.dm"
#include "code\datums\ruins.dm"
#include "code\datums\shuttles.dm"
#include "code\datums\snake_fashion.dm"
@@ -416,6 +416,7 @@
#include "code\datums\uplink_item.dm"
#include "code\datums\verb_callback.dm"
#include "code\datums\vision_override.dm"
+#include "code\datums\voice.dm"
#include "code\datums\weakrefs.dm"
#include "code\datums\cache\air_alarm.dm"
#include "code\datums\cache\apc.dm"
@@ -446,7 +447,6 @@
#include "code\datums\components\conveyor_movement.dm"
#include "code\datums\components\cross_shock.dm"
#include "code\datums\components\decal.dm"
-#include "code\datums\components\ritual_object.dm"
#include "code\datums\components\defibrillator.dm"
#include "code\datums\components\drift.dm"
#include "code\datums\components\ducttape.dm"
@@ -465,6 +465,7 @@
#include "code\datums\components\persistent_overlay.dm"
#include "code\datums\components\proximity_monitor.dm"
#include "code\datums\components\radioactivity.dm"
+#include "code\datums\components\ritual_object.dm"
#include "code\datums\components\shielded.dm"
#include "code\datums\components\slippery.dm"
#include "code\datums\components\spawner.dm"
@@ -3140,7 +3141,6 @@
#include "code\modules\tgui\plugins\modal.dm"
#include "code\modules\tgui\states\admin.dm"
#include "code\modules\tgui\states\always.dm"
-#include "code\modules\tgui\states\range.dm"
#include "code\modules\tgui\states\conscious.dm"
#include "code\modules\tgui\states\contained.dm"
#include "code\modules\tgui\states\deep_inventory.dm"
@@ -3152,6 +3152,7 @@
#include "code\modules\tgui\states\notcontained.dm"
#include "code\modules\tgui\states\observer.dm"
#include "code\modules\tgui\states\physical.dm"
+#include "code\modules\tgui\states\range.dm"
#include "code\modules\tgui\states\self.dm"
#include "code\modules\tgui\states\strippable_state.dm"
#include "code\modules\tgui\states\zlevel.dm"