mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'juliancoffee/i18n-gender-chat' into 'master'
First step to enabling grammatical genders See merge request veloren/veloren!4301
This commit is contained in:
commit
a2d52d09fc
@ -1,7 +1,29 @@
|
||||
## Player events
|
||||
## Player events, $user_gender should be available
|
||||
|
||||
hud-chat-online_msg = [{ $name }] is online now
|
||||
hud-chat-offline_msg = [{ $name }] went offline
|
||||
## Buff deaths
|
||||
hud-chat-goodbye = Goodbye!
|
||||
hud-chat-connection_lost = Connection lost. Kicking in { $time } seconds.
|
||||
|
||||
## Player /tell messages, $user_gender should be available
|
||||
|
||||
hud-chat-tell-to = To [{ $alias }]: { $msg }
|
||||
hud-chat-tell-from = From [{ $alias }]: { $msg }
|
||||
|
||||
# Npc /tell messages, no gender info, sadly
|
||||
|
||||
hud-chat-tell-to-npc = To [{ $alias }]: { $msg }
|
||||
hud-chat-tell-from-npc = From [{ $alias }]: { $msg }
|
||||
|
||||
# Generic messages
|
||||
|
||||
hud-chat-message = [{ $alias }]: { $msg }
|
||||
hud-chat-message-with-name = [{ $alias }] { $name }: { $msg }
|
||||
hud-chat-message-in-group = ({ $group }) [{ $alias }]: { $msg }
|
||||
hud-chat-message-with-name-in-group = ({ $group }) [{ $alias }] { $name }: { $msg }
|
||||
|
||||
## PvP Buff deaths, both $attacker_gender and $victim_gender are available
|
||||
|
||||
hud-chat-died_of_pvp_buff_msg =
|
||||
.burning = [{ $victim }] died of: burning caused by [{ $attacker }]
|
||||
.bleeding = [{ $victim }] died of: bleeding caused by [{ $attacker }]
|
||||
@ -9,13 +31,9 @@ hud-chat-died_of_pvp_buff_msg =
|
||||
.crippled = [{ $victim }] died of: crippled caused by [{ $attacker }]
|
||||
.frozen = [{ $victim }] died of: frozen caused by [{ $attacker }]
|
||||
.mysterious = [{ $victim }] died of: secret caused by [{ $attacker }]
|
||||
hud-chat-died_of_buff_nonexistent_msg =
|
||||
.burning = [{ $victim }] died of: burning
|
||||
.bleeding = [{ $victim }] died of: bleeding
|
||||
.curse = [{ $victim }] died of: curse
|
||||
.crippled = [{ $victim }] died of: crippled
|
||||
.frozen = [{ $victim }] died of: frozen
|
||||
.mysterious = [{ $victim }] died of: secret
|
||||
|
||||
## PvE Buff deaths, only $victim_gender is available
|
||||
|
||||
hud-chat-died_of_npc_buff_msg =
|
||||
.burning = [{ $victim }] died of: burning caused by { $attacker }
|
||||
.bleeding = [{ $victim }] died of: bleeding caused by { $attacker }
|
||||
@ -23,31 +41,47 @@ hud-chat-died_of_npc_buff_msg =
|
||||
.crippled = [{ $victim }] died of: crippled caused by { $attacker }
|
||||
.frozen = [{ $victim }] died of: frozen caused by { $attacker }
|
||||
.mysterious = [{ $victim }] died of: secret caused by { $attacker }
|
||||
## PvP deaths
|
||||
|
||||
## Random Buff deaths, only $victim_gender is available
|
||||
|
||||
hud-chat-died_of_buff_nonexistent_msg =
|
||||
.burning = [{ $victim }] died of: burning
|
||||
.bleeding = [{ $victim }] died of: bleeding
|
||||
.curse = [{ $victim }] died of: curse
|
||||
.crippled = [{ $victim }] died of: crippled
|
||||
.frozen = [{ $victim }] died of: frozen
|
||||
.mysterious = [{ $victim }] died of: secret
|
||||
|
||||
## Other PvP deaths, both $attacker_gender and $victim_gender are available
|
||||
|
||||
hud-chat-pvp_melee_kill_msg = [{ $attacker }] defeated [{ $victim }]
|
||||
hud-chat-pvp_ranged_kill_msg = [{ $attacker }] shot [{ $victim }]
|
||||
hud-chat-pvp_explosion_kill_msg = [{ $attacker }] blew up [{ $victim }]
|
||||
hud-chat-pvp_energy_kill_msg = [{ $attacker }] killed [{ $victim }] with magic
|
||||
hud-chat-pvp_other_kill_msg = [{ $attacker }] killed [{ $victim }]
|
||||
## PvE deaths
|
||||
|
||||
## Other PvE deaths, only $victim_gender is available
|
||||
|
||||
hud-chat-npc_melee_kill_msg = { $attacker } killed [{ $victim }]
|
||||
hud-chat-npc_ranged_kill_msg = { $attacker } shot [{ $victim }]
|
||||
hud-chat-npc_explosion_kill_msg = { $attacker } blew up [{ $victim }]
|
||||
hud-chat-npc_energy_kill_msg = { $attacker } killed [{ $victim }] with magic
|
||||
hud-chat-npc_other_kill_msg = { $attacker } killed [{ $victim }]
|
||||
## Other deaths
|
||||
hud-chat-environmental_kill_msg = [{ $name }] died in { $environment }
|
||||
|
||||
## Other deaths, only $victim_gender is available
|
||||
|
||||
hud-chat-fall_kill_msg = [{ $name }] died from fall damage
|
||||
hud-chat-suicide_msg = [{ $name }] died from self-inflicted wounds
|
||||
hud-chat-default_death_msg = [{ $name }] died
|
||||
## Utils
|
||||
|
||||
## Chat utils
|
||||
|
||||
hud-chat-all = All
|
||||
hud-chat-you = You
|
||||
hud-chat-chat_tab_hover_tooltip = Right click for settings
|
||||
hud-loot-pickup-msg = {$actor} picked up { $amount ->
|
||||
[one] { $item }
|
||||
*[other] {$amount}x {$item}
|
||||
|
||||
## HUD Pickup message
|
||||
|
||||
hud-loot-pickup-msg = { $amount ->
|
||||
[one] { $actor } picked up { $item }
|
||||
*[other] { $actor } picked up {$amount}x {$item}
|
||||
}
|
||||
hud-chat-loot_fail = Your Inventory is full!
|
||||
hud-chat-goodbye = Goodbye!
|
||||
hud-chat-connection_lost = Connection lost. Kicking in { $time } seconds.
|
@ -1,57 +1,169 @@
|
||||
## Player events
|
||||
hud-chat-online_msg = [{ $name }] зайшов/-ла на сервер
|
||||
hud-chat-offline_msg = [{ $name }] вийшов/-ла з серверу
|
||||
## Buff deaths
|
||||
hud-chat-online_msg = [{ $name }] { $user_gender ->
|
||||
[she] зайшла на сервер
|
||||
*[he] зайшов на сервер
|
||||
}
|
||||
hud-chat-offline_msg = [{ $name }] { $user_gender ->
|
||||
[she] вийшла з серверу
|
||||
*[he] вийшов з серверу
|
||||
}
|
||||
hud-chat-goodbye = До побачення!
|
||||
hud-chat-connection_lost = З'єднання втрачено. Відключення через { $time ->
|
||||
[one] { $time } секунду
|
||||
[few] { $time } секунди
|
||||
*[other] { $time } секунд
|
||||
}
|
||||
|
||||
## PvP Buff deaths
|
||||
hud-chat-died_of_pvp_buff_msg =
|
||||
.burning = [{ $victim }] згорів/-ла живцем через [{ $attacker }]
|
||||
.bleeding = [{ $victim }] помер/-ла від кровотечі через [{ $attacker }]
|
||||
.curse = [{ $victim }] помер/-ла від прокльону через [{ $attacker }]
|
||||
.crippled = [{ $victim }] загинув/-ла від травм через [{ $attacker }]
|
||||
.frozen = [{ $victim }] замерз/-ла на смерть через [{ $attacker }]
|
||||
.mysterious = [{ $victim }] помер/-ла таємничою смертю через [{ $attacker }]
|
||||
hud-chat-died_of_buff_nonexistent_msg =
|
||||
.burning = [{ $victim }] згорів/-ла живцем
|
||||
.bleeding = [{ $victim }] помер/-ла від кровотечі
|
||||
.curse = [{ $victim }] помер/-ла від прокльону
|
||||
.crippled = [{ $victim }] загинув/-ла від травм
|
||||
.frozen = [{ $victim }] замерз/-ла на смерть
|
||||
.mysterious = [{ $victim }] помер/-ла таємничою смертю
|
||||
.burning = { $attacker_gender ->
|
||||
[she] [{ $attacker }] спалила [{ $victim }] живцем
|
||||
*[he] [{ $attacker }] спалив [{ $victim }] живцем
|
||||
}
|
||||
.bleeding = { $victim_gender ->
|
||||
[she] [{$victim}] втратила занадто багато крові отримавши поранення від [{ $attacker }]
|
||||
*[he] [{$victim}] втратив занадто багато крові отримавши поранення від [{ $attacker }]
|
||||
}
|
||||
.curse = { $victim_gender ->
|
||||
[she] [{ $victim }] померла від прокляття накладеного [{ $attacker }]
|
||||
*[he] [{ $victim }] помер від прокляття накладеного [{ $attacker }]
|
||||
}
|
||||
.crippled = { $victim_gender ->
|
||||
[she] [{ $victim }] загинула від отриманих травм через [{ $attacker }]
|
||||
*[he] [{ $victim }] загинув від отриманих травм через [{ $attacker }]
|
||||
}
|
||||
.frozen = { $victim_gender ->
|
||||
[she] [{ $victim }] замерзла на смерть через [{ $attacker }]
|
||||
*[he] [{ $victim }] замерз на смерть через [{ $attacker }]
|
||||
}
|
||||
.mysterious = { $victim_gender ->
|
||||
[she] [{ $victim }] померла ... через [{ $attacker }] ... як?
|
||||
*[he] [{ $victim }] помер ... через [{ $attacker }] ... як?
|
||||
}
|
||||
|
||||
## PvE buff deaths
|
||||
hud-chat-died_of_npc_buff_msg =
|
||||
.burning = [{ $victim }] згорів/-ла живцем через { $attacker }
|
||||
.bleeding = [{ $victim }] помер/-ла від кровотечі через { $attacker }
|
||||
.curse = [{ $victim }] помер/-ла від прокльону через { $attacker }
|
||||
.crippled = [{ $victim }] загинув/-ла від травм через { $attacker }
|
||||
.frozen = [{ $victim }] замерз/-ла на смерть через { $attacker }
|
||||
.mysterious = [{ $victim }] помер/-ла таємничою смертю через { $attacker }
|
||||
.burning = { $victim_gender ->
|
||||
[she] [{ $victim }] отримала через [{ $attacker }] опіки несумісні з життям
|
||||
*[he] [{ $victim }] отримав через [{ $attacker }] опіки несумісні з життям
|
||||
}
|
||||
.bleeding = { $victim_gender ->
|
||||
[she] [{ $victim }] втратила занадто багато крові отримавши поранення від [{ $attacker }]
|
||||
*[he] [{ $victim }] втратив занадто багато крові отримавши поранення від [{ $attacker }]
|
||||
}
|
||||
.curse = { $victim_gender ->
|
||||
[she] [{ $victim }] померла від прокляття накладеного [{ $attacker }]
|
||||
*[he] [{ $victim }] помер від прокляття накладеного [{ $attacker }]
|
||||
}
|
||||
.crippled = { $victim_gender ->
|
||||
[she] [{ $victim }] загинула від отриманих травм через [{ $attacker }]
|
||||
*[he] [{ $victim }] загинув від отриманих травм через [{ $attacker }]
|
||||
}
|
||||
.frozen = { $victim_gender ->
|
||||
[she] [{ $victim }] замерзла на смерть через [{ $attacker }]
|
||||
*[he] [{ $victim }] замерз на смерть через [{ $attacker }]
|
||||
}
|
||||
.mysterious = { $victim_gender ->
|
||||
[she] [{ $victim }] померла ... через [{ $attacker }] ... як?
|
||||
*[he] [{ $victim }] помер ... через [{ $attacker }] ... як?
|
||||
}
|
||||
|
||||
## Random buff deaths
|
||||
hud-chat-died_of_buff_nonexistent_msg =
|
||||
.burning = { $victim_gender ->
|
||||
[she] [{ $victim }] отримала опіки несумісні з життям
|
||||
*[he] [{ $victim }] отримав опіки несумісні з життям
|
||||
}
|
||||
.bleeding = { $victim_gender ->
|
||||
[she] [{ $victim }] втратила занадто багато крові
|
||||
*[he] [{ $victim }] втратив занадто багато крові
|
||||
}
|
||||
.curse = { $victim_gender ->
|
||||
[she] [{ $victim }] померла від прокляття
|
||||
*[he] [{ $victim }] помер від прокляття
|
||||
}
|
||||
.crippled = { $victim_gender ->
|
||||
[she] [{ $victim }] загинула від отриманих травм
|
||||
*[he] [{ $victim }] загинув від отриманих травм
|
||||
}
|
||||
.frozen = { $victim_gender ->
|
||||
[she] [{ $victim }] замерзла на смерть
|
||||
*[he] [{ $victim }] замерз на смерть
|
||||
}
|
||||
.mysterious = { $victim_gender ->
|
||||
[she] [{ $victim }] померла ... як?
|
||||
*[he] [{ $victim }] помер ... як?
|
||||
}
|
||||
|
||||
## PvP deaths
|
||||
hud-chat-pvp_melee_kill_msg = [{ $attacker }] переміг/-ла [{ $victim }]
|
||||
hud-chat-pvp_ranged_kill_msg = [{ $attacker }] застрелив/-ла [{ $victim }]
|
||||
hud-chat-pvp_explosion_kill_msg = [{ $attacker }] підірвав/-ла [{ $victim }]
|
||||
hud-chat-pvp_energy_kill_msg = [{ $attacker }] вбив/-ла [{ $victim }] магією
|
||||
hud-chat-pvp_other_kill_msg = { $attacker } вбив/-ла [{ $victim }]
|
||||
hud-chat-pvp_melee_kill_msg = { $victim_gender ->
|
||||
[she] [{ $victim }] вбита [{ $attacker }] у ближньому двобої
|
||||
*[he] [{ $victim }] вбитий [{ $attacker }] у ближньому двобої
|
||||
}
|
||||
hud-chat-pvp_ranged_kill_msg = { $victim_gender ->
|
||||
[she] [{ $victim }] впала вбита після влучного пострілу [{ $attacker }]
|
||||
*[he] [{ $victim }] впав вбитий після влучного пострілу [{ $attacker }]
|
||||
}
|
||||
hud-chat-pvp_explosion_kill_msg = { $victim_gender ->
|
||||
[she] [{ $victim }] розлетілась на атоми від удару [{ $attacker }]
|
||||
*[he] [{ $victim }] розлетівся на атоми від удару [{ $attacker }]
|
||||
}
|
||||
hud-chat-pvp_energy_kill_msg = { $victim_gender ->
|
||||
[she] [{ $victim }] впала вбита не встигнувши ухилитися від енергетичної атаки [{ $attacker }]
|
||||
*[he] [{ $victim }] впав вбитий не встигнувши ухилитися від енергетичної атаки [{ $attacker }]
|
||||
}
|
||||
hud-chat-pvp_other_kill_msg = { $victim_gender ->
|
||||
[she] [{ $victim }] вбита [{ $attacker }]
|
||||
*[he] [{ $victim }] вбитий [{ $attacker }]
|
||||
}
|
||||
|
||||
## PvE deaths
|
||||
hud-chat-npc_melee_kill_msg = { $attacker } вбив/-ла [{ $victim }]
|
||||
hud-chat-npc_ranged_kill_msg = { $attacker } застрелив/-ла [{ $victim }]
|
||||
hud-chat-npc_explosion_kill_msg = { $attacker } підірвав/-ла [{ $victim }]
|
||||
hud-chat-npc_energy_kill_msg = { $attacker } вбив/-ла [{ $victim }] магією
|
||||
hud-chat-npc_other_kill_msg = { $attacker } вбив/-ла [{ $victim }]
|
||||
hud-chat-npc_melee_kill_msg = { $victim_gender ->
|
||||
[she] [{ $victim }] вбита [{ $attacker }] у ближньому двобої
|
||||
*[he] [{ $victim }] вбитий [{ $attacker }] у ближньому двобої
|
||||
}
|
||||
hud-chat-npc_ranged_kill_msg = { $victim_gender ->
|
||||
[she] [{ $victim }] впала вбита після влучного пострілу [{ $attacker }]
|
||||
*[he] [{ $victim }] впав вбитий після влучного пострілу [{ $attacker }]
|
||||
}
|
||||
hud-chat-npc_explosion_kill_msg = { $victim_gender ->
|
||||
[she] [{ $victim }] розлетілась на атоми від удару [{ $attacker }]
|
||||
*[he] [{ $victim }] розлетівся на атоми від удару [{ $attacker }]
|
||||
}
|
||||
hud-chat-npc_energy_kill_msg = { $victim_gender ->
|
||||
[she] [{ $victim }] впала вбита не встигнувши ухилитися від енергетичної атаки [{ $attacker }]
|
||||
*[he] [{ $victim }] впав вбитий не встигнувши ухилитися від енергетичної атаки [{ $attacker }]
|
||||
}
|
||||
hud-chat-npc_other_kill_msg = { $victim_gender ->
|
||||
[she] [{ $victim }] вбита [{ $attacker }]
|
||||
*[he] [{ $victim }] вбитий [{ $attacker }]
|
||||
}
|
||||
|
||||
## Other deaths
|
||||
hud-chat-environmental_kill_msg = [{ $name }] помер/-ла в { $environment }
|
||||
hud-chat-fall_kill_msg = [{ $name }] помер/-ла від падіння
|
||||
hud-chat-suicide_msg = [{ $name }] помер/-ла від самозаподіяних ран
|
||||
hud-chat-default_death_msg = [{ $name }] помер/-ла
|
||||
## Utils
|
||||
hud-chat-all = Усі
|
||||
hud-chat-you = Ти
|
||||
|
||||
hud-chat-fall_kill_msg = { $victim_gender ->
|
||||
[she] [{ $name }] померла від падіння
|
||||
*[he] [{ $name }] помер від падіння
|
||||
}
|
||||
hud-chat-suicide_msg = { $victim_gender ->
|
||||
[she] [{ $name }] померла від самозаподіяних ран
|
||||
*[he] [{ $name }] помер від самозаподіяних ран
|
||||
}
|
||||
hud-chat-default_death_msg = { $victim_gender ->
|
||||
[she] [{ $name }] померла
|
||||
*[he] [{ $name }] помер
|
||||
}
|
||||
|
||||
## Chat utils
|
||||
|
||||
hud-chat-all = Все
|
||||
hud-chat-chat_tab_hover_tooltip = Правий клік для налаштування
|
||||
|
||||
# hud-chat-you = Ви
|
||||
|
||||
## HUD Pickup message
|
||||
|
||||
hud-loot-pickup-msg = {$actor} підняли { $amount ->
|
||||
[1] { $item }
|
||||
*[other] {$amount}x {$item}
|
||||
}
|
||||
hud-chat-loot_fail = Ваш інвентар переповнено!
|
||||
hud-chat-goodbye = До побачення!
|
||||
hud-chat-connection_lost = З'єднання втрачено. Перепідключення через { $time ->
|
||||
[one] { $time } секунду
|
||||
[few] { $time } секунди
|
||||
*[other] { $time } секунд
|
||||
}
|
@ -2250,6 +2250,7 @@ impl Client {
|
||||
player_info.character = match &player_info.character {
|
||||
Some(character) => Some(msg::CharacterInfo {
|
||||
name: character.name.to_string(),
|
||||
gender: character.gender,
|
||||
}),
|
||||
None => {
|
||||
warn!(
|
||||
@ -2870,10 +2871,13 @@ impl Client {
|
||||
}
|
||||
|
||||
/// Change player alias to "You" if client belongs to matching player
|
||||
// TODO: move this to voxygen or i18n-helpers and properly localize there
|
||||
// or what's better, just remove completely, it won't properly work with
|
||||
// localization anyway.
|
||||
pub fn personalize_alias(&self, uid: Uid, alias: String) -> String {
|
||||
let client_uid = self.uid().expect("Client doesn't have a Uid!!!");
|
||||
if client_uid == uid {
|
||||
"You".to_string() // TODO: Localize
|
||||
"You".to_string()
|
||||
} else {
|
||||
alias
|
||||
}
|
||||
@ -2884,9 +2888,10 @@ impl Client {
|
||||
pub fn lookup_msg_context(&self, msg: &comp::ChatMsg) -> ChatTypeContext {
|
||||
let mut result = ChatTypeContext {
|
||||
you: self.uid().expect("Client doesn't have a Uid!!!"),
|
||||
player_alias: HashMap::new(),
|
||||
player_info: HashMap::new(),
|
||||
entity_name: HashMap::new(),
|
||||
};
|
||||
|
||||
let name_of_uid = |uid| {
|
||||
let ecs = self.state.ecs();
|
||||
(
|
||||
@ -2897,53 +2902,52 @@ impl Client {
|
||||
.find(|(_, u)| u == &uid)
|
||||
.map(|(c, _)| c.name.clone())
|
||||
};
|
||||
let mut alias_of_uid = |uid| match self.player_list.get(uid) {
|
||||
Some(player_info) => {
|
||||
result.player_alias.insert(*uid, player_info.clone());
|
||||
},
|
||||
None => {
|
||||
result
|
||||
.entity_name
|
||||
.insert(*uid, name_of_uid(uid).unwrap_or_else(|| "<?>".to_string()));
|
||||
},
|
||||
|
||||
let mut add_data_of = |uid| {
|
||||
match self.player_list.get(uid) {
|
||||
Some(player_info) => {
|
||||
result.player_info.insert(*uid, player_info.clone());
|
||||
},
|
||||
None => {
|
||||
result
|
||||
.entity_name
|
||||
.insert(*uid, name_of_uid(uid).unwrap_or_else(|| "<?>".to_string()));
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
match &msg.chat_type {
|
||||
comp::ChatType::Online(uid) | comp::ChatType::Offline(uid) => {
|
||||
alias_of_uid(uid);
|
||||
},
|
||||
comp::ChatType::CommandError => (),
|
||||
comp::ChatType::CommandInfo => (),
|
||||
comp::ChatType::FactionMeta(_) => (),
|
||||
comp::ChatType::GroupMeta(_) => (),
|
||||
comp::ChatType::Online(uid) | comp::ChatType::Offline(uid) => add_data_of(uid),
|
||||
comp::ChatType::Kill(kill_source, victim) => {
|
||||
alias_of_uid(victim);
|
||||
add_data_of(victim);
|
||||
|
||||
match kill_source {
|
||||
KillSource::Player(attacker_uid, _) => {
|
||||
alias_of_uid(attacker_uid);
|
||||
add_data_of(attacker_uid);
|
||||
},
|
||||
KillSource::NonPlayer(_, _) => (),
|
||||
KillSource::Environment(_) => (),
|
||||
KillSource::FallDamage => (),
|
||||
KillSource::Suicide => (),
|
||||
KillSource::NonExistent(_) => (),
|
||||
KillSource::Other => (),
|
||||
KillSource::NonPlayer(_, _)
|
||||
| KillSource::FallDamage
|
||||
| KillSource::Suicide
|
||||
| KillSource::NonExistent(_)
|
||||
| KillSource::Other => (),
|
||||
};
|
||||
},
|
||||
comp::ChatType::Tell(from, to) | comp::ChatType::NpcTell(from, to) => {
|
||||
alias_of_uid(from);
|
||||
alias_of_uid(to);
|
||||
add_data_of(from);
|
||||
add_data_of(to);
|
||||
},
|
||||
comp::ChatType::Say(uid)
|
||||
| comp::ChatType::Region(uid)
|
||||
| comp::ChatType::World(uid)
|
||||
| comp::ChatType::NpcSay(uid) => {
|
||||
alias_of_uid(uid);
|
||||
},
|
||||
comp::ChatType::Group(uid, _) | comp::ChatType::Faction(uid, _) => {
|
||||
alias_of_uid(uid);
|
||||
},
|
||||
comp::ChatType::Npc(uid) => alias_of_uid(uid),
|
||||
comp::ChatType::Meta => (),
|
||||
| comp::ChatType::NpcSay(uid)
|
||||
| comp::ChatType::Group(uid, _)
|
||||
| comp::ChatType::Faction(uid, _)
|
||||
| comp::ChatType::Npc(uid) => add_data_of(uid),
|
||||
comp::ChatType::CommandError
|
||||
| comp::ChatType::CommandInfo
|
||||
| comp::ChatType::FactionMeta(_)
|
||||
| comp::ChatType::GroupMeta(_)
|
||||
| comp::ChatType::Meta => (),
|
||||
};
|
||||
result
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use crate::sync;
|
||||
use common::{
|
||||
calendar::Calendar,
|
||||
character::{self, CharacterItem},
|
||||
comp::{self, invite::InviteKind, item::MaterialStatManifest, Content},
|
||||
comp::{self, body::Gender, invite::InviteKind, item::MaterialStatManifest, Content},
|
||||
event::UpdateCharacterMetadata,
|
||||
lod,
|
||||
outcome::Outcome,
|
||||
@ -35,7 +35,7 @@ pub enum ServerMsg {
|
||||
Init(Box<ServerInit>),
|
||||
/// Result to `ClientMsg::Register`. send ONCE
|
||||
RegisterAnswer(ServerRegisterAnswer),
|
||||
///Msg that can be send ALWAYS as soon as client is registered, e.g. `Chat`
|
||||
/// Msg that can be send ALWAYS as soon as client is registered, e.g. `Chat`
|
||||
General(ServerGeneral),
|
||||
Ping(PingMsg),
|
||||
}
|
||||
@ -257,13 +257,14 @@ pub struct PlayerInfo {
|
||||
/// used for localisation, filled by client and used by i18n code
|
||||
pub struct ChatTypeContext {
|
||||
pub you: Uid,
|
||||
pub player_alias: HashMap<Uid, PlayerInfo>,
|
||||
pub player_info: HashMap<Uid, PlayerInfo>,
|
||||
pub entity_name: HashMap<Uid, String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CharacterInfo {
|
||||
pub name: String,
|
||||
pub gender: Option<Gender>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
@ -198,6 +198,20 @@ impl<
|
||||
const EXTENSION: &'static str = "ron";
|
||||
}
|
||||
|
||||
/// Semantic gender aka body_type
|
||||
///
|
||||
/// Should be used for localization with extreme care.
|
||||
/// For basically everything except *maybe* humanoids, it's simply wrong to
|
||||
/// assume that this may be used as grammatical gender.
|
||||
///
|
||||
/// TODO: remove this and instead add GUI for players to choose preferred
|
||||
/// gender. Read a comment for `gender_str` in voxygen/i18n-helpers/src/lib.rs.
|
||||
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
|
||||
pub enum Gender {
|
||||
Masculine,
|
||||
Feminine,
|
||||
}
|
||||
|
||||
impl Body {
|
||||
pub fn is_same_species_as(&self, other: &Body) -> bool {
|
||||
match self {
|
||||
@ -1360,6 +1374,17 @@ impl Body {
|
||||
|
||||
try_localize(self).unwrap_or_else(|| Content::localized("body-npc-speech-generic"))
|
||||
}
|
||||
|
||||
/// Read comment on `Gender` for more
|
||||
pub fn humanoid_gender(&self) -> Option<Gender> {
|
||||
match self {
|
||||
Body::Humanoid(b) => match b.body_type {
|
||||
humanoid::BodyType::Male => Some(Gender::Masculine),
|
||||
humanoid::BodyType::Female => Some(Gender::Feminine),
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Body {
|
||||
|
@ -57,6 +57,11 @@ impl ChatMode {
|
||||
pub const fn default() -> Self { Self::World }
|
||||
}
|
||||
|
||||
/// Enum representing death types
|
||||
///
|
||||
/// All variants should be strictly typed, no string content.
|
||||
///
|
||||
/// If it's too complicated to create an enum for death type, consult i18n team
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum KillType {
|
||||
Buff(BuffKind),
|
||||
@ -65,15 +70,17 @@ pub enum KillType {
|
||||
Explosion,
|
||||
Energy,
|
||||
Other,
|
||||
// Projectile(String), TODO: add projectile name when available
|
||||
// Projectile(Type), TODO: add projectile name when available
|
||||
}
|
||||
|
||||
/// Enum representing death reasons
|
||||
///
|
||||
/// All variants should be strictly typed, no string content.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum KillSource {
|
||||
Player(Uid, KillType),
|
||||
NonPlayer(String, KillType),
|
||||
NonExistent(KillType),
|
||||
Environment(String),
|
||||
FallDamage,
|
||||
Suicide,
|
||||
Other,
|
||||
|
@ -54,7 +54,7 @@ pub use self::{
|
||||
body::{
|
||||
arthropod, biped_large, biped_small, bird_large, bird_medium, crustacean, dragon,
|
||||
fish_medium, fish_small, golem, humanoid, item_drop, object, quadruped_low,
|
||||
quadruped_medium, quadruped_small, ship, theropod, AllBodies, Body, BodyData,
|
||||
quadruped_medium, quadruped_small, ship, theropod, AllBodies, Body, BodyData, Gender,
|
||||
},
|
||||
buff::{
|
||||
Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffKey, BuffKind, BuffSource, Buffs,
|
||||
|
@ -17,12 +17,14 @@ pub struct PlayerInfo {
|
||||
alias: String,
|
||||
}
|
||||
|
||||
/// Enum representing death reasons
|
||||
///
|
||||
/// All variants should be strictly typed, no string content.
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub enum KillSource {
|
||||
Player(PlayerInfo, KillType),
|
||||
NonPlayer(String, KillType),
|
||||
NonExistent(KillType),
|
||||
Environment(String),
|
||||
FallDamage,
|
||||
Suicide,
|
||||
Other,
|
||||
@ -160,7 +162,6 @@ impl ChatExporter {
|
||||
},
|
||||
comp::chat::KillSource::NonPlayer(str, t) => KillSource::NonPlayer(str, t),
|
||||
comp::chat::KillSource::NonExistent(t) => KillSource::NonExistent(t),
|
||||
comp::chat::KillSource::Environment(str) => KillSource::Environment(str),
|
||||
comp::chat::KillSource::FallDamage => KillSource::FallDamage,
|
||||
comp::chat::KillSource::Suicide => KillSource::Suicide,
|
||||
comp::chat::KillSource::Other => KillSource::Other,
|
||||
|
@ -166,7 +166,7 @@ impl Client {
|
||||
ServerMsg::RegisterAnswer(m) => PreparedMsg::new(0, &m, &self.register_stream_params),
|
||||
ServerMsg::General(g) => {
|
||||
match g {
|
||||
//Character Screen related
|
||||
// Character Screen related
|
||||
ServerGeneral::CharacterDataLoadResult(_)
|
||||
| ServerGeneral::CharacterListUpdate(_)
|
||||
| ServerGeneral::CharacterActionError(_)
|
||||
@ -176,7 +176,7 @@ impl Client {
|
||||
| ServerGeneral::SpectatorSuccess(_) => {
|
||||
PreparedMsg::new(1, &g, &self.character_screen_stream_params)
|
||||
},
|
||||
//In-game related
|
||||
// In-game related
|
||||
ServerGeneral::GroupUpdate(_)
|
||||
| ServerGeneral::Invite { .. }
|
||||
| ServerGeneral::InvitePending(_)
|
||||
|
@ -522,6 +522,8 @@ pub fn handle_possess(server: &mut Server, possessor_uid: Uid, possessee_uid: Ui
|
||||
character: ecs.read_storage::<comp::Stats>().get(possessee).map(|s| {
|
||||
msg::CharacterInfo {
|
||||
name: s.name.clone(),
|
||||
// NOTE: hack, read docs on body::Gender for more
|
||||
gender: s.original_body.humanoid_gender(),
|
||||
}
|
||||
}),
|
||||
uuid: player.uuid(),
|
||||
|
@ -724,6 +724,8 @@ impl StateExt for State {
|
||||
self.notify_players(ServerGeneral::PlayerListUpdate(
|
||||
PlayerListUpdate::SelectedCharacter(player_uid, CharacterInfo {
|
||||
name: String::from(&stats.name),
|
||||
// NOTE: hack, read docs on body::Gender for more
|
||||
gender: stats.original_body.humanoid_gender(),
|
||||
}),
|
||||
));
|
||||
|
||||
|
@ -99,6 +99,8 @@ impl<'a> System<'a> for Sys {
|
||||
player_alias: player.alias.clone(),
|
||||
character: stats.map(|stats| CharacterInfo {
|
||||
name: stats.name.clone(),
|
||||
// NOTE: hack, read docs for body::Gender for more
|
||||
gender: stats.original_body.humanoid_gender(),
|
||||
}),
|
||||
uuid: player.uuid(),
|
||||
}),
|
||||
|
@ -1,9 +1,13 @@
|
||||
#![feature(let_chains)]
|
||||
use std::borrow::Cow;
|
||||
|
||||
use common::comp::{
|
||||
chat::{KillSource, KillType},
|
||||
BuffKind, ChatMsg, ChatType, Content,
|
||||
use common::{
|
||||
comp::{
|
||||
body::Gender,
|
||||
chat::{KillSource, KillType},
|
||||
BuffKind, ChatMsg, ChatType, Content,
|
||||
},
|
||||
uid::Uid,
|
||||
};
|
||||
use common_net::msg::{ChatTypeContext, PlayerInfo};
|
||||
use i18n::Localization;
|
||||
@ -16,250 +20,405 @@ pub fn localize_chat_message(
|
||||
) -> (ChatType<String>, String) {
|
||||
let info = lookup_fn(&msg);
|
||||
|
||||
let name_format = |uid: &common::uid::Uid| match info.player_alias.get(uid).cloned() {
|
||||
Some(pi) => insert_alias(info.you == *uid, pi, localization),
|
||||
let name_format_or_complex = |complex, uid: &Uid| match info.player_info.get(uid).cloned() {
|
||||
Some(pi) => {
|
||||
if complex {
|
||||
insert_alias(info.you == *uid, pi, localization)
|
||||
} else {
|
||||
pi.player_alias
|
||||
}
|
||||
},
|
||||
None => info
|
||||
.entity_name
|
||||
.get(uid)
|
||||
.cloned()
|
||||
.expect("client didn't proved enough info"),
|
||||
.expect("client didn't provided enough info"),
|
||||
};
|
||||
|
||||
let message_format = |from: &common::uid::Uid, content: &Content, group: Option<&String>| {
|
||||
let alias = name_format(from);
|
||||
let name = if let Some(pi) = info.player_alias.get(from).cloned() && show_char_name {
|
||||
// Some messages do suffer from complicated logic of insert_alias.
|
||||
// This includes every notification-like message, like death.
|
||||
let name_format = |uid: &Uid| name_format_or_complex(false, uid);
|
||||
|
||||
// This is a hack, kind of.
|
||||
//
|
||||
// Current implementation just checks if our player is humanoid, and if so,
|
||||
// we take the body_type of its character and assume it as grammatical gender.
|
||||
//
|
||||
// In short,
|
||||
// body_type of character
|
||||
// -> sex of character
|
||||
// -> gender of player.
|
||||
// -> grammatical gender for use in messages.
|
||||
//
|
||||
// This is obviously, wrong, but it's good enough approximation, after all,
|
||||
// players do choose their characters.
|
||||
//
|
||||
// In the future, we will want special GUI where players can specify their
|
||||
// gender (and change it!), and we do want to handle more genders than just
|
||||
// male and female.
|
||||
//
|
||||
// Ideally, the system should handle following (if we exclude plurals):
|
||||
// - Female
|
||||
// - Male
|
||||
// - Neuter (or fallback Female)
|
||||
// - Neuter (or fallback Male)
|
||||
// - Intermediate (or fallback Female)
|
||||
// - Intermediate (or fallback Male)
|
||||
// and maybe more, not sure.
|
||||
//
|
||||
// What is supported by language and what is not, as well as maybe how to
|
||||
// convert genders into strings to match, should go into _manifest.ron file
|
||||
//
|
||||
// So let's say language only supports male and female, we will convert all
|
||||
// genders to these, using some fallbacks, and pass it.
|
||||
//
|
||||
// If the language can represent Female, Male and Neuter, we can pass these.
|
||||
//
|
||||
// Exact design of such a complex system is honestly up to discussion.
|
||||
let gender_str = |uid: &Uid| {
|
||||
if let Some(pi) = info.player_info.get(uid) {
|
||||
match pi.character.as_ref().and_then(|c| c.gender) {
|
||||
Some(Gender::Feminine) => "she".to_owned(),
|
||||
Some(Gender::Masculine) => "he".to_owned(),
|
||||
None => "??".to_owned(),
|
||||
}
|
||||
} else {
|
||||
"??".to_owned()
|
||||
}
|
||||
};
|
||||
|
||||
// This is where the most fun begings.
|
||||
//
|
||||
// Unlike people, "items" can have their own gender, which is completely
|
||||
// independent of everything, including common sense.
|
||||
//
|
||||
// For example, word "masculinity" can be feminine in some languages,
|
||||
// as well as word "boy", and vice versa.
|
||||
//
|
||||
// So we can't rely on body_type, at all. And even if we did try, our
|
||||
// body_type isn't even always represents animal sex, there are some
|
||||
// animals that use body_type to represent their kind, like different
|
||||
// types of Fox ("male" fox is forest, "female" is arctic one).
|
||||
// And what about Mindflayer? They do have varied body_type, but do they
|
||||
// even have concept of gender?
|
||||
//
|
||||
// Our use case is probably less cryptic, after all we are limited by
|
||||
// mostly sentient things, but that doesn't help at all.
|
||||
//
|
||||
// Common example is word "spider", which can be feminine in one languages
|
||||
// and masculine in other, and sometimes even neuter.
|
||||
//
|
||||
// Oh, and I want to add that we are talking about grammatical genders, and
|
||||
// languages define their own grammar. There are languages that have more
|
||||
// than three grammatical genders, there are languages that don't have
|
||||
// male/female distinction and instead realy on animacy/non-animacy.
|
||||
// What has an animacy and what doesn't is for language to decide.
|
||||
// There are languages as well that mix these concepts and may have neuter,
|
||||
// female, masculine with animacy, masculine with animacy. Some languages
|
||||
// have their own scheme of things that arbitrarily picks noun-class per
|
||||
// noun.
|
||||
// Don't get me wrong. *All* languages do pick the gender for the word
|
||||
// arbitrary as I showed at the beginning, it's just some languages have
|
||||
// not just different mapping, but different gender set as well.
|
||||
//
|
||||
// The *only* option we have is fetch the gender per each name entry from
|
||||
// localization files.
|
||||
//
|
||||
// I'm not 100% sure what should be the implementation of it, but I imagine
|
||||
// that Stats::name() should be changed to include a way to reference where
|
||||
// to grab the gender associated with this name, so translation then can
|
||||
// pick right article or use right adjective/verb connected with NPC in the
|
||||
// context of the message.
|
||||
let _gender_str_npc = || "idk".to_owned();
|
||||
|
||||
let message_format = |from: &Uid, content: &Content, group: Option<&String>| {
|
||||
let alias = name_format_or_complex(true, from);
|
||||
|
||||
let name = if let Some(pi) = info.player_info.get(from).cloned() && show_char_name {
|
||||
pi.character.map(|c| c.name)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let message = localization.get_content(content);
|
||||
match (group, name) {
|
||||
(Some(group), None) => format!("({group}) [{alias}]: {message}"),
|
||||
(None, None) => format!("[{alias}]: {message}"),
|
||||
(Some(group), Some(name)) => format!("({group}) [{alias}] {name}: {message}"),
|
||||
(None, Some(name)) => format!("[{alias}] {name}: {message}"),
|
||||
}
|
||||
|
||||
let line = match group {
|
||||
Some(group) => match name {
|
||||
Some(name) => localization.get_msg_ctx(
|
||||
"hud-chat-message-in-group-with-name",
|
||||
&i18n::fluent_args! {
|
||||
"group" => group,
|
||||
"alias" => alias,
|
||||
"name" => name,
|
||||
"msg" => message,
|
||||
},
|
||||
),
|
||||
None => {
|
||||
localization.get_msg_ctx("hud-chat-message-in-group", &i18n::fluent_args! {
|
||||
"group" => group,
|
||||
"alias" => alias,
|
||||
"msg" => message,
|
||||
})
|
||||
},
|
||||
},
|
||||
None => match name {
|
||||
Some(name) => {
|
||||
localization.get_msg_ctx("hud-chat-message-with-name", &i18n::fluent_args! {
|
||||
"alias" => alias,
|
||||
"name" => name,
|
||||
"msg" => message,
|
||||
})
|
||||
},
|
||||
None => localization.get_msg_ctx("hud-chat-message", &i18n::fluent_args! {
|
||||
"alias" => alias,
|
||||
"msg" => message,
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
line.into_owned()
|
||||
};
|
||||
|
||||
let new_msg = match &msg.chat_type {
|
||||
ChatType::Online(uid) => localization
|
||||
.get_msg_ctx("hud-chat-online_msg", &i18n::fluent_args! {
|
||||
"user_gender" => gender_str(uid),
|
||||
"name" => name_format(uid),
|
||||
})
|
||||
.into_owned(),
|
||||
ChatType::Offline(uid) => localization
|
||||
.get_msg_ctx("hud-chat-offline_msg", &i18n::fluent_args! {
|
||||
"name" => name_format(uid
|
||||
),
|
||||
"user_gender" => gender_str(uid),
|
||||
"name" => name_format(uid),
|
||||
})
|
||||
.into_owned(),
|
||||
ChatType::CommandError => localization.get_content(msg.content()),
|
||||
ChatType::CommandInfo => localization.get_content(msg.content()),
|
||||
ChatType::FactionMeta(_) => localization.get_content(msg.content()),
|
||||
ChatType::GroupMeta(_) => localization.get_content(msg.content()),
|
||||
ChatType::CommandError
|
||||
| ChatType::CommandInfo
|
||||
| ChatType::Meta
|
||||
| ChatType::FactionMeta(_)
|
||||
| ChatType::GroupMeta(_) => localization.get_content(msg.content()),
|
||||
ChatType::Tell(from, to) => {
|
||||
let from_alias = name_format(from);
|
||||
let to_alias = name_format(to);
|
||||
// TODO: internationalise
|
||||
if *from == info.you {
|
||||
format!(
|
||||
"To [{to_alias}]: {}",
|
||||
localization.get_content(msg.content())
|
||||
)
|
||||
// If `from` is you, it means you're writing to someone
|
||||
// and you want to see who you're writing to.
|
||||
//
|
||||
// Otherwise, someone writes to you, and you want to see
|
||||
// who is that person that's writing to you.
|
||||
let (key, person_to_show) = if info.you == *from {
|
||||
("hud-chat-tell-to", to)
|
||||
} else {
|
||||
format!(
|
||||
"From [{from_alias}]: {}",
|
||||
localization.get_content(msg.content())
|
||||
)
|
||||
}
|
||||
},
|
||||
ChatType::Say(uid) => message_format(uid, msg.content(), None),
|
||||
ChatType::Group(uid, s) => message_format(uid, msg.content(), Some(s)),
|
||||
ChatType::Faction(uid, s) => message_format(uid, msg.content(), Some(s)),
|
||||
ChatType::Region(uid) => message_format(uid, msg.content(), None),
|
||||
ChatType::World(uid) => message_format(uid, msg.content(), None),
|
||||
// NPCs can't talk. Should be filtered by hud/mod.rs for voxygen and
|
||||
// should be filtered by server (due to not having a Pos) for chat-cli
|
||||
ChatType::Npc(uid) => message_format(uid, msg.content(), None),
|
||||
ChatType::NpcSay(uid) => message_format(uid, msg.content(), None),
|
||||
ChatType::NpcTell(from, to) => {
|
||||
let from_alias = name_format(from);
|
||||
let to_alias = name_format(to);
|
||||
// TODO: internationalise
|
||||
if *from == info.you {
|
||||
format!(
|
||||
"To [{to_alias}]: {}",
|
||||
localization.get_content(msg.content())
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"From [{from_alias}]: {}",
|
||||
localization.get_content(msg.content())
|
||||
)
|
||||
}
|
||||
},
|
||||
ChatType::Meta => localization.get_content(msg.content()),
|
||||
ChatType::Kill(kill_source, victim) => {
|
||||
let get_buff_ident = |buff| match buff {
|
||||
BuffKind::Burning => "burning",
|
||||
BuffKind::Bleeding => "bleeding",
|
||||
BuffKind::Cursed => "curse",
|
||||
BuffKind::Crippled => "crippled",
|
||||
BuffKind::Frozen => "frozen",
|
||||
BuffKind::Regeneration
|
||||
| BuffKind::Saturation
|
||||
| BuffKind::Potion
|
||||
| BuffKind::Agility
|
||||
| BuffKind::CampfireHeal
|
||||
| BuffKind::EnergyRegen
|
||||
| BuffKind::IncreaseMaxEnergy
|
||||
| BuffKind::IncreaseMaxHealth
|
||||
| BuffKind::Invulnerability
|
||||
| BuffKind::ProtectingWard
|
||||
| BuffKind::Frenzied
|
||||
| BuffKind::Hastened
|
||||
| BuffKind::Fortitude
|
||||
| BuffKind::Reckless
|
||||
| BuffKind::Flame
|
||||
| BuffKind::Frigid
|
||||
| BuffKind::Lifesteal
|
||||
// | BuffKind::SalamanderAspect
|
||||
| BuffKind::ImminentCritical
|
||||
| BuffKind::Fury
|
||||
| BuffKind::Sunderer
|
||||
| BuffKind::Defiance
|
||||
| BuffKind::Bloodfeast
|
||||
| BuffKind::Berserk => {
|
||||
tracing::error!("Player was killed by a positive buff!");
|
||||
"mysterious"
|
||||
},
|
||||
BuffKind::Wet
|
||||
| BuffKind::Ensnared
|
||||
| BuffKind::Poisoned
|
||||
| BuffKind::Parried
|
||||
| BuffKind::PotionSickness
|
||||
| BuffKind::Polymorphed
|
||||
| BuffKind::Heatstroke => {
|
||||
tracing::error!("Player was killed by a debuff that doesn't do damage!");
|
||||
"mysterious"
|
||||
},
|
||||
("hud-chat-tell-from", from)
|
||||
};
|
||||
|
||||
match kill_source {
|
||||
// Buff deaths
|
||||
KillSource::Player(attacker, KillType::Buff(buff_kind)) => {
|
||||
let buff_ident = get_buff_ident(*buff_kind);
|
||||
localization
|
||||
.get_msg_ctx(key, &i18n::fluent_args! {
|
||||
"alias" => name_format(person_to_show),
|
||||
"user_gender" => gender_str(person_to_show),
|
||||
})
|
||||
.into_owned()
|
||||
},
|
||||
ChatType::Say(uid) | ChatType::Region(uid) | ChatType::World(uid) => {
|
||||
message_format(uid, msg.content(), None)
|
||||
},
|
||||
ChatType::Group(uid, descriptor) | ChatType::Faction(uid, descriptor) => {
|
||||
message_format(uid, msg.content(), Some(descriptor))
|
||||
},
|
||||
ChatType::Npc(uid) | ChatType::NpcSay(uid) => message_format(uid, msg.content(), None),
|
||||
ChatType::NpcTell(from, to) => {
|
||||
// If `from` is you, it means you're writing to someone
|
||||
// and you want to see who you're writing to.
|
||||
//
|
||||
// Otherwise, someone writes to you, and you want to see
|
||||
// who is that person that's writing to you.
|
||||
//
|
||||
// Hopefully, no gendering needed, because for npc, we
|
||||
// simply don't know.
|
||||
let (key, person_to_show) = if info.you == *from {
|
||||
("hud-chat-tell-to-npc", to)
|
||||
} else {
|
||||
("hud-chat-tell-from-npc", from)
|
||||
};
|
||||
|
||||
let s = localization
|
||||
.get_attr_ctx(
|
||||
"hud-chat-died_of_pvp_buff_msg",
|
||||
buff_ident,
|
||||
&i18n::fluent_args! {
|
||||
"victim" => name_format(victim),
|
||||
"attacker" => name_format(attacker),
|
||||
},
|
||||
)
|
||||
.into_owned();
|
||||
Cow::Owned(s)
|
||||
},
|
||||
KillSource::NonPlayer(attacker_name, KillType::Buff(buff_kind)) => {
|
||||
let buff_ident = get_buff_ident(*buff_kind);
|
||||
|
||||
let s = localization
|
||||
.get_attr_ctx(
|
||||
"hud-chat-died_of_npc_buff_msg",
|
||||
buff_ident,
|
||||
&i18n::fluent_args! {
|
||||
"victim" => name_format(victim),
|
||||
"attacker" => attacker_name,
|
||||
},
|
||||
)
|
||||
.into_owned();
|
||||
Cow::Owned(s)
|
||||
},
|
||||
KillSource::NonExistent(KillType::Buff(buff_kind)) => {
|
||||
let buff_ident = get_buff_ident(*buff_kind);
|
||||
|
||||
let s = localization
|
||||
.get_attr_ctx(
|
||||
"hud-chat-died_of_buff_nonexistent_msg",
|
||||
buff_ident,
|
||||
&i18n::fluent_args! {
|
||||
"victim" => name_format(victim),
|
||||
},
|
||||
)
|
||||
.into_owned();
|
||||
Cow::Owned(s)
|
||||
},
|
||||
// PvP deaths
|
||||
KillSource::Player(attacker, kill_type) => {
|
||||
let key = match kill_type {
|
||||
KillType::Melee => "hud-chat-pvp_melee_kill_msg",
|
||||
KillType::Projectile => "hud-chat-pvp_ranged_kill_msg",
|
||||
KillType::Explosion => "hud-chat-pvp_explosion_kill_msg",
|
||||
KillType::Energy => "hud-chat-pvp_energy_kill_msg",
|
||||
KillType::Other => "hud-chat-pvp_other_kill_msg",
|
||||
&KillType::Buff(_) => unreachable!("handled above"),
|
||||
};
|
||||
localization.get_msg_ctx(key, &i18n::fluent_args! {
|
||||
"victim" => name_format(victim),
|
||||
"attacker" => name_format(attacker),
|
||||
})
|
||||
},
|
||||
// PvE deaths
|
||||
KillSource::NonPlayer(attacker_name, kill_type) => {
|
||||
let key = match kill_type {
|
||||
KillType::Melee => "hud-chat-npc_melee_kill_msg",
|
||||
KillType::Projectile => "hud-chat-npc_ranged_kill_msg",
|
||||
KillType::Explosion => "hud-chat-npc_explosion_kill_msg",
|
||||
KillType::Energy => "hud-chat-npc_energy_kill_msg",
|
||||
KillType::Other => "hud-chat-npc_other_kill_msg",
|
||||
&KillType::Buff(_) => unreachable!("handled above"),
|
||||
};
|
||||
localization.get_msg_ctx(key, &i18n::fluent_args! {
|
||||
"victim" => name_format(victim),
|
||||
"attacker" => attacker_name,
|
||||
})
|
||||
},
|
||||
// Other deaths
|
||||
KillSource::Environment(environment) => {
|
||||
localization.get_msg_ctx("hud-chat-environment_kill_msg", &i18n::fluent_args! {
|
||||
"name" => name_format(victim),
|
||||
"environment" => environment,
|
||||
})
|
||||
},
|
||||
KillSource::FallDamage => {
|
||||
localization.get_msg_ctx("hud-chat-fall_kill_msg", &i18n::fluent_args! {
|
||||
"name" => name_format(victim),
|
||||
})
|
||||
},
|
||||
KillSource::Suicide => {
|
||||
localization.get_msg_ctx("hud-chat-suicide_msg", &i18n::fluent_args! {
|
||||
"name" => name_format(victim),
|
||||
})
|
||||
},
|
||||
KillSource::NonExistent(_) | KillSource::Other => {
|
||||
localization.get_msg_ctx("hud-chat-default_death_msg", &i18n::fluent_args! {
|
||||
"name" => name_format(victim),
|
||||
})
|
||||
},
|
||||
}
|
||||
.into_owned()
|
||||
localization
|
||||
.get_msg_ctx(key, &i18n::fluent_args! {
|
||||
"alias" => name_format(person_to_show),
|
||||
})
|
||||
.into_owned()
|
||||
},
|
||||
ChatType::Kill(kill_source, victim) => {
|
||||
localize_kill_message(kill_source, victim, name_format, gender_str, localization)
|
||||
},
|
||||
};
|
||||
|
||||
(msg.chat_type, new_msg)
|
||||
}
|
||||
|
||||
fn insert_alias(you: bool, info: PlayerInfo, localization: &Localization) -> String {
|
||||
const YOU: &str = "hud-chat-you";
|
||||
fn localize_kill_message(
|
||||
kill_source: &KillSource,
|
||||
victim: &Uid,
|
||||
name_format: impl Fn(&Uid) -> String,
|
||||
gender_str: impl Fn(&Uid) -> String,
|
||||
localization: &Localization,
|
||||
) -> String {
|
||||
match kill_source {
|
||||
// PvP deaths
|
||||
KillSource::Player(attacker, kill_type) => {
|
||||
let key = match kill_type {
|
||||
KillType::Melee => "hud-chat-pvp_melee_kill_msg",
|
||||
KillType::Projectile => "hud-chat-pvp_ranged_kill_msg",
|
||||
KillType::Explosion => "hud-chat-pvp_explosion_kill_msg",
|
||||
KillType::Energy => "hud-chat-pvp_energy_kill_msg",
|
||||
KillType::Other => "hud-chat-pvp_other_kill_msg",
|
||||
KillType::Buff(buff_kind) => {
|
||||
let buff_ident = get_buff_ident(*buff_kind);
|
||||
|
||||
return localization
|
||||
.get_attr_ctx(
|
||||
"hud-chat-died_of_pvp_buff_msg",
|
||||
buff_ident,
|
||||
&i18n::fluent_args! {
|
||||
"victim" => name_format(victim),
|
||||
"victim_gender" => gender_str(victim),
|
||||
"attacker" => name_format(attacker),
|
||||
"attacker_gender" => gender_str(attacker),
|
||||
},
|
||||
)
|
||||
.into_owned();
|
||||
},
|
||||
};
|
||||
localization.get_msg_ctx(key, &i18n::fluent_args! {
|
||||
"victim" => name_format(victim),
|
||||
"victim_gender" => gender_str(victim),
|
||||
"attacker" => name_format(attacker),
|
||||
"attacker_gender" => gender_str(attacker),
|
||||
})
|
||||
},
|
||||
// PvE deaths
|
||||
KillSource::NonPlayer(attacker_name, kill_type) => {
|
||||
let key = match kill_type {
|
||||
KillType::Melee => "hud-chat-npc_melee_kill_msg",
|
||||
KillType::Projectile => "hud-chat-npc_ranged_kill_msg",
|
||||
KillType::Explosion => "hud-chat-npc_explosion_kill_msg",
|
||||
KillType::Energy => "hud-chat-npc_energy_kill_msg",
|
||||
KillType::Other => "hud-chat-npc_other_kill_msg",
|
||||
KillType::Buff(buff_kind) => {
|
||||
let buff_ident = get_buff_ident(*buff_kind);
|
||||
|
||||
return localization
|
||||
.get_attr_ctx(
|
||||
"hud-chat-died_of_npc_buff_msg",
|
||||
buff_ident,
|
||||
&i18n::fluent_args! {
|
||||
"victim" => name_format(victim),
|
||||
"victim_gender" => gender_str(victim),
|
||||
"attacker" => attacker_name,
|
||||
},
|
||||
)
|
||||
.into_owned();
|
||||
},
|
||||
};
|
||||
localization.get_msg_ctx(key, &i18n::fluent_args! {
|
||||
"victim" => name_format(victim),
|
||||
"victim_gender" => gender_str(victim),
|
||||
"attacker" => attacker_name,
|
||||
})
|
||||
},
|
||||
// Other deaths
|
||||
KillSource::FallDamage => {
|
||||
localization.get_msg_ctx("hud-chat-fall_kill_msg", &i18n::fluent_args! {
|
||||
"name" => name_format(victim),
|
||||
"victim_gender" => gender_str(victim),
|
||||
})
|
||||
},
|
||||
KillSource::Suicide => {
|
||||
localization.get_msg_ctx("hud-chat-suicide_msg", &i18n::fluent_args! {
|
||||
"name" => name_format(victim),
|
||||
"victim_gender" => gender_str(victim),
|
||||
})
|
||||
},
|
||||
KillSource::NonExistent(KillType::Buff(buff_kind)) => {
|
||||
let buff_ident = get_buff_ident(*buff_kind);
|
||||
|
||||
let s = localization
|
||||
.get_attr_ctx(
|
||||
"hud-chat-died_of_buff_nonexistent_msg",
|
||||
buff_ident,
|
||||
&i18n::fluent_args! {
|
||||
"victim" => name_format(victim),
|
||||
"victim_gender" => gender_str(victim),
|
||||
},
|
||||
)
|
||||
.into_owned();
|
||||
Cow::Owned(s)
|
||||
},
|
||||
KillSource::NonExistent(_) | KillSource::Other => {
|
||||
localization.get_msg_ctx("hud-chat-default_death_msg", &i18n::fluent_args! {
|
||||
"name" => name_format(victim),
|
||||
"victim_gender" => gender_str(victim),
|
||||
})
|
||||
},
|
||||
}
|
||||
.into_owned()
|
||||
}
|
||||
|
||||
/// Determines .attr for `hud-chat-died-of-buff` messages
|
||||
fn get_buff_ident(buff: BuffKind) -> &'static str {
|
||||
match buff {
|
||||
BuffKind::Burning => "burning",
|
||||
BuffKind::Bleeding => "bleeding",
|
||||
BuffKind::Cursed => "curse",
|
||||
BuffKind::Crippled => "crippled",
|
||||
BuffKind::Frozen => "frozen",
|
||||
BuffKind::Regeneration
|
||||
| BuffKind::Saturation
|
||||
| BuffKind::Potion
|
||||
| BuffKind::Agility
|
||||
| BuffKind::CampfireHeal
|
||||
| BuffKind::EnergyRegen
|
||||
| BuffKind::IncreaseMaxEnergy
|
||||
| BuffKind::IncreaseMaxHealth
|
||||
| BuffKind::Invulnerability
|
||||
| BuffKind::ProtectingWard
|
||||
| BuffKind::Frenzied
|
||||
| BuffKind::Hastened
|
||||
| BuffKind::Fortitude
|
||||
| BuffKind::Reckless
|
||||
| BuffKind::Flame
|
||||
| BuffKind::Frigid
|
||||
| BuffKind::Lifesteal
|
||||
// | BuffKind::SalamanderAspect
|
||||
| BuffKind::ImminentCritical
|
||||
| BuffKind::Fury
|
||||
| BuffKind::Sunderer
|
||||
| BuffKind::Defiance
|
||||
| BuffKind::Bloodfeast
|
||||
| BuffKind::Berserk => {
|
||||
tracing::error!("Player was killed by a positive buff!");
|
||||
"mysterious"
|
||||
},
|
||||
BuffKind::Wet
|
||||
| BuffKind::Ensnared
|
||||
| BuffKind::Poisoned
|
||||
| BuffKind::Parried
|
||||
| BuffKind::PotionSickness
|
||||
| BuffKind::Polymorphed
|
||||
| BuffKind::Heatstroke => {
|
||||
tracing::error!("Player was killed by a debuff that doesn't do damage!");
|
||||
"mysterious"
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Used for inserting spacing for mod badge icon next to alias
|
||||
// TODO: consider passing '$is_you' to hud-chat-message strings along with
|
||||
// $spacing variable, for more flexible translations.
|
||||
fn insert_alias(_replace_you: bool, info: PlayerInfo, _localization: &Localization) -> String {
|
||||
// Leave space for a mod badge icon.
|
||||
const MOD_SPACING: &str = " ";
|
||||
match (info.is_moderator, you) {
|
||||
(false, false) => info.player_alias,
|
||||
(false, true) => localization.get_msg(YOU).to_string(),
|
||||
(true, false) => format!("{}{}", MOD_SPACING, info.player_alias),
|
||||
(true, true) => format!("{}{}", MOD_SPACING, &localization.get_msg(YOU),),
|
||||
|
||||
if info.is_moderator {
|
||||
format!("{}{}", MOD_SPACING, info.player_alias)
|
||||
} else {
|
||||
info.player_alias
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -481,7 +481,7 @@ impl<'a> Widget for Chat<'a> {
|
||||
.and_then(|uid| {
|
||||
self.client
|
||||
.lookup_msg_context(m)
|
||||
.player_alias
|
||||
.player_info
|
||||
.get(&uid)
|
||||
.map(|i| i.is_moderator)
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user