From e6f2dc314c8bb063471e10a5738fd0f1efcf5b79 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Mon, 19 Jul 2021 20:52:12 +0300 Subject: [PATCH 001/155] Deduplicate skillbar slots --- voxygen/src/hud/skillbar.rs | 544 ++++++++++++++---------------------- 1 file changed, 204 insertions(+), 340 deletions(-) diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index fa367a3ab0..493267172b 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -131,6 +131,151 @@ widget_ids! { } } +// TODO: extend as you need it +// Make it public to use throughout the code? +#[derive(Clone, Copy)] +enum PositionSpecifier { + MidBottomWithMarginOn(widget::Id, f64), + TopRightWithMarginsOn(widget::Id, f64, f64), + BottomRightWithMarginsOn(widget::Id, f64, f64), + BottomLeftWithMarginsOn(widget::Id, f64, f64), + RightFrom(widget::Id, f64), +} + +trait Position { + fn position(self, request: PositionSpecifier) -> Self; +} + +impl Position for W { + fn position(self, request: PositionSpecifier) -> Self { + match request { + PositionSpecifier::MidBottomWithMarginOn(other, margin) => { + self.mid_bottom_with_margin_on(other, margin) + }, + PositionSpecifier::TopRightWithMarginsOn(other, top, right) => { + self.top_right_with_margins_on(other, top, right) + }, + PositionSpecifier::BottomRightWithMarginsOn(other, bottom, right) => { + self.bottom_right_with_margins_on(other, bottom, right) + }, + PositionSpecifier::BottomLeftWithMarginsOn(other, bottom, left) => { + self.bottom_left_with_margins_on(other, bottom, left) + }, + PositionSpecifier::RightFrom(other, offset) => self.right_from(other, offset), + } + } +} + +#[derive(Clone, Copy)] +struct SlotEntry { + slot: hotbar::Slot, + widget_id: widget::Id, + position: PositionSpecifier, + game_input: GameInput, + shortcut_position: PositionSpecifier, + shortcut_position_bg: PositionSpecifier, + shortcut_widget_ids: (widget::Id, widget::Id), +} + +fn slots_entries(state: &State, slot_offset: f64) -> [SlotEntry; 10] { + use PositionSpecifier::*; + + [ + // 1th - 5th slots + SlotEntry { + slot: hotbar::Slot::One, + widget_id: state.ids.slot1, + position: BottomLeftWithMarginsOn(state.ids.frame, 0.0, 0.0), + game_input: GameInput::Slot1, + shortcut_position: BottomLeftWithMarginsOn(state.ids.slot1_text_bg, 1.0, 1.0), + shortcut_position_bg: TopRightWithMarginsOn(state.ids.slot1, 3.0, 5.0), + shortcut_widget_ids: (state.ids.slot1_text, state.ids.slot1_text_bg), + }, + SlotEntry { + slot: hotbar::Slot::Two, + widget_id: state.ids.slot2, + position: RightFrom(state.ids.slot1, slot_offset), + game_input: GameInput::Slot2, + shortcut_position: BottomLeftWithMarginsOn(state.ids.slot2_text_bg, 1.0, 1.0), + shortcut_position_bg: TopRightWithMarginsOn(state.ids.slot2, 3.0, 5.0), + shortcut_widget_ids: (state.ids.slot2_text, state.ids.slot2_text_bg), + }, + SlotEntry { + slot: hotbar::Slot::Three, + widget_id: state.ids.slot3, + position: RightFrom(state.ids.slot2, slot_offset), + game_input: GameInput::Slot3, + shortcut_position: BottomLeftWithMarginsOn(state.ids.slot3_text_bg, 1.0, 1.0), + shortcut_position_bg: TopRightWithMarginsOn(state.ids.slot3, 3.0, 5.0), + shortcut_widget_ids: (state.ids.slot3_text, state.ids.slot3_text_bg), + }, + SlotEntry { + slot: hotbar::Slot::Four, + widget_id: state.ids.slot4, + position: RightFrom(state.ids.slot3, slot_offset), + game_input: GameInput::Slot4, + shortcut_position: BottomLeftWithMarginsOn(state.ids.slot4_text_bg, 1.0, 1.0), + shortcut_position_bg: TopRightWithMarginsOn(state.ids.slot4, 3.0, 5.0), + shortcut_widget_ids: (state.ids.slot4_text, state.ids.slot4_text_bg), + }, + SlotEntry { + slot: hotbar::Slot::Five, + widget_id: state.ids.slot5, + position: RightFrom(state.ids.slot4, slot_offset), + game_input: GameInput::Slot5, + shortcut_position: BottomLeftWithMarginsOn(state.ids.slot5_text_bg, 1.0, 1.0), + shortcut_position_bg: TopRightWithMarginsOn(state.ids.slot5, 3.0, 5.0), + shortcut_widget_ids: (state.ids.slot5_text, state.ids.slot5_text_bg), + }, + // 6th - 10th slots + SlotEntry { + slot: hotbar::Slot::Six, + widget_id: state.ids.slot6, + position: RightFrom(state.ids.m2_slot_bg, slot_offset), + game_input: GameInput::Slot6, + shortcut_position: BottomLeftWithMarginsOn(state.ids.slot6_text_bg, 1.0, 1.0), + shortcut_position_bg: TopRightWithMarginsOn(state.ids.slot6, 3.0, 5.0), + shortcut_widget_ids: (state.ids.slot6_text, state.ids.slot6_text_bg), + }, + SlotEntry { + slot: hotbar::Slot::Seven, + widget_id: state.ids.slot7, + position: RightFrom(state.ids.slot6, slot_offset), + game_input: GameInput::Slot7, + shortcut_position: BottomLeftWithMarginsOn(state.ids.slot7_text_bg, 1.0, 1.0), + shortcut_position_bg: TopRightWithMarginsOn(state.ids.slot7, 3.0, 5.0), + shortcut_widget_ids: (state.ids.slot7_text, state.ids.slot7_text_bg), + }, + SlotEntry { + slot: hotbar::Slot::Eight, + widget_id: state.ids.slot8, + position: RightFrom(state.ids.slot7, slot_offset), + game_input: GameInput::Slot8, + shortcut_position: BottomLeftWithMarginsOn(state.ids.slot8_text_bg, 1.0, 1.0), + shortcut_position_bg: TopRightWithMarginsOn(state.ids.slot8, 3.0, 5.0), + shortcut_widget_ids: (state.ids.slot8_text, state.ids.slot8_text_bg), + }, + SlotEntry { + slot: hotbar::Slot::Nine, + widget_id: state.ids.slot9, + position: RightFrom(state.ids.slot8, slot_offset), + game_input: GameInput::Slot9, + shortcut_position: BottomLeftWithMarginsOn(state.ids.slot9_text_bg, 1.0, 1.0), + shortcut_position_bg: TopRightWithMarginsOn(state.ids.slot9, 3.0, 5.0), + shortcut_widget_ids: (state.ids.slot9_text, state.ids.slot9_text_bg), + }, + SlotEntry { + slot: hotbar::Slot::Ten, + widget_id: state.ids.slot10, + position: RightFrom(state.ids.slot9, slot_offset), + game_input: GameInput::Slot10, + shortcut_position: BottomLeftWithMarginsOn(state.ids.slot10_text_bg, 1.0, 1.0), + shortcut_position_bg: TopRightWithMarginsOn(state.ids.slot10, 3.0, 5.0), + shortcut_widget_ids: (state.ids.slot10_text, state.ids.slot10_text_bg), + }, + ] +} + #[derive(WidgetCommon)] pub struct Skillbar<'a> { client: &'a Client, @@ -578,78 +723,58 @@ impl<'a> Widget for Skillbar<'a> { }, }) }; - // Slot 1-5 - // Slot 1 + + let slots = slots_entries(state, slot_offset); + slot_maker.empty_slot = self.imgs.skillbar_slot; slot_maker.selected_slot = self.imgs.skillbar_slot; - let slot = slot_maker - .fabricate(hotbar::Slot::One, [40.0; 2]) - .filled_slot(self.imgs.skillbar_slot) - .bottom_left_with_margins_on(state.ids.frame, 0.0, 0.0); - if let Some(item) = slot_content(hotbar::Slot::One) { - slot.with_item_tooltip(self.item_tooltip_manager, item, &None, &item_tooltip) - .set(state.ids.slot1, ui); - } else if let Some((title, desc)) = tooltip_text(hotbar::Slot::One) { - slot.with_tooltip(self.tooltip_manager, title, desc, &tooltip, TEXT_COLOR) - .set(state.ids.slot1, ui); - } else { - slot.set(state.ids.slot1, ui); - } - // Slot 2 - let slot = slot_maker - .fabricate(hotbar::Slot::Two, [40.0; 2]) - .filled_slot(self.imgs.skillbar_slot) - .right_from(state.ids.slot1, slot_offset); - if let Some(item) = slot_content(hotbar::Slot::Two) { - slot.with_item_tooltip(self.item_tooltip_manager, item, &None, &item_tooltip) - .set(state.ids.slot2, ui); - } else if let Some((title, desc)) = tooltip_text(hotbar::Slot::Two) { - slot.with_tooltip(self.tooltip_manager, title, desc, &tooltip, TEXT_COLOR) - .set(state.ids.slot2, ui); - } else { - slot.set(state.ids.slot2, ui); - } - // Slot 3 - let slot = slot_maker - .fabricate(hotbar::Slot::Three, [40.0; 2]) - .filled_slot(self.imgs.skillbar_slot) - .right_from(state.ids.slot2, slot_offset); - if let Some(item) = slot_content(hotbar::Slot::Three) { - slot.with_item_tooltip(self.item_tooltip_manager, item, &None, &item_tooltip) - .set(state.ids.slot3, ui); - } else if let Some((title, desc)) = tooltip_text(hotbar::Slot::Three) { - slot.with_tooltip(self.tooltip_manager, title, desc, &tooltip, TEXT_COLOR) - .set(state.ids.slot3, ui); - } else { - slot.set(state.ids.slot3, ui); - } - // Slot 4 - let slot = slot_maker - .fabricate(hotbar::Slot::Four, [40.0; 2]) - .filled_slot(self.imgs.skillbar_slot) - .right_from(state.ids.slot3, slot_offset); - if let Some(item) = slot_content(hotbar::Slot::Four) { - slot.with_item_tooltip(self.item_tooltip_manager, item, &None, &item_tooltip) - .set(state.ids.slot4, ui); - } else if let Some((title, desc)) = tooltip_text(hotbar::Slot::Four) { - slot.with_tooltip(self.tooltip_manager, title, desc, &tooltip, TEXT_COLOR) - .set(state.ids.slot4, ui); - } else { - slot.set(state.ids.slot4, ui); - } - // Slot 5 - let slot = slot_maker - .fabricate(hotbar::Slot::Five, [40.0; 2]) - .filled_slot(self.imgs.skillbar_slot) - .right_from(state.ids.slot4, slot_offset); - if let Some(item) = slot_content(hotbar::Slot::Five) { - slot.with_item_tooltip(self.item_tooltip_manager, item, &None, &item_tooltip) - .set(state.ids.slot5, ui); - } else if let Some((title, desc)) = tooltip_text(hotbar::Slot::Five) { - slot.with_tooltip(self.tooltip_manager, title, desc, &tooltip, TEXT_COLOR) - .set(state.ids.slot5, ui); - } else { - slot.set(state.ids.slot5, ui); + for entry in slots { + let slot = slot_maker + .fabricate(entry.slot, [40.0; 2]) + .filled_slot(self.imgs.skillbar_slot) + .position(entry.position); + // if there is an item attached, show item tooltip + if let Some(item) = slot_content(entry.slot) { + slot.with_item_tooltip(self.item_tooltip_manager, item, &None, &item_tooltip) + .set(entry.widget_id, ui); + // if we can gather some text to display, show it + } else if let Some((title, desc)) = tooltip_text(entry.slot) { + slot.with_tooltip(self.tooltip_manager, title, desc, &tooltip, TEXT_COLOR) + .set(entry.widget_id, ui); + // if not, just set slot + } else { + slot.set(entry.widget_id, ui); + } + + // shortcuts + if let ShortcutNumbers::On = shortcuts { + if let Some(key) = &self + .global_state + .settings + .controls + .get_binding(entry.game_input) + { + let position = entry.shortcut_position; + let position_bg = entry.shortcut_position_bg; + let (id, id_bg) = entry.shortcut_widget_ids; + + let key_desc = key.display_string(key_layout); + // shortcut text + Text::new(&key_desc) + .position(position) + .font_size(self.fonts.cyri.scale(8)) + .font_id(self.fonts.cyri.conrod_id) + .color(TEXT_COLOR) + .set(id, ui); + // shortcut background + Text::new(&key_desc) + .position(position_bg) + .font_size(self.fonts.cyri.scale(8)) + .font_id(self.fonts.cyri.conrod_id) + .color(BLACK) + .set(id_bg, ui); + } + } } // Slot M1 Image::new(self.imgs.skillbar_slot) @@ -749,271 +874,7 @@ impl<'a> Widget for Skillbar<'a> { } }) .set(state.ids.m2_content, ui); - // Slot 6-10 - // Slot 6 - slot_maker.empty_slot = self.imgs.skillbar_slot; - slot_maker.selected_slot = self.imgs.skillbar_slot; - let slot = slot_maker - .fabricate(hotbar::Slot::Six, [40.0; 2]) - .filled_slot(self.imgs.skillbar_slot) - .right_from(state.ids.m2_slot_bg, slot_offset); - if let Some(item) = slot_content(hotbar::Slot::Six) { - slot.with_item_tooltip(self.item_tooltip_manager, item, &None, &item_tooltip) - .set(state.ids.slot6, ui); - } else if let Some((title, desc)) = tooltip_text(hotbar::Slot::Six) { - slot.with_tooltip(self.tooltip_manager, title, desc, &tooltip, TEXT_COLOR) - .set(state.ids.slot6, ui); - } else { - slot.set(state.ids.slot6, ui); - } - // Slot 7 - let slot = slot_maker - .fabricate(hotbar::Slot::Seven, [40.0; 2]) - .filled_slot(self.imgs.skillbar_slot) - .right_from(state.ids.slot6, slot_offset); - if let Some(item) = slot_content(hotbar::Slot::Seven) { - slot.with_item_tooltip(self.item_tooltip_manager, item, &None, &item_tooltip) - .set(state.ids.slot7, ui); - } else if let Some((title, desc)) = tooltip_text(hotbar::Slot::Seven) { - slot.with_tooltip(self.tooltip_manager, title, desc, &tooltip, TEXT_COLOR) - .set(state.ids.slot7, ui); - } else { - slot.set(state.ids.slot7, ui); - } - // Slot 8 - let slot = slot_maker - .fabricate(hotbar::Slot::Eight, [40.0; 2]) - .filled_slot(self.imgs.skillbar_slot) - .right_from(state.ids.slot7, slot_offset); - if let Some(item) = slot_content(hotbar::Slot::Eight) { - slot.with_item_tooltip(self.item_tooltip_manager, item, &None, &item_tooltip) - .set(state.ids.slot8, ui); - } else if let Some((title, desc)) = tooltip_text(hotbar::Slot::Eight) { - slot.with_tooltip(self.tooltip_manager, title, desc, &tooltip, TEXT_COLOR) - .set(state.ids.slot8, ui); - } else { - slot.set(state.ids.slot8, ui); - } - // Slot 9 - let slot = slot_maker - .fabricate(hotbar::Slot::Nine, [40.0; 2]) - .filled_slot(self.imgs.skillbar_slot) - .right_from(state.ids.slot8, slot_offset); - if let Some(item) = slot_content(hotbar::Slot::Nine) { - slot.with_item_tooltip(self.item_tooltip_manager, item, &None, &item_tooltip) - .set(state.ids.slot9, ui); - } else if let Some((title, desc)) = tooltip_text(hotbar::Slot::Nine) { - slot.with_tooltip(self.tooltip_manager, title, desc, &tooltip, TEXT_COLOR) - .set(state.ids.slot9, ui); - } else { - slot.set(state.ids.slot9, ui); - } - // Quickslot - slot_maker.empty_slot = self.imgs.skillbar_slot; - slot_maker.selected_slot = self.imgs.skillbar_slot; - let slot = slot_maker - .fabricate(hotbar::Slot::Ten, [40.0; 2]) - .filled_slot(self.imgs.skillbar_slot) - .right_from(state.ids.slot9, slot_offset); - if let Some((title, desc)) = tooltip_text(hotbar::Slot::Ten) { - slot.with_tooltip(self.tooltip_manager, title, desc, &tooltip, TEXT_COLOR) - .set(state.ids.slot10, ui); - } else { - slot.set(state.ids.slot10, ui); - } - // Shortcuts - if let ShortcutNumbers::On = shortcuts { - if let Some(slot1) = &self - .global_state - .settings - .controls - .get_binding(GameInput::Slot1) - { - Text::new(slot1.display_string(key_layout).as_str()) - .top_right_with_margins_on(state.ids.slot1, 3.0, 5.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(BLACK) - .set(state.ids.slot1_text_bg, ui); - Text::new(slot1.display_string(key_layout).as_str()) - .bottom_left_with_margins_on(state.ids.slot1_text_bg, 1.0, 1.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(TEXT_COLOR) - .set(state.ids.slot1_text, ui); - } - if let Some(slot2) = &self - .global_state - .settings - .controls - .get_binding(GameInput::Slot2) - { - Text::new(slot2.display_string(key_layout).as_str()) - .top_right_with_margins_on(state.ids.slot2, 3.0, 5.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(BLACK) - .set(state.ids.slot2_text_bg, ui); - Text::new(slot2.display_string(key_layout).as_str()) - .bottom_left_with_margins_on(state.ids.slot2_text_bg, 1.0, 1.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(TEXT_COLOR) - .set(state.ids.slot2_text, ui); - } - if let Some(slot3) = &self - .global_state - .settings - .controls - .get_binding(GameInput::Slot3) - { - Text::new(slot3.display_string(key_layout).as_str()) - .top_right_with_margins_on(state.ids.slot3, 3.0, 5.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(BLACK) - .set(state.ids.slot3_text_bg, ui); - Text::new(slot3.display_string(key_layout).as_str()) - .bottom_left_with_margins_on(state.ids.slot3_text_bg, 1.0, 1.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(TEXT_COLOR) - .set(state.ids.slot3_text, ui); - } - if let Some(slot4) = &self - .global_state - .settings - .controls - .get_binding(GameInput::Slot4) - { - Text::new(slot4.display_string(key_layout).as_str()) - .top_right_with_margins_on(state.ids.slot4, 3.0, 5.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(BLACK) - .set(state.ids.slot4_text_bg, ui); - Text::new(slot4.display_string(key_layout).as_str()) - .bottom_left_with_margins_on(state.ids.slot4_text_bg, 1.0, 1.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(TEXT_COLOR) - .set(state.ids.slot4_text, ui); - } - if let Some(slot5) = &self - .global_state - .settings - .controls - .get_binding(GameInput::Slot5) - { - Text::new(slot5.display_string(key_layout).as_str()) - .top_right_with_margins_on(state.ids.slot5, 3.0, 5.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(BLACK) - .set(state.ids.slot5_text_bg, ui); - Text::new(slot5.display_string(key_layout).as_str()) - .bottom_left_with_margins_on(state.ids.slot5_text_bg, 1.0, 1.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(TEXT_COLOR) - .set(state.ids.slot5_text, ui); - } - if let Some(slot6) = &self - .global_state - .settings - .controls - .get_binding(GameInput::Slot6) - { - Text::new(slot6.display_string(key_layout).as_str()) - .top_right_with_margins_on(state.ids.slot6, 3.0, 5.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(BLACK) - .set(state.ids.slot6_text_bg, ui); - Text::new(slot6.display_string(key_layout).as_str()) - .bottom_right_with_margins_on(state.ids.slot6_text_bg, 1.0, 1.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(TEXT_COLOR) - .set(state.ids.slot6_text, ui); - } - if let Some(slot7) = &self - .global_state - .settings - .controls - .get_binding(GameInput::Slot7) - { - Text::new(slot7.display_string(key_layout).as_str()) - .top_right_with_margins_on(state.ids.slot7, 3.0, 5.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(BLACK) - .set(state.ids.slot7_text_bg, ui); - Text::new(slot7.display_string(key_layout).as_str()) - .bottom_right_with_margins_on(state.ids.slot7_text_bg, 1.0, 1.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(TEXT_COLOR) - .set(state.ids.slot7_text, ui); - } - if let Some(slot8) = &self - .global_state - .settings - .controls - .get_binding(GameInput::Slot8) - { - Text::new(slot8.display_string(key_layout).as_str()) - .top_right_with_margins_on(state.ids.slot8, 3.0, 5.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(BLACK) - .set(state.ids.slot8_text_bg, ui); - Text::new(slot8.display_string(key_layout).as_str()) - .bottom_right_with_margins_on(state.ids.slot8_text_bg, 1.0, 1.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(TEXT_COLOR) - .set(state.ids.slot8_text, ui); - } - if let Some(slot9) = &self - .global_state - .settings - .controls - .get_binding(GameInput::Slot9) - { - Text::new(slot9.display_string(key_layout).as_str()) - .top_right_with_margins_on(state.ids.slot9, 3.0, 5.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(BLACK) - .set(state.ids.slot9_text_bg, ui); - Text::new(slot9.display_string(key_layout).as_str()) - .bottom_right_with_margins_on(state.ids.slot9_text_bg, 1.0, 1.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(TEXT_COLOR) - .set(state.ids.slot9_text, ui); - } - if let Some(slot10) = &self - .global_state - .settings - .controls - .get_binding(GameInput::Slot10) - { - Text::new(slot10.display_string(key_layout).as_str()) - .top_right_with_margins_on(state.ids.slot10, 3.0, 5.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(BLACK) - .set(state.ids.slot10_text_bg, ui); - Text::new(slot10.display_string(key_layout).as_str()) - .bottom_right_with_margins_on(state.ids.slot10_text_bg, 1.0, 1.0) - .font_size(self.fonts.cyri.scale(8)) - .font_id(self.fonts.cyri.conrod_id) - .color(TEXT_COLOR) - .set(state.ids.slot10_text, ui); - } - }; + // M1 and M2 icons Image::new(self.imgs.m1_ico) .w_h(16.0, 18.0) @@ -1044,17 +905,20 @@ impl<'a> Widget for Skillbar<'a> { Rectangle::fill_with([10.0, 10.0], color::TRANSPARENT) .middle_of(ui.window) .set(state.ids.combo_align, ui); + let bg_align = PositionSpecifier::MidBottomWithMarginOn( + state.ids.combo_align, + -350.0 + time_since_last_update * -8.0, + ); + let align = + PositionSpecifier::BottomRightWithMarginsOn(state.ids.combo_bg, 1.0, 1.0); Text::new(combo_txt.as_str()) - .mid_bottom_with_margin_on( - state.ids.combo_align, - -350.0 + time_since_last_update * -8.0, - ) + .position(bg_align) .font_size(self.fonts.cyri.scale(fnt_size)) .font_id(self.fonts.cyri.conrod_id) .color(Color::Rgba(0.0, 0.0, 0.0, alpha)) .set(state.ids.combo_bg, ui); Text::new(combo_txt.as_str()) - .bottom_right_with_margins_on(state.ids.combo_bg, 1.0, 1.0) + .position(align) .font_size(self.fonts.cyri.scale(fnt_size)) .font_id(self.fonts.cyri.conrod_id) .color(fnt_col) From e6c451ca4bde47af070f9746935e23f3ab040c9f Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Tue, 20 Jul 2021 20:58:31 +0300 Subject: [PATCH 002/155] Prettify skillbar code --- voxygen/src/hud/skillbar.rs | 100 ++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 56 deletions(-) diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index 493267172b..4cb45961f9 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -177,7 +177,7 @@ struct SlotEntry { shortcut_widget_ids: (widget::Id, widget::Id), } -fn slots_entries(state: &State, slot_offset: f64) -> [SlotEntry; 10] { +fn slot_entries(state: &State, slot_offset: f64) -> [SlotEntry; 10] { use PositionSpecifier::*; [ @@ -590,7 +590,8 @@ impl<'a> Widget for Skillbar<'a> { .set(state.ids.stamina_txt, ui); } // Slots - let content_source = (self.hotbar, self.inventory, self.energy, self.skillset); // TODO: avoid this + // TODO: avoid this + let content_source = (self.hotbar, self.inventory, self.energy, self.skillset); let image_source = (self.item_imgs, self.imgs); let mut slot_maker = SlotMaker { // TODO: is a separate image needed for the frame? @@ -660,74 +661,61 @@ impl<'a> Widget for Skillbar<'a> { .desc_text_color(TEXT_COLOR); let slot_content = |slot| { - content_source - .0 - .get(slot) - .and_then(|content| match content { - hotbar::SlotContents::Inventory(i) => content_source.1.get(i), - _ => None, - }) + let (hotbar, inventory, ..) = content_source; + hotbar.get(slot).and_then(|content| match content { + hotbar::SlotContents::Inventory(i) => inventory.get(i), + _ => None, + }) }; // Helper let tooltip_text = |slot| { - content_source - .0 - .get(slot) - .and_then(|content| match content { - hotbar::SlotContents::Inventory(i) => content_source - .1 - .get(i) - .map(|item| (item.name(), item.description())), - hotbar::SlotContents::Ability3 => content_source - .1 - .equipped(EquipSlot::ActiveMainhand) - .map(|i| i.kind()) - .and_then(|kind| match kind { - ItemKind::Tool(Tool { kind, .. }) => ability_description(kind), - _ => None, - }), - hotbar::SlotContents::Ability4 => { - let hands = |equip_slot| match content_source - .1 - .equipped(equip_slot) - .map(|i| i.kind()) - { + let (hotbar, inventory, ..) = content_source; + hotbar.get(slot).and_then(|content| match content { + hotbar::SlotContents::Inventory(i) => inventory + .get(i) + .map(|item| (item.name(), item.description())), + hotbar::SlotContents::Ability3 => inventory + .equipped(EquipSlot::ActiveMainhand) + .map(|i| i.kind()) + .and_then(|kind| match kind { + ItemKind::Tool(Tool { kind, .. }) => ability_description(kind), + _ => None, + }), + hotbar::SlotContents::Ability4 => { + let hands = + |equip_slot| match inventory.equipped(equip_slot).map(|i| i.kind()) { Some(ItemKind::Tool(tool)) => Some(tool.hands), _ => None, }; - let active_tool_hands = hands(EquipSlot::ActiveMainhand); - let second_tool_hands = hands(EquipSlot::ActiveOffhand); + let active_tool_hands = hands(EquipSlot::ActiveMainhand); + let second_tool_hands = hands(EquipSlot::ActiveOffhand); - let equip_slot = match (active_tool_hands, second_tool_hands) { - (Some(Hands::Two), _) => Some(EquipSlot::ActiveMainhand), - (Some(_), Some(Hands::One)) => Some(EquipSlot::ActiveOffhand), - (Some(Hands::One), _) => Some(EquipSlot::ActiveMainhand), - (None, Some(_)) => Some(EquipSlot::ActiveOffhand), - (_, _) => None, - }; + let equip_slot = match (active_tool_hands, second_tool_hands) { + (Some(Hands::Two), _) => Some(EquipSlot::ActiveMainhand), + (Some(_), Some(Hands::One)) => Some(EquipSlot::ActiveOffhand), + (Some(Hands::One), _) => Some(EquipSlot::ActiveMainhand), + (None, Some(_)) => Some(EquipSlot::ActiveOffhand), + (_, _) => None, + }; - if let Some(equip_slot) = equip_slot { - content_source - .1 - .equipped(equip_slot) - .map(|i| i.kind()) - .and_then(|kind| match kind { - ItemKind::Tool(Tool { kind, .. }) => ability_description(kind), - _ => None, - }) - } else { - None - } - }, - }) + equip_slot.and_then(|equip_slot| { + inventory + .equipped(equip_slot) + .map(|i| i.kind()) + .and_then(|kind| match kind { + ItemKind::Tool(Tool { kind, .. }) => ability_description(kind), + _ => None, + }) + }) + }, + }) }; - let slots = slots_entries(state, slot_offset); - slot_maker.empty_slot = self.imgs.skillbar_slot; slot_maker.selected_slot = self.imgs.skillbar_slot; + let slots = slot_entries(state, slot_offset); for entry in slots { let slot = slot_maker .fabricate(entry.slot, [40.0; 2]) From 1bdab02aade956bc9b518fe6d976b586bc51faf3 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Tue, 20 Jul 2021 22:28:16 +0300 Subject: [PATCH 003/155] Deduplicate bar text --- common/src/comp/energy.rs | 4 ++ common/src/comp/health.rs | 3 +- voxygen/src/hud/skillbar.rs | 122 ++++++++++++++++-------------------- 3 files changed, 60 insertions(+), 69 deletions(-) diff --git a/common/src/comp/energy.rs b/common/src/comp/energy.rs index d096414e0c..3cdae6d9b0 100644 --- a/common/src/comp/energy.rs +++ b/common/src/comp/energy.rs @@ -2,6 +2,7 @@ use crate::comp::Body; use serde::{Deserialize, Serialize}; use specs::{Component, DerefFlaggedStorage}; use specs_idvs::IdvStorage; +use std::cmp; pub const ENERGY_PER_LEVEL: u32 = 50; #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] @@ -116,6 +117,9 @@ impl Energy { }); } } + + /// Returns the fraction of energy an entity has remaining + pub fn fraction(&self) -> f32 { self.current as f32 / cmp::max(self.maximum, 1) as f32 } } pub struct EnergyChange { diff --git a/common/src/comp/health.rs b/common/src/comp/health.rs index 7f39648b34..7747db8691 100644 --- a/common/src/comp/health.rs +++ b/common/src/comp/health.rs @@ -2,6 +2,7 @@ use crate::comp::Body; use crate::{uid::Uid, DamageSource}; use serde::{Deserialize, Serialize}; +use std::cmp; #[cfg(not(target_arch = "wasm32"))] use specs::{Component, DerefFlaggedStorage}; @@ -142,7 +143,7 @@ impl Health { } /// Returns the fraction of health an entity has remaining - pub fn fraction(&self) -> f32 { self.current as f32 / self.maximum.max(1) as f32 } + pub fn fraction(&self) -> f32 { self.current as f32 / cmp::max(self.maximum, 1) as f32 } } #[cfg(not(target_arch = "wasm32"))] diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index 4cb45961f9..99ea95e319 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -29,10 +29,12 @@ use common::comp::{ Energy, Health, Inventory, SkillSet, }; use conrod_core::{ + UiCell, color, widget::{self, Button, Image, Rectangle, Text}, widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon, }; +use std::cmp; use vek::*; widget_ids! { @@ -373,20 +375,22 @@ impl<'a> Widget for Skillbar<'a> { common_base::prof_span!("Skillbar::update"); let widget::UpdateArgs { state, ui, .. } = args; - let max_hp = self.health.base_max().max(self.health.maximum()); - - let mut hp_percentage = self.health.current() as f64 / max_hp as f64 * 100.0; - let mut energy_percentage = - self.energy.current() as f64 / self.energy.maximum() as f64 * 100.0; - if self.health.is_dead { - hp_percentage = 0.0; - energy_percentage = 0.0; + let (hp_percentage, energy_percentage): (f64, f64) = if self.health.is_dead { + (0.0, 0.0) + } else { + let max_hp = cmp::max(self.health.base_max(), self.health.maximum()) as f64; + let current_hp = self.health.current() as f64; + ( + current_hp / max_hp * 100.0, + (self.energy.fraction() * 100.0).into(), + ) }; let bar_values = self.global_state.settings.interface.bar_numbers; let shortcuts = self.global_state.settings.interface.shortcut_numbers; - let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; //Animation timer + // Animation timer + let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani); let localized_strings = self.localized_strings; @@ -514,81 +518,63 @@ impl<'a> Widget for Skillbar<'a> { .set(state.ids.frame_stamina, ui); } // Bar Text - // Values - if let BarNumbers::Values = bar_values { - let mut hp_txt = format!( - "{}/{}", - (self.health.current() / 10).max(1) as u32, /* Don't show 0 health for - * living players */ - (self.health.maximum() / 10) as u32 - ); - let mut energy_txt = format!( - "{}/{}", - (self.energy.current() / 10) as u32, - (self.energy.maximum() / 10) as u32 - ); - if self.health.is_dead { - hp_txt = self.localized_strings.get("hud.group.dead").to_string(); - energy_txt = self.localized_strings.get("hud.group.dead").to_string(); - }; - Text::new(&hp_txt) + let show_bar_text = |hp_txt: &str, energy_txt: &str, ui: &mut UiCell| { + Text::new(hp_txt) .middle_of(state.ids.frame_health) .font_size(self.fonts.cyri.scale(12)) .font_id(self.fonts.cyri.conrod_id) .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) .set(state.ids.hp_txt_bg, ui); - Text::new(&hp_txt) + Text::new(hp_txt) .bottom_left_with_margins_on(state.ids.hp_txt_bg, 2.0, 2.0) .font_size(self.fonts.cyri.scale(12)) .font_id(self.fonts.cyri.conrod_id) .color(TEXT_COLOR) .set(state.ids.hp_txt, ui); - Text::new(&energy_txt) + Text::new(energy_txt) .middle_of(state.ids.frame_stamina) .font_size(self.fonts.cyri.scale(12)) .font_id(self.fonts.cyri.conrod_id) .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) .set(state.ids.stamina_txt_bg, ui); - Text::new(&energy_txt) - .bottom_left_with_margins_on(state.ids.stamina_txt_bg, 2.0, 2.0) - .font_size(self.fonts.cyri.scale(12)) - .font_id(self.fonts.cyri.conrod_id) - .color(TEXT_COLOR) - .set(state.ids.stamina_txt, ui); - } - //Percentages - if let BarNumbers::Percent = bar_values { - let mut hp_txt = format!("{}%", hp_percentage as u32); - let mut energy_txt = format!("{}", energy_percentage as u32); - if self.health.is_dead { - hp_txt = self.localized_strings.get("hud.group.dead").to_string(); - energy_txt = self.localized_strings.get("hud.group.dead").to_string(); - }; - Text::new(&hp_txt) - .middle_of(state.ids.frame_health) - .font_size(self.fonts.cyri.scale(12)) - .font_id(self.fonts.cyri.conrod_id) - .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) - .set(state.ids.hp_txt_bg, ui); - Text::new(&hp_txt) - .bottom_left_with_margins_on(state.ids.hp_txt_bg, 2.0, 2.0) - .font_size(self.fonts.cyri.scale(12)) - .font_id(self.fonts.cyri.conrod_id) - .color(TEXT_COLOR) - .set(state.ids.hp_txt, ui); - Text::new(&energy_txt) - .middle_of(state.ids.frame_stamina) - .font_size(self.fonts.cyri.scale(12)) - .font_id(self.fonts.cyri.conrod_id) - .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) - .set(state.ids.stamina_txt_bg, ui); - Text::new(&energy_txt) + Text::new(energy_txt) .bottom_left_with_margins_on(state.ids.stamina_txt_bg, 2.0, 2.0) .font_size(self.fonts.cyri.scale(12)) .font_id(self.fonts.cyri.conrod_id) .color(TEXT_COLOR) .set(state.ids.stamina_txt, ui); + }; + let bar_text = if self.health.is_dead { + Some(( + self.localized_strings.get("hud.group.dead").to_owned(), + self.localized_strings.get("hud.group.dead").to_owned(), + )) + } else if let BarNumbers::Values = bar_values { + Some(( + format!( + "{}/{}", + (self.health.current() / 10).max(1) as u32, /* Don't show 0 health for + * living players */ + (self.health.maximum() / 10) as u32 + ), + format!( + "{}/{}", + (self.energy.current() / 10) as u32, + (self.energy.maximum() / 10) as u32 + ), + )) + } else if let BarNumbers::Percent = bar_values { + Some(( + format!("{}%", hp_percentage as u32), + format!("{}%", energy_percentage as u32), + )) + } else { + None + }; + if let Some((hp_txt, energy_txt)) = bar_text { + show_bar_text(&hp_txt, &energy_txt, ui); } + // Slots // TODO: avoid this let content_source = (self.hotbar, self.inventory, self.energy, self.skillset); @@ -683,11 +669,11 @@ impl<'a> Widget for Skillbar<'a> { _ => None, }), hotbar::SlotContents::Ability4 => { - let hands = - |equip_slot| match inventory.equipped(equip_slot).map(|i| i.kind()) { - Some(ItemKind::Tool(tool)) => Some(tool.hands), - _ => None, - }; + let hands = |equip_slot| match inventory.equipped(equip_slot).map(|i| i.kind()) + { + Some(ItemKind::Tool(tool)) => Some(tool.hands), + _ => None, + }; let active_tool_hands = hands(EquipSlot::ActiveMainhand); let second_tool_hands = hands(EquipSlot::ActiveOffhand); From 034913a22d9899f33e3ec9550bf53357c2114129 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Tue, 20 Jul 2021 23:28:41 +0300 Subject: [PATCH 004/155] Update skillbar ability text --- voxygen/src/hud/skillbar.rs | 46 ++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index 99ea95e319..96f43d0f0e 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -29,10 +29,9 @@ use common::comp::{ Energy, Health, Inventory, SkillSet, }; use conrod_core::{ - UiCell, color, widget::{self, Button, Image, Rectangle, Text}, - widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon, + widget_ids, Color, Colorable, Positionable, Sizeable, UiCell, Widget, WidgetCommon, }; use std::cmp; use vek::*; @@ -873,9 +872,10 @@ impl<'a> Widget for Skillbar<'a> { (1.0 - combo_cnt / (combo_cnt + 5.0)).max(0.17), alpha, ); - + // Increase size for higher counts, + // "flash" on update by increasing the font size by 2. let fnt_size = ((14.0 + combo.timer as f32 * 0.8).min(30.0)) as u32 - + if (time_since_last_update) < 0.1 { 2 } else { 0 }; // Increase size for higher counts, "flash" on update by increasing the font size by 2 + + if (time_since_last_update) < 0.1 { 2 } else { 0 }; Rectangle::fill_with([10.0, 10.0], color::TRANSPARENT) .middle_of(ui.window) .set(state.ids.combo_align, ui); @@ -906,29 +906,43 @@ fn ability_description(tool: &ToolKind) -> Option<(&str, &str)> { match tool { ToolKind::Hammer => Some(( "Smash of Doom", - "\nAn AOE attack with knockback. \nLeaps to position of cursor.", + concat!( + "\n", + "An AOE attack with knockback.\n", + "Leaps to position of cursor.", + ), + )), + ToolKind::Axe => Some(( + "Axe Jump", + concat!("\n", "A jump with the slashing leap to position of cursor."), )), - ToolKind::Axe => Some(("Spin Leap", "\nA slashing running spin leap.")), ToolKind::Staff => Some(( - "Firebomb", - "\nWhirls a big fireball into the air. \nExplodes the ground and does\na big amount \ - of damage", + "Ring of Fire", + concat!("\n", "Explodes the gound with fire shockwave."), )), ToolKind::Sword => Some(( "Whirlwind", - "\nMove forward while spinning with \n your sword.", + concat!("\n", "Move forward while spinning with your sword."), )), ToolKind::Bow => Some(( "Burst", - "\nLaunches a burst of arrows at the top \nof a running leap.", - )), - ToolKind::Debug => Some(( - "Possessing Arrow", - "\nShoots a poisonous arrow.\nLets you control your target.", + concat!("\n", "Launches a burst of arrows into your target"), )), ToolKind::Sceptre => Some(( "Thorn Bulwark", - "\nProtects you and your group with thorns\nfor a short amount of time.", + concat!( + "\n", + "Protects you and your group with thorns\n", + "for a short amount of time.", + ), + )), + ToolKind::Debug => Some(( + "Possessing Arrow", + concat!( + "\n", + "Shoots a poisonous arrow.\n", + "Lets you control your target." + ), )), _ => None, } From 930a156cab349951376baa6283f7a588dd48ac0f Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Wed, 21 Jul 2021 17:53:03 +0300 Subject: [PATCH 005/155] display_shortened for keys --- voxygen/src/hud/buttons.rs | 7 ++++-- voxygen/src/hud/settings_window/controls.rs | 15 ++++++++--- voxygen/src/hud/skillbar.rs | 4 ++- voxygen/src/window.rs | 28 +++++++++++++++++++-- 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/voxygen/src/hud/buttons.rs b/voxygen/src/hud/buttons.rs index 67384475b5..79bde0effd 100644 --- a/voxygen/src/hud/buttons.rs +++ b/voxygen/src/hud/buttons.rs @@ -425,9 +425,12 @@ impl<'a> Buttons<'a> { text: widget::Id, ) { let key_layout = &self.global_state.window.key_layout; + let key_desc = key_mouse + .display_shortened(key_layout) + .unwrap_or_else(|| key_mouse.display_string(key_layout)); //Create shadow - Text::new(key_mouse.display_string(key_layout).as_str()) + Text::new(&key_desc) .bottom_right_with_margins_on(button_identifier, 0.0, 0.0) .font_size(10) .font_id(self.fonts.cyri.conrod_id) @@ -435,7 +438,7 @@ impl<'a> Buttons<'a> { .set(text_background, ui); //Create button - Text::new(key_mouse.display_string(key_layout).as_str()) + Text::new(&key_desc) .bottom_right_with_margins_on(text_background, 1.0, 1.0) .font_size(10) .font_id(self.fonts.cyri.conrod_id) diff --git a/voxygen/src/hud/settings_window/controls.rs b/voxygen/src/hud/settings_window/controls.rs index ee9b129ecd..51b842f936 100644 --- a/voxygen/src/hud/settings_window/controls.rs +++ b/voxygen/src/hud/settings_window/controls.rs @@ -123,12 +123,19 @@ impl<'a> Widget for Controls<'a> { let (key_string, key_color) = if self.global_state.window.remapping_keybindings == Some(game_input) { ( - String::from(self.localized_strings.get("hud.settings.awaitingkey")), + self.localized_strings + .get("hud.settings.awaitingkey") + .to_owned(), TEXT_COLOR, ) } else if let Some(key) = controls.get_binding(game_input) { ( - key.display_string(key_layout), + format!( + "{} {}", + key.display_string(key_layout), + key.display_shortened(key_layout) + .map_or("".to_owned(), |short| format!("({})", short)) + ), if controls.has_conflicting_bindings(key) { TEXT_BIND_CONFLICT_COLOR } else { @@ -137,7 +144,9 @@ impl<'a> Widget for Controls<'a> { ) } else { ( - String::from(self.localized_strings.get("hud.settings.unbound")), + self.localized_strings + .get("hud.settings.unbound") + .to_owned(), ERROR_COLOR, ) }; diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index 96f43d0f0e..fe34b6a8a3 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -731,7 +731,9 @@ impl<'a> Widget for Skillbar<'a> { let position_bg = entry.shortcut_position_bg; let (id, id_bg) = entry.shortcut_widget_ids; - let key_desc = key.display_string(key_layout); + let key_desc = key + .display_shortened(key_layout) + .unwrap_or_else(|| key.display_string(key_layout)); // shortcut text Text::new(&key_desc) .position(position) diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index 6df984ff32..3663e3443a 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -106,6 +106,7 @@ pub enum KeyMouse { } impl KeyMouse { + /// Returns key description (e.g Left Shift) pub fn display_string(&self, key_layout: &Option) -> String { use self::KeyMouse::*; use winit::event::{MouseButton, VirtualKeyCode::*}; @@ -225,6 +226,7 @@ impl KeyMouse { Key(MediaSelect) => "MediaSelect", Key(MediaStop) => "MediaStop", Key(Minus) => "-", + Key(Plus) => "+", Key(NumpadMultiply) => "Numpad *", Key(Mute) => "Mute", Key(MyComputer) => "My Computer", @@ -322,7 +324,6 @@ impl KeyMouse { Key(Paste) => "Paste", Key(Cut) => "Cut", Key(Asterisk) => "*", - Key(Plus) => "+", Mouse(MouseButton::Left) => "Left Click", Mouse(MouseButton::Right) => "Right Click", Mouse(MouseButton::Middle) => "Middle Click", @@ -339,7 +340,30 @@ impl KeyMouse { }, }; - String::from(key_string) + key_string.to_owned() + } + + /// Returns shortened key name (e.g. Left Click -> LMB) + /// + /// Use it in case if space does really matter. + pub fn display_shortened(&self, _key_layout: &Option) -> Option { + use self::KeyMouse::*; + use winit::event::{MouseButton, VirtualKeyCode::*}; + let key_string = match self { + Mouse(MouseButton::Left) => "M1", + Mouse(MouseButton::Right) => "M2", + Mouse(MouseButton::Middle) => "M3", + Mouse(MouseButton::Other(button)) => { + // Additional mouse buttons after middle click start at 1 + return Some(format!("M{}", button + 3)); + }, + Key(Back) => "Back", + Key(LShift) => "LShft", + Key(RShift) => "RShft", + _ => return None, + }; + + Some(key_string.to_owned()) } } From 4811ede2ea9d9a6875a3eb515eebabb609f446d0 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Thu, 22 Jul 2021 22:57:04 +0300 Subject: [PATCH 006/155] Split Skillbar::update to separate stages --- voxygen/src/hud/mod.rs | 34 ++++ voxygen/src/hud/skillbar.rs | 340 +++++++++++++++++------------------- 2 files changed, 195 insertions(+), 179 deletions(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 66cf68cf19..856447eb5b 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -316,6 +316,40 @@ widget_ids! { } } +// TODO: extend as you need it +#[derive(Clone, Copy)] +pub enum PositionSpecifier { + MidBottomWithMarginOn(widget::Id, f64), + TopRightWithMarginsOn(widget::Id, f64, f64), + BottomRightWithMarginsOn(widget::Id, f64, f64), + BottomLeftWithMarginsOn(widget::Id, f64, f64), + RightFrom(widget::Id, f64), +} + +pub trait Position { + fn position(self, request: PositionSpecifier) -> Self; +} + +impl Position for W { + fn position(self, request: PositionSpecifier) -> Self { + match request { + PositionSpecifier::MidBottomWithMarginOn(other, margin) => { + self.mid_bottom_with_margin_on(other, margin) + }, + PositionSpecifier::TopRightWithMarginsOn(other, top, right) => { + self.top_right_with_margins_on(other, top, right) + }, + PositionSpecifier::BottomRightWithMarginsOn(other, bottom, right) => { + self.bottom_right_with_margins_on(other, bottom, right) + }, + PositionSpecifier::BottomLeftWithMarginsOn(other, bottom, left) => { + self.bottom_left_with_margins_on(other, bottom, left) + }, + PositionSpecifier::RightFrom(other, offset) => self.right_from(other, offset), + } + } +} + #[derive(Clone, Copy)] pub struct BuffInfo { kind: comp::BuffKind, diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index fe34b6a8a3..f122b0e06f 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -7,7 +7,7 @@ use super::{ }; use crate::{ game_input::GameInput, - hud::ComboFloater, + hud::{ComboFloater, Position, PositionSpecifier}, i18n::Localization, ui::{ fonts::Fonts, @@ -132,41 +132,6 @@ widget_ids! { } } -// TODO: extend as you need it -// Make it public to use throughout the code? -#[derive(Clone, Copy)] -enum PositionSpecifier { - MidBottomWithMarginOn(widget::Id, f64), - TopRightWithMarginsOn(widget::Id, f64, f64), - BottomRightWithMarginsOn(widget::Id, f64, f64), - BottomLeftWithMarginsOn(widget::Id, f64, f64), - RightFrom(widget::Id, f64), -} - -trait Position { - fn position(self, request: PositionSpecifier) -> Self; -} - -impl Position for W { - fn position(self, request: PositionSpecifier) -> Self { - match request { - PositionSpecifier::MidBottomWithMarginOn(other, margin) => { - self.mid_bottom_with_margin_on(other, margin) - }, - PositionSpecifier::TopRightWithMarginsOn(other, top, right) => { - self.top_right_with_margins_on(other, top, right) - }, - PositionSpecifier::BottomRightWithMarginsOn(other, bottom, right) => { - self.bottom_right_with_margins_on(other, bottom, right) - }, - PositionSpecifier::BottomLeftWithMarginsOn(other, bottom, left) => { - self.bottom_left_with_margins_on(other, bottom, left) - }, - PositionSpecifier::RightFrom(other, offset) => self.right_from(other, offset), - } - } -} - #[derive(Clone, Copy)] struct SlotEntry { slot: hotbar::Slot, @@ -351,29 +316,53 @@ impl<'a> Skillbar<'a> { combo, } } -} -pub struct State { - ids: Ids, -} + fn show_death_message(&self, state: &State, ui: &mut UiCell) { + let localized_strings = self.localized_strings; + let key_layout = &self.global_state.window.key_layout; -impl<'a> Widget for Skillbar<'a> { - type Event = (); - type State = State; - type Style = (); - - fn init_state(&self, id_gen: widget::id::Generator) -> Self::State { - State { - ids: Ids::new(id_gen), + if let Some(key) = self + .global_state + .settings + .controls + .get_binding(GameInput::Respawn) + { + Text::new(localized_strings.get("hud.you_died")) + .middle_of(ui.window) + .font_size(self.fonts.cyri.scale(50)) + .font_id(self.fonts.cyri.conrod_id) + .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) + .set(state.ids.death_message_1_bg, ui); + Text::new( + &localized_strings + .get("hud.press_key_to_respawn") + .replace("{key}", key.display_string(key_layout).as_str()), + ) + .mid_bottom_with_margin_on(state.ids.death_message_1_bg, -120.0) + .font_size(self.fonts.cyri.scale(30)) + .font_id(self.fonts.cyri.conrod_id) + .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) + .set(state.ids.death_message_2_bg, ui); + Text::new(localized_strings.get("hud.you_died")) + .bottom_left_with_margins_on(state.ids.death_message_1_bg, 2.0, 2.0) + .font_size(self.fonts.cyri.scale(50)) + .font_id(self.fonts.cyri.conrod_id) + .color(CRITICAL_HP_COLOR) + .set(state.ids.death_message_1, ui); + Text::new( + &localized_strings + .get("hud.press_key_to_respawn") + .replace("{key}", key.display_string(key_layout).as_str()), + ) + .bottom_left_with_margins_on(state.ids.death_message_2_bg, 2.0, 2.0) + .font_size(self.fonts.cyri.scale(30)) + .font_id(self.fonts.cyri.conrod_id) + .color(CRITICAL_HP_COLOR) + .set(state.ids.death_message_2, ui); } } - fn style(&self) -> Self::Style {} - - fn update(self, args: widget::UpdateArgs) -> Self::Event { - common_base::prof_span!("Skillbar::update"); - let widget::UpdateArgs { state, ui, .. } = args; - + fn show_stat_bars(&self, state: &State, ui: &mut UiCell) { let (hp_percentage, energy_percentage): (f64, f64) = if self.health.is_dead { (0.0, 0.0) } else { @@ -385,67 +374,10 @@ impl<'a> Widget for Skillbar<'a> { ) }; - let bar_values = self.global_state.settings.interface.bar_numbers; - let shortcuts = self.global_state.settings.interface.shortcut_numbers; - // Animation timer let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani); - - let localized_strings = self.localized_strings; - let key_layout = &self.global_state.window.key_layout; - - let slot_offset = 3.0; - - // Death message - if self.health.is_dead { - if let Some(key) = self - .global_state - .settings - .controls - .get_binding(GameInput::Respawn) - { - Text::new(localized_strings.get("hud.you_died")) - .middle_of(ui.window) - .font_size(self.fonts.cyri.scale(50)) - .font_id(self.fonts.cyri.conrod_id) - .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) - .set(state.ids.death_message_1_bg, ui); - Text::new( - &localized_strings - .get("hud.press_key_to_respawn") - .replace("{key}", key.display_string(key_layout).as_str()), - ) - .mid_bottom_with_margin_on(state.ids.death_message_1_bg, -120.0) - .font_size(self.fonts.cyri.scale(30)) - .font_id(self.fonts.cyri.conrod_id) - .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) - .set(state.ids.death_message_2_bg, ui); - Text::new(localized_strings.get("hud.you_died")) - .bottom_left_with_margins_on(state.ids.death_message_1_bg, 2.0, 2.0) - .font_size(self.fonts.cyri.scale(50)) - .font_id(self.fonts.cyri.conrod_id) - .color(CRITICAL_HP_COLOR) - .set(state.ids.death_message_1, ui); - Text::new( - &localized_strings - .get("hud.press_key_to_respawn") - .replace("{key}", key.display_string(key_layout).as_str()), - ) - .bottom_left_with_margins_on(state.ids.death_message_2_bg, 2.0, 2.0) - .font_size(self.fonts.cyri.scale(30)) - .font_id(self.fonts.cyri.conrod_id) - .color(CRITICAL_HP_COLOR) - .set(state.ids.death_message_2, ui); - } - } - // Skillbar - // Alignment and BG - let alignment_size = 40.0 * 12.0 + slot_offset * 11.0; - Rectangle::fill_with([alignment_size, 80.0], color::TRANSPARENT) - .mid_bottom_with_margin_on(ui.window, 10.0) - .set(state.ids.frame, ui); - // Health and Stamina bar + let bar_values = self.global_state.settings.interface.bar_numbers; let show_health = self.health.current() != self.health.maximum(); let show_stamina = self.energy.current() != self.energy.maximum(); let decayed_health = 1.0 - self.health.maximum() as f64 / self.health.base_max() as f64; @@ -517,32 +449,6 @@ impl<'a> Widget for Skillbar<'a> { .set(state.ids.frame_stamina, ui); } // Bar Text - let show_bar_text = |hp_txt: &str, energy_txt: &str, ui: &mut UiCell| { - Text::new(hp_txt) - .middle_of(state.ids.frame_health) - .font_size(self.fonts.cyri.scale(12)) - .font_id(self.fonts.cyri.conrod_id) - .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) - .set(state.ids.hp_txt_bg, ui); - Text::new(hp_txt) - .bottom_left_with_margins_on(state.ids.hp_txt_bg, 2.0, 2.0) - .font_size(self.fonts.cyri.scale(12)) - .font_id(self.fonts.cyri.conrod_id) - .color(TEXT_COLOR) - .set(state.ids.hp_txt, ui); - Text::new(energy_txt) - .middle_of(state.ids.frame_stamina) - .font_size(self.fonts.cyri.scale(12)) - .font_id(self.fonts.cyri.conrod_id) - .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) - .set(state.ids.stamina_txt_bg, ui); - Text::new(energy_txt) - .bottom_left_with_margins_on(state.ids.stamina_txt_bg, 2.0, 2.0) - .font_size(self.fonts.cyri.scale(12)) - .font_id(self.fonts.cyri.conrod_id) - .color(TEXT_COLOR) - .set(state.ids.stamina_txt, ui); - }; let bar_text = if self.health.is_dead { Some(( self.localized_strings.get("hud.group.dead").to_owned(), @@ -571,12 +477,41 @@ impl<'a> Widget for Skillbar<'a> { None }; if let Some((hp_txt, energy_txt)) = bar_text { - show_bar_text(&hp_txt, &energy_txt, ui); - } + Text::new(&hp_txt) + .middle_of(state.ids.frame_health) + .font_size(self.fonts.cyri.scale(12)) + .font_id(self.fonts.cyri.conrod_id) + .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) + .set(state.ids.hp_txt_bg, ui); + Text::new(&hp_txt) + .bottom_left_with_margins_on(state.ids.hp_txt_bg, 2.0, 2.0) + .font_size(self.fonts.cyri.scale(12)) + .font_id(self.fonts.cyri.conrod_id) + .color(TEXT_COLOR) + .set(state.ids.hp_txt, ui); + + Text::new(&energy_txt) + .middle_of(state.ids.frame_stamina) + .font_size(self.fonts.cyri.scale(12)) + .font_id(self.fonts.cyri.conrod_id) + .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) + .set(state.ids.stamina_txt_bg, ui); + Text::new(&energy_txt) + .bottom_left_with_margins_on(state.ids.stamina_txt_bg, 2.0, 2.0) + .font_size(self.fonts.cyri.scale(12)) + .font_id(self.fonts.cyri.conrod_id) + .color(TEXT_COLOR) + .set(state.ids.stamina_txt, ui); + } + } + + fn show_slotbar(&mut self, state: &State, ui: &mut UiCell, slot_offset: f64) { + let shortcuts = self.global_state.settings.interface.shortcut_numbers; + let key_layout = &self.global_state.window.key_layout; - // Slots // TODO: avoid this let content_source = (self.hotbar, self.inventory, self.energy, self.skillset); + let image_source = (self.item_imgs, self.imgs); let mut slot_maker = SlotMaker { // TODO: is a separate image needed for the frame? @@ -700,6 +635,7 @@ impl<'a> Widget for Skillbar<'a> { slot_maker.empty_slot = self.imgs.skillbar_slot; slot_maker.selected_slot = self.imgs.skillbar_slot; + let slots = slot_entries(state, slot_offset); for entry in slots { let slot = slot_maker @@ -859,47 +795,93 @@ impl<'a> Widget for Skillbar<'a> { .w_h(16.0, 18.0) .mid_bottom_with_margin_on(state.ids.m2_content, -11.0) .set(state.ids.m2_ico, ui); + } + + fn show_combo_counter(&self, combo: ComboFloater, state: &State, ui: &mut UiCell) { + if combo.combo > 0 { + let combo_txt = format!("{} Combo", combo.combo); + let combo_cnt = combo.combo as f32; + let time_since_last_update = comp::combo::COMBO_DECAY_START - combo.timer; + let alpha = (1.0 - time_since_last_update * 0.2).min(1.0) as f32; + let fnt_col = Color::Rgba( + // White -> Yellow -> Red text color gradient depending on count + (1.0 - combo_cnt / (combo_cnt + 20.0)).max(0.79), + (1.0 - combo_cnt / (combo_cnt + 80.0)).max(0.19), + (1.0 - combo_cnt / (combo_cnt + 5.0)).max(0.17), + alpha, + ); + // Increase size for higher counts, + // "flash" on update by increasing the font size by 2. + let fnt_size = ((14.0 + combo.timer as f32 * 0.8).min(30.0)) as u32 + + if (time_since_last_update) < 0.1 { 2 } else { 0 }; + + Rectangle::fill_with([10.0, 10.0], color::TRANSPARENT) + .middle_of(ui.window) + .set(state.ids.combo_align, ui); + + Text::new(combo_txt.as_str()) + .mid_bottom_with_margin_on( + state.ids.combo_align, + -350.0 + time_since_last_update * -8.0, + ) + .font_size(self.fonts.cyri.scale(fnt_size)) + .font_id(self.fonts.cyri.conrod_id) + .color(Color::Rgba(0.0, 0.0, 0.0, alpha)) + .set(state.ids.combo_bg, ui); + Text::new(combo_txt.as_str()) + .bottom_right_with_margins_on(state.ids.combo_bg, 1.0, 1.0) + .font_size(self.fonts.cyri.scale(fnt_size)) + .font_id(self.fonts.cyri.conrod_id) + .color(fnt_col) + .set(state.ids.combo, ui); + } + } +} + +pub struct State { + ids: Ids, +} + +impl<'a> Widget for Skillbar<'a> { + type Event = (); + type State = State; + type Style = (); + + fn init_state(&self, id_gen: widget::id::Generator) -> Self::State { + State { + ids: Ids::new(id_gen), + } + } + + fn style(&self) -> Self::Style {} + + fn update(mut self, args: widget::UpdateArgs) -> Self::Event { + common_base::prof_span!("Skillbar::update"); + let widget::UpdateArgs { state, ui, .. } = args; + + let slot_offset = 3.0; + + // Death message + if self.health.is_dead { + self.show_death_message(state, ui); + } + + // Skillbar + // Alignment and BG + let alignment_size = 40.0 * 12.0 + slot_offset * 11.0; + Rectangle::fill_with([alignment_size, 80.0], color::TRANSPARENT) + .mid_bottom_with_margin_on(ui.window, 10.0) + .set(state.ids.frame, ui); + + // Health and Stamina bar + self.show_stat_bars(state, ui); + + // Slots + self.show_slotbar(state, ui, slot_offset); // Combo Counter if let Some(combo) = self.combo { - if combo.combo > 0 { - let combo_txt = format!("{} Combo", combo.combo); - let combo_cnt = combo.combo as f32; - let time_since_last_update = comp::combo::COMBO_DECAY_START - combo.timer; - let alpha = (1.0 - time_since_last_update * 0.2).min(1.0) as f32; - let fnt_col = Color::Rgba( - // White -> Yellow -> Red text color gradient depending on count - (1.0 - combo_cnt / (combo_cnt + 20.0)).max(0.79), - (1.0 - combo_cnt / (combo_cnt + 80.0)).max(0.19), - (1.0 - combo_cnt / (combo_cnt + 5.0)).max(0.17), - alpha, - ); - // Increase size for higher counts, - // "flash" on update by increasing the font size by 2. - let fnt_size = ((14.0 + combo.timer as f32 * 0.8).min(30.0)) as u32 - + if (time_since_last_update) < 0.1 { 2 } else { 0 }; - Rectangle::fill_with([10.0, 10.0], color::TRANSPARENT) - .middle_of(ui.window) - .set(state.ids.combo_align, ui); - let bg_align = PositionSpecifier::MidBottomWithMarginOn( - state.ids.combo_align, - -350.0 + time_since_last_update * -8.0, - ); - let align = - PositionSpecifier::BottomRightWithMarginsOn(state.ids.combo_bg, 1.0, 1.0); - Text::new(combo_txt.as_str()) - .position(bg_align) - .font_size(self.fonts.cyri.scale(fnt_size)) - .font_id(self.fonts.cyri.conrod_id) - .color(Color::Rgba(0.0, 0.0, 0.0, alpha)) - .set(state.ids.combo_bg, ui); - Text::new(combo_txt.as_str()) - .position(align) - .font_size(self.fonts.cyri.scale(fnt_size)) - .font_id(self.fonts.cyri.conrod_id) - .color(fnt_col) - .set(state.ids.combo, ui); - } + self.show_combo_counter(combo, state, ui); } } } From 4adc045627242d327ba4d3274ea8fd7086042644 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Sat, 24 Jul 2021 21:41:07 +0300 Subject: [PATCH 007/155] Added comments on PositionSpecifier usage --- common/src/comp/energy.rs | 3 +-- common/src/comp/health.rs | 3 +-- voxygen/src/hud/mod.rs | 48 +++++++++++++++++++++++++++++++++++++ voxygen/src/hud/skillbar.rs | 37 ++++++++++++++-------------- voxygen/src/main.rs | 4 +--- 5 files changed, 69 insertions(+), 26 deletions(-) diff --git a/common/src/comp/energy.rs b/common/src/comp/energy.rs index 3cdae6d9b0..db3ae03eb0 100644 --- a/common/src/comp/energy.rs +++ b/common/src/comp/energy.rs @@ -2,7 +2,6 @@ use crate::comp::Body; use serde::{Deserialize, Serialize}; use specs::{Component, DerefFlaggedStorage}; use specs_idvs::IdvStorage; -use std::cmp; pub const ENERGY_PER_LEVEL: u32 = 50; #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] @@ -119,7 +118,7 @@ impl Energy { } /// Returns the fraction of energy an entity has remaining - pub fn fraction(&self) -> f32 { self.current as f32 / cmp::max(self.maximum, 1) as f32 } + pub fn fraction(&self) -> f32 { self.current as f32 / self.maximum.max(1) as f32 } } pub struct EnergyChange { diff --git a/common/src/comp/health.rs b/common/src/comp/health.rs index 7747db8691..7f39648b34 100644 --- a/common/src/comp/health.rs +++ b/common/src/comp/health.rs @@ -2,7 +2,6 @@ use crate::comp::Body; use crate::{uid::Uid, DamageSource}; use serde::{Deserialize, Serialize}; -use std::cmp; #[cfg(not(target_arch = "wasm32"))] use specs::{Component, DerefFlaggedStorage}; @@ -143,7 +142,7 @@ impl Health { } /// Returns the fraction of health an entity has remaining - pub fn fraction(&self) -> f32 { self.current as f32 / cmp::max(self.maximum, 1) as f32 } + pub fn fraction(&self) -> f32 { self.current as f32 / self.maximum.max(1) as f32 } } #[cfg(not(target_arch = "wasm32"))] diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 856447eb5b..af9304279d 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -316,6 +316,8 @@ widget_ids! { } } +/// Specifier to use with `Position::position` +/// Read its documentation for more // TODO: extend as you need it #[derive(Clone, Copy)] pub enum PositionSpecifier { @@ -326,6 +328,52 @@ pub enum PositionSpecifier { RightFrom(widget::Id, f64), } +/// Trait which enables you to declare widget position +/// to use later on widget creation. +/// It is implemented for all widgets which are implement Positionable, +/// so you can easily change your code to use this method. +/// +/// Consider this example: +/// ```text +/// let slot1 = slot_maker +/// .fabricate(hotbar::Slot::One, [40.0; 2]) +/// .filled_slot(self.imgs.skillbar_slot) +/// .bottom_left_with_margins_on(state.ids.frame, 0.0, 0.0); +/// if condition { +/// call_slot1(slot1); +/// } else { +/// call_slot2(slot1); +/// } +/// let slot2 = slot_maker +/// .fabricate(hotbar::Slot::Two, [40.0; 2]) +/// .filled_slot(self.imgs.skillbar_slot) +/// .right_from(state.ids.slot1, slot_offset); +/// if condition { +/// call_slot1(slot2); +/// } else { +/// call_slot2(slot2); +/// } +/// ``` +/// Despite being identical, you can't easily deduplicate code +/// which uses slot1 and slot2 as they are calling methods to position itself. +/// This can be solved if you declare position and use it later like so +/// ```text +/// let slots = [ +/// (hotbar::Slot::One, BottomLeftWithMarginsOn(state.ids.frame, 0.0, 0.0)), +/// (hotbar::Slot::Two, RightFrom(state.ids.slot1, slot_offset)), +/// ]; +/// for (slot, pos) in slots { +/// let slot = slot_maker +/// .fabricate(slot, [40.0; 2]) +/// .filled_slot(self.imgs.skillbar_slot) +/// .position(pos); +/// if condition { +/// call_slot1(slot); +/// } else { +/// call_slot2(slot); +/// } +/// } +/// ``` pub trait Position { fn position(self, request: PositionSpecifier) -> Self; } diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index f122b0e06f..5514adf1b9 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -886,47 +886,46 @@ impl<'a> Widget for Skillbar<'a> { } } +#[rustfmt::skip] fn ability_description(tool: &ToolKind) -> Option<(&str, &str)> { match tool { ToolKind::Hammer => Some(( "Smash of Doom", - concat!( - "\n", - "An AOE attack with knockback.\n", - "Leaps to position of cursor.", - ), + "\n\ + An AOE attack with knockback.\n\ + Leaps to position of cursor.", )), ToolKind::Axe => Some(( "Axe Jump", - concat!("\n", "A jump with the slashing leap to position of cursor."), + "\n\ + A jump with the slashing leap to position of cursor.", )), ToolKind::Staff => Some(( "Ring of Fire", - concat!("\n", "Explodes the gound with fire shockwave."), + "\n\ + Explodes the gound with fire shockwave.", )), ToolKind::Sword => Some(( "Whirlwind", - concat!("\n", "Move forward while spinning with your sword."), + "\n\ + Move forward while spinning with your sword.", )), ToolKind::Bow => Some(( "Burst", - concat!("\n", "Launches a burst of arrows into your target"), + "\n\ + Launches a burst of arrows into your target", )), ToolKind::Sceptre => Some(( "Thorn Bulwark", - concat!( - "\n", - "Protects you and your group with thorns\n", - "for a short amount of time.", - ), + "\n\ + Protects you and your group with thorns\n\ + for a short amount of time.", )), ToolKind::Debug => Some(( "Possessing Arrow", - concat!( - "\n", - "Shoots a poisonous arrow.\n", - "Lets you control your target." - ), + "\n\ + Shoots a poisonous arrow.\n\ + Lets you control your target.", )), _ => None, } diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index 9550a440e6..2a52b98e68 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -111,9 +111,7 @@ fn main() { Panic Payload: {:?}\n\ PanicInfo: {}\n\ Game version: {} [{}]", - logs_dir - .join("voxygen.log.") - .display(), + logs_dir.join("voxygen.log.").display(), reason, panic_info, common::util::GIT_HASH.to_string(), From 01d1089a46915004d2a6297e8e6929dd34fb8916 Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 29 Jul 2021 03:08:43 -0400 Subject: [PATCH 008/155] Add comment to physics and replace magic number in climbing boost with a named constant, fixes #1002 --- common/src/states/climb.rs | 9 ++++++--- common/systems/src/phys.rs | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/common/src/states/climb.rs b/common/src/states/climb.rs index 71d87e84ec..9719790b56 100644 --- a/common/src/states/climb.rs +++ b/common/src/states/climb.rs @@ -68,10 +68,13 @@ impl CharacterBehavior for Data { .then(|| data.body.jump_impulse()) .flatten() { + // How strong the climb boost is relative to a normal jump + const CLIMB_BOOST_JUMP_FACTOR: f32 = 0.5; // They've climbed atop something, give them a boost - update - .local_events - .push_front(LocalEvent::Jump(data.entity, 0.5 * impulse / data.mass.0)); + update.local_events.push_front(LocalEvent::Jump( + data.entity, + CLIMB_BOOST_JUMP_FACTOR * impulse / data.mass.0, + )); }; update.character = CharacterState::Idle {}; return update; diff --git a/common/systems/src/phys.rs b/common/systems/src/phys.rs index 39a5e62fb0..8c8104a1ce 100644 --- a/common/systems/src/phys.rs +++ b/common/systems/src/phys.rs @@ -668,6 +668,8 @@ impl<'a> PhysicsData<'a> { ) .join() { + // Note: updating ori with the rest of the cache values above was attempted but + // it did not work (investigate root cause?) previous_phys_cache.ori = ori.to_quat(); } drop(guard); From a6b7e93854d2162b72f85136c9e2b9aa8250e4cf Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Thu, 29 Jul 2021 17:28:51 +0300 Subject: [PATCH 009/155] Improve ability descriptions --- voxygen/src/hud/skillbar.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index 5514adf1b9..debac354c9 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -903,7 +903,7 @@ fn ability_description(tool: &ToolKind) -> Option<(&str, &str)> { ToolKind::Staff => Some(( "Ring of Fire", "\n\ - Explodes the gound with fire shockwave.", + Ignites the ground with fiery shockwave.", )), ToolKind::Sword => Some(( "Whirlwind", @@ -913,7 +913,7 @@ fn ability_description(tool: &ToolKind) -> Option<(&str, &str)> { ToolKind::Bow => Some(( "Burst", "\n\ - Launches a burst of arrows into your target", + Launches a burst of arrows", )), ToolKind::Sceptre => Some(( "Thorn Bulwark", From c56ecee988bbfaa3a92dafca690363af0d673e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Thu, 29 Jul 2021 18:05:27 +0100 Subject: [PATCH 010/155] Fix non uniform control flow in shader --- assets/voxygen/shaders/include/shadows.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/voxygen/shaders/include/shadows.glsl b/assets/voxygen/shaders/include/shadows.glsl index bd65dd3b5c..25018a00e1 100644 --- a/assets/voxygen/shaders/include/shadows.glsl +++ b/assets/voxygen/shaders/include/shadows.glsl @@ -77,7 +77,7 @@ float ShadowCalculationPoint(uint lightIndex, vec3 fragToLight, vec3 fragNorm, / // currentDepth = -currentDepth * 0.5 + 0.5; - float visibility = texture(samplerCubeShadow(t_point_shadow_maps, s_point_shadow_maps), vec4(fragToLight, currentDepth));// / (screen_res.w/* - screen_res.z*/)/*1.0 -bias*//*-(currentDepth - bias) / screen_res.w*//*-screen_res.w*/); + float visibility = textureGrad(samplerCubeShadow(t_point_shadow_maps, s_point_shadow_maps), vec4(fragToLight, currentDepth), vec3(0), vec3(0));// / (screen_res.w/* - screen_res.z*/)/*1.0 -bias*//*-(currentDepth - bias) / screen_res.w*//*-screen_res.w*/); /* if (visibility == 1.0 || visibility == 0.0) { return visibility; } */ From 93045ba1eef6e4e3074c1c24e2110bc336da53ea Mon Sep 17 00:00:00 2001 From: Thomas Kosel Date: Thu, 29 Jul 2021 20:09:31 +0200 Subject: [PATCH 011/155] reducing complexity of character_behavior's run method by extracting logical pieces. --- common/systems/src/character_behavior.rs | 246 ++++++++++++----------- 1 file changed, 132 insertions(+), 114 deletions(-) diff --git a/common/systems/src/character_behavior.rs b/common/systems/src/character_behavior.rs index 80d3586d2f..c1da0b563d 100644 --- a/common/systems/src/character_behavior.rs +++ b/common/systems/src/character_behavior.rs @@ -5,9 +5,9 @@ use specs::{ use common::{ comp::{ - self, inventory::item::MaterialStatManifest, Beam, Body, CharacterState, Combo, Controller, - Density, Energy, Health, Inventory, InventoryManip, Mass, Melee, Mounting, Ori, - PhysicsState, Poise, PoiseState, Pos, SkillSet, StateUpdate, Stats, Vel, + self, inventory::item::MaterialStatManifest, Beam, Body, CharacterState, Combo, + ControlAction, Controller, Density, Energy, Health, Inventory, InventoryManip, Mass, Melee, + Mounting, Ori, PhysicsState, Poise, PoiseState, Pos, SkillSet, StateUpdate, Stats, Vel, }, event::{Emitter, EventBus, LocalEvent, ServerEvent}, outcome::Outcome, @@ -22,37 +22,6 @@ use common::{ use common_ecs::{Job, Origin, Phase, System}; use std::time::Duration; -fn incorporate_update( - join: &mut JoinStruct, - mut state_update: StateUpdate, - server_emitter: &mut Emitter, -) { - // TODO: if checking equality is expensive use optional field in StateUpdate - if *join.char_state != state_update.character { - *join.char_state = state_update.character - }; - *join.pos = state_update.pos; - *join.vel = state_update.vel; - *join.ori = state_update.ori; - *join.density = state_update.density; - // Note: might be changed every tick by timer anyway - if *join.energy != state_update.energy { - *join.energy = state_update.energy - }; - join.controller - .queued_inputs - .append(&mut state_update.queued_inputs); - for input in state_update.removed_inputs { - join.controller.queued_inputs.remove(&input); - } - if state_update.swap_equipped_weapons { - server_emitter.emit(ServerEvent::InventoryManip( - join.entity, - InventoryManip::SwapEquippedWeapons, - )); - } -} - #[derive(SystemData)] pub struct ReadData<'a> { entities: Entities<'a>, @@ -303,50 +272,14 @@ impl<'a> System<'a> for Sys { &read_data.dt, &read_data.msm, ); - let mut state_update = match j.character { - CharacterState::Idle => states::idle::Data.handle_event(&j, action), - CharacterState::Talk => states::talk::Data.handle_event(&j, action), - CharacterState::Climb(data) => data.handle_event(&j, action), - CharacterState::Glide(data) => data.handle_event(&j, action), - CharacterState::GlideWield => { - states::glide_wield::Data.handle_event(&j, action) - }, - CharacterState::Stunned(data) => data.handle_event(&j, action), - CharacterState::Sit => { - states::sit::Data::handle_event(&states::sit::Data, &j, action) - }, - CharacterState::Dance => { - states::dance::Data::handle_event(&states::dance::Data, &j, action) - }, - CharacterState::Sneak => { - states::sneak::Data::handle_event(&states::sneak::Data, &j, action) - }, - CharacterState::BasicBlock(data) => data.handle_event(&j, action), - CharacterState::Roll(data) => data.handle_event(&j, action), - CharacterState::Wielding => states::wielding::Data.handle_event(&j, action), - CharacterState::Equipping(data) => data.handle_event(&j, action), - CharacterState::ComboMelee(data) => data.handle_event(&j, action), - CharacterState::BasicMelee(data) => data.handle_event(&j, action), - CharacterState::BasicRanged(data) => data.handle_event(&j, action), - CharacterState::Boost(data) => data.handle_event(&j, action), - CharacterState::DashMelee(data) => data.handle_event(&j, action), - CharacterState::LeapMelee(data) => data.handle_event(&j, action), - CharacterState::SpinMelee(data) => data.handle_event(&j, action), - CharacterState::ChargedMelee(data) => data.handle_event(&j, action), - CharacterState::ChargedRanged(data) => data.handle_event(&j, action), - CharacterState::RepeaterRanged(data) => data.handle_event(&j, action), - CharacterState::Shockwave(data) => data.handle_event(&j, action), - CharacterState::BasicBeam(data) => data.handle_event(&j, action), - CharacterState::BasicAura(data) => data.handle_event(&j, action), - CharacterState::Blink(data) => data.handle_event(&j, action), - CharacterState::BasicSummon(data) => data.handle_event(&j, action), - CharacterState::SelfBuff(data) => data.handle_event(&j, action), - CharacterState::SpriteSummon(data) => data.handle_event(&j, action), - CharacterState::UseItem(data) => data.handle_event(&j, action), - }; - local_emitter.append(&mut state_update.local_events); - server_emitter.append(&mut state_update.server_events); - incorporate_update(&mut join_struct, state_update, &mut server_emitter); + let mut state_update = ::handle_action_of_current_state(action, &j); + + ::emit_state_updates( + &mut server_emitter, + &mut local_emitter, + &mut state_update, + ); + ::incorporate_update(&mut join_struct, state_update, &mut server_emitter); } // Mounted occurs after control actions have been handled @@ -366,43 +299,128 @@ impl<'a> System<'a> for Sys { &read_data.msm, ); - let mut state_update = match j.character { - CharacterState::Idle => states::idle::Data.behavior(&j), - CharacterState::Talk => states::talk::Data.behavior(&j), - CharacterState::Climb(data) => data.behavior(&j), - CharacterState::Glide(data) => data.behavior(&j), - CharacterState::GlideWield => states::glide_wield::Data.behavior(&j), - CharacterState::Stunned(data) => data.behavior(&j), - CharacterState::Sit => states::sit::Data::behavior(&states::sit::Data, &j), - CharacterState::Dance => states::dance::Data::behavior(&states::dance::Data, &j), - CharacterState::Sneak => states::sneak::Data::behavior(&states::sneak::Data, &j), - CharacterState::BasicBlock(data) => data.behavior(&j), - CharacterState::Roll(data) => data.behavior(&j), - CharacterState::Wielding => states::wielding::Data.behavior(&j), - CharacterState::Equipping(data) => data.behavior(&j), - CharacterState::ComboMelee(data) => data.behavior(&j), - CharacterState::BasicMelee(data) => data.behavior(&j), - CharacterState::BasicRanged(data) => data.behavior(&j), - CharacterState::Boost(data) => data.behavior(&j), - CharacterState::DashMelee(data) => data.behavior(&j), - CharacterState::LeapMelee(data) => data.behavior(&j), - CharacterState::SpinMelee(data) => data.behavior(&j), - CharacterState::ChargedMelee(data) => data.behavior(&j), - CharacterState::ChargedRanged(data) => data.behavior(&j), - CharacterState::RepeaterRanged(data) => data.behavior(&j), - CharacterState::Shockwave(data) => data.behavior(&j), - CharacterState::BasicBeam(data) => data.behavior(&j), - CharacterState::BasicAura(data) => data.behavior(&j), - CharacterState::Blink(data) => data.behavior(&j), - CharacterState::BasicSummon(data) => data.behavior(&j), - CharacterState::SelfBuff(data) => data.behavior(&j), - CharacterState::SpriteSummon(data) => data.behavior(&j), - CharacterState::UseItem(data) => data.behavior(&j), - }; + let mut state_update = ::execute_behavior_of_current_state(&j); - local_emitter.append(&mut state_update.local_events); - server_emitter.append(&mut state_update.server_events); - incorporate_update(&mut join_struct, state_update, &mut server_emitter); + ::emit_state_updates(&mut server_emitter, &mut local_emitter, &mut state_update); + ::incorporate_update(&mut join_struct, state_update, &mut server_emitter); + } + } +} + +impl Sys { + fn execute_behavior_of_current_state(j: &JoinData) -> StateUpdate { + match j.character { + CharacterState::Idle => states::idle::Data.behavior(&j), + CharacterState::Talk => states::talk::Data.behavior(&j), + CharacterState::Climb(data) => data.behavior(&j), + CharacterState::Glide(data) => data.behavior(&j), + CharacterState::GlideWield => states::glide_wield::Data.behavior(&j), + CharacterState::Stunned(data) => data.behavior(&j), + CharacterState::Sit => states::sit::Data::behavior(&states::sit::Data, &j), + CharacterState::Dance => states::dance::Data::behavior(&states::dance::Data, &j), + CharacterState::Sneak => states::sneak::Data::behavior(&states::sneak::Data, &j), + CharacterState::BasicBlock(data) => data.behavior(&j), + CharacterState::Roll(data) => data.behavior(&j), + CharacterState::Wielding => states::wielding::Data.behavior(&j), + CharacterState::Equipping(data) => data.behavior(&j), + CharacterState::ComboMelee(data) => data.behavior(&j), + CharacterState::BasicMelee(data) => data.behavior(&j), + CharacterState::BasicRanged(data) => data.behavior(&j), + CharacterState::Boost(data) => data.behavior(&j), + CharacterState::DashMelee(data) => data.behavior(&j), + CharacterState::LeapMelee(data) => data.behavior(&j), + CharacterState::SpinMelee(data) => data.behavior(&j), + CharacterState::ChargedMelee(data) => data.behavior(&j), + CharacterState::ChargedRanged(data) => data.behavior(&j), + CharacterState::RepeaterRanged(data) => data.behavior(&j), + CharacterState::Shockwave(data) => data.behavior(&j), + CharacterState::BasicBeam(data) => data.behavior(&j), + CharacterState::BasicAura(data) => data.behavior(&j), + CharacterState::Blink(data) => data.behavior(&j), + CharacterState::BasicSummon(data) => data.behavior(&j), + CharacterState::SelfBuff(data) => data.behavior(&j), + CharacterState::SpriteSummon(data) => data.behavior(&j), + CharacterState::UseItem(data) => data.behavior(&j), + } + } + + fn handle_action_of_current_state(action: ControlAction, j: &JoinData) -> StateUpdate { + match j.character { + CharacterState::Idle => states::idle::Data.handle_event(&j, action), + CharacterState::Talk => states::talk::Data.handle_event(&j, action), + CharacterState::Climb(data) => data.handle_event(&j, action), + CharacterState::Glide(data) => data.handle_event(&j, action), + CharacterState::GlideWield => states::glide_wield::Data.handle_event(&j, action), + CharacterState::Stunned(data) => data.handle_event(&j, action), + CharacterState::Sit => states::sit::Data::handle_event(&states::sit::Data, &j, action), + CharacterState::Dance => { + states::dance::Data::handle_event(&states::dance::Data, &j, action) + }, + CharacterState::Sneak => { + states::sneak::Data::handle_event(&states::sneak::Data, &j, action) + }, + CharacterState::BasicBlock(data) => data.handle_event(&j, action), + CharacterState::Roll(data) => data.handle_event(&j, action), + CharacterState::Wielding => states::wielding::Data.handle_event(&j, action), + CharacterState::Equipping(data) => data.handle_event(&j, action), + CharacterState::ComboMelee(data) => data.handle_event(&j, action), + CharacterState::BasicMelee(data) => data.handle_event(&j, action), + CharacterState::BasicRanged(data) => data.handle_event(&j, action), + CharacterState::Boost(data) => data.handle_event(&j, action), + CharacterState::DashMelee(data) => data.handle_event(&j, action), + CharacterState::LeapMelee(data) => data.handle_event(&j, action), + CharacterState::SpinMelee(data) => data.handle_event(&j, action), + CharacterState::ChargedMelee(data) => data.handle_event(&j, action), + CharacterState::ChargedRanged(data) => data.handle_event(&j, action), + CharacterState::RepeaterRanged(data) => data.handle_event(&j, action), + CharacterState::Shockwave(data) => data.handle_event(&j, action), + CharacterState::BasicBeam(data) => data.handle_event(&j, action), + CharacterState::BasicAura(data) => data.handle_event(&j, action), + CharacterState::Blink(data) => data.handle_event(&j, action), + CharacterState::BasicSummon(data) => data.handle_event(&j, action), + CharacterState::SelfBuff(data) => data.handle_event(&j, action), + CharacterState::SpriteSummon(data) => data.handle_event(&j, action), + CharacterState::UseItem(data) => data.handle_event(&j, action), + } + } + + fn emit_state_updates( + server_emitter: &mut Emitter, + local_emitter: &mut Emitter, + state_update: &mut StateUpdate, + ) { + local_emitter.append(&mut state_update.local_events); + server_emitter.append(&mut state_update.server_events); + } + + fn incorporate_update( + join: &mut JoinStruct, + mut state_update: StateUpdate, + server_emitter: &mut Emitter, + ) { + // TODO: if checking equality is expensive use optional field in StateUpdate + if *join.char_state != state_update.character { + *join.char_state = state_update.character + }; + *join.pos = state_update.pos; + *join.vel = state_update.vel; + *join.ori = state_update.ori; + *join.density = state_update.density; + // Note: might be changed every tick by timer anyway + if *join.energy != state_update.energy { + *join.energy = state_update.energy + }; + join.controller + .queued_inputs + .append(&mut state_update.queued_inputs); + for input in state_update.removed_inputs { + join.controller.queued_inputs.remove(&input); + } + if state_update.swap_equipped_weapons { + server_emitter.emit(ServerEvent::InventoryManip( + join.entity, + InventoryManip::SwapEquippedWeapons, + )); } } } From c9c32eea65fc723d8c90ef54dec59b1b8e6bceb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Fri, 23 Jul 2021 12:25:59 +0200 Subject: [PATCH 012/155] add a argument for i18n to enable csv generation --- voxygen/i18n/src/analysis.rs | 9 ++++++++- voxygen/i18n/src/bin/i18n-check.rs | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/voxygen/i18n/src/analysis.rs b/voxygen/i18n/src/analysis.rs index dcf8ec3f11..d0328e63a7 100644 --- a/voxygen/i18n/src/analysis.rs +++ b/voxygen/i18n/src/analysis.rs @@ -291,6 +291,7 @@ fn test_localization_directory( ref_manifest: &Path, i18n_references: &HashMap, be_verbose: bool, + csv_enabled: bool, repo: &git2::Repository, head_ref: &git2::Reference, ) -> Option { @@ -494,11 +495,14 @@ fn print_translation_stats( /// `root_dir` - absolute path to main repo /// `assets_path` - relative path to asset directory (right now it is /// 'assets/voxygen/i18n') +/// be_verbose - +/// csv_enabled - generate csv files in target folder pub fn test_specific_localization( code: &str, root_dir: &Path, assets_path: &Path, be_verbose: bool, + csv_enabled: bool, ) { // Relative paths from root of repo to assets let ref_lang_dir = assets_path.join(REFERENCE_LANG); @@ -533,6 +537,7 @@ pub fn test_specific_localization( &ref_manifest, &reference_i18n, be_verbose, + csv_enabled, &repo, &head_ref, ); @@ -542,7 +547,8 @@ pub fn test_specific_localization( /// `root_dir` - absolute path to main repo /// `assets_path` - relative path to asset directory (right now it is /// 'assets/voxygen/i18n') -pub fn test_all_localizations(root_dir: &Path, assets_path: &Path, be_verbose: bool) { +/// csv_enabled - generate csv files in target folder +pub fn test_all_localizations(root_dir: &Path, assets_path: &Path, be_verbose: bool, csv_enabled: bool) { let ref_lang_dir = assets_path.join(REFERENCE_LANG); let ref_manifest = ref_lang_dir.join(LANG_MANIFEST_FILE.to_string() + ".ron"); @@ -585,6 +591,7 @@ pub fn test_all_localizations(root_dir: &Path, assets_path: &Path, be_verbose: b &ref_manifest, &reference_i18n, be_verbose, + csv_enabled, &repo, &head_ref, ); diff --git a/voxygen/i18n/src/bin/i18n-check.rs b/voxygen/i18n/src/bin/i18n-check.rs index cc45d256bb..6af88157e7 100644 --- a/voxygen/i18n/src/bin/i18n-check.rs +++ b/voxygen/i18n/src/bin/i18n-check.rs @@ -28,11 +28,17 @@ fn main() { .long("verbose") .help("print additional information"), ) + .arg( + Arg::with_name("csv") + .long("csv") + .help("generate csv files per language in target folder"), + ) .get_matches(); // Generate paths let root = common_assets::find_root().expect("Failed to find root of repository"); let asset_path = Path::new("assets/voxygen/i18n/"); + let csv_enabled = matches.is_present("csv"); if let Some(code) = matches.value_of("CODE") { analysis::test_specific_localization( @@ -40,10 +46,11 @@ fn main() { &root, &asset_path, matches.is_present("verbose"), + csv_enabled, ); } if matches.is_present("test") { - analysis::test_all_localizations(&root, &asset_path, matches.is_present("verbose")); + analysis::test_all_localizations(&root, &asset_path, matches.is_present("verbose"), csv_enabled); } if matches.is_present("verify") { verification::verify_all_localizations(&root, &asset_path); From c501b2eb705793d6a3d93ba6211058c20fff3ab6 Mon Sep 17 00:00:00 2001 From: "Dr. Dystopia" Date: Fri, 23 Jul 2021 13:32:00 +0200 Subject: [PATCH 013/155] base framework to print csv --- voxygen/i18n/src/analysis.rs | 65 +++-- voxygen/i18n/src/bin/i18n-check.rs | 7 +- voxygen/i18n/src/data.rs | 437 ----------------------------- voxygen/i18n/src/lib.rs | 364 +++++++++++++++++++++++- voxygen/i18n/src/raw.rs | 136 +++++++++ voxygen/i18n/src/verification.rs | 56 ++-- 6 files changed, 570 insertions(+), 495 deletions(-) delete mode 100644 voxygen/i18n/src/data.rs create mode 100644 voxygen/i18n/src/raw.rs diff --git a/voxygen/i18n/src/analysis.rs b/voxygen/i18n/src/analysis.rs index d0328e63a7..89841df7d1 100644 --- a/voxygen/i18n/src/analysis.rs +++ b/voxygen/i18n/src/analysis.rs @@ -1,7 +1,7 @@ use ron::de::from_bytes; use std::path::{Path, PathBuf}; -use crate::data::{ +use crate::raw::{ i18n_directories, LocalizationFragment, RawLocalization, LANG_MANIFEST_FILE, REFERENCE_LANG, }; use hashbrown::{HashMap, HashSet}; @@ -27,6 +27,7 @@ struct LocalizationStats { #[derive(Default)] struct LocalizationAnalysis { + uptodate: Vec<(String, Option)>, notfound: Vec<(String, Option)>, unused: Vec<(String, Option)>, outdated: Vec<(String, Option)>, @@ -39,11 +40,11 @@ impl LocalizationAnalysis { state: LocalizationState, ) -> Option<&mut Vec<(String, Option)>> { match state { + LocalizationState::UpToDate => Some(&mut self.uptodate), LocalizationState::NotFound => Some(&mut self.notfound), LocalizationState::Unused => Some(&mut self.unused), LocalizationState::Outdated => Some(&mut self.outdated), LocalizationState::Unknown => Some(&mut self.unknown), - _ => None, } } @@ -53,9 +54,7 @@ impl LocalizationAnalysis { be_verbose: bool, ref_i18n_map: &HashMap, ) { - let entries = self - .get_mut(state) - .unwrap_or_else(|| panic!("called on invalid state: {:?}", state)); + let entries = self.unwrap_entries(state); if entries.is_empty() { return; } @@ -63,9 +62,7 @@ impl LocalizationAnalysis { entries.sort(); for (key, commit_id) in entries { if be_verbose { - let our_commit = commit_id - .map(|s| format!("{}", s)) - .unwrap_or_else(|| "None".to_owned()); + let our_commit = LocalizationAnalysis::create_our_commit(commit_id); let ref_commit = ref_i18n_map .get(key) .and_then(|s| s.commit_id) @@ -77,6 +74,32 @@ impl LocalizationAnalysis { } } } + + //TODO: Add which file each faulty translation is in + fn csv(&mut self, state: LocalizationState) { + let entries = self.unwrap_entries(state); + for (key, commit_id) in entries { + let our_commit = LocalizationAnalysis::create_our_commit(commit_id); + println!( + "{},{},{},{:?},{}", + "sv", "_manifest.yml", key, state, our_commit + ); + } + } + + fn unwrap_entries( + &mut self, + state: LocalizationState, + ) -> &mut Vec<(String, Option)> { + self.get_mut(state) + .unwrap_or_else(|| panic!("called on invalid state: {:?}", state)) + } + + fn create_our_commit(commit_id: &mut Option) -> String { + commit_id + .map(|s| format!("{}", s)) + .unwrap_or_else(|| "None".to_owned()) + } } #[derive(Copy, Clone, Debug)] @@ -329,14 +352,7 @@ fn test_localization_directory( let mut state_map = LocalizationAnalysis::default(); let result = gather_results(current_i18n, &mut state_map); - print_translation_stats( - i18n_references, - &result, - &mut state_map, - be_verbose, - relfile, - ref_manifest, - ); + print_csv_file(&mut state_map, relfile); Some(result) } @@ -490,6 +506,16 @@ fn print_translation_stats( ); } +fn print_csv_file(state_map: &mut LocalizationAnalysis, relfile: PathBuf) { + println!("country_code,file_name,translation_code,status,git_commit"); + + state_map.csv(LocalizationState::UpToDate); + state_map.csv(LocalizationState::NotFound); + state_map.csv(LocalizationState::Unused); + state_map.csv(LocalizationState::Outdated); + state_map.csv(LocalizationState::Unknown); +} + /// Test one language /// `code` - name of the directory in assets (de_DE for example) /// `root_dir` - absolute path to main repo @@ -548,7 +574,12 @@ pub fn test_specific_localization( /// `assets_path` - relative path to asset directory (right now it is /// 'assets/voxygen/i18n') /// csv_enabled - generate csv files in target folder -pub fn test_all_localizations(root_dir: &Path, assets_path: &Path, be_verbose: bool, csv_enabled: bool) { +pub fn test_all_localizations( + root_dir: &Path, + assets_path: &Path, + be_verbose: bool, + csv_enabled: bool, +) { let ref_lang_dir = assets_path.join(REFERENCE_LANG); let ref_manifest = ref_lang_dir.join(LANG_MANIFEST_FILE.to_string() + ".ron"); diff --git a/voxygen/i18n/src/bin/i18n-check.rs b/voxygen/i18n/src/bin/i18n-check.rs index 6af88157e7..f3bdf0a490 100644 --- a/voxygen/i18n/src/bin/i18n-check.rs +++ b/voxygen/i18n/src/bin/i18n-check.rs @@ -50,7 +50,12 @@ fn main() { ); } if matches.is_present("test") { - analysis::test_all_localizations(&root, &asset_path, matches.is_present("verbose"), csv_enabled); + analysis::test_all_localizations( + &root, + &asset_path, + matches.is_present("verbose"), + csv_enabled, + ); } if matches.is_present("verify") { verification::verify_all_localizations(&root, &asset_path); diff --git a/voxygen/i18n/src/data.rs b/voxygen/i18n/src/data.rs deleted file mode 100644 index 2240134fe2..0000000000 --- a/voxygen/i18n/src/data.rs +++ /dev/null @@ -1,437 +0,0 @@ -use crate::assets::{self, source::DirEntry, AssetExt, AssetGuard, AssetHandle}; -use deunicode::deunicode; -use hashbrown::{HashMap, HashSet}; -use serde::{Deserialize, Serialize}; -use std::{ - fs, io, - path::{Path, PathBuf}, -}; -use tracing::warn; - -/// The reference language, aka the more up-to-date localization data. -/// Also the default language at first startup. -pub const REFERENCE_LANG: &str = "en"; - -pub const LANG_MANIFEST_FILE: &str = "_manifest"; - -/// How a language can be described -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct LanguageMetadata { - /// A human friendly language name (e.g. "English (US)") - pub language_name: String, - - /// A short text identifier for this language (e.g. "en_US") - /// - /// On the opposite of `language_name` that can change freely, - /// `language_identifier` value shall be stable in time as it - /// is used by setting components to store the language - /// selected by the user. - pub language_identifier: String, -} - -/// Store font metadata -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct Font { - /// Key to retrieve the font in the asset system - pub asset_key: String, - - /// Scale ratio to resize the UI text dynamicly - scale_ratio: f32, -} - -impl Font { - /// Scale input size to final UI size - pub fn scale(&self, value: u32) -> u32 { (value as f32 * self.scale_ratio).round() as u32 } -} - -/// Store font metadata -pub type Fonts = HashMap; - -/// Raw localization data, expect the strings to not be loaded here -/// However, metadata informations are correct -/// See `Language` for more info on each attributes -#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] -pub(crate) struct RawLocalization { - pub(crate) convert_utf8_to_ascii: bool, - pub(crate) fonts: Fonts, - pub(crate) metadata: LanguageMetadata, - pub(crate) string_map: HashMap, - pub(crate) vector_map: HashMap>, -} - -/// Store internationalization data -#[derive(Debug, PartialEq, Serialize, Deserialize)] -struct Language { - /// A map storing the localized texts - /// - /// Localized content can be accessed using a String key. - pub(crate) string_map: HashMap, - - /// A map for storing variations of localized texts, for example multiple - /// ways of saying "Help, I'm under attack". Used primarily for npc - /// dialogue. - pub(crate) vector_map: HashMap>, - - /// Whether to convert the input text encoded in UTF-8 - /// into a ASCII version by using the `deunicode` crate. - pub(crate) convert_utf8_to_ascii: bool, - - /// Font configuration is stored here - pub(crate) fonts: Fonts, - - pub(crate) metadata: LanguageMetadata, -} - -/// Store internationalization maps -/// These structs are meant to be merged into a Language -#[derive(Debug, PartialEq, Serialize, Deserialize)] -pub(crate) struct LocalizationFragment { - /// A map storing the localized texts - /// - /// Localized content can be accessed using a String key. - pub(crate) string_map: HashMap, - - /// A map for storing variations of localized texts, for example multiple - /// ways of saying "Help, I'm under attack". Used primarily for npc - /// dialogue. - pub(crate) vector_map: HashMap>, -} - -impl Language { - /// Get a localized text from the given key - pub fn get<'a>(&'a self, key: &'a str) -> Option<&str> { - self.string_map.get(key).map(String::as_str) - } - - /// Get a variation of localized text from the given key - /// - /// `index` should be a random number from `0` to `u16::max()` - /// - /// If the key is not present in the localization object - /// then the key is returned. - pub fn get_variation<'a>(&'a self, key: &'a str, index: u16) -> Option<&str> { - self.vector_map.get(key).and_then(|v| { - if v.is_empty() { - None - } else { - Some(v[index as usize % v.len()].as_str()) - } - }) - } -} - -impl Default for Language { - fn default() -> Self { - Self { - string_map: HashMap::default(), - vector_map: HashMap::default(), - ..Default::default() - } - } -} - -impl From for Language { - fn from(raw: RawLocalization) -> Self { - Self { - string_map: raw.string_map, - vector_map: raw.vector_map, - convert_utf8_to_ascii: raw.convert_utf8_to_ascii, - fonts: raw.fonts, - metadata: raw.metadata, - } - } -} -impl From for LocalizationFragment { - fn from(raw: RawLocalization) -> Self { - Self { - string_map: raw.string_map, - vector_map: raw.vector_map, - } - } -} - -impl assets::Asset for RawLocalization { - type Loader = assets::RonLoader; - - const EXTENSION: &'static str = "ron"; -} -impl assets::Asset for LocalizationFragment { - type Loader = assets::RonLoader; - - const EXTENSION: &'static str = "ron"; -} - -impl assets::Compound for Language { - fn load( - cache: &assets::AssetCache, - asset_key: &str, - ) -> Result { - let raw = cache - .load::(&[asset_key, ".", LANG_MANIFEST_FILE].concat())? - .cloned(); - let mut localization = Language::from(raw); - - // Walk through files in the folder, collecting localization fragment to merge - // inside the asked_localization - for localization_asset in cache - .load_dir::(asset_key, true)? - .iter() - { - localization - .string_map - .extend(localization_asset.read().string_map.clone()); - localization - .vector_map - .extend(localization_asset.read().vector_map.clone()); - } - - // Update the text if UTF-8 to ASCII conversion is enabled - if localization.convert_utf8_to_ascii { - for value in localization.string_map.values_mut() { - *value = deunicode(value); - } - - for value in localization.vector_map.values_mut() { - *value = value.iter().map(|s| deunicode(s)).collect(); - } - } - localization.metadata.language_name = deunicode(&localization.metadata.language_name); - - Ok(localization) - } -} - -/// the central data structure to handle localization in veloren -// inherit Copy+Clone from AssetHandle -#[derive(Debug, PartialEq, Copy, Clone)] -pub struct LocalizationHandle { - active: AssetHandle, - fallback: Option>, - pub use_english_fallback: bool, -} - -// RAII guard returned from Localization::read(), resembles AssetGuard -pub struct LocalizationGuard { - active: AssetGuard, - fallback: Option>, -} - -// arbitrary choice to minimize changing all of veloren -pub type Localization = LocalizationGuard; - -impl LocalizationGuard { - /// Get a localized text from the given key - /// - /// First lookup is done in the active language, second in - /// the fallback (if present). - /// If the key is not present in the localization object - /// then the key is returned. - pub fn get<'a>(&'a self, key: &'a str) -> &str { - self.active.get(key).unwrap_or_else(|| { - self.fallback - .as_ref() - .and_then(|f| f.get(key)) - .unwrap_or(key) - }) - } - - /// Get a variation of localized text from the given key - /// - /// `index` should be a random number from `0` to `u16::max()` - /// - /// If the key is not present in the localization object - /// then the key is returned. - pub fn get_variation<'a>(&'a self, key: &'a str, index: u16) -> &str { - self.active.get_variation(key, index).unwrap_or_else(|| { - self.fallback - .as_ref() - .and_then(|f| f.get_variation(key, index)) - .unwrap_or(key) - }) - } - - /// Return the missing keys compared to the reference language - fn list_missing_entries(&self) -> (HashSet, HashSet) { - if let Some(ref_lang) = &self.fallback { - let reference_string_keys: HashSet<_> = ref_lang.string_map.keys().cloned().collect(); - let string_keys: HashSet<_> = self.active.string_map.keys().cloned().collect(); - let strings = reference_string_keys - .difference(&string_keys) - .cloned() - .collect(); - - let reference_vector_keys: HashSet<_> = ref_lang.vector_map.keys().cloned().collect(); - let vector_keys: HashSet<_> = self.active.vector_map.keys().cloned().collect(); - let vectors = reference_vector_keys - .difference(&vector_keys) - .cloned() - .collect(); - - (strings, vectors) - } else { - (HashSet::default(), HashSet::default()) - } - } - - /// Log missing entries (compared to the reference language) as warnings - pub fn log_missing_entries(&self) { - let (missing_strings, missing_vectors) = self.list_missing_entries(); - for missing_key in missing_strings { - warn!( - "[{:?}] Missing string key {:?}", - self.metadata().language_identifier, - missing_key - ); - } - for missing_key in missing_vectors { - warn!( - "[{:?}] Missing vector key {:?}", - self.metadata().language_identifier, - missing_key - ); - } - } - - pub fn fonts(&self) -> &Fonts { &self.active.fonts } - - pub fn metadata(&self) -> &LanguageMetadata { &self.active.metadata } -} - -impl LocalizationHandle { - pub fn set_english_fallback(&mut self, use_english_fallback: bool) { - self.use_english_fallback = use_english_fallback; - } - - pub fn read(&self) -> LocalizationGuard { - LocalizationGuard { - active: self.active.read(), - fallback: if self.use_english_fallback { - self.fallback.map(|f| f.read()) - } else { - None - }, - } - } - - pub fn load(specifier: &str) -> Result { - let default_key = ["voxygen.i18n.", REFERENCE_LANG].concat(); - let language_key = ["voxygen.i18n.", specifier].concat(); - let is_default = language_key == default_key; - Ok(Self { - active: Language::load(&language_key)?, - fallback: if is_default { - None - } else { - Language::load(&default_key).ok() - }, - use_english_fallback: false, - }) - } - - pub fn load_expect(specifier: &str) -> Self { - Self::load(specifier).expect("Can't load language files") - } - - pub fn reloaded(&mut self) -> bool { self.active.reloaded() } -} - -struct FindManifests; - -impl assets::Compound for FindManifests { - fn load(_: &assets::AssetCache, _: &str) -> Result { - Ok(Self) - } -} - -impl assets::DirLoadable for FindManifests { - fn select_ids( - source: &S, - specifier: &str, - ) -> io::Result> { - let mut specifiers = Vec::new(); - - source.read_dir(specifier, &mut |entry| { - if let DirEntry::Directory(spec) = entry { - let manifest_spec = [spec, ".", LANG_MANIFEST_FILE].concat(); - if source.exists(DirEntry::File(&manifest_spec, "ron")) { - specifiers.push(manifest_spec.into()); - } - } - })?; - - Ok(specifiers) - } -} - -#[derive(Clone, Debug)] -struct LocalizationList(Vec); - -impl assets::Compound for LocalizationList { - fn load( - cache: &assets::AssetCache, - specifier: &str, - ) -> Result { - // List language directories - let languages = assets::load_dir::(specifier, false) - .unwrap_or_else(|e| panic!("Failed to get manifests from {}: {:?}", specifier, e)) - .ids() - .filter_map(|spec| cache.load::(spec).ok()) - .map(|localization| localization.read().metadata.clone()) - .collect(); - - Ok(LocalizationList(languages)) - } -} - -/// Load all the available languages located in the voxygen asset directory -pub fn list_localizations() -> Vec { - LocalizationList::load_expect_cloned("voxygen.i18n").0 -} - -/// List localization directories as a `PathBuf` vector -pub fn i18n_directories(i18n_dir: &Path) -> Vec { - fs::read_dir(i18n_dir) - .unwrap() - .map(|res| res.map(|e| e.path()).unwrap()) - .filter(|e| e.is_dir()) - .collect() -} - -#[cfg(test)] -mod tests { - use super::assets; - // Test that localization list is loaded (not empty) - #[test] - fn test_localization_list() { - let list = super::list_localizations(); - assert!(!list.is_empty()); - } - - // Test that reference language can be loaded - #[test] - fn test_localization_handle() { - let _ = super::LocalizationHandle::load_expect(super::REFERENCE_LANG); - } - - // Test to verify all languages that they are VALID and loadable, without - // need of git just on the local assets folder - #[test] - fn verify_all_localizations() { - // Generate paths - let i18n_asset_path = std::path::Path::new("assets/voxygen/i18n/"); - let root_dir = assets::find_root().expect("Failed to discover repository root"); - crate::verification::verify_all_localizations(&root_dir, i18n_asset_path); - } - - // Test to verify all languages and print missing and faulty localisation - #[test] - #[ignore] - fn test_all_localizations() { - // Options - let be_verbose = true; - // Generate paths - let i18n_asset_path = std::path::Path::new("assets/voxygen/i18n/"); - let root_dir = assets::find_root().expect("Failed to discover repository root"); - crate::analysis::test_all_localizations(&root_dir, i18n_asset_path, be_verbose); - } -} diff --git a/voxygen/i18n/src/lib.rs b/voxygen/i18n/src/lib.rs index 1d8462e15d..d0b9f85e8c 100644 --- a/voxygen/i18n/src/lib.rs +++ b/voxygen/i18n/src/lib.rs @@ -1,7 +1,365 @@ #[cfg(any(feature = "bin", test))] pub mod analysis; -mod data; +pub mod raw; pub mod verification; -use common_assets as assets; -pub use data::*; +use common_assets::{self, source::DirEntry, AssetExt, AssetGuard, AssetHandle}; +use hashbrown::{HashMap, HashSet}; +use serde::{Deserialize, Serialize}; +use std::{ + fs, io, + path::{Path, PathBuf}, +}; +use tracing::warn; +use raw::{RawManifest, RawFragment, RawLanguage}; + +/// The reference language, aka the more up-to-date localization data. +/// Also the default language at first startup. +pub const REFERENCE_LANG: &str = "en"; + +pub const LANG_MANIFEST_FILE: &str = "_manifest"; + +pub(crate) const LANG_EXTENSION: &str = "ron"; + +/// How a language can be described +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct LanguageMetadata { + /// A human friendly language name (e.g. "English (US)") + pub language_name: String, + + /// A short text identifier for this language (e.g. "en_US") + /// + /// On the opposite of `language_name` that can change freely, + /// `language_identifier` value shall be stable in time as it + /// is used by setting components to store the language + /// selected by the user. + pub language_identifier: String, +} + +/// Store font metadata +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Font { + /// Key to retrieve the font in the asset system + pub asset_key: String, + + /// Scale ratio to resize the UI text dynamically + scale_ratio: f32, +} + +impl Font { + /// Scale input size to final UI size + pub fn scale(&self, value: u32) -> u32 { (value as f32 * self.scale_ratio).round() as u32 } +} + +/// Store font metadata +pub type Fonts = HashMap; + +/// Store internationalization data +#[derive(Debug, PartialEq, Serialize, Deserialize)] +struct Language { + /// A map storing the localized texts + /// + /// Localized content can be accessed using a String key. + pub(crate) string_map: HashMap, + + /// A map for storing variations of localized texts, for example multiple + /// ways of saying "Help, I'm under attack". Used primarily for npc + /// dialogue. + pub(crate) vector_map: HashMap>, + + /// Whether to convert the input text encoded in UTF-8 + /// into a ASCII version by using the `deunicode` crate. + pub(crate) convert_utf8_to_ascii: bool, + + /// Font configuration is stored here + pub(crate) fonts: Fonts, + + pub(crate) metadata: LanguageMetadata, +} + +impl Language { + /// Get a localized text from the given key + pub fn get<'a>(&'a self, key: &'a str) -> Option<&str> { + self.string_map.get(key).map(String::as_str) + } + + /// Get a variation of localized text from the given key + /// + /// `index` should be a random number from `0` to `u16::max()` + /// + /// If the key is not present in the localization object + /// then the key is returned. + pub fn get_variation<'a>(&'a self, key: &'a str, index: u16) -> Option<&str> { + self.vector_map.get(key).and_then(|v| { + if v.is_empty() { + None + } else { + Some(v[index as usize % v.len()].as_str()) + } + }) + } +} + +impl common_assets::Compound for Language { + fn load( + cache: &common_assets::AssetCache, + asset_key: &str, + ) -> Result { + let manifest = cache + .load::(&[asset_key, ".", LANG_MANIFEST_FILE].concat())? + .cloned(); + + // Walk through files in the folder, collecting localization fragment to merge + // inside the asked_localization + let mut fragments = HashMap::new(); + for fragment_asset in cache + .load_dir::(asset_key, true)? + .iter() + { + let read = fragment_asset.read(); + fragments.insert(PathBuf::from(fragment_asset.id()), read.clone()); + } + + Ok(Language::from(RawLanguage{ + manifest, + fragments, + })) + } +} + +/// the central data structure to handle localization in veloren +// inherit Copy+Clone from AssetHandle +#[derive(Debug, PartialEq, Copy, Clone)] +pub struct LocalizationHandle { + active: AssetHandle, + fallback: Option>, + pub use_english_fallback: bool, +} + +// RAII guard returned from Localization::read(), resembles AssetGuard +pub struct LocalizationGuard { + active: AssetGuard, + fallback: Option>, +} + +// arbitrary choice to minimize changing all of veloren +pub type Localization = LocalizationGuard; + +impl LocalizationGuard { + /// Get a localized text from the given key + /// + /// First lookup is done in the active language, second in + /// the fallback (if present). + /// If the key is not present in the localization object + /// then the key is returned. + pub fn get<'a>(&'a self, key: &'a str) -> &str { + self.active.get(key).unwrap_or_else(|| { + self.fallback + .as_ref() + .and_then(|f| f.get(key)) + .unwrap_or(key) + }) + } + + /// Get a variation of localized text from the given key + /// + /// `index` should be a random number from `0` to `u16::max()` + /// + /// If the key is not present in the localization object + /// then the key is returned. + pub fn get_variation<'a>(&'a self, key: &'a str, index: u16) -> &str { + self.active.get_variation(key, index).unwrap_or_else(|| { + self.fallback + .as_ref() + .and_then(|f| f.get_variation(key, index)) + .unwrap_or(key) + }) + } + + /// Return the missing keys compared to the reference language + fn list_missing_entries(&self) -> (HashSet, HashSet) { + if let Some(ref_lang) = &self.fallback { + let reference_string_keys: HashSet<_> = ref_lang.string_map.keys().cloned().collect(); + let string_keys: HashSet<_> = self.active.string_map.keys().cloned().collect(); + let strings = reference_string_keys + .difference(&string_keys) + .cloned() + .collect(); + + let reference_vector_keys: HashSet<_> = ref_lang.vector_map.keys().cloned().collect(); + let vector_keys: HashSet<_> = self.active.vector_map.keys().cloned().collect(); + let vectors = reference_vector_keys + .difference(&vector_keys) + .cloned() + .collect(); + + (strings, vectors) + } else { + (HashSet::default(), HashSet::default()) + } + } + + /// Log missing entries (compared to the reference language) as warnings + pub fn log_missing_entries(&self) { + let (missing_strings, missing_vectors) = self.list_missing_entries(); + for missing_key in missing_strings { + warn!( + "[{:?}] Missing string key {:?}", + self.metadata().language_identifier, + missing_key + ); + } + for missing_key in missing_vectors { + warn!( + "[{:?}] Missing vector key {:?}", + self.metadata().language_identifier, + missing_key + ); + } + } + + pub fn fonts(&self) -> &Fonts { &self.active.fonts } + + pub fn metadata(&self) -> &LanguageMetadata { &self.active.metadata } +} + +impl LocalizationHandle { + pub fn set_english_fallback(&mut self, use_english_fallback: bool) { + self.use_english_fallback = use_english_fallback; + } + + pub fn read(&self) -> LocalizationGuard { + LocalizationGuard { + active: self.active.read(), + fallback: if self.use_english_fallback { + self.fallback.map(|f| f.read()) + } else { + None + }, + } + } + + pub fn load(specifier: &str) -> Result { + let default_key = ["voxygen.i18n.", REFERENCE_LANG].concat(); + let language_key = ["voxygen.i18n.", specifier].concat(); + let is_default = language_key == default_key; + Ok(Self { + active: Language::load(&language_key)?, + fallback: if is_default { + None + } else { + Language::load(&default_key).ok() + }, + use_english_fallback: false, + }) + } + + pub fn load_expect(specifier: &str) -> Self { + Self::load(specifier).expect("Can't load language files") + } + + pub fn reloaded(&mut self) -> bool { self.active.reloaded() } +} + +struct FindManifests; + +impl common_assets::Compound for FindManifests { + fn load(_: &common_assets::AssetCache, _: &str) -> Result { + Ok(Self) + } +} + +impl common_assets::DirLoadable for FindManifests { + fn select_ids( + source: &S, + specifier: &str, + ) -> io::Result> { + let mut specifiers = Vec::new(); + + source.read_dir(specifier, &mut |entry| { + if let DirEntry::Directory(spec) = entry { + let manifest_spec = [spec, ".", LANG_MANIFEST_FILE].concat(); + if source.exists(DirEntry::File(&manifest_spec, LANG_EXTENSION)) { + specifiers.push(manifest_spec.into()); + } + } + })?; + + Ok(specifiers) + } +} + +#[derive(Clone, Debug)] +struct LocalizationList(Vec); + +impl common_assets::Compound for LocalizationList { + fn load( + cache: &common_assets::AssetCache, + specifier: &str, + ) -> Result { + // List language directories + let languages = common_assets::load_dir::(specifier, false) + .unwrap_or_else(|e| panic!("Failed to get manifests from {}: {:?}", specifier, e)) + .ids() + .filter_map(|spec| cache.load::(spec).ok()) + .map(|localization| localization.read().metadata.clone()) + .collect(); + + Ok(LocalizationList(languages)) + } +} + +/// Load all the available languages located in the voxygen asset directory +pub fn list_localizations() -> Vec { + LocalizationList::load_expect_cloned("voxygen.i18n").0 +} + +/// List localization directories as a `PathBuf` vector +pub fn i18n_directories(i18n_dir: &Path) -> Vec { + fs::read_dir(i18n_dir) + .unwrap() + .map(|res| res.map(|e| e.path()).unwrap()) + .filter(|e| e.is_dir()) + .collect() +} + +#[cfg(test)] +mod tests { + use std::path::Path; + use common_assets; + + // Test that localization list is loaded (not empty) + #[test] + fn test_localization_list() { + let list = super::list_localizations(); + assert!(!list.is_empty()); + } + + // Test that reference language can be loaded + #[test] + fn test_localization_handle() { + let _ = super::LocalizationHandle::load_expect(super::REFERENCE_LANG); + } + + // Test to verify all languages that they are VALID and loadable, without + // need of git just on the local assets folder + #[test] + fn verify_all_localizations() { + // Generate paths + let i18n_root_path = Path::new("assets/voxygen/i18n/"); + let root_dir = common_assets::find_root().expect("Failed to discover repository root"); + crate::verification::verify_all_localizations(&root_dir, i18n_root_path); + } + + // Test to verify all languages and print missing and faulty localisation + #[test] + #[ignore] + fn test_all_localizations() { + // Options + let be_verbose = true; + // Generate paths + let i18n_root_path = Path::new("assets/voxygen/i18n/"); + let root_dir = common_assets::find_root().expect("Failed to discover repository root"); + crate::analysis::test_all_localizations(&root_dir, i18n_root_path, be_verbose); + } +} diff --git a/voxygen/i18n/src/raw.rs b/voxygen/i18n/src/raw.rs new file mode 100644 index 0000000000..e04d64e706 --- /dev/null +++ b/voxygen/i18n/src/raw.rs @@ -0,0 +1,136 @@ +//! handle the loading of a `Language` +use hashbrown::hash_map::HashMap; +use std::path::{Path, PathBuf}; +use serde::{Deserialize, Serialize}; +use std::fs; +use ron::de::from_reader; +use deunicode::deunicode; +use crate::{Fonts, LanguageMetadata, LANG_MANIFEST_FILE, LANG_EXTENSION}; +use crate::Language; + +/// Raw localization metadata from LANG_MANIFEST_FILE file +/// See `Language` for more info on each attributes +#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] +pub(crate) struct RawManifest { + pub(crate) convert_utf8_to_ascii: bool, + pub(crate) fonts: Fonts, + pub(crate) metadata: LanguageMetadata, +} + +/// Raw localization data from one specific file +/// These structs are meant to be merged into a Language +#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] +pub(crate) struct RawFragment { + pub(crate) string_map: HashMap, + pub(crate) vector_map: HashMap>, +} + +pub(crate) struct RawLanguage { + pub(crate) manifest: RawManifest, + pub(crate) fragments: HashMap, +} + +#[derive(Debug)] +pub(crate) enum RawError { + RonError(ron::Error), +} + +/// `i18n_root_path` - absolute path to i18n path which contains `en`, `de_DE`, `fr_FR` folders +pub(crate) fn load_manifest(i18n_root_path: &Path, language_identifier: &str) -> Result { + let manifest_file = i18n_root_path.join(language_identifier).join(format!("{}.{}", LANG_MANIFEST_FILE, LANG_EXTENSION)); + println!("file , {:?}", manifest_file); + let f = fs::File::open(&manifest_file)?; + Ok(from_reader(f).map_err(RawError::RonError)?) +} + +/// `i18n_root_path` - absolute path to i18n path which contains `en`, `de_DE`, `fr_FR` files +pub(crate) fn load_raw_language(i18n_root_path: &Path, manifest: RawManifest) -> Result { + // Walk through each file in the directory + let mut fragments = HashMap::new(); + let language_identifier = &manifest.metadata.language_identifier; + let language_dir = i18n_root_path.join(language_identifier); + for fragment_file in language_dir.read_dir().unwrap().flatten() { + let file_type = fragment_file.file_type()?; + if file_type.is_dir() { + // TODO: recursive + continue; + } + if file_type.is_file() { + let full_path = fragment_file.path(); + let relative_path = full_path.strip_prefix(&i18n_root_path).unwrap(); + let f = fs::File::open(&full_path)?; + let fragment = from_reader(f).map_err(RawError::RonError)?; + fragments.insert(relative_path.to_path_buf(), fragment); + } + } + Ok(RawLanguage{ + manifest, + fragments, + }) +} + +impl From for Language { + fn from(raw: RawLanguage) -> Self { + + let mut string_map = HashMap::new(); + let mut vector_map = HashMap::new(); + + for (_, fragment) in raw.fragments { + string_map.extend(fragment.string_map); + vector_map.extend(fragment.vector_map); + } + + let convert_utf8_to_ascii = raw.manifest.convert_utf8_to_ascii; + + // Update the text if UTF-8 to ASCII conversion is enabled + if convert_utf8_to_ascii { + for value in string_map.values_mut() { + *value = deunicode(value); + } + + for value in vector_map.values_mut() { + *value = value.iter().map(|s| deunicode(s)).collect(); + } + } + let mut metadata = raw.manifest.metadata; + metadata.language_name = deunicode(&metadata.language_name); + + Self { + string_map, + vector_map, + convert_utf8_to_ascii, + fonts: raw.manifest.fonts, + metadata: metadata, + } + } +} + +impl core::fmt::Display for RawError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + RawError::RonError(e) => write!(f, "{}", e), + } + } +} + +impl std::error::Error for RawError {} + + +impl From for common_assets::Error { + fn from(e: RawError) -> Self { + Self::Conversion(Box::new(e)) + } +} + + +impl common_assets::Asset for RawManifest { + type Loader = common_assets::RonLoader; + + const EXTENSION: &'static str = LANG_EXTENSION; +} + +impl common_assets::Asset for RawFragment { + type Loader = common_assets::RonLoader; + + const EXTENSION: &'static str = LANG_EXTENSION; +} \ No newline at end of file diff --git a/voxygen/i18n/src/verification.rs b/voxygen/i18n/src/verification.rs index ad7897c386..9a62974abc 100644 --- a/voxygen/i18n/src/verification.rs +++ b/voxygen/i18n/src/verification.rs @@ -1,34 +1,7 @@ -use ron::de::from_reader; -use std::{fs, path::Path}; +use std::{path::Path}; -use crate::data::{i18n_directories, LocalizationFragment, LANG_MANIFEST_FILE, REFERENCE_LANG}; - -fn verify_localization_directory(root_dir: &Path, directory_path: &Path) { - // Walk through each file in the directory - for i18n_file in root_dir.join(&directory_path).read_dir().unwrap().flatten() { - if let Ok(file_type) = i18n_file.file_type() { - // Skip folders and the manifest file (which does not contain the same struct we - // want to load) - if file_type.is_file() { - let full_path = i18n_file.path(); - println!("-> {:?}", full_path.strip_prefix(&root_dir).unwrap()); - let f = fs::File::open(&full_path).expect("Failed opening file"); - let _loc: LocalizationFragment = match from_reader(f) { - Ok(v) => v, - Err(e) => { - panic!( - "Could not parse {} RON file, error: {}", - full_path.to_string_lossy(), - e - ); - }, - }; - } else if file_type.is_dir() { - verify_localization_directory(root_dir, &i18n_file.path()); - } - } - } -} +use crate::{i18n_directories, LANG_MANIFEST_FILE, REFERENCE_LANG}; +use crate::raw; /// Test to verify all languages that they are VALID and loadable, without /// need of git just on the local assets folder @@ -36,17 +9,18 @@ fn verify_localization_directory(root_dir: &Path, directory_path: &Path) { /// `asset_path` - relative path to asset directory (right now it is /// 'assets/voxygen/i18n') pub fn verify_all_localizations(root_dir: &Path, asset_path: &Path) { - let ref_i18n_dir_path = asset_path.join(REFERENCE_LANG); - let ref_i18n_path = ref_i18n_dir_path.join(LANG_MANIFEST_FILE.to_string() + ".ron"); + let i18n_root_path = root_dir.join(asset_path); + let ref_i18n_path = i18n_root_path.join(REFERENCE_LANG); + let ref_i18n_manifest_path = ref_i18n_path.join(LANG_MANIFEST_FILE.to_string() + "." + crate::LANG_EXTENSION); assert!( - root_dir.join(&ref_i18n_dir_path).is_dir(), + root_dir.join(&ref_i18n_path).is_dir(), "Reference language folder doesn't exist, something is wrong!" ); assert!( - root_dir.join(&ref_i18n_path).is_file(), + root_dir.join(&ref_i18n_manifest_path).is_file(), "Reference language manifest file doesn't exist, something is wrong!" ); - let i18n_directories = i18n_directories(&root_dir.join(asset_path)); + let i18n_directories = i18n_directories(&i18n_root_path); // This simple check ONLY guarantees that an arbitrary minimum of translation // files exists. It's just to notice unintentional deletion of all // files, or modifying the paths. In case you want to delete all @@ -57,11 +31,19 @@ pub fn verify_all_localizations(root_dir: &Path, asset_path: &Path) { folder is empty?" ); for i18n_directory in i18n_directories { + let display_language_identifier = i18n_directory.strip_prefix(&root_dir).unwrap().as_os_str().to_str().unwrap(); + let language_identifier = i18n_directory.strip_prefix(&i18n_root_path).unwrap().as_os_str().to_str().unwrap(); println!( "verifying {:?}", - i18n_directory.strip_prefix(&root_dir).unwrap() + display_language_identifier ); // Walk through each files and try to load them - verify_localization_directory(root_dir, &i18n_directory); + verify_localization_directory(root_dir, &asset_path, language_identifier); } } + +fn verify_localization_directory(root_dir: &Path, asset_path: &Path, language_identifier: &str) { + let i18n_path = root_dir.join(asset_path); + let manifest = raw::load_manifest(&i18n_path, language_identifier).expect("error accessing manifest file"); + raw::load_raw_language(&i18n_path, manifest).expect("error accessing fragment file"); +} \ No newline at end of file From a5696e83a961c36de8850de64fce149167d1485e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Tue, 27 Jul 2021 20:07:08 +0200 Subject: [PATCH 014/155] experiment with a git cache --- voxygen/i18n/src/bin/i18n-check.rs | 6 +- voxygen/i18n/src/gitfragments.rs | 172 +++++++++++++++++++++++++++++ voxygen/i18n/src/lib.rs | 6 +- voxygen/i18n/src/raw.rs | 45 ++++---- voxygen/i18n/src/verification.rs | 4 +- 5 files changed, 208 insertions(+), 25 deletions(-) create mode 100644 voxygen/i18n/src/gitfragments.rs diff --git a/voxygen/i18n/src/bin/i18n-check.rs b/voxygen/i18n/src/bin/i18n-check.rs index f3bdf0a490..174bb0b9d6 100644 --- a/voxygen/i18n/src/bin/i18n-check.rs +++ b/voxygen/i18n/src/bin/i18n-check.rs @@ -1,3 +1,4 @@ +/* use clap::{App, Arg}; use std::path::Path; use veloren_i18n::{analysis, verification}; @@ -60,4 +61,7 @@ fn main() { if matches.is_present("verify") { verification::verify_all_localizations(&root, &asset_path); } -} +}*/ + + +fn main() {} \ No newline at end of file diff --git a/voxygen/i18n/src/gitfragments.rs b/voxygen/i18n/src/gitfragments.rs new file mode 100644 index 0000000000..ac415e4ad8 --- /dev/null +++ b/voxygen/i18n/src/gitfragments.rs @@ -0,0 +1,172 @@ +//! fragment attached with git versioning information +use hashbrown::{HashMap}; +use std::path::{Path, PathBuf}; +use std::sync::RwLock; +use std::sync::Arc; +use crate::raw::{RawFragment}; + +struct GitCache<'a> { + pub root_dir: PathBuf, + pub blobs: RwLock>>>, + pub repo: git2::Repository, + //pub head_ref: git2::Reference<'a>, +} + +impl<'a> GitCache<'a> { + pub fn new(root_dir: &Path) -> Self { + let repo = git2::Repository::discover(&root_dir) + .unwrap_or_else(|_| panic!("Failed to open the Git repository at {:?}", &root_dir)); + //let head_ref = repo.head().expect("Impossible to get the HEAD reference"); + + let root_dir = root_dir.to_path_buf(); + let blobs = RwLock::new(HashMap::new()); + Self { + root_dir, + blobs, + repo, + //head_ref, + } + } + /// Returns the Git blob associated with the given reference and path + fn read_file_from_path( + &'a self, + reference: &git2::Reference, + path: &std::path::Path, + ) -> Arc> { + // return from cache + let lock = self.blobs.read().unwrap(); + if let Some(blob) = lock.get(path) { + return blob.clone(); + } + drop(lock); + // load file not in cache + let tree = reference + .peel_to_tree() + .expect("Impossible to peel HEAD to a tree object"); + let blob = Arc::new(tree.get_path(path) + .unwrap_or_else(|_| { + panic!( + "Impossible to find the file {:?} in reference {:?}", + path, + reference.name() + ) + }) + .to_object(&self.repo) + .unwrap() + .peel_to_blob() + .expect("Impossible to fetch the Git object")); + let mut lock = self.blobs.write().unwrap(); + let pathbuf = path.to_path_buf(); + lock.insert(pathbuf, blob.clone()); + blob + } +} + +/* +/// Extend a Fragment with historical git data +/// The actual translation gets dropped +fn generate_key_version<'a>( + repo: &'a GitCache, + path: &Path, + fragment: RawFragment, +) -> RawFragment { + let file_blob = repo.read_file_from_path(path); + // Find key start lines + let file_content = std::str::from_utf8(file_blob.content()).expect("Got non UTF-8 file"); + let mut to_process: HashSet<&String> = localization.string_map.keys().collect(); + for (line_nb, line) in file_content.lines().enumerate() { + let mut found_key = None; + + for key in to_process.iter() { + if correspond(line, key) { + found_key = Some(key.to_owned()); + } + } + + if let Some(key) = found_key { + keys.get_mut(key).unwrap().key_line = Some(line_nb); + to_process.remove(key); + }; + } + + +}*/ + +/* + +fn generate_key_version<'a>( + repo: &'a git2::Repository, + fragment: &RawFragment, + path: &std::path::Path, + file_blob: &git2::Blob, +) -> HashMap { + let mut keys: HashMap = localization + .string_map + .keys() + .map(|k| (k.to_owned(), LocalizationEntryState::new())) + .collect(); + // Find key start lines + let file_content = std::str::from_utf8(file_blob.content()).expect("Got non UTF-8 file"); + let mut to_process: HashSet<&String> = localization.string_map.keys().collect(); + for (line_nb, line) in file_content.lines().enumerate() { + let mut found_key = None; + + for key in to_process.iter() { + if correspond(line, key) { + found_key = Some(key.to_owned()); + } + } + + if let Some(key) = found_key { + keys.get_mut(key).unwrap().key_line = Some(line_nb); + to_process.remove(key); + }; + } + + let mut error_check_set: Vec = vec![]; + // Find commit for each keys + repo.blame_file(path, None) + .expect("Impossible to generate the Git blame") + .iter() + .for_each(|e: git2::BlameHunk| { + for (key, state) in keys.iter_mut() { + let line = match state.key_line { + Some(l) => l, + None => { + if !error_check_set.contains(key) { + eprintln!( + "Key {} does not have a git line in it's state! Skipping key.", + key + ); + error_check_set.push(key.clone()); + } + continue; + }, + }; + + if line + 1 >= e.final_start_line() + && line + 1 < e.final_start_line() + e.lines_in_hunk() + { + state.chuck_line_range = Some(( + e.final_start_line(), + e.final_start_line() + e.lines_in_hunk(), + )); + state.commit_id = match state.commit_id { + Some(existing_commit) => { + match repo.graph_descendant_of(e.final_commit_id(), existing_commit) { + Ok(true) => Some(e.final_commit_id()), + Ok(false) => Some(existing_commit), + Err(err) => panic!("{}", err), + } + }, + None => Some(e.final_commit_id()), + }; + } + } + }); + + keys +} + + + */ \ No newline at end of file diff --git a/voxygen/i18n/src/lib.rs b/voxygen/i18n/src/lib.rs index d0b9f85e8c..0c946db4c1 100644 --- a/voxygen/i18n/src/lib.rs +++ b/voxygen/i18n/src/lib.rs @@ -1,5 +1,7 @@ #[cfg(any(feature = "bin", test))] -pub mod analysis; +pub mod gitfragments; +//#[cfg(any(feature = "bin", test))] +//pub mod analysis; pub mod raw; pub mod verification; @@ -113,7 +115,7 @@ impl common_assets::Compound for Language { // inside the asked_localization let mut fragments = HashMap::new(); for fragment_asset in cache - .load_dir::(asset_key, true)? + .load_dir::>(asset_key, true)? .iter() { let read = fragment_asset.read(); diff --git a/voxygen/i18n/src/raw.rs b/voxygen/i18n/src/raw.rs index e04d64e706..318bd3bbcd 100644 --- a/voxygen/i18n/src/raw.rs +++ b/voxygen/i18n/src/raw.rs @@ -20,14 +20,14 @@ pub(crate) struct RawManifest { /// Raw localization data from one specific file /// These structs are meant to be merged into a Language #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] -pub(crate) struct RawFragment { - pub(crate) string_map: HashMap, - pub(crate) vector_map: HashMap>, +pub(crate) struct RawFragment { + pub(crate) string_map: HashMap, + pub(crate) vector_map: HashMap>, } -pub(crate) struct RawLanguage { +pub(crate) struct RawLanguage { pub(crate) manifest: RawManifest, - pub(crate) fragments: HashMap, + pub(crate) fragments: HashMap>, } #[derive(Debug)] @@ -44,18 +44,26 @@ pub(crate) fn load_manifest(i18n_root_path: &Path, language_identifier: &str) -> } /// `i18n_root_path` - absolute path to i18n path which contains `en`, `de_DE`, `fr_FR` files -pub(crate) fn load_raw_language(i18n_root_path: &Path, manifest: RawManifest) -> Result { +pub(crate) fn load_raw_language(i18n_root_path: &Path, manifest: RawManifest) -> Result, common_assets::Error> { + let language_identifier = &manifest.metadata.language_identifier; + let fragments = recursive_load_raw_language(i18n_root_path, language_identifier, Path::new(""))?; + Ok(RawLanguage{ + manifest, + fragments, + }) +} + +fn recursive_load_raw_language(i18n_root_path: &Path, language_identifier: &str, subfolder: &Path) -> Result>, common_assets::Error> { // Walk through each file in the directory let mut fragments = HashMap::new(); - let language_identifier = &manifest.metadata.language_identifier; - let language_dir = i18n_root_path.join(language_identifier); - for fragment_file in language_dir.read_dir().unwrap().flatten() { + let search_dir = i18n_root_path.join(language_identifier).join(subfolder); + for fragment_file in search_dir.read_dir().unwrap().flatten() { let file_type = fragment_file.file_type()?; if file_type.is_dir() { - // TODO: recursive - continue; - } - if file_type.is_file() { + let full_path = fragment_file.path(); + let relative_path = full_path.strip_prefix(&search_dir).unwrap(); + fragments.extend(recursive_load_raw_language(i18n_root_path, language_identifier, relative_path)?); + } else if file_type.is_file() { let full_path = fragment_file.path(); let relative_path = full_path.strip_prefix(&i18n_root_path).unwrap(); let f = fs::File::open(&full_path)?; @@ -63,14 +71,11 @@ pub(crate) fn load_raw_language(i18n_root_path: &Path, manifest: RawManifest) -> fragments.insert(relative_path.to_path_buf(), fragment); } } - Ok(RawLanguage{ - manifest, - fragments, - }) + Ok(fragments) } -impl From for Language { - fn from(raw: RawLanguage) -> Self { +impl From> for Language { + fn from(raw: RawLanguage) -> Self { let mut string_map = HashMap::new(); let mut vector_map = HashMap::new(); @@ -129,7 +134,7 @@ impl common_assets::Asset for RawManifest { const EXTENSION: &'static str = LANG_EXTENSION; } -impl common_assets::Asset for RawFragment { +impl common_assets::Asset for RawFragment { type Loader = common_assets::RonLoader; const EXTENSION: &'static str = LANG_EXTENSION; diff --git a/voxygen/i18n/src/verification.rs b/voxygen/i18n/src/verification.rs index 9a62974abc..89d8146757 100644 --- a/voxygen/i18n/src/verification.rs +++ b/voxygen/i18n/src/verification.rs @@ -31,8 +31,8 @@ pub fn verify_all_localizations(root_dir: &Path, asset_path: &Path) { folder is empty?" ); for i18n_directory in i18n_directories { - let display_language_identifier = i18n_directory.strip_prefix(&root_dir).unwrap().as_os_str().to_str().unwrap(); - let language_identifier = i18n_directory.strip_prefix(&i18n_root_path).unwrap().as_os_str().to_str().unwrap(); + let display_language_identifier = i18n_directory.strip_prefix(&root_dir).unwrap().to_str().unwrap(); + let language_identifier = i18n_directory.strip_prefix(&i18n_root_path).unwrap().to_str().unwrap(); println!( "verifying {:?}", display_language_identifier From bdda5ccd72f8d509202c21a1a01f58f50933b1df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Wed, 28 Jul 2021 15:20:09 +0200 Subject: [PATCH 015/155] redo i18n git analysis completly and introduce a way to export csv data also improve the performance by caching git_graph_descendant --- voxygen/i18n/src/analysis.rs | 883 ++++++++--------------------- voxygen/i18n/src/bin/i18n-check.rs | 29 +- voxygen/i18n/src/gitfragments.rs | 279 +++++---- voxygen/i18n/src/lib.rs | 28 +- voxygen/i18n/src/raw.rs | 149 +++-- voxygen/i18n/src/stats.rs | 205 +++++++ voxygen/i18n/src/verification.rs | 54 +- 7 files changed, 743 insertions(+), 884 deletions(-) create mode 100644 voxygen/i18n/src/stats.rs diff --git a/voxygen/i18n/src/analysis.rs b/voxygen/i18n/src/analysis.rs index 89841df7d1..c336816f28 100644 --- a/voxygen/i18n/src/analysis.rs +++ b/voxygen/i18n/src/analysis.rs @@ -1,686 +1,283 @@ -use ron::de::from_bytes; -use std::path::{Path, PathBuf}; - -use crate::raw::{ - i18n_directories, LocalizationFragment, RawLocalization, LANG_MANIFEST_FILE, REFERENCE_LANG, +use crate::{ + gitfragments::{ + read_file_from_path, transform_fragment, LocalizationEntryState, LocalizationState, + }, + i18n_directories, + raw::{self, RawFragment, RawLanguage}, + stats::{ + print_csv_file, print_overall_stats, print_translation_stats, LocalizationAnalysis, + LocalizationStats, + }, + REFERENCE_LANG, }; -use hashbrown::{HashMap, HashSet}; +use hashbrown::{hash_map::Entry, HashMap, HashSet}; +use ron::de::from_bytes; +use std::path::Path; -#[derive(Copy, Clone, Eq, Hash, Debug, PartialEq)] -enum LocalizationState { - UpToDate, - NotFound, - Outdated, - Unknown, - Unused, -} - -#[derive(Debug, PartialEq)] -struct LocalizationStats { - uptodate_entries: usize, - outdated_entries: usize, - unused_entries: usize, - notfound_entries: usize, - errors: usize, - real_entry_count: usize, -} - -#[derive(Default)] -struct LocalizationAnalysis { - uptodate: Vec<(String, Option)>, - notfound: Vec<(String, Option)>, - unused: Vec<(String, Option)>, - outdated: Vec<(String, Option)>, - unknown: Vec<(String, Option)>, -} - -impl LocalizationAnalysis { - fn get_mut( - &mut self, - state: LocalizationState, - ) -> Option<&mut Vec<(String, Option)>> { - match state { - LocalizationState::UpToDate => Some(&mut self.uptodate), - LocalizationState::NotFound => Some(&mut self.notfound), - LocalizationState::Unused => Some(&mut self.unused), - LocalizationState::Outdated => Some(&mut self.outdated), - LocalizationState::Unknown => Some(&mut self.unknown), - } - } - - fn show( - &mut self, - state: LocalizationState, - be_verbose: bool, - ref_i18n_map: &HashMap, - ) { - let entries = self.unwrap_entries(state); - if entries.is_empty() { - return; - } - println!("\n\t[{:?}]", state); - entries.sort(); - for (key, commit_id) in entries { - if be_verbose { - let our_commit = LocalizationAnalysis::create_our_commit(commit_id); - let ref_commit = ref_i18n_map - .get(key) - .and_then(|s| s.commit_id) - .map(|s| format!("{}", s)) - .unwrap_or_else(|| "None".to_owned()); - println!("{:60}| {:40} | {:40}", key, our_commit, ref_commit,); - } else { - println!("{}", key); - } - } - } - - //TODO: Add which file each faulty translation is in - fn csv(&mut self, state: LocalizationState) { - let entries = self.unwrap_entries(state); - for (key, commit_id) in entries { - let our_commit = LocalizationAnalysis::create_our_commit(commit_id); - println!( - "{},{},{},{:?},{}", - "sv", "_manifest.yml", key, state, our_commit - ); - } - } - - fn unwrap_entries( - &mut self, - state: LocalizationState, - ) -> &mut Vec<(String, Option)> { - self.get_mut(state) - .unwrap_or_else(|| panic!("called on invalid state: {:?}", state)) - } - - fn create_our_commit(commit_id: &mut Option) -> String { - commit_id - .map(|s| format!("{}", s)) - .unwrap_or_else(|| "None".to_owned()) - } -} - -#[derive(Copy, Clone, Debug)] -struct LocalizationEntryState { - key_line: Option, - chuck_line_range: Option<(usize, usize)>, - commit_id: Option, - state: LocalizationState, -} - -impl LocalizationEntryState { - fn new() -> LocalizationEntryState { - LocalizationEntryState { - key_line: None, - chuck_line_range: None, - commit_id: None, - state: LocalizationState::Unknown, - } - } -} - -/// Returns the Git blob associated with the given reference and path -fn read_file_from_path<'a>( - repo: &'a git2::Repository, - reference: &git2::Reference, - path: &std::path::Path, -) -> git2::Blob<'a> { - let tree = reference - .peel_to_tree() - .expect("Impossible to peel HEAD to a tree object"); - tree.get_path(path) - .unwrap_or_else(|_| { - panic!( - "Impossible to find the file {:?} in reference {:?}", - path, - reference.name() - ) - }) - .to_object(repo) - .unwrap() - .peel_to_blob() - .expect("Impossible to fetch the Git object") -} - -fn correspond(line: &str, key: &str) -> bool { - let pat = { - // Get left part of split - let mut begin = line - .split(':') - .next() - .expect("split always produces value") - .trim() - .chars(); - // Remove quotes - begin.next(); - begin.next_back(); - begin.as_str() - }; - - pat == key -} - -fn generate_key_version<'a>( - repo: &'a git2::Repository, - localization: &LocalizationFragment, - path: &std::path::Path, - file_blob: &git2::Blob, -) -> HashMap { - let mut keys: HashMap = localization - .string_map - .keys() - .map(|k| (k.to_owned(), LocalizationEntryState::new())) - .collect(); - // Find key start lines - let file_content = std::str::from_utf8(file_blob.content()).expect("Got non UTF-8 file"); - let mut to_process: HashSet<&String> = localization.string_map.keys().collect(); - for (line_nb, line) in file_content.lines().enumerate() { - let mut found_key = None; - - for key in to_process.iter() { - if correspond(line, key) { - found_key = Some(key.to_owned()); - } - } - - if let Some(key) = found_key { - keys.get_mut(key).unwrap().key_line = Some(line_nb); - to_process.remove(key); - }; - } - - let mut error_check_set: Vec = vec![]; - // Find commit for each keys - repo.blame_file(path, None) - .expect("Impossible to generate the Git blame") - .iter() - .for_each(|e: git2::BlameHunk| { - for (key, state) in keys.iter_mut() { - let line = match state.key_line { - Some(l) => l, - None => { - if !error_check_set.contains(key) { - eprintln!( - "Key {} does not have a git line in it's state! Skipping key.", - key - ); - error_check_set.push(key.clone()); - } - continue; - }, - }; - - if line + 1 >= e.final_start_line() - && line + 1 < e.final_start_line() + e.lines_in_hunk() - { - state.chuck_line_range = Some(( - e.final_start_line(), - e.final_start_line() + e.lines_in_hunk(), - )); - state.commit_id = match state.commit_id { - Some(existing_commit) => { - match repo.graph_descendant_of(e.final_commit_id(), existing_commit) { - Ok(true) => Some(e.final_commit_id()), - Ok(false) => Some(existing_commit), - Err(err) => panic!("{}", err), - } - }, - None => Some(e.final_commit_id()), - }; - } - } - }); - - keys -} - -fn complete_key_versions<'a>( +/// Fill the entry State base information (except `state`) for a complete +/// language +fn gather_entry_state<'a>( repo: &'a git2::Repository, head_ref: &git2::Reference, - i18n_key_versions: &mut HashMap, - root_dir: &Path, - lang_dir: &Path, -) { - //TODO: review unwraps in this file + language_identifier: &str, + root_path: &Path, + relative_i18n_root_path: &Path, +) -> RawLanguage { + println!("-> {:?}", &language_identifier); + let i18n_root_path = root_path.join(relative_i18n_root_path); + // load standard manifest + let manifest = raw::load_manifest(&i18n_root_path, language_identifier) + .expect("failed to load language manifest"); + // transform language into LocalizationEntryState + let mut fragments = HashMap::new(); // For each file in directory - for i18n_file in root_dir.join(&lang_dir).read_dir().unwrap().flatten() { - if let Ok(file_type) = i18n_file.file_type() { - if file_type.is_file() { - println!("-> {:?}", i18n_file.file_name()); + let files = raw::fragments_pathes_in_language(&i18n_root_path, language_identifier) + .expect("failed to get all files in language"); + for subpath in files { + let path = relative_i18n_root_path + .join(language_identifier) + .join(&subpath); + println!(" -> {:?}", &subpath); + let i18n_blob = read_file_from_path(repo, head_ref, &path); + let fragment: RawFragment = from_bytes(i18n_blob.content()).unwrap_or_else(|e| { + panic!( + "Could not parse {} RON file, skipping: {}", + subpath.to_string_lossy(), + e + ) + }); + let frag = transform_fragment(repo, (&path, fragment), &i18n_blob); + fragments.insert(subpath.to_path_buf(), frag); + } - let full_path = i18n_file.path(); - let path = full_path.strip_prefix(root_dir).unwrap(); - let i18n_blob = read_file_from_path(repo, head_ref, path); - let i18n: LocalizationFragment = - from_bytes(i18n_blob.content()).unwrap_or_else(|e| { - panic!( - "Could not parse {} RON file, skipping: {}", - i18n_file.path().to_string_lossy(), - e - ) - }); - i18n_key_versions.extend(generate_key_version(repo, &i18n, path, &i18n_blob)); - } else if file_type.is_dir() { - // If it's a directory, recursively check it - complete_key_versions( - repo, - head_ref, - i18n_key_versions, - root_dir, - &i18n_file.path(), + RawLanguage:: { + manifest, + fragments, + } +} + +/// fills in the `state` +fn compare_lang_with_reference( + current_i18n: &mut RawLanguage, + i18n_references: &RawLanguage, + repo: &git2::Repository, +) { + // git graph decendent of is slow, so we cache it + let mut graph_decendent_of_cache = HashMap::new(); + + let mut cached_graph_descendant_of = |commit, ancestor| -> bool { + let key = (commit, ancestor); + match graph_decendent_of_cache.entry(key) { + Entry::Occupied(entry) => { + return *entry.get(); + }, + Entry::Vacant(entry) => { + let value = repo.graph_descendant_of(commit, ancestor).unwrap_or(false); + *entry.insert(value) + }, + } + }; + + // match files + for (ref_path, ref_fragment) in i18n_references.fragments.iter() { + let cur_fragment = match current_i18n.fragments.get_mut(ref_path) { + Some(c) => c, + None => { + eprintln!( + "language {} is missing file: {:?}", + current_i18n.manifest.metadata.language_identifier, ref_path ); + continue; + }, + }; + + for (ref_key, ref_state) in ref_fragment.string_map.iter() { + match cur_fragment.string_map.get_mut(ref_key) { + Some(state) => { + let commit_id = match state.commit_id { + Some(c) => c, + None => { + eprintln!( + "Commit ID of key {} in i18n file {} is missing! Skipping key.", + ref_key, + ref_path.to_string_lossy() + ); + continue; + }, + }; + let ref_commit_id = match ref_state.commit_id { + Some(c) => c, + None => { + eprintln!( + "Commit ID of key {} in reference i18n file is missing! Skipping \ + key.", + ref_key + ); + continue; + }, + }; + if commit_id != ref_commit_id + && !cached_graph_descendant_of(commit_id, ref_commit_id) + { + state.state = Some(LocalizationState::Outdated); + } else { + state.state = Some(LocalizationState::UpToDate); + } + }, + None => { + cur_fragment + .string_map + .insert(ref_key.to_owned(), LocalizationEntryState { + key_line: None, + chuck_line_range: None, + commit_id: None, + state: Some(LocalizationState::NotFound), + }); + }, } } - } -} -fn gather_state( - loc: &RawLocalization, - i18n_blob: &git2::Blob, - ref_manifest: &Path, - root_dir: &Path, - lang_dir: &Path, - repo: &git2::Repository, - head_ref: &git2::Reference, -) -> HashMap { - // Generate map - let mut i18n_map = generate_key_version( - repo, - &LocalizationFragment::from(loc.clone()), - ref_manifest, - i18n_blob, - ); - - // Gathering info about keys from language - complete_key_versions(repo, head_ref, &mut i18n_map, root_dir, lang_dir); - - i18n_map -} - -// Helper function to test localization directory -// `lang_dir` - path to localization directory. Relative from root of the -// repo. -// `root_dir` - absolute path to repo -// `ref_manifest` - path to reference manifest -// `i18n_references` - keys from reference language -// `repo` - git object for main repo -// `head_ref` - HEAD -fn test_localization_directory( - lang_dir: &Path, - root_dir: &Path, - ref_manifest: &Path, - i18n_references: &HashMap, - be_verbose: bool, - csv_enabled: bool, - repo: &git2::Repository, - head_ref: &git2::Reference, -) -> Option { - let relfile = lang_dir.join(&(LANG_MANIFEST_FILE.to_string() + ".ron")); - if relfile == ref_manifest { - return None; - } - println!("\n-----------------------------------"); - println!("{:?}", relfile); - println!("-----------------------------------"); - - // Find the localization entry state - let current_blob = read_file_from_path(repo, head_ref, &relfile); - let current_loc: RawLocalization = from_bytes(current_blob.content()).unwrap_or_else(|e| { - panic!( - "Could not parse {} RON file, skipping: {}", - relfile.to_string_lossy(), - e - ) - }); - - // Gather state of current localization - let mut current_i18n = gather_state( - ¤t_loc, - ¤t_blob, - ref_manifest, - root_dir, - lang_dir, - repo, - head_ref, - ); - - // Comparing with reference localization - fill_info(&mut current_i18n, i18n_references, repo, &relfile); - - let mut state_map = LocalizationAnalysis::default(); - let result = gather_results(current_i18n, &mut state_map); - print_csv_file(&mut state_map, relfile); - Some(result) -} - -fn fill_info( - current_i18n: &mut HashMap, - i18n_references: &HashMap, - repo: &git2::Repository, - relfile: &Path, -) { - for (ref_key, ref_state) in i18n_references.iter() { - match current_i18n.get_mut(ref_key) { - Some(state) => { - let commit_id = match state.commit_id { - Some(c) => c, - None => { - eprintln!( - "Commit ID of key {} in i18n file {} is missing! Skipping key.", - ref_key, - relfile.to_string_lossy() - ); - continue; - }, - }; - let ref_commit_id = match ref_state.commit_id { - Some(c) => c, - None => { - eprintln!( - "Commit ID of key {} in reference i18n file is missing! Skipping key.", - ref_key - ); - continue; - }, - }; - if commit_id != ref_commit_id - && !repo - .graph_descendant_of(commit_id, ref_commit_id) - .unwrap_or(false) - { - state.state = LocalizationState::Outdated; - } else { - state.state = LocalizationState::UpToDate; - } - }, - None => { - current_i18n.insert(ref_key.to_owned(), LocalizationEntryState { - key_line: None, - chuck_line_range: None, - commit_id: None, - state: LocalizationState::NotFound, - }); - }, + let ref_keys: HashSet<&String> = ref_fragment.string_map.keys().collect(); + for (_, state) in cur_fragment + .string_map + .iter_mut() + .filter(|&(k, _)| !ref_keys.contains(k)) + { + state.state = Some(LocalizationState::Unused); } } - - let ref_keys: HashSet<&String> = i18n_references.keys().collect(); - for (_, state) in current_i18n - .iter_mut() - .filter(|&(k, _)| !ref_keys.contains(k)) - { - state.state = LocalizationState::Unused; - } } fn gather_results( - current_i18n: HashMap, - state_map: &mut LocalizationAnalysis, -) -> LocalizationStats { - let mut uptodate_entries = 0; - let mut outdated_entries = 0; - let mut unused_entries = 0; - let mut notfound_entries = 0; - let mut unknown_entries = 0; + current_i18n: &RawLanguage, +) -> (LocalizationAnalysis, LocalizationStats) { + let mut state_map = + LocalizationAnalysis::new(¤t_i18n.manifest.metadata.language_identifier); + let mut stats = LocalizationStats::default(); - let keys: Vec<&String> = current_i18n.keys().collect(); - for key in keys { - let entry = current_i18n.get(key).unwrap(); - match entry.state { - LocalizationState::Outdated => outdated_entries += 1, - LocalizationState::NotFound => notfound_entries += 1, - LocalizationState::Unknown => unknown_entries += 1, - LocalizationState::Unused => unused_entries += 1, - LocalizationState::UpToDate => uptodate_entries += 1, - }; - if entry.state != LocalizationState::UpToDate { - let state_keys = state_map - .get_mut(entry.state) - .expect("vectors must be added"); - state_keys.push((key.to_owned(), entry.commit_id)); + for (file, fragments) in ¤t_i18n.fragments { + for (key, entry) in &fragments.string_map { + match entry.state { + Some(LocalizationState::Outdated) => stats.outdated_entries += 1, + Some(LocalizationState::NotFound) => stats.notfound_entries += 1, + None => stats.errors += 1, + Some(LocalizationState::Unused) => stats.unused_entries += 1, + Some(LocalizationState::UpToDate) => stats.uptodate_entries += 1, + }; + if entry.state != Some(LocalizationState::UpToDate) { + let state_keys = state_map.data.get_mut(&entry.state).expect("prefiled"); + state_keys.push((file.clone(), key.to_owned(), entry.commit_id)); + } } } - // Calculate key count that actually matter for the status of the translation - // Unused entries don't break the game - let current_i18n_entry_count = current_i18n.len(); - let real_entry_count = current_i18n_entry_count - unused_entries; - - LocalizationStats { - uptodate_entries, - unused_entries, - outdated_entries, - notfound_entries, - errors: unknown_entries, - real_entry_count, + for (_, entries) in state_map.data.iter_mut() { + entries.sort(); } + + (state_map, stats) } -fn print_translation_stats( - ref_i18n_map: &HashMap, - stats: &LocalizationStats, - state_map: &mut LocalizationAnalysis, - be_verbose: bool, - relfile: PathBuf, - ref_manifest: &Path, +/// completely analysis multiple languages without printing +fn complete_analysis( + language_identifiers: &[&str], + root_path: &Path, + relative_i18n_root_path: &Path, +) -> ( + HashMap, + /* ref lang */ RawLanguage, ) { - let uptodate_percent = - (stats.uptodate_entries as f32 / stats.real_entry_count as f32) * 100_f32; - let outdated_percent = - (stats.outdated_entries as f32 / stats.real_entry_count as f32) * 100_f32; - let untranslated_percent = - ((stats.errors + stats.errors) as f32 / stats.real_entry_count as f32) * 100_f32; + let mut result = HashMap::new(); + // Initialize Git objects + let repo = git2::Repository::discover(&root_path) + .unwrap_or_else(|_| panic!("Failed to open the Git repository at {:?}", &root_path)); + let head_ref = repo.head().expect("Impossible to get the HEAD reference"); - // Display - if be_verbose { - println!( - "\n{:60}| {:40} | {:40}", - "Key name", - relfile.to_str().unwrap(), - ref_manifest.to_str().unwrap(), + // Read Reference Language + let ref_language = gather_entry_state( + &repo, + &head_ref, + REFERENCE_LANG, + root_path, + relative_i18n_root_path, + ); + for &language_identifier in language_identifiers { + let mut cur_language = gather_entry_state( + &repo, + &head_ref, + language_identifier, + root_path, + relative_i18n_root_path, ); - } else { - println!("\nKey name"); + compare_lang_with_reference(&mut cur_language, &ref_language, &repo); + let (state_map, stats) = gather_results(&cur_language); + result.insert(language_identifier.to_owned(), (state_map, stats)); } - - state_map.show(LocalizationState::NotFound, be_verbose, ref_i18n_map); - state_map.show(LocalizationState::Unused, be_verbose, ref_i18n_map); - state_map.show(LocalizationState::Outdated, be_verbose, ref_i18n_map); - state_map.show(LocalizationState::Unknown, be_verbose, ref_i18n_map); - - println!( - "\n{} up-to-date, {} outdated, {} unused, {} not found, {} unknown entries", - stats.uptodate_entries, - stats.outdated_entries, - stats.unused_entries, - stats.notfound_entries, - stats.errors, - ); - - println!( - "{:.2}% up-to-date, {:.2}% outdated, {:.2}% untranslated\n", - uptodate_percent, outdated_percent, untranslated_percent, - ); -} - -fn print_csv_file(state_map: &mut LocalizationAnalysis, relfile: PathBuf) { - println!("country_code,file_name,translation_code,status,git_commit"); - - state_map.csv(LocalizationState::UpToDate); - state_map.csv(LocalizationState::NotFound); - state_map.csv(LocalizationState::Unused); - state_map.csv(LocalizationState::Outdated); - state_map.csv(LocalizationState::Unknown); + (result, ref_language) } /// Test one language -/// `code` - name of the directory in assets (de_DE for example) -/// `root_dir` - absolute path to main repo -/// `assets_path` - relative path to asset directory (right now it is -/// 'assets/voxygen/i18n') -/// be_verbose - -/// csv_enabled - generate csv files in target folder -pub fn test_specific_localization( - code: &str, - root_dir: &Path, - assets_path: &Path, +/// - `code`: name of the directory in assets (de_DE for example) +/// - `root_path`: absolute path to main repo +/// - `relative_i18n_root_path`: relative path to asset directory (right now it +/// is 'assets/voxygen/i18n') +/// - be_verbose: print extra info +/// - csv_enabled: generate csv files in target folder +pub fn test_specific_localizations( + language_identifiers: &[&str], + root_path: &Path, + relative_i18n_root_path: &Path, be_verbose: bool, csv_enabled: bool, ) { - // Relative paths from root of repo to assets - let ref_lang_dir = assets_path.join(REFERENCE_LANG); - let ref_manifest = ref_lang_dir.join(LANG_MANIFEST_FILE.to_string() + ".ron"); - - // Initialize Git objects - let repo = git2::Repository::discover(&root_dir) - .unwrap_or_else(|_| panic!("Failed to open the Git repository at {:?}", &root_dir)); - let head_ref = repo.head().expect("Impossible to get the HEAD reference"); - - // Read HEAD for the reference language manifest - let ref_manifest_blob = read_file_from_path(&repo, &head_ref, &ref_manifest); - let loc: RawLocalization = from_bytes(ref_manifest_blob.content()) - .expect("Expect to parse reference i18n RON file, can't proceed without it"); - - // Gathering info about keys from reference language - let reference_i18n = gather_state( - &loc, - &ref_manifest_blob, - &ref_manifest, - root_dir, - &ref_lang_dir, - &repo, - &head_ref, - ); - - // Testing how specific language is localized - let dir = assets_path.join(code); - test_localization_directory( - &dir, - root_dir, - &ref_manifest, - &reference_i18n, - be_verbose, - csv_enabled, - &repo, - &head_ref, - ); + let (analysis, reference_language) = + complete_analysis(language_identifiers, root_path, relative_i18n_root_path); + for (language_identifier, (state_map, stats)) in &analysis { + if csv_enabled { + print_csv_file(state_map); + } else { + print_translation_stats( + language_identifier, + &reference_language, + stats, + state_map, + be_verbose, + ); + } + } + if analysis.len() > 1 { + print_overall_stats(analysis); + } } /// Test all localizations -/// `root_dir` - absolute path to main repo -/// `assets_path` - relative path to asset directory (right now it is -/// 'assets/voxygen/i18n') -/// csv_enabled - generate csv files in target folder pub fn test_all_localizations( - root_dir: &Path, - assets_path: &Path, + root_path: &Path, + relative_i18n_root_path: &Path, be_verbose: bool, csv_enabled: bool, ) { - let ref_lang_dir = assets_path.join(REFERENCE_LANG); - let ref_manifest = ref_lang_dir.join(LANG_MANIFEST_FILE.to_string() + ".ron"); - - if !root_dir.join(&ref_lang_dir).is_dir() { - panic!("Reference language folder not found {:?}", &ref_lang_dir) - } - if !root_dir.join(&ref_manifest).is_file() { - panic!("Reference language file not found {:?}", &ref_manifest) - } - - // Initialize Git objects - let repo = git2::Repository::discover(&root_dir) - .unwrap_or_else(|_| panic!("Failed to open the Git repository at {:?}", &root_dir)); - let head_ref = repo.head().expect("Impossible to get the HEAD reference"); - - // Read HEAD for the reference language file - let ref_manifest_blob = read_file_from_path(&repo, &head_ref, &ref_manifest); - let loc: RawLocalization = from_bytes(ref_manifest_blob.content()) - .expect("Expect to parse reference i18n RON file, can't proceed without it"); - - // Gathering info about keys from reference language - let reference_i18n = gather_state( - &loc, - &ref_manifest_blob, - &ref_manifest, - root_dir, - &ref_lang_dir, - &repo, - &head_ref, - ); - + let i18n_root_path = root_path.join(relative_i18n_root_path); // Compare to other reference files - let i18n_directories = i18n_directories(&root_dir.join(assets_path)); - let mut i18n_entry_counts: HashMap = HashMap::new(); - for dir in &i18n_directories { - let rel_dir = dir.strip_prefix(root_dir).unwrap(); - let result = test_localization_directory( - rel_dir, - root_dir, - &ref_manifest, - &reference_i18n, - be_verbose, - csv_enabled, - &repo, - &head_ref, - ); - if let Some(values) = result { - i18n_entry_counts.insert(dir.clone(), values); - } - } - - print_overall_stats(i18n_entry_counts); -} - -fn print_overall_stats(i18n_entry_counts: HashMap) { - let mut overall_uptodate_entry_count = 0; - let mut overall_outdated_entry_count = 0; - let mut overall_untranslated_entry_count = 0; - let mut overall_real_entry_count = 0; - - println!("-----------------------------------------------------------------------------"); - println!("Overall Translation Status"); - println!("-----------------------------------------------------------------------------"); - println!( - "{:12}| {:8} | {:8} | {:8} | {:8} | {:8}", - "", "up-to-date", "outdated", "untranslated", "unused", "errors", + let language_identifiers = i18n_directories(&i18n_root_path) + .into_iter() + .map(|p| { + p.strip_prefix(&i18n_root_path) + .unwrap() + .to_str() + .unwrap() + .to_owned() + }) + .collect::>(); + test_specific_localizations( + &language_identifiers + .iter() + .map(|s| s.as_str()) + .collect::>(), + root_path, + relative_i18n_root_path, + be_verbose, + csv_enabled, ); - - let mut i18n_stats: Vec<(&PathBuf, &LocalizationStats)> = i18n_entry_counts.iter().collect(); - i18n_stats.sort_by_key(|(_, result)| result.notfound_entries); - - for (path, test_result) in i18n_stats { - let LocalizationStats { - uptodate_entries: uptodate, - outdated_entries: outdated, - unused_entries: unused, - notfound_entries: untranslated, - errors, - real_entry_count: real, - } = test_result; - overall_uptodate_entry_count += uptodate; - overall_outdated_entry_count += outdated; - overall_untranslated_entry_count += untranslated; - overall_real_entry_count += real; - - println!( - "{:12}|{:8} |{:6} |{:8} |{:6} |{:8}", - path.file_name().unwrap().to_string_lossy(), - uptodate, - outdated, - untranslated, - unused, - errors, - ); - } - - println!( - "\n{:.2}% up-to-date, {:.2}% outdated, {:.2}% untranslated", - (overall_uptodate_entry_count as f32 / overall_real_entry_count as f32) * 100_f32, - (overall_outdated_entry_count as f32 / overall_real_entry_count as f32) * 100_f32, - (overall_untranslated_entry_count as f32 / overall_real_entry_count as f32) * 100_f32, - ); - println!("-----------------------------------------------------------------------------\n"); } diff --git a/voxygen/i18n/src/bin/i18n-check.rs b/voxygen/i18n/src/bin/i18n-check.rs index 174bb0b9d6..9972850b15 100644 --- a/voxygen/i18n/src/bin/i18n-check.rs +++ b/voxygen/i18n/src/bin/i18n-check.rs @@ -1,4 +1,3 @@ -/* use clap::{App, Arg}; use std::path::Path; use veloren_i18n::{analysis, verification}; @@ -37,31 +36,29 @@ fn main() { .get_matches(); // Generate paths - let root = common_assets::find_root().expect("Failed to find root of repository"); - let asset_path = Path::new("assets/voxygen/i18n/"); + let root_path = common_assets::find_root().expect("Failed to find root of repository"); + let relative_i18n_root_path = Path::new("assets/voxygen/i18n/"); + let be_verbose = matches.is_present("verbose"); let csv_enabled = matches.is_present("csv"); if let Some(code) = matches.value_of("CODE") { - analysis::test_specific_localization( - code, - &root, - &asset_path, - matches.is_present("verbose"), + analysis::test_specific_localizations( + &[code], + &root_path, + relative_i18n_root_path, + be_verbose, csv_enabled, ); } if matches.is_present("test") { analysis::test_all_localizations( - &root, - &asset_path, - matches.is_present("verbose"), + &root_path, + relative_i18n_root_path, + be_verbose, csv_enabled, ); } if matches.is_present("verify") { - verification::verify_all_localizations(&root, &asset_path); + verification::verify_all_localizations(&root_path, relative_i18n_root_path); } -}*/ - - -fn main() {} \ No newline at end of file +} diff --git a/voxygen/i18n/src/gitfragments.rs b/voxygen/i18n/src/gitfragments.rs index ac415e4ad8..e517360d42 100644 --- a/voxygen/i18n/src/gitfragments.rs +++ b/voxygen/i18n/src/gitfragments.rs @@ -1,172 +1,157 @@ //! fragment attached with git versioning information -use hashbrown::{HashMap}; -use std::path::{Path, PathBuf}; -use std::sync::RwLock; -use std::sync::Arc; -use crate::raw::{RawFragment}; +use crate::raw::RawFragment; +use hashbrown::HashMap; +use std::path::Path; -struct GitCache<'a> { - pub root_dir: PathBuf, - pub blobs: RwLock>>>, - pub repo: git2::Repository, - //pub head_ref: git2::Reference<'a>, +#[derive(Copy, Clone, Eq, Hash, Debug, PartialEq)] +pub(crate) enum LocalizationState { + UpToDate, + NotFound, + Outdated, + Unused, } -impl<'a> GitCache<'a> { - pub fn new(root_dir: &Path) -> Self { - let repo = git2::Repository::discover(&root_dir) - .unwrap_or_else(|_| panic!("Failed to open the Git repository at {:?}", &root_dir)); - //let head_ref = repo.head().expect("Impossible to get the HEAD reference"); +pub(crate) const ALL_LOCALIZATION_STATES: [Option; 5] = [ + Some(LocalizationState::UpToDate), + Some(LocalizationState::NotFound), + Some(LocalizationState::Outdated), + Some(LocalizationState::Unused), + None, +]; - let root_dir = root_dir.to_path_buf(); - let blobs = RwLock::new(HashMap::new()); - Self { - root_dir, - blobs, - repo, - //head_ref, +#[derive(Copy, Clone, Debug)] +pub(crate) struct LocalizationEntryState { + pub(crate) key_line: Option, + pub(crate) chuck_line_range: Option<(usize, usize)>, + pub(crate) commit_id: Option, + pub(crate) state: Option, +} + +impl LocalizationState { + pub(crate) fn print(this: &Option) -> String { + match this { + Some(LocalizationState::UpToDate) => "UpToDate", + Some(LocalizationState::NotFound) => "NotFound", + Some(LocalizationState::Outdated) => "Outdated", + Some(LocalizationState::Unused) => "Unused", + None => "Unknown", } - } - /// Returns the Git blob associated with the given reference and path - fn read_file_from_path( - &'a self, - reference: &git2::Reference, - path: &std::path::Path, - ) -> Arc> { - // return from cache - let lock = self.blobs.read().unwrap(); - if let Some(blob) = lock.get(path) { - return blob.clone(); - } - drop(lock); - // load file not in cache - let tree = reference - .peel_to_tree() - .expect("Impossible to peel HEAD to a tree object"); - let blob = Arc::new(tree.get_path(path) - .unwrap_or_else(|_| { - panic!( - "Impossible to find the file {:?} in reference {:?}", - path, - reference.name() - ) - }) - .to_object(&self.repo) - .unwrap() - .peel_to_blob() - .expect("Impossible to fetch the Git object")); - let mut lock = self.blobs.write().unwrap(); - let pathbuf = path.to_path_buf(); - lock.insert(pathbuf, blob.clone()); - blob + .to_owned() } } -/* +impl LocalizationEntryState { + fn new(key_line: Option) -> LocalizationEntryState { + LocalizationEntryState { + key_line, + chuck_line_range: None, + commit_id: None, + state: None, + } + } +} + +/// Returns the Git blob associated with the given reference and path +pub(crate) fn read_file_from_path<'a>( + repo: &'a git2::Repository, + reference: &git2::Reference, + path: &std::path::Path, +) -> git2::Blob<'a> { + let tree = reference + .peel_to_tree() + .expect("Impossible to peel HEAD to a tree object"); + tree.get_path(path) + .unwrap_or_else(|_| { + panic!( + "Impossible to find the file {:?} in reference {:?}", + path, + reference.name() + ) + }) + .to_object(repo) + .unwrap() + .peel_to_blob() + .expect("Impossible to fetch the Git object") +} + /// Extend a Fragment with historical git data /// The actual translation gets dropped -fn generate_key_version<'a>( - repo: &'a GitCache, - path: &Path, - fragment: RawFragment, -) -> RawFragment { - let file_blob = repo.read_file_from_path(path); - // Find key start lines - let file_content = std::str::from_utf8(file_blob.content()).expect("Got non UTF-8 file"); - let mut to_process: HashSet<&String> = localization.string_map.keys().collect(); - for (line_nb, line) in file_content.lines().enumerate() { - let mut found_key = None; - - for key in to_process.iter() { - if correspond(line, key) { - found_key = Some(key.to_owned()); - } - } - - if let Some(key) = found_key { - keys.get_mut(key).unwrap().key_line = Some(line_nb); - to_process.remove(key); - }; - } - - -}*/ - -/* - -fn generate_key_version<'a>( +/// TODO: transform vector_map too +pub(crate) fn transform_fragment<'a>( repo: &'a git2::Repository, - fragment: &RawFragment, - path: &std::path::Path, + fragment: (&Path, RawFragment), file_blob: &git2::Blob, -) -> HashMap { - let mut keys: HashMap = localization - .string_map - .keys() - .map(|k| (k.to_owned(), LocalizationEntryState::new())) - .collect(); - // Find key start lines +) -> RawFragment { + let (path, fragment) = fragment; + // Find key start lines by searching all lines which have `:` in them (as they + // are probably keys) and getting the first part of such line trimming + // whitespace and quotes. Quite buggy heuristic let file_content = std::str::from_utf8(file_blob.content()).expect("Got non UTF-8 file"); - let mut to_process: HashSet<&String> = localization.string_map.keys().collect(); - for (line_nb, line) in file_content.lines().enumerate() { - let mut found_key = None; + // we only need the key part of the file to process + let file_content_keys = file_content.lines().enumerate().filter_map(|(no, line)| { + line.split_once(':').map(|(key, _)| { + let mut key = key.trim().chars(); + key.next(); + key.next_back(); + (no, key.as_str()) + }) + }); + //speed up the search by sorting all keys! + let mut file_content_keys_sorted = file_content_keys.into_iter().collect::>(); + file_content_keys_sorted.sort_by_key(|(_, key)| *key); - for key in to_process.iter() { - if correspond(line, key) { - found_key = Some(key.to_owned()); - } - } + let mut result = RawFragment:: { + string_map: HashMap::new(), + vector_map: HashMap::new(), + }; - if let Some(key) = found_key { - keys.get_mut(key).unwrap().key_line = Some(line_nb); - to_process.remove(key); - }; + for (original_key, _) in fragment.string_map { + let line_nb = file_content_keys_sorted + .binary_search_by_key(&original_key.as_str(), |(_, key)| *key) + .map_or_else( + |_| { + eprintln!( + "Key {} does not have a git line in it's state!", + original_key + ); + None + }, + |id| Some(file_content_keys_sorted[id].0), + ); + + result + .string_map + .insert(original_key, LocalizationEntryState::new(line_nb)); } - let mut error_check_set: Vec = vec![]; - // Find commit for each keys - repo.blame_file(path, None) + // Find commit for each keys, THIS PART IS SLOW (2s/4s) + for e in repo + .blame_file(path, None) .expect("Impossible to generate the Git blame") .iter() - .for_each(|e: git2::BlameHunk| { - for (key, state) in keys.iter_mut() { - let line = match state.key_line { - Some(l) => l, - None => { - if !error_check_set.contains(key) { - eprintln!( - "Key {} does not have a git line in it's state! Skipping key.", - key - ); - error_check_set.push(key.clone()); - } - continue; - }, - }; - - if line + 1 >= e.final_start_line() - && line + 1 < e.final_start_line() + e.lines_in_hunk() - { - state.chuck_line_range = Some(( - e.final_start_line(), - e.final_start_line() + e.lines_in_hunk(), - )); - state.commit_id = match state.commit_id { - Some(existing_commit) => { - match repo.graph_descendant_of(e.final_commit_id(), existing_commit) { - Ok(true) => Some(e.final_commit_id()), - Ok(false) => Some(existing_commit), - Err(err) => panic!("{}", err), - } + { + for (_, state) in result.string_map.iter_mut() { + if let Some(line) = state.key_line { + let range = ( + e.final_start_line(), + e.final_start_line() + e.lines_in_hunk(), + ); + if line + 1 >= range.0 && line + 1 < range.1 { + state.chuck_line_range = Some(range); + state.commit_id = state.commit_id.map_or_else( + || Some(e.final_commit_id()), + |existing_commit| match repo + .graph_descendant_of(e.final_commit_id(), existing_commit) + { + Ok(true) => Some(e.final_commit_id()), + Ok(false) => Some(existing_commit), + Err(err) => panic!("{}", err), }, - None => Some(e.final_commit_id()), - }; + ); } } - }); + } + } - keys + result } - - - */ \ No newline at end of file diff --git a/voxygen/i18n/src/lib.rs b/voxygen/i18n/src/lib.rs index 0c946db4c1..9360823ee1 100644 --- a/voxygen/i18n/src/lib.rs +++ b/voxygen/i18n/src/lib.rs @@ -1,19 +1,20 @@ #[cfg(any(feature = "bin", test))] +pub mod analysis; +#[cfg(any(feature = "bin", test))] pub mod gitfragments; -//#[cfg(any(feature = "bin", test))] -//pub mod analysis; pub mod raw; +#[cfg(any(feature = "bin", test))] pub mod stats; pub mod verification; use common_assets::{self, source::DirEntry, AssetExt, AssetGuard, AssetHandle}; use hashbrown::{HashMap, HashSet}; +use raw::{RawFragment, RawLanguage, RawManifest}; use serde::{Deserialize, Serialize}; use std::{ fs, io, path::{Path, PathBuf}, }; use tracing::warn; -use raw::{RawManifest, RawFragment, RawLanguage}; /// The reference language, aka the more up-to-date localization data. /// Also the default language at first startup. @@ -118,11 +119,18 @@ impl common_assets::Compound for Language { .load_dir::>(asset_key, true)? .iter() { + let id = fragment_asset.id(); + // Activate this once ._manifest is fully transformed and only contains metadata + // or regex: "(_: &common_assets::AssetCache, _: &str) -> Result { + fn load( + _: &common_assets::AssetCache, + _: &str, + ) -> Result { Ok(Self) } } @@ -328,7 +339,6 @@ pub fn i18n_directories(i18n_dir: &Path) -> Vec { #[cfg(test)] mod tests { use std::path::Path; - use common_assets; // Test that localization list is loaded (not empty) #[test] @@ -357,11 +367,9 @@ mod tests { #[test] #[ignore] fn test_all_localizations() { - // Options - let be_verbose = true; // Generate paths let i18n_root_path = Path::new("assets/voxygen/i18n/"); let root_dir = common_assets::find_root().expect("Failed to discover repository root"); - crate::analysis::test_all_localizations(&root_dir, i18n_root_path, be_verbose); + crate::analysis::test_all_localizations(&root_dir, i18n_root_path, true, false); } } diff --git a/voxygen/i18n/src/raw.rs b/voxygen/i18n/src/raw.rs index 318bd3bbcd..e3e00a8d4e 100644 --- a/voxygen/i18n/src/raw.rs +++ b/voxygen/i18n/src/raw.rs @@ -1,12 +1,24 @@ //! handle the loading of a `Language` -use hashbrown::hash_map::HashMap; -use std::path::{Path, PathBuf}; -use serde::{Deserialize, Serialize}; -use std::fs; -use ron::de::from_reader; +//! Paths: +//! - `root_path`: repo part, git main folder +//! - `language_identifier`: `en`, `de_DE`, `fr_FR`, etc.. +//! - `relative_i18n_root_path`: relative path to i18n path which contains +//! `language_identifier` folders from `root_path` +//! - `i18n_root_path`: absolute path to `relative_i18n_root_path` +//! - `i18n_path`: absolute path to `i18n_root_path` + `language_identifier` +//! - `subfolder`: all folders in `i18n_path` +//! +//! wherever possible we use relative paths only. So expect 1 absolute +//! `root_path` or `i18n_root_path` to be required and all others be relative. +use crate::{Fonts, Language, LanguageMetadata, LANG_EXTENSION, LANG_MANIFEST_FILE}; use deunicode::deunicode; -use crate::{Fonts, LanguageMetadata, LANG_MANIFEST_FILE, LANG_EXTENSION}; -use crate::Language; +use hashbrown::hash_map::HashMap; +use ron::de::from_reader; +use serde::{Deserialize, Serialize}; +use std::{ + fs, + path::{Path, PathBuf}, +}; /// Raw localization metadata from LANG_MANIFEST_FILE file /// See `Language` for more info on each attributes @@ -27,7 +39,7 @@ pub(crate) struct RawFragment { pub(crate) struct RawLanguage { pub(crate) manifest: RawManifest, - pub(crate) fragments: HashMap>, + pub(crate) fragments: HashMap>, } #[derive(Debug)] @@ -35,48 +47,52 @@ pub(crate) enum RawError { RonError(ron::Error), } -/// `i18n_root_path` - absolute path to i18n path which contains `en`, `de_DE`, `fr_FR` folders -pub(crate) fn load_manifest(i18n_root_path: &Path, language_identifier: &str) -> Result { - let manifest_file = i18n_root_path.join(language_identifier).join(format!("{}.{}", LANG_MANIFEST_FILE, LANG_EXTENSION)); - println!("file , {:?}", manifest_file); +/// `i18n_root_path` - absolute path to i18n path which contains `en`, `de_DE`, +/// `fr_FR` folders +pub(crate) fn load_manifest( + i18n_root_path: &Path, + language_identifier: &str, +) -> Result { + let manifest_file = i18n_root_path + .join(language_identifier) + .join(format!("{}.{}", LANG_MANIFEST_FILE, LANG_EXTENSION)); + tracing::debug!(?manifest_file, "manifest loaded"); let f = fs::File::open(&manifest_file)?; - Ok(from_reader(f).map_err(RawError::RonError)?) + let manifest: RawManifest = from_reader(f).map_err(RawError::RonError)?; + // verify that the folder name `de_DE` matches the value inside the metadata! + assert_eq!(manifest.metadata.language_identifier, language_identifier); + Ok(manifest) } -/// `i18n_root_path` - absolute path to i18n path which contains `en`, `de_DE`, `fr_FR` files -pub(crate) fn load_raw_language(i18n_root_path: &Path, manifest: RawManifest) -> Result, common_assets::Error> { +/// `i18n_root_path` - absolute path to i18n path which contains `en`, `de_DE`, +/// `fr_FR` files +pub(crate) fn load_raw_language( + i18n_root_path: &Path, + manifest: RawManifest, +) -> Result, common_assets::Error> { let language_identifier = &manifest.metadata.language_identifier; - let fragments = recursive_load_raw_language(i18n_root_path, language_identifier, Path::new(""))?; - Ok(RawLanguage{ + let i18n_path = i18n_root_path.join(language_identifier); + + //get List of files + let files = fragments_pathes_in_language(i18n_root_path, language_identifier)?; + + // Walk through each file in the directory + let mut fragments = HashMap::new(); + for fragment_file in &files { + let relative_path = fragment_file.strip_prefix(&i18n_path).unwrap(); + let f = fs::File::open(fragment_file)?; + let fragment = from_reader(f).map_err(RawError::RonError)?; + fragments.insert(relative_path.to_path_buf(), fragment); + } + + Ok(RawLanguage { manifest, fragments, }) } -fn recursive_load_raw_language(i18n_root_path: &Path, language_identifier: &str, subfolder: &Path) -> Result>, common_assets::Error> { - // Walk through each file in the directory - let mut fragments = HashMap::new(); - let search_dir = i18n_root_path.join(language_identifier).join(subfolder); - for fragment_file in search_dir.read_dir().unwrap().flatten() { - let file_type = fragment_file.file_type()?; - if file_type.is_dir() { - let full_path = fragment_file.path(); - let relative_path = full_path.strip_prefix(&search_dir).unwrap(); - fragments.extend(recursive_load_raw_language(i18n_root_path, language_identifier, relative_path)?); - } else if file_type.is_file() { - let full_path = fragment_file.path(); - let relative_path = full_path.strip_prefix(&i18n_root_path).unwrap(); - let f = fs::File::open(&full_path)?; - let fragment = from_reader(f).map_err(RawError::RonError)?; - fragments.insert(relative_path.to_path_buf(), fragment); - } - } - Ok(fragments) -} - impl From> for Language { fn from(raw: RawLanguage) -> Self { - let mut string_map = HashMap::new(); let mut vector_map = HashMap::new(); @@ -105,11 +121,56 @@ impl From> for Language { vector_map, convert_utf8_to_ascii, fonts: raw.manifest.fonts, - metadata: metadata, + metadata, } } } +pub(crate) fn fragments_pathes_in_language( + i18n_root_path: &Path, + language_identifier: &str, +) -> Result, std::io::Error> { + let mut result = vec![]; + recursive_fragments_paths_in_language( + i18n_root_path, + language_identifier, + Path::new(""), + &mut result, + )?; + Ok(result) +} + +/// i18n_path = i18n_root_path.join(REFERENCE_LANG); +fn recursive_fragments_paths_in_language( + i18n_root_path: &Path, + language_identifier: &str, + subfolder: &Path, + result: &mut Vec, +) -> Result<(), std::io::Error> { + let i18n_path = i18n_root_path.join(language_identifier); + let search_dir = i18n_path.join(subfolder); + for fragment_file in search_dir.read_dir().unwrap().flatten() { + let file_type = fragment_file.file_type()?; + if file_type.is_dir() { + let full_path = fragment_file.path(); + let relative_path = full_path.strip_prefix(&i18n_path).unwrap(); + recursive_fragments_paths_in_language( + i18n_root_path, + language_identifier, + relative_path, + result, + )?; + } else if file_type.is_file() { + let full_path = fragment_file.path(); + let relative_path = full_path.strip_prefix(&i18n_path).unwrap(); + if relative_path != Path::new(&format!("{}.{}", LANG_MANIFEST_FILE, LANG_EXTENSION)) { + result.push(relative_path.to_path_buf()); + } + } + } + Ok(()) +} + impl core::fmt::Display for RawError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { @@ -120,14 +181,10 @@ impl core::fmt::Display for RawError { impl std::error::Error for RawError {} - impl From for common_assets::Error { - fn from(e: RawError) -> Self { - Self::Conversion(Box::new(e)) - } + fn from(e: RawError) -> Self { Self::Conversion(Box::new(e)) } } - impl common_assets::Asset for RawManifest { type Loader = common_assets::RonLoader; @@ -138,4 +195,4 @@ impl common_assets::Asset for RawFragment { type Loader = common_assets::RonLoader; const EXTENSION: &'static str = LANG_EXTENSION; -} \ No newline at end of file +} diff --git a/voxygen/i18n/src/stats.rs b/voxygen/i18n/src/stats.rs new file mode 100644 index 0000000000..a353e7ef29 --- /dev/null +++ b/voxygen/i18n/src/stats.rs @@ -0,0 +1,205 @@ +use crate::{ + gitfragments::{LocalizationEntryState, LocalizationState, ALL_LOCALIZATION_STATES}, + raw::RawLanguage, +}; +use hashbrown::HashMap; +use std::path::PathBuf; + +#[derive(Default, Debug, PartialEq)] +pub(crate) struct LocalizationStats { + pub(crate) uptodate_entries: usize, + pub(crate) notfound_entries: usize, + pub(crate) unused_entries: usize, + pub(crate) outdated_entries: usize, + pub(crate) errors: usize, +} + +#[allow(clippy::type_complexity)] +pub(crate) struct LocalizationAnalysis { + language_identifier: String, + pub(crate) data: HashMap, Vec<(PathBuf, String, Option)>>, +} + +impl LocalizationStats { + /// Calculate key count that actually matter for the status of the + /// translation Unused entries don't break the game + pub(crate) fn get_real_entry_count(&self) -> usize { + self.outdated_entries + self.notfound_entries + self.errors + self.uptodate_entries + } +} + +impl LocalizationAnalysis { + pub(crate) fn new(language_identifier: &str) -> Self { + let mut data = HashMap::new(); + data.insert(Some(LocalizationState::UpToDate), vec![]); + data.insert(Some(LocalizationState::NotFound), vec![]); + data.insert(Some(LocalizationState::Unused), vec![]); + data.insert(Some(LocalizationState::Outdated), vec![]); + data.insert(None, vec![]); + Self { + language_identifier: language_identifier.to_owned(), + data, + } + } + + fn show( + &self, + state: Option, + reference_language: &RawLanguage, + be_verbose: bool, + ) { + let entries = self.data.get(&state).unwrap_or_else(|| { + panic!( + "called on invalid state: {}", + LocalizationState::print(&state) + ) + }); + if entries.is_empty() { + return; + } + println!("\n\t[{}]", LocalizationState::print(&state)); + for (path, key, commit_id) in entries { + if be_verbose { + let our_commit = LocalizationAnalysis::print_commit(commit_id); + let ref_commit = reference_language + .fragments + .get(path) + .and_then(|entry| entry.string_map.get(key)) + .and_then(|s| s.commit_id) + .map(|s| format!("{}", s)) + .unwrap_or_else(|| "None".to_owned()); + println!("{:60}| {:40} | {:40}", key, our_commit, ref_commit,); + } else { + println!("{}", key); + } + } + } + + fn csv(&self, state: Option) { + let entries = self + .data + .get(&state) + .unwrap_or_else(|| panic!("called on invalid state: {:?}", state)); + for (path, key, commit_id) in entries { + let our_commit = LocalizationAnalysis::print_commit(commit_id); + println!( + "{},{:?},{},{},{}", + self.language_identifier, + path, + key, + LocalizationState::print(&state), + our_commit + ); + } + } + + fn print_commit(commit_id: &Option) -> String { + commit_id + .map(|s| format!("{}", s)) + .unwrap_or_else(|| "None".to_owned()) + } +} + +pub(crate) fn print_translation_stats( + language_identifier: &str, + reference_language: &RawLanguage, + stats: &LocalizationStats, + state_map: &LocalizationAnalysis, + be_verbose: bool, +) { + let real_entry_count = stats.get_real_entry_count() as f32; + let uptodate_percent = (stats.uptodate_entries as f32 / real_entry_count) * 100_f32; + let outdated_percent = (stats.outdated_entries as f32 / real_entry_count) * 100_f32; + let untranslated_percent = ((stats.errors + stats.errors) as f32 / real_entry_count) * 100_f32; + + // Display + if be_verbose { + println!( + "\n{:60}| {:40} | {:40}", + "Key name", + language_identifier, + reference_language.manifest.metadata.language_identifier, + ); + } else { + println!("\nKey name"); + } + + for state in &ALL_LOCALIZATION_STATES { + if state == &Some(LocalizationState::UpToDate) { + continue; + } + state_map.show(*state, reference_language, be_verbose); + } + + println!( + "\n{} up-to-date, {} outdated, {} unused, {} not found, {} unknown entries", + stats.uptodate_entries, + stats.outdated_entries, + stats.unused_entries, + stats.notfound_entries, + stats.errors, + ); + + println!( + "{:.2}% up-to-date, {:.2}% outdated, {:.2}% untranslated\n", + uptodate_percent, outdated_percent, untranslated_percent, + ); +} + +pub(crate) fn print_csv_file(state_map: &LocalizationAnalysis) { + println!("country_code,file_name,translation_code,status,git_commit"); + + for state in &ALL_LOCALIZATION_STATES { + if state == &Some(LocalizationState::UpToDate) { + continue; + } + state_map.csv(*state); + } +} + +pub(crate) fn print_overall_stats( + analysis: HashMap, +) { + let mut overall_uptodate_entry_count = 0; + let mut overall_outdated_entry_count = 0; + let mut overall_untranslated_entry_count = 0; + let mut overall_real_entry_count = 0; + + println!("-----------------------------------------------------------------------------"); + println!("Overall Translation Status"); + println!("-----------------------------------------------------------------------------"); + println!( + "{:12}| {:8} | {:8} | {:8} | {:8} | {:8}", + "", "up-to-date", "outdated", "untranslated", "unused", "errors", + ); + + let mut i18n_stats: Vec<(&String, &(_, LocalizationStats))> = analysis.iter().collect(); + i18n_stats.sort_by_key(|(_, (_, v))| v.notfound_entries); + + for (path, (_, test_result)) in i18n_stats { + let LocalizationStats { + uptodate_entries: uptodate, + outdated_entries: outdated, + unused_entries: unused, + notfound_entries: untranslated, + errors, + } = test_result; + overall_uptodate_entry_count += uptodate; + overall_outdated_entry_count += outdated; + overall_untranslated_entry_count += untranslated; + overall_real_entry_count += test_result.get_real_entry_count(); + + println!( + "{:12}|{:8} |{:6} |{:8} |{:6} |{:8}", + path, uptodate, outdated, untranslated, unused, errors, + ); + } + + println!( + "\n{:.2}% up-to-date, {:.2}% outdated, {:.2}% untranslated", + (overall_uptodate_entry_count as f32 / overall_real_entry_count as f32) * 100_f32, + (overall_outdated_entry_count as f32 / overall_real_entry_count as f32) * 100_f32, + (overall_untranslated_entry_count as f32 / overall_real_entry_count as f32) * 100_f32, + ); + println!("-----------------------------------------------------------------------------\n"); +} diff --git a/voxygen/i18n/src/verification.rs b/voxygen/i18n/src/verification.rs index 89d8146757..6e0c697eab 100644 --- a/voxygen/i18n/src/verification.rs +++ b/voxygen/i18n/src/verification.rs @@ -1,23 +1,23 @@ -use std::{path::Path}; +use std::path::Path; -use crate::{i18n_directories, LANG_MANIFEST_FILE, REFERENCE_LANG}; -use crate::raw; +use crate::{i18n_directories, raw, LANG_MANIFEST_FILE, REFERENCE_LANG}; /// Test to verify all languages that they are VALID and loadable, without /// need of git just on the local assets folder -/// `root_dir` - absolute path to main repo -/// `asset_path` - relative path to asset directory (right now it is -/// 'assets/voxygen/i18n') -pub fn verify_all_localizations(root_dir: &Path, asset_path: &Path) { - let i18n_root_path = root_dir.join(asset_path); +/// `root_path` - absolute path to main repo +/// `relative_i18n_root_path` - relative path to asset directory (right now it +/// is 'assets/voxygen/i18n') +pub fn verify_all_localizations(root_path: &Path, relative_i18n_root_path: &Path) { + let i18n_root_path = root_path.join(relative_i18n_root_path); let ref_i18n_path = i18n_root_path.join(REFERENCE_LANG); - let ref_i18n_manifest_path = ref_i18n_path.join(LANG_MANIFEST_FILE.to_string() + "." + crate::LANG_EXTENSION); + let ref_i18n_manifest_path = + ref_i18n_path.join(LANG_MANIFEST_FILE.to_string() + "." + crate::LANG_EXTENSION); assert!( - root_dir.join(&ref_i18n_path).is_dir(), + root_path.join(&ref_i18n_path).is_dir(), "Reference language folder doesn't exist, something is wrong!" ); assert!( - root_dir.join(&ref_i18n_manifest_path).is_file(), + root_path.join(&ref_i18n_manifest_path).is_file(), "Reference language manifest file doesn't exist, something is wrong!" ); let i18n_directories = i18n_directories(&i18n_root_path); @@ -31,19 +31,29 @@ pub fn verify_all_localizations(root_dir: &Path, asset_path: &Path) { folder is empty?" ); for i18n_directory in i18n_directories { - let display_language_identifier = i18n_directory.strip_prefix(&root_dir).unwrap().to_str().unwrap(); - let language_identifier = i18n_directory.strip_prefix(&i18n_root_path).unwrap().to_str().unwrap(); - println!( - "verifying {:?}", - display_language_identifier - ); + let display_language_identifier = i18n_directory + .strip_prefix(&root_path) + .unwrap() + .to_str() + .unwrap(); + let language_identifier = i18n_directory + .strip_prefix(&i18n_root_path) + .unwrap() + .to_str() + .unwrap(); + println!("verifying {:?}", display_language_identifier); // Walk through each files and try to load them - verify_localization_directory(root_dir, &asset_path, language_identifier); + verify_localization_directory(root_path, relative_i18n_root_path, language_identifier); } } -fn verify_localization_directory(root_dir: &Path, asset_path: &Path, language_identifier: &str) { - let i18n_path = root_dir.join(asset_path); - let manifest = raw::load_manifest(&i18n_path, language_identifier).expect("error accessing manifest file"); +fn verify_localization_directory( + root_path: &Path, + relative_i18n_root_path: &Path, + language_identifier: &str, +) { + let i18n_path = root_path.join(relative_i18n_root_path); + let manifest = + raw::load_manifest(&i18n_path, language_identifier).expect("error accessing manifest file"); raw::load_raw_language(&i18n_path, manifest).expect("error accessing fragment file"); -} \ No newline at end of file +} From c3aa4c54a99eef421ef421e4a11fe5703bdaea9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Thu, 29 Jul 2021 11:29:15 +0200 Subject: [PATCH 016/155] extract path logic --- voxygen/i18n/src/analysis.rs | 148 +++++++++-------------------- voxygen/i18n/src/bin/i18n-check.rs | 20 +--- voxygen/i18n/src/lib.rs | 35 +++---- voxygen/i18n/src/path.rs | 138 +++++++++++++++++++++++++++ voxygen/i18n/src/raw.rs | 100 ++++--------------- voxygen/i18n/src/stats.rs | 12 +-- voxygen/i18n/src/verification.rs | 49 +++------- 7 files changed, 233 insertions(+), 269 deletions(-) create mode 100644 voxygen/i18n/src/path.rs diff --git a/voxygen/i18n/src/analysis.rs b/voxygen/i18n/src/analysis.rs index c336816f28..e15d298839 100644 --- a/voxygen/i18n/src/analysis.rs +++ b/voxygen/i18n/src/analysis.rs @@ -2,7 +2,7 @@ use crate::{ gitfragments::{ read_file_from_path, transform_fragment, LocalizationEntryState, LocalizationState, }, - i18n_directories, + path::{BasePath, LangPath}, raw::{self, RawFragment, RawLanguage}, stats::{ print_csv_file, print_overall_stats, print_translation_stats, LocalizationAnalysis, @@ -10,45 +10,35 @@ use crate::{ }, REFERENCE_LANG, }; -use hashbrown::{hash_map::Entry, HashMap, HashSet}; +use hashbrown::{hash_map::Entry, HashMap}; use ron::de::from_bytes; -use std::path::Path; /// Fill the entry State base information (except `state`) for a complete /// language fn gather_entry_state<'a>( repo: &'a git2::Repository, head_ref: &git2::Reference, - language_identifier: &str, - root_path: &Path, - relative_i18n_root_path: &Path, + path: &LangPath, ) -> RawLanguage { - println!("-> {:?}", &language_identifier); - let i18n_root_path = root_path.join(relative_i18n_root_path); + println!("-> {:?}", path.language_identifier()); // load standard manifest - let manifest = raw::load_manifest(&i18n_root_path, language_identifier) - .expect("failed to load language manifest"); + let manifest = raw::load_manifest(path).expect("failed to load language manifest"); // transform language into LocalizationEntryState let mut fragments = HashMap::new(); // For each file in directory - let files = raw::fragments_pathes_in_language(&i18n_root_path, language_identifier) + let files = path + .fragments() .expect("failed to get all files in language"); - for subpath in files { - let path = relative_i18n_root_path - .join(language_identifier) - .join(&subpath); - println!(" -> {:?}", &subpath); - let i18n_blob = read_file_from_path(repo, head_ref, &path); - let fragment: RawFragment = from_bytes(i18n_blob.content()).unwrap_or_else(|e| { - panic!( - "Could not parse {} RON file, skipping: {}", - subpath.to_string_lossy(), - e - ) - }); - let frag = transform_fragment(repo, (&path, fragment), &i18n_blob); - fragments.insert(subpath.to_path_buf(), frag); + for sub_path in files { + let fullpath = path.sub_path(&sub_path); + let gitpath = fullpath.strip_prefix(path.base().root_path()).unwrap(); + println!(" -> {:?}", &sub_path); + let i18n_blob = read_file_from_path(repo, head_ref, gitpath); + let fragment: RawFragment = from_bytes(i18n_blob.content()) + .unwrap_or_else(|e| panic!("Could not parse {:?} RON file, error: {}", sub_path, e)); + let frag = transform_fragment(repo, (gitpath, fragment), &i18n_blob); + fragments.insert(sub_path, frag); } RawLanguage:: { @@ -138,11 +128,10 @@ fn compare_lang_with_reference( } } - let ref_keys: HashSet<&String> = ref_fragment.string_map.keys().collect(); for (_, state) in cur_fragment .string_map .iter_mut() - .filter(|&(k, _)| !ref_keys.contains(k)) + .filter(|&(k, _)| ref_fragment.string_map.get(k).is_none()) { state.state = Some(LocalizationState::Unused); } @@ -179,67 +168,42 @@ fn gather_results( (state_map, stats) } -/// completely analysis multiple languages without printing -fn complete_analysis( - language_identifiers: &[&str], - root_path: &Path, - relative_i18n_root_path: &Path, -) -> ( - HashMap, - /* ref lang */ RawLanguage, -) { - let mut result = HashMap::new(); - // Initialize Git objects - let repo = git2::Repository::discover(&root_path) - .unwrap_or_else(|_| panic!("Failed to open the Git repository at {:?}", &root_path)); - let head_ref = repo.head().expect("Impossible to get the HEAD reference"); - - // Read Reference Language - let ref_language = gather_entry_state( - &repo, - &head_ref, - REFERENCE_LANG, - root_path, - relative_i18n_root_path, - ); - for &language_identifier in language_identifiers { - let mut cur_language = gather_entry_state( - &repo, - &head_ref, - language_identifier, - root_path, - relative_i18n_root_path, - ); - compare_lang_with_reference(&mut cur_language, &ref_language, &repo); - let (state_map, stats) = gather_results(&cur_language); - result.insert(language_identifier.to_owned(), (state_map, stats)); - } - (result, ref_language) -} - /// Test one language /// - `code`: name of the directory in assets (de_DE for example) -/// - `root_path`: absolute path to main repo -/// - `relative_i18n_root_path`: relative path to asset directory (right now it -/// is 'assets/voxygen/i18n') -/// - be_verbose: print extra info -/// - csv_enabled: generate csv files in target folder +/// - `path`: path to repo +/// - `be_verbose`: print extra info +/// - `csv_enabled`: generate csv files in target folder pub fn test_specific_localizations( + path: &BasePath, language_identifiers: &[&str], - root_path: &Path, - relative_i18n_root_path: &Path, be_verbose: bool, csv_enabled: bool, ) { - let (analysis, reference_language) = - complete_analysis(language_identifiers, root_path, relative_i18n_root_path); + //complete analysis + let mut analysis = HashMap::new(); + // Initialize Git objects + let repo = git2::Repository::discover(path.root_path()) + .unwrap_or_else(|_| panic!("Failed to open the Git repository {:?}", path.root_path())); + let head_ref = repo.head().expect("Impossible to get the HEAD reference"); + + // Read Reference Language + let ref_language = gather_entry_state(&repo, &head_ref, &path.i18n_path(REFERENCE_LANG)); + for &language_identifier in language_identifiers { + let mut cur_language = + gather_entry_state(&repo, &head_ref, &path.i18n_path(language_identifier)); + compare_lang_with_reference(&mut cur_language, &ref_language, &repo); + let (state_map, stats) = gather_results(&cur_language); + analysis.insert(language_identifier.to_owned(), (state_map, stats)); + } + + //printing for (language_identifier, (state_map, stats)) in &analysis { if csv_enabled { print_csv_file(state_map); } else { print_translation_stats( language_identifier, - &reference_language, + &ref_language, stats, state_map, be_verbose, @@ -252,32 +216,12 @@ pub fn test_specific_localizations( } /// Test all localizations -pub fn test_all_localizations( - root_path: &Path, - relative_i18n_root_path: &Path, - be_verbose: bool, - csv_enabled: bool, -) { - let i18n_root_path = root_path.join(relative_i18n_root_path); +pub fn test_all_localizations(path: &BasePath, be_verbose: bool, csv_enabled: bool) { // Compare to other reference files - let language_identifiers = i18n_directories(&i18n_root_path) - .into_iter() - .map(|p| { - p.strip_prefix(&i18n_root_path) - .unwrap() - .to_str() - .unwrap() - .to_owned() - }) + let languages = path.i18n_directories(); + let language_identifiers = languages + .iter() + .map(|s| s.language_identifier()) .collect::>(); - test_specific_localizations( - &language_identifiers - .iter() - .map(|s| s.as_str()) - .collect::>(), - root_path, - relative_i18n_root_path, - be_verbose, - csv_enabled, - ); + test_specific_localizations(path, &language_identifiers, be_verbose, csv_enabled); } diff --git a/voxygen/i18n/src/bin/i18n-check.rs b/voxygen/i18n/src/bin/i18n-check.rs index 9972850b15..f9062b7b46 100644 --- a/voxygen/i18n/src/bin/i18n-check.rs +++ b/voxygen/i18n/src/bin/i18n-check.rs @@ -1,5 +1,4 @@ use clap::{App, Arg}; -use std::path::Path; use veloren_i18n::{analysis, verification}; fn main() { @@ -37,28 +36,17 @@ fn main() { // Generate paths let root_path = common_assets::find_root().expect("Failed to find root of repository"); - let relative_i18n_root_path = Path::new("assets/voxygen/i18n/"); + let path = veloren_i18n::BasePath::new(&root_path); let be_verbose = matches.is_present("verbose"); let csv_enabled = matches.is_present("csv"); if let Some(code) = matches.value_of("CODE") { - analysis::test_specific_localizations( - &[code], - &root_path, - relative_i18n_root_path, - be_verbose, - csv_enabled, - ); + analysis::test_specific_localizations(&path, &[code], be_verbose, csv_enabled); } if matches.is_present("test") { - analysis::test_all_localizations( - &root_path, - relative_i18n_root_path, - be_verbose, - csv_enabled, - ); + analysis::test_all_localizations(&path, be_verbose, csv_enabled); } if matches.is_present("verify") { - verification::verify_all_localizations(&root_path, relative_i18n_root_path); + verification::verify_all_localizations(&path); } } diff --git a/voxygen/i18n/src/lib.rs b/voxygen/i18n/src/lib.rs index 9360823ee1..160a5118c0 100644 --- a/voxygen/i18n/src/lib.rs +++ b/voxygen/i18n/src/lib.rs @@ -1,29 +1,27 @@ #[cfg(any(feature = "bin", test))] pub mod analysis; #[cfg(any(feature = "bin", test))] -pub mod gitfragments; -pub mod raw; +mod gitfragments; +mod path; +mod raw; #[cfg(any(feature = "bin", test))] pub mod stats; pub mod verification; +//reexport +pub use path::BasePath; + +use crate::path::{LANG_EXTENSION, LANG_MANIFEST_FILE}; use common_assets::{self, source::DirEntry, AssetExt, AssetGuard, AssetHandle}; use hashbrown::{HashMap, HashSet}; use raw::{RawFragment, RawLanguage, RawManifest}; use serde::{Deserialize, Serialize}; -use std::{ - fs, io, - path::{Path, PathBuf}, -}; +use std::{io, path::PathBuf}; use tracing::warn; /// The reference language, aka the more up-to-date localization data. /// Also the default language at first startup. pub const REFERENCE_LANG: &str = "en"; -pub const LANG_MANIFEST_FILE: &str = "_manifest"; - -pub(crate) const LANG_EXTENSION: &str = "ron"; - /// How a language can be described #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct LanguageMetadata { @@ -327,18 +325,9 @@ pub fn list_localizations() -> Vec { LocalizationList::load_expect_cloned("voxygen.i18n").0 } -/// List localization directories as a `PathBuf` vector -pub fn i18n_directories(i18n_dir: &Path) -> Vec { - fs::read_dir(i18n_dir) - .unwrap() - .map(|res| res.map(|e| e.path()).unwrap()) - .filter(|e| e.is_dir()) - .collect() -} - #[cfg(test)] mod tests { - use std::path::Path; + use crate::path::BasePath; // Test that localization list is loaded (not empty) #[test] @@ -358,9 +347,8 @@ mod tests { #[test] fn verify_all_localizations() { // Generate paths - let i18n_root_path = Path::new("assets/voxygen/i18n/"); let root_dir = common_assets::find_root().expect("Failed to discover repository root"); - crate::verification::verify_all_localizations(&root_dir, i18n_root_path); + crate::verification::verify_all_localizations(&BasePath::new(&root_dir)); } // Test to verify all languages and print missing and faulty localisation @@ -368,8 +356,7 @@ mod tests { #[ignore] fn test_all_localizations() { // Generate paths - let i18n_root_path = Path::new("assets/voxygen/i18n/"); let root_dir = common_assets::find_root().expect("Failed to discover repository root"); - crate::analysis::test_all_localizations(&root_dir, i18n_root_path, true, false); + crate::analysis::test_all_localizations(&BasePath::new(&root_dir), true, false); } } diff --git a/voxygen/i18n/src/path.rs b/voxygen/i18n/src/path.rs new file mode 100644 index 0000000000..a8f961eef5 --- /dev/null +++ b/voxygen/i18n/src/path.rs @@ -0,0 +1,138 @@ +use std::path::{Path, PathBuf}; + +pub(crate) const LANG_MANIFEST_FILE: &str = "_manifest"; +pub(crate) const LANG_EXTENSION: &str = "ron"; + +#[derive(Clone)] +pub struct BasePath { + ///repo part, git main folder + root_path: PathBuf, + ///relative path to i18n path which contains, currently + /// 'assets/voxygen/i18n' + relative_i18n_root_path: PathBuf, + ///i18n_root_folder + cache: PathBuf, +} + +impl BasePath { + pub fn new(root_path: &Path) -> Self { + let relative_i18n_root_path = Path::new("assets/voxygen/i18n").to_path_buf(); + let cache = root_path.join(&relative_i18n_root_path); + assert!( + cache.is_dir(), + "i18n_root_path folder doesn't exist, something is wrong!" + ); + Self { + root_path: root_path.to_path_buf(), + relative_i18n_root_path, + cache, + } + } + + pub fn root_path(&self) -> &Path { &self.root_path } + + pub fn relative_i18n_root_path(&self) -> &Path { &self.relative_i18n_root_path } + + /// absolute path to `relative_i18n_root_path` + pub fn i18n_root_path(&self) -> &Path { &self.cache } + + pub fn i18n_path(&self, language_identifier: &str) -> LangPath { + LangPath::new(self, language_identifier) + } + + /// List localization directories + pub fn i18n_directories(&self) -> Vec { + std::fs::read_dir(&self.cache) + .unwrap() + .map(|res| res.unwrap()) + .filter(|e| e.file_type().unwrap().is_dir()) + .map(|e| LangPath::new(self, e.file_name().to_str().unwrap())) + .collect() + } +} + +impl core::fmt::Debug for BasePath { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:?}", &self.cache) + } +} + +#[derive(Clone)] +pub struct LangPath { + base: BasePath, + /// `en`, `de_DE`, `fr_FR`, etc.. + language_identifier: String, + /// i18n_path + cache: PathBuf, +} + +impl LangPath { + fn new(base: &BasePath, language_identifier: &str) -> Self { + let cache = base.i18n_root_path().join(language_identifier); + if !cache.is_dir() { + panic!("language folder '{}' doesn't exist", language_identifier); + } + Self { + base: base.clone(), + language_identifier: language_identifier.to_owned(), + cache, + } + } + + pub fn base(&self) -> &BasePath { &self.base } + + pub fn language_identifier(&self) -> &str { &self.language_identifier } + + ///absolute path to `i18n_root_path` + `language_identifier` + pub fn i18n_path(&self) -> &Path { &self.cache } + + /// fragment or manifest file, based on a path + pub fn sub_path(&self, sub_path: &Path) -> PathBuf { self.cache.join(sub_path) } + + /// fragment or manifest file, based on a string without extension + pub fn file(&self, name_without_extension: &str) -> PathBuf { + self.cache + .join(format!("{}.{}", name_without_extension, LANG_EXTENSION)) + } + + /// return all fragments sub_pathes + pub(crate) fn fragments(&self) -> Result, std::io::Error> { + let mut result = vec![]; + recursive_fragments_paths_in_language(self, Path::new(""), &mut result)?; + Ok(result) + } +} + +//unwraps cant fail as they are in same Path +fn recursive_fragments_paths_in_language( + lpath: &LangPath, + subfolder: &Path, + result: &mut Vec, +) -> Result<(), std::io::Error> { + let search_dir = lpath.sub_path(subfolder); + for fragment_file in search_dir.read_dir()?.flatten() { + let file_type = fragment_file.file_type()?; + let full_path = fragment_file.path(); + let relative_path = full_path.strip_prefix(lpath.i18n_path()).unwrap(); + if file_type.is_dir() { + recursive_fragments_paths_in_language(lpath, relative_path, result)?; + } else if file_type.is_file() + && relative_path != Path::new(&format!("{}.{}", LANG_MANIFEST_FILE, LANG_EXTENSION)) + { + result.push(relative_path.to_path_buf()); + } + } + Ok(()) +} + +impl core::fmt::Debug for LangPath { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!( + f, + "{:?}", + self.base + .relative_i18n_root_path + .join(&self.language_identifier) + ) + } +} diff --git a/voxygen/i18n/src/raw.rs b/voxygen/i18n/src/raw.rs index e3e00a8d4e..56e4e4b1c7 100644 --- a/voxygen/i18n/src/raw.rs +++ b/voxygen/i18n/src/raw.rs @@ -1,24 +1,13 @@ //! handle the loading of a `Language` -//! Paths: -//! - `root_path`: repo part, git main folder -//! - `language_identifier`: `en`, `de_DE`, `fr_FR`, etc.. -//! - `relative_i18n_root_path`: relative path to i18n path which contains -//! `language_identifier` folders from `root_path` -//! - `i18n_root_path`: absolute path to `relative_i18n_root_path` -//! - `i18n_path`: absolute path to `i18n_root_path` + `language_identifier` -//! - `subfolder`: all folders in `i18n_path` -//! -//! wherever possible we use relative paths only. So expect 1 absolute -//! `root_path` or `i18n_root_path` to be required and all others be relative. -use crate::{Fonts, Language, LanguageMetadata, LANG_EXTENSION, LANG_MANIFEST_FILE}; +use crate::{ + path::{LangPath, LANG_EXTENSION, LANG_MANIFEST_FILE}, + Fonts, Language, LanguageMetadata, +}; use deunicode::deunicode; use hashbrown::hash_map::HashMap; use ron::de::from_reader; use serde::{Deserialize, Serialize}; -use std::{ - fs, - path::{Path, PathBuf}, -}; +use std::{fs, path::PathBuf}; /// Raw localization metadata from LANG_MANIFEST_FILE file /// See `Language` for more info on each attributes @@ -47,42 +36,32 @@ pub(crate) enum RawError { RonError(ron::Error), } -/// `i18n_root_path` - absolute path to i18n path which contains `en`, `de_DE`, -/// `fr_FR` folders -pub(crate) fn load_manifest( - i18n_root_path: &Path, - language_identifier: &str, -) -> Result { - let manifest_file = i18n_root_path - .join(language_identifier) - .join(format!("{}.{}", LANG_MANIFEST_FILE, LANG_EXTENSION)); - tracing::debug!(?manifest_file, "manifest loaded"); +pub(crate) fn load_manifest(path: &LangPath) -> Result { + let manifest_file = path.file(LANG_MANIFEST_FILE); + tracing::debug!(?manifest_file, "manifest loading"); let f = fs::File::open(&manifest_file)?; let manifest: RawManifest = from_reader(f).map_err(RawError::RonError)?; // verify that the folder name `de_DE` matches the value inside the metadata! - assert_eq!(manifest.metadata.language_identifier, language_identifier); + assert_eq!( + manifest.metadata.language_identifier, + path.language_identifier() + ); Ok(manifest) } -/// `i18n_root_path` - absolute path to i18n path which contains `en`, `de_DE`, -/// `fr_FR` files pub(crate) fn load_raw_language( - i18n_root_path: &Path, + path: &LangPath, manifest: RawManifest, ) -> Result, common_assets::Error> { - let language_identifier = &manifest.metadata.language_identifier; - let i18n_path = i18n_root_path.join(language_identifier); - //get List of files - let files = fragments_pathes_in_language(i18n_root_path, language_identifier)?; + let files = path.fragments()?; // Walk through each file in the directory let mut fragments = HashMap::new(); - for fragment_file in &files { - let relative_path = fragment_file.strip_prefix(&i18n_path).unwrap(); - let f = fs::File::open(fragment_file)?; + for sub_path in files { + let f = fs::File::open(path.sub_path(&sub_path))?; let fragment = from_reader(f).map_err(RawError::RonError)?; - fragments.insert(relative_path.to_path_buf(), fragment); + fragments.insert(sub_path, fragment); } Ok(RawLanguage { @@ -126,51 +105,6 @@ impl From> for Language { } } -pub(crate) fn fragments_pathes_in_language( - i18n_root_path: &Path, - language_identifier: &str, -) -> Result, std::io::Error> { - let mut result = vec![]; - recursive_fragments_paths_in_language( - i18n_root_path, - language_identifier, - Path::new(""), - &mut result, - )?; - Ok(result) -} - -/// i18n_path = i18n_root_path.join(REFERENCE_LANG); -fn recursive_fragments_paths_in_language( - i18n_root_path: &Path, - language_identifier: &str, - subfolder: &Path, - result: &mut Vec, -) -> Result<(), std::io::Error> { - let i18n_path = i18n_root_path.join(language_identifier); - let search_dir = i18n_path.join(subfolder); - for fragment_file in search_dir.read_dir().unwrap().flatten() { - let file_type = fragment_file.file_type()?; - if file_type.is_dir() { - let full_path = fragment_file.path(); - let relative_path = full_path.strip_prefix(&i18n_path).unwrap(); - recursive_fragments_paths_in_language( - i18n_root_path, - language_identifier, - relative_path, - result, - )?; - } else if file_type.is_file() { - let full_path = fragment_file.path(); - let relative_path = full_path.strip_prefix(&i18n_path).unwrap(); - if relative_path != Path::new(&format!("{}.{}", LANG_MANIFEST_FILE, LANG_EXTENSION)) { - result.push(relative_path.to_path_buf()); - } - } - } - Ok(()) -} - impl core::fmt::Display for RawError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { diff --git a/voxygen/i18n/src/stats.rs b/voxygen/i18n/src/stats.rs index a353e7ef29..9ab93fd062 100644 --- a/voxygen/i18n/src/stats.rs +++ b/voxygen/i18n/src/stats.rs @@ -45,7 +45,7 @@ impl LocalizationAnalysis { fn show( &self, state: Option, - reference_language: &RawLanguage, + ref_language: &RawLanguage, be_verbose: bool, ) { let entries = self.data.get(&state).unwrap_or_else(|| { @@ -61,7 +61,7 @@ impl LocalizationAnalysis { for (path, key, commit_id) in entries { if be_verbose { let our_commit = LocalizationAnalysis::print_commit(commit_id); - let ref_commit = reference_language + let ref_commit = ref_language .fragments .get(path) .and_then(|entry| entry.string_map.get(key)) @@ -102,7 +102,7 @@ impl LocalizationAnalysis { pub(crate) fn print_translation_stats( language_identifier: &str, - reference_language: &RawLanguage, + ref_language: &RawLanguage, stats: &LocalizationStats, state_map: &LocalizationAnalysis, be_verbose: bool, @@ -116,9 +116,7 @@ pub(crate) fn print_translation_stats( if be_verbose { println!( "\n{:60}| {:40} | {:40}", - "Key name", - language_identifier, - reference_language.manifest.metadata.language_identifier, + "Key name", language_identifier, ref_language.manifest.metadata.language_identifier, ); } else { println!("\nKey name"); @@ -128,7 +126,7 @@ pub(crate) fn print_translation_stats( if state == &Some(LocalizationState::UpToDate) { continue; } - state_map.show(*state, reference_language, be_verbose); + state_map.show(*state, ref_language, be_verbose); } println!( diff --git a/voxygen/i18n/src/verification.rs b/voxygen/i18n/src/verification.rs index 6e0c697eab..fa784b9db5 100644 --- a/voxygen/i18n/src/verification.rs +++ b/voxygen/i18n/src/verification.rs @@ -1,26 +1,17 @@ -use std::path::Path; +use crate::path::{BasePath, LangPath, LANG_MANIFEST_FILE}; -use crate::{i18n_directories, raw, LANG_MANIFEST_FILE, REFERENCE_LANG}; +use crate::{raw, REFERENCE_LANG}; /// Test to verify all languages that they are VALID and loadable, without /// need of git just on the local assets folder -/// `root_path` - absolute path to main repo -/// `relative_i18n_root_path` - relative path to asset directory (right now it -/// is 'assets/voxygen/i18n') -pub fn verify_all_localizations(root_path: &Path, relative_i18n_root_path: &Path) { - let i18n_root_path = root_path.join(relative_i18n_root_path); - let ref_i18n_path = i18n_root_path.join(REFERENCE_LANG); - let ref_i18n_manifest_path = - ref_i18n_path.join(LANG_MANIFEST_FILE.to_string() + "." + crate::LANG_EXTENSION); +pub fn verify_all_localizations(path: &BasePath) { + let ref_i18n_path = path.i18n_path(REFERENCE_LANG); + let ref_i18n_manifest_path = ref_i18n_path.file(LANG_MANIFEST_FILE); assert!( - root_path.join(&ref_i18n_path).is_dir(), - "Reference language folder doesn't exist, something is wrong!" - ); - assert!( - root_path.join(&ref_i18n_manifest_path).is_file(), + ref_i18n_manifest_path.is_file(), "Reference language manifest file doesn't exist, something is wrong!" ); - let i18n_directories = i18n_directories(&i18n_root_path); + let i18n_directories = path.i18n_directories(); // This simple check ONLY guarantees that an arbitrary minimum of translation // files exists. It's just to notice unintentional deletion of all // files, or modifying the paths. In case you want to delete all @@ -31,29 +22,13 @@ pub fn verify_all_localizations(root_path: &Path, relative_i18n_root_path: &Path folder is empty?" ); for i18n_directory in i18n_directories { - let display_language_identifier = i18n_directory - .strip_prefix(&root_path) - .unwrap() - .to_str() - .unwrap(); - let language_identifier = i18n_directory - .strip_prefix(&i18n_root_path) - .unwrap() - .to_str() - .unwrap(); - println!("verifying {:?}", display_language_identifier); + println!("verifying {:?}", i18n_directory); // Walk through each files and try to load them - verify_localization_directory(root_path, relative_i18n_root_path, language_identifier); + verify_localization_directory(&i18n_directory); } } -fn verify_localization_directory( - root_path: &Path, - relative_i18n_root_path: &Path, - language_identifier: &str, -) { - let i18n_path = root_path.join(relative_i18n_root_path); - let manifest = - raw::load_manifest(&i18n_path, language_identifier).expect("error accessing manifest file"); - raw::load_raw_language(&i18n_path, manifest).expect("error accessing fragment file"); +fn verify_localization_directory(path: &LangPath) { + let manifest = raw::load_manifest(path).expect("error accessing manifest file"); + raw::load_raw_language(path, manifest).expect("error accessing fragment file"); } From aa3ede79c1490e595651bb9fa506780ae7508456 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 29 Jul 2021 19:04:07 +0000 Subject: [PATCH 017/155] Prevented mountable pets --- server/src/state_ext.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs index 90bb228af1..9d91e90357 100644 --- a/server/src/state_ext.rs +++ b/server/src/state_ext.rs @@ -560,7 +560,6 @@ impl StateExt for State { ) .with(comp::Scale(1.0)) .with(comp::Vel(Vec3::new(0.0, 0.0, 0.0))) - .with(comp::MountState::Unmounted) .build(); restore_pet(self.ecs(), pet_entity, entity, pet); From 4c0b74150df45a6015d31a9da58d627d156b6198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Thu, 29 Jul 2021 20:47:45 +0200 Subject: [PATCH 018/155] remove some reexports --- .gitlab/scripts/unittest.sh | 2 +- Cargo.lock | 30 ++++++++++---------- voxygen/Cargo.toml | 2 +- voxygen/i18n/Cargo.toml | 2 +- voxygen/i18n/src/bin/i18n-check.rs | 4 +-- voxygen/src/hud/bag.rs | 2 +- voxygen/src/hud/buffs.rs | 2 +- voxygen/src/hud/buttons.rs | 2 +- voxygen/src/hud/chat.rs | 3 +- voxygen/src/hud/crafting.rs | 10 +++---- voxygen/src/hud/diary.rs | 6 ++-- voxygen/src/hud/esc_menu.rs | 3 +- voxygen/src/hud/group.rs | 2 +- voxygen/src/hud/loot_scroller.rs | 6 ++-- voxygen/src/hud/map.rs | 2 +- voxygen/src/hud/mod.rs | 2 +- voxygen/src/hud/overhead.rs | 2 +- voxygen/src/hud/overitem.rs | 2 +- voxygen/src/hud/popup.rs | 3 +- voxygen/src/hud/prompt_dialog.rs | 2 +- voxygen/src/hud/settings_window/chat.rs | 2 +- voxygen/src/hud/settings_window/controls.rs | 2 +- voxygen/src/hud/settings_window/gameplay.rs | 2 +- voxygen/src/hud/settings_window/interface.rs | 2 +- voxygen/src/hud/settings_window/language.rs | 2 +- voxygen/src/hud/settings_window/mod.rs | 2 +- voxygen/src/hud/settings_window/sound.rs | 2 +- voxygen/src/hud/settings_window/video.rs | 2 +- voxygen/src/hud/skillbar.rs | 2 +- voxygen/src/hud/social.rs | 7 ++--- voxygen/src/hud/trade.rs | 2 +- voxygen/src/hud/util.rs | 3 +- voxygen/src/lib.rs | 4 --- voxygen/src/main.rs | 2 +- voxygen/src/menu/char_selection/ui/mod.rs | 2 +- voxygen/src/menu/main/mod.rs | 2 +- voxygen/src/menu/main/ui/connecting.rs | 13 ++++----- voxygen/src/menu/main/ui/disclaimer.rs | 2 +- voxygen/src/menu/main/ui/login.rs | 26 ++++++++--------- voxygen/src/menu/main/ui/mod.rs | 10 +++---- voxygen/src/menu/main/ui/servers.rs | 10 +++---- voxygen/src/session/mod.rs | 3 +- voxygen/src/session/settings_change.rs | 2 +- voxygen/src/settings/language.rs | 1 - voxygen/src/ui/cache.rs | 2 +- voxygen/src/ui/fonts.rs | 2 +- voxygen/src/ui/ice/cache.rs | 2 +- voxygen/src/ui/ice/mod.rs | 2 +- voxygen/src/ui/ice/renderer/mod.rs | 2 +- voxygen/src/ui/mod.rs | 2 +- voxygen/src/ui/widgets/item_tooltip.rs | 14 ++++----- voxygen/src/window.rs | 3 +- 52 files changed, 104 insertions(+), 121 deletions(-) diff --git a/.gitlab/scripts/unittest.sh b/.gitlab/scripts/unittest.sh index a4193d3914..4bb46b4995 100755 --- a/.gitlab/scripts/unittest.sh +++ b/.gitlab/scripts/unittest.sh @@ -1,7 +1,7 @@ #!/bin/bash export VELOREN_ASSETS="$(pwd)/assets" rm -r target/debug/incremental/veloren_* || echo "all good" # TMP FIX FOR 2021-03-22-nightly -time cargo test --package veloren-i18n --lib test_all_localizations -- --nocapture --ignored && +time cargo test --package veloren-voxygen-i18n --lib test_all_localizations -- --nocapture --ignored && time cargo test --package veloren-common-assets asset_tweak::tests --features asset_tweak --lib && ( rm -r target/debug/incremental* || echo "all good" ) && # TMP FIX FOR 2021-03-22-nightly time cargo test \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 0274d8ca78..3132f6e3fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6017,20 +6017,6 @@ dependencies = [ "veloren-common-net", ] -[[package]] -name = "veloren-i18n" -version = "0.10.0" -dependencies = [ - "clap", - "deunicode", - "git2", - "hashbrown 0.11.2", - "ron", - "serde", - "tracing", - "veloren-common-assets", -] - [[package]] name = "veloren-network" version = "0.3.0" @@ -6236,10 +6222,10 @@ dependencies = [ "veloren-common-net", "veloren-common-state", "veloren-common-systems", - "veloren-i18n", "veloren-server", "veloren-voxygen-anim", "veloren-voxygen-egui", + "veloren-voxygen-i18n", "veloren-world", "wgpu", "wgpu-profiler", @@ -6295,6 +6281,20 @@ dependencies = [ "veloren-voxygen-egui", ] +[[package]] +name = "veloren-voxygen-i18n" +version = "0.10.0" +dependencies = [ + "clap", + "deunicode", + "git2", + "hashbrown 0.11.2", + "ron", + "serde", + "tracing", + "veloren-common-assets", +] + [[package]] name = "veloren-world" version = "0.10.0" diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 924be04100..c7504d5890 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -46,7 +46,7 @@ common-systems = {package = "veloren-common-systems", path = "../common/systems" common-state = {package = "veloren-common-state", path = "../common/state"} anim = {package = "veloren-voxygen-anim", path = "anim"} -i18n = {package = "veloren-i18n", path = "i18n"} +i18n = {package = "veloren-voxygen-i18n", path = "i18n"} voxygen-egui = {package = "veloren-voxygen-egui", path = "egui", optional = true } # Graphics diff --git a/voxygen/i18n/Cargo.toml b/voxygen/i18n/Cargo.toml index 388586679b..5ebbbb05d1 100644 --- a/voxygen/i18n/Cargo.toml +++ b/voxygen/i18n/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["juliancoffee ", "Rémy Phelipot"] edition = "2018" -name = "veloren-i18n" +name = "veloren-voxygen-i18n" description = "Crate for internalization and diagnostic of existing localizations." version = "0.10.0" diff --git a/voxygen/i18n/src/bin/i18n-check.rs b/voxygen/i18n/src/bin/i18n-check.rs index f9062b7b46..6a868a950f 100644 --- a/voxygen/i18n/src/bin/i18n-check.rs +++ b/voxygen/i18n/src/bin/i18n-check.rs @@ -1,5 +1,5 @@ use clap::{App, Arg}; -use veloren_i18n::{analysis, verification}; +use veloren_voxygen_i18n::{analysis, verification, BasePath}; fn main() { let matches = App::new("i18n-check") @@ -36,7 +36,7 @@ fn main() { // Generate paths let root_path = common_assets::find_root().expect("Failed to find root of repository"); - let path = veloren_i18n::BasePath::new(&root_path); + let path = BasePath::new(&root_path); let be_verbose = matches.is_present("verbose"); let csv_enabled = matches.is_present("csv"); diff --git a/voxygen/src/hud/bag.rs b/voxygen/src/hud/bag.rs index 343df2f232..4a21b416db 100644 --- a/voxygen/src/hud/bag.rs +++ b/voxygen/src/hud/bag.rs @@ -7,7 +7,6 @@ use super::{ }; use crate::{ game_input::GameInput, - i18n::Localization, ui::{ fonts::Fonts, slot::{ContentSize, SlotMaker}, @@ -31,6 +30,7 @@ use conrod_core::{ widget::{self, Button, Image, Rectangle, Scrollbar, State as ConrodState, Text}, widget_ids, Color, Colorable, Positionable, Scalar, Sizeable, UiCell, Widget, WidgetCommon, }; +use i18n::Localization; use crate::hud::slots::SlotKind; use specs::Entity as EcsEntity; diff --git a/voxygen/src/hud/buffs.rs b/voxygen/src/hud/buffs.rs index 5fc82242df..393dd06fc0 100644 --- a/voxygen/src/hud/buffs.rs +++ b/voxygen/src/hud/buffs.rs @@ -4,10 +4,10 @@ use super::{ }; use crate::{ hud::{self, BuffPosition}, - i18n::Localization, ui::{fonts::Fonts, ImageFrame, Tooltip, TooltipManager, Tooltipable}, GlobalState, }; +use i18n::Localization; use common::comp::{BuffKind, Buffs, Energy, Health}; use conrod_core::{ diff --git a/voxygen/src/hud/buttons.rs b/voxygen/src/hud/buttons.rs index 79bde0effd..d046c8a783 100644 --- a/voxygen/src/hud/buttons.rs +++ b/voxygen/src/hud/buttons.rs @@ -4,7 +4,6 @@ use super::{ }; use crate::{ game_input::GameInput, - i18n::Localization, ui::{fonts::Fonts, ImageFrame, Tooltip, TooltipManager, Tooltipable}, window::KeyMouse, GlobalState, @@ -15,6 +14,7 @@ use conrod_core::{ widget::{self, Button, Image, Text}, widget_ids, Color, Colorable, Positionable, Sizeable, UiCell, Widget, WidgetCommon, }; +use i18n::Localization; widget_ids! { struct Ids { bag, diff --git a/voxygen/src/hud/chat.rs b/voxygen/src/hud/chat.rs index c05177e1ca..8a48c212e7 100644 --- a/voxygen/src/hud/chat.rs +++ b/voxygen/src/hud/chat.rs @@ -2,7 +2,7 @@ use super::{ img_ids::Imgs, ChatTab, ERROR_COLOR, FACTION_COLOR, GROUP_COLOR, INFO_COLOR, KILL_COLOR, OFFLINE_COLOR, ONLINE_COLOR, REGION_COLOR, SAY_COLOR, TELL_COLOR, TEXT_COLOR, WORLD_COLOR, }; -use crate::{i18n::Localization, settings::chat::MAX_CHAT_TABS, ui::fonts::Fonts, GlobalState}; +use crate::{settings::chat::MAX_CHAT_TABS, ui::fonts::Fonts, GlobalState}; use client::{cmd, Client}; use common::comp::{ chat::{KillSource, KillType}, @@ -22,6 +22,7 @@ use conrod_core::{ widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Ui, UiCell, Widget, WidgetCommon, }; +use i18n::Localization; use std::collections::{HashSet, VecDeque}; widget_ids! { diff --git a/voxygen/src/hud/crafting.rs b/voxygen/src/hud/crafting.rs index 79093537ac..dd2e917b9c 100644 --- a/voxygen/src/hud/crafting.rs +++ b/voxygen/src/hud/crafting.rs @@ -4,12 +4,9 @@ use super::{ item_imgs::{animate_by_pulse, ItemImgs, ItemKey::Tool}, Show, TEXT_COLOR, TEXT_DULL_RED_COLOR, TEXT_GRAY_COLOR, UI_HIGHLIGHT_0, UI_MAIN, }; -use crate::{ - i18n::Localization, - ui::{ - fonts::Fonts, ImageFrame, ItemTooltip, ItemTooltipManager, ItemTooltipable, Tooltip, - TooltipManager, Tooltipable, - }, +use crate::ui::{ + fonts::Fonts, ImageFrame, ItemTooltip, ItemTooltipManager, ItemTooltipable, Tooltip, + TooltipManager, Tooltipable, }; use client::{self, Client}; use common::{ @@ -29,6 +26,7 @@ use conrod_core::{ widget::{self, Button, Image, Rectangle, Scrollbar, Text, TextEdit}, widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; +use i18n::Localization; use std::sync::Arc; use strum::IntoEnumIterator; diff --git a/voxygen/src/hud/diary.rs b/voxygen/src/hud/diary.rs index 8112d784d1..da5af98b50 100644 --- a/voxygen/src/hud/diary.rs +++ b/voxygen/src/hud/diary.rs @@ -3,16 +3,14 @@ use super::{ item_imgs::{animate_by_pulse, ItemImgs, ItemKey::Tool}, Show, CRITICAL_HP_COLOR, HP_COLOR, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN, XP_COLOR, }; -use crate::{ - i18n::Localization, - ui::{fonts::Fonts, ImageFrame, Tooltip, TooltipManager, Tooltipable}, -}; +use crate::ui::{fonts::Fonts, ImageFrame, Tooltip, TooltipManager, Tooltipable}; use conrod_core::{ color, image::Id, widget::{self, button, Button, Image, Rectangle, Text}, widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, UiCell, Widget, WidgetCommon, }; +use i18n::Localization; use client::{self, Client}; use common::comp::{ diff --git a/voxygen/src/hud/esc_menu.rs b/voxygen/src/hud/esc_menu.rs index 5573cf3ad6..92f989ad68 100644 --- a/voxygen/src/hud/esc_menu.rs +++ b/voxygen/src/hud/esc_menu.rs @@ -1,9 +1,10 @@ use super::{img_ids::Imgs, settings_window::SettingsTab, TEXT_COLOR}; -use crate::{i18n::Localization, ui::fonts::Fonts}; +use crate::ui::fonts::Fonts; use conrod_core::{ widget::{self, Button, Image}, widget_ids, Color, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; +use i18n::Localization; widget_ids! { struct Ids { diff --git a/voxygen/src/hud/group.rs b/voxygen/src/hud/group.rs index 74ee3ed8b2..71fb4a5f56 100644 --- a/voxygen/src/hud/group.rs +++ b/voxygen/src/hud/group.rs @@ -9,7 +9,6 @@ use super::{ use crate::{ game_input::GameInput, hud, - i18n::Localization, settings::Settings, ui::{fonts::Fonts, ImageFrame, Tooltip, TooltipManager, Tooltipable}, GlobalState, @@ -27,6 +26,7 @@ use conrod_core::{ widget::{self, Button, Image, Rectangle, Scrollbar, Text}, widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; +use i18n::Localization; use specs::{saveload::MarkerAllocator, WorldExt}; widget_ids! { diff --git a/voxygen/src/hud/loot_scroller.rs b/voxygen/src/hud/loot_scroller.rs index 676291465b..53e88d6820 100644 --- a/voxygen/src/hud/loot_scroller.rs +++ b/voxygen/src/hud/loot_scroller.rs @@ -4,10 +4,7 @@ use super::{ item_imgs::ItemImgs, Show, Windows, TEXT_COLOR, }; -use crate::{ - i18n::Localization, - ui::{fonts::Fonts, ImageFrame, ItemTooltip, ItemTooltipManager, ItemTooltipable}, -}; +use crate::ui::{fonts::Fonts, ImageFrame, ItemTooltip, ItemTooltipManager, ItemTooltipable}; use client::Client; use common::comp::inventory::item::{ItemDef, MaterialStatManifest, Quality}; use conrod_core::{ @@ -16,6 +13,7 @@ use conrod_core::{ widget::{self, Image, List, Rectangle, Scrollbar, Text}, widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon, }; +use i18n::Localization; use std::{collections::VecDeque, sync::Arc}; widget_ids! { diff --git a/voxygen/src/hud/map.rs b/voxygen/src/hud/map.rs index 3742f2565c..9039add9b4 100644 --- a/voxygen/src/hud/map.rs +++ b/voxygen/src/hud/map.rs @@ -4,7 +4,6 @@ use super::{ TEXT_BG, TEXT_BLUE_COLOR, TEXT_COLOR, TEXT_GRAY_COLOR, TEXT_VELORITE, UI_HIGHLIGHT_0, UI_MAIN, }; use crate::{ - i18n::Localization, session::settings_change::{Interface as InterfaceChange, Interface::*}, ui::{fonts::Fonts, img_ids, ImageFrame, Tooltip, TooltipManager, Tooltipable}, GlobalState, @@ -17,6 +16,7 @@ use conrod_core::{ widget::{self, Button, Image, Rectangle, Text}, widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; +use i18n::Localization; use specs::{saveload::MarkerAllocator, WorldExt}; use vek::*; diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index af9304279d..4a3b4693ba 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -55,7 +55,6 @@ use crate::{ ecs::{comp as vcomp, comp::HpFloaterList}, game_input::GameInput, hud::{img_ids::ImgsRot, prompt_dialog::DialogOutcomeEvent}, - i18n::Localization, render::UiDrawer, scene::camera::{self, Camera}, session::{ @@ -100,6 +99,7 @@ use conrod_core::{ widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, }; use hashbrown::{HashMap, HashSet}; +use i18n::Localization; use rand::Rng; use specs::{Entity as EcsEntity, Join, WorldExt}; use std::{ diff --git a/voxygen/src/hud/overhead.rs b/voxygen/src/hud/overhead.rs index 4d58d7aef0..c0c191e50d 100644 --- a/voxygen/src/hud/overhead.rs +++ b/voxygen/src/hud/overhead.rs @@ -5,7 +5,6 @@ use super::{ }; use crate::{ hud::{get_buff_image, get_buff_info}, - i18n::Localization, settings::InterfaceSettings, ui::{fonts::Fonts, Ingameable}, }; @@ -16,6 +15,7 @@ use conrod_core::{ widget::{self, Image, Rectangle, Text}, widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon, }; +use i18n::Localization; const MAX_BUBBLE_WIDTH: f64 = 250.0; widget_ids! { diff --git a/voxygen/src/hud/overitem.rs b/voxygen/src/hud/overitem.rs index 368350389b..7522e04f06 100644 --- a/voxygen/src/hud/overitem.rs +++ b/voxygen/src/hud/overitem.rs @@ -1,6 +1,5 @@ use crate::{ game_input::GameInput, - i18n::Localization, settings::ControlSettings, ui::{fonts::Fonts, Ingameable}, }; @@ -9,6 +8,7 @@ use conrod_core::{ widget::{self, RoundedRectangle, Text}, widget_ids, Color, Colorable, Positionable, Widget, WidgetCommon, }; +use i18n::Localization; use std::borrow::Cow; use keyboard_keynames::key_layout::KeyLayout; diff --git a/voxygen/src/hud/popup.rs b/voxygen/src/hud/popup.rs index 843bc57baf..a87feaecb2 100644 --- a/voxygen/src/hud/popup.rs +++ b/voxygen/src/hud/popup.rs @@ -1,11 +1,12 @@ use super::Show; -use crate::{i18n::Localization, ui::fonts::Fonts}; +use crate::ui::fonts::Fonts; use client::{self, Client}; use common_net::msg::Notification; use conrod_core::{ widget::{self, Text}, widget_ids, Color, Colorable, Positionable, Widget, WidgetCommon, }; +use i18n::Localization; use std::{collections::VecDeque, time::Instant}; widget_ids! { diff --git a/voxygen/src/hud/prompt_dialog.rs b/voxygen/src/hud/prompt_dialog.rs index 599eca1953..769100fc86 100644 --- a/voxygen/src/hud/prompt_dialog.rs +++ b/voxygen/src/hud/prompt_dialog.rs @@ -2,7 +2,6 @@ use super::{img_ids::Imgs, TEXT_COLOR, UI_HIGHLIGHT_0}; use crate::{ game_input::GameInput, hud::{Event, PromptDialogSettings}, - i18n::LocalizationHandle, settings::Settings, ui::fonts::Fonts, }; @@ -10,6 +9,7 @@ use conrod_core::{ widget::{self, Button, Image, Text}, widget_ids, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; +use i18n::LocalizationHandle; use keyboard_keynames::key_layout::KeyLayout; widget_ids! { diff --git a/voxygen/src/hud/settings_window/chat.rs b/voxygen/src/hud/settings_window/chat.rs index 60c540d8fd..6f74fcd20b 100644 --- a/voxygen/src/hud/settings_window/chat.rs +++ b/voxygen/src/hud/settings_window/chat.rs @@ -2,7 +2,6 @@ use super::{RESET_BUTTONS_HEIGHT, RESET_BUTTONS_WIDTH}; use crate::{ hud::{img_ids::Imgs, ChatTab, Show, TEXT_COLOR, TEXT_GRAY_COLOR, UI_HIGHLIGHT_0, UI_MAIN}, - i18n::Localization, session::settings_change::{Chat as ChatChange, Chat::*}, settings::chat::MAX_CHAT_TABS, ui::{fonts::Fonts, ImageSlider, ToggleButton}, @@ -14,6 +13,7 @@ use conrod_core::{ widget::{self, Button, DropDownList, Image, Rectangle, Text, TextEdit}, widget_ids, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; +use i18n::Localization; use std::cmp::Ordering; widget_ids! { diff --git a/voxygen/src/hud/settings_window/controls.rs b/voxygen/src/hud/settings_window/controls.rs index 51b842f936..005ba006b6 100644 --- a/voxygen/src/hud/settings_window/controls.rs +++ b/voxygen/src/hud/settings_window/controls.rs @@ -3,7 +3,6 @@ use super::{RESET_BUTTONS_HEIGHT, RESET_BUTTONS_WIDTH}; use crate::{ game_input::GameInput, hud::{img_ids::Imgs, ERROR_COLOR, TEXT_BIND_CONFLICT_COLOR, TEXT_COLOR}, - i18n::Localization, session::settings_change::{Control as ControlChange, Control::*}, ui::fonts::Fonts, GlobalState, @@ -14,6 +13,7 @@ use conrod_core::{ widget::{self, Button, Rectangle, Scrollbar, Text}, widget_ids, Borderable, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; +use i18n::Localization; use strum::IntoEnumIterator; widget_ids! { diff --git a/voxygen/src/hud/settings_window/gameplay.rs b/voxygen/src/hud/settings_window/gameplay.rs index bb059f528d..010c71739b 100644 --- a/voxygen/src/hud/settings_window/gameplay.rs +++ b/voxygen/src/hud/settings_window/gameplay.rs @@ -2,7 +2,6 @@ use super::{RESET_BUTTONS_HEIGHT, RESET_BUTTONS_WIDTH}; use crate::{ hud::{img_ids::Imgs, PressBehavior, MENU_BG, TEXT_COLOR}, - i18n::Localization, session::settings_change::{Gameplay as GameplayChange, Gameplay::*}, ui::{fonts::Fonts, ImageSlider, ToggleButton}, GlobalState, @@ -13,6 +12,7 @@ use conrod_core::{ widget::{self, Button, DropDownList, Rectangle, Scrollbar, Text}, widget_ids, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; +use i18n::Localization; widget_ids! { struct Ids { diff --git a/voxygen/src/hud/settings_window/interface.rs b/voxygen/src/hud/settings_window/interface.rs index f39def8fa6..27f4745a60 100644 --- a/voxygen/src/hud/settings_window/interface.rs +++ b/voxygen/src/hud/settings_window/interface.rs @@ -4,7 +4,6 @@ use crate::{ hud::{ img_ids::Imgs, BarNumbers, BuffPosition, CrosshairType, ShortcutNumbers, Show, TEXT_COLOR, }, - i18n::Localization, session::settings_change::{Interface as InterfaceChange, Interface::*}, ui::{fonts::Fonts, ImageSlider, ScaleMode, ToggleButton}, GlobalState, @@ -15,6 +14,7 @@ use conrod_core::{ widget::{self, Button, Image, Rectangle, Scrollbar, Text}, widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; +use i18n::Localization; widget_ids! { struct Ids{ diff --git a/voxygen/src/hud/settings_window/language.rs b/voxygen/src/hud/settings_window/language.rs index e1cb5787c7..5745b81bca 100644 --- a/voxygen/src/hud/settings_window/language.rs +++ b/voxygen/src/hud/settings_window/language.rs @@ -1,6 +1,5 @@ use crate::{ hud::{img_ids::Imgs, TEXT_COLOR}, - i18n::{list_localizations, Localization}, session::settings_change::{Language as LanguageChange, Language::*}, ui::{fonts::Fonts, ToggleButton}, GlobalState, @@ -10,6 +9,7 @@ use conrod_core::{ widget::{self, Button, Rectangle, Scrollbar, Text}, widget_ids, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; +use i18n::{list_localizations, Localization}; widget_ids! { struct Ids { diff --git a/voxygen/src/hud/settings_window/mod.rs b/voxygen/src/hud/settings_window/mod.rs index 73de93697a..e72101755f 100644 --- a/voxygen/src/hud/settings_window/mod.rs +++ b/voxygen/src/hud/settings_window/mod.rs @@ -8,7 +8,6 @@ mod video; use crate::{ hud::{img_ids::Imgs, Show, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN}, - i18n::Localization, session::settings_change::SettingsChange, ui::fonts::Fonts, GlobalState, @@ -18,6 +17,7 @@ use conrod_core::{ widget::{self, Button, Image, Rectangle, Text}, widget_ids, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; +use i18n::Localization; use strum::IntoEnumIterator; use strum_macros::EnumIter; diff --git a/voxygen/src/hud/settings_window/sound.rs b/voxygen/src/hud/settings_window/sound.rs index f563b48f9e..ed655a0765 100644 --- a/voxygen/src/hud/settings_window/sound.rs +++ b/voxygen/src/hud/settings_window/sound.rs @@ -2,7 +2,6 @@ use super::{RESET_BUTTONS_HEIGHT, RESET_BUTTONS_WIDTH}; use crate::{ hud::{img_ids::Imgs, TEXT_COLOR}, - i18n::Localization, session::settings_change::{Audio as AudioChange, Audio::*}, ui::{fonts::Fonts, ImageSlider}, GlobalState, @@ -13,6 +12,7 @@ use conrod_core::{ widget::{self, Button, Rectangle, Scrollbar, Text}, widget_ids, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; +use i18n::Localization; widget_ids! { struct Ids { diff --git a/voxygen/src/hud/settings_window/video.rs b/voxygen/src/hud/settings_window/video.rs index c638602f30..e577ecb6d6 100644 --- a/voxygen/src/hud/settings_window/video.rs +++ b/voxygen/src/hud/settings_window/video.rs @@ -5,7 +5,6 @@ use crate::{ img_ids::Imgs, CRITICAL_HP_COLOR, HP_COLOR, LOW_HP_COLOR, MENU_BG, STAMINA_COLOR, TEXT_COLOR, }, - i18n::Localization, render::{ AaMode, CloudMode, FluidMode, LightingMode, PresentMode, RenderMode, ShadowMapMode, ShadowMode, UpscaleMode, @@ -23,6 +22,7 @@ use conrod_core::{ widget_ids, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; use core::convert::TryFrom; +use i18n::Localization; use itertools::Itertools; use std::iter::once; diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index debac354c9..07eae60057 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -8,7 +8,6 @@ use super::{ use crate::{ game_input::GameInput, hud::{ComboFloater, Position, PositionSpecifier}, - i18n::Localization, ui::{ fonts::Fonts, slot::{ContentSize, SlotMaker}, @@ -17,6 +16,7 @@ use crate::{ }, GlobalState, }; +use i18n::Localization; use client::{self, Client}; use common::comp::{ diff --git a/voxygen/src/hud/social.rs b/voxygen/src/hud/social.rs index 8c81cf06a7..6af6a1494e 100644 --- a/voxygen/src/hud/social.rs +++ b/voxygen/src/hud/social.rs @@ -2,11 +2,7 @@ use super::{ img_ids::{Imgs, ImgsRot}, Show, TEXT_COLOR, TEXT_COLOR_3, UI_HIGHLIGHT_0, UI_MAIN, }; - -use crate::{ - i18n::Localization, - ui::{fonts::Fonts, ImageFrame, Tooltip, TooltipManager, Tooltipable}, -}; +use crate::ui::{fonts::Fonts, ImageFrame, Tooltip, TooltipManager, Tooltipable}; use client::{self, Client}; use common::{comp::group, uid::Uid}; use conrod_core::{ @@ -14,6 +10,7 @@ use conrod_core::{ widget::{self, Button, Image, Rectangle, Scrollbar, Text, TextEdit}, widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; +use i18n::Localization; use itertools::Itertools; use std::time::Instant; diff --git a/voxygen/src/hud/trade.rs b/voxygen/src/hud/trade.rs index 1aa46459e9..83023f4e7d 100644 --- a/voxygen/src/hud/trade.rs +++ b/voxygen/src/hud/trade.rs @@ -6,7 +6,6 @@ use super::{ }; use crate::{ hud::bag::{BackgroundIds, InventoryScroller}, - i18n::Localization, ui::{ fonts::Fonts, slot::{ContentSize, SlotMaker}, @@ -28,6 +27,7 @@ use conrod_core::{ widget::{self, Button, Image, Rectangle, State as ConrodState, Text}, widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, UiCell, Widget, WidgetCommon, }; +use i18n::Localization; use specs::Entity as EcsEntity; use vek::*; diff --git a/voxygen/src/hud/util.rs b/voxygen/src/hud/util.rs index e383027404..0b7342abf1 100644 --- a/voxygen/src/hud/util.rs +++ b/voxygen/src/hud/util.rs @@ -11,10 +11,9 @@ use common::{ effect::Effect, trade::{Good, SitePrices}, }; +use i18n::Localization; use std::{borrow::Cow, fmt::Write}; -use crate::i18n::Localization; - pub fn price_desc( prices: &Option, item_definition_id: &str, diff --git a/voxygen/src/lib.rs b/voxygen/src/lib.rs index 304710c011..cf4d673534 100644 --- a/voxygen/src/lib.rs +++ b/voxygen/src/lib.rs @@ -33,10 +33,6 @@ pub mod settings; pub mod singleplayer; pub mod window; -// Reexports -pub use crate::error::Error; -pub use i18n; - #[cfg(feature = "singleplayer")] use crate::singleplayer::Singleplayer; #[cfg(feature = "egui-ui")] diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index 2a52b98e68..f7dff8f1c7 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -2,9 +2,9 @@ #![feature(bool_to_option)] #![recursion_limit = "2048"] +use i18n::{self, LocalizationHandle}; use veloren_voxygen::{ audio::AudioFrontend, - i18n::{self, LocalizationHandle}, profile::Profile, run, scene::terrain::SpriteRenderContext, diff --git a/voxygen/src/menu/char_selection/ui/mod.rs b/voxygen/src/menu/char_selection/ui/mod.rs index d48bfafe6e..b26d7c8fbe 100644 --- a/voxygen/src/menu/char_selection/ui/mod.rs +++ b/voxygen/src/menu/char_selection/ui/mod.rs @@ -1,5 +1,4 @@ use crate::{ - i18n::{Localization, LocalizationHandle}, render::UiDrawer, ui::{ self, @@ -26,6 +25,7 @@ use common::{ comp::{self, humanoid, inventory::slot::EquipSlot, Inventory, Item}, LoadoutBuilder, }; +use i18n::{Localization, LocalizationHandle}; //ImageFrame, Tooltip, use crate::settings::Settings; //use std::time::Duration; diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 06457e5069..910174901a 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -6,7 +6,6 @@ use super::char_selection::CharSelectionState; #[cfg(feature = "singleplayer")] use crate::singleplayer::Singleplayer; use crate::{ - i18n::LocalizationHandle, render::{Drawer, GlobalsBindGroup}, settings::Settings, window::Event, @@ -20,6 +19,7 @@ use client::{ use client_init::{ClientInit, Error as InitError, Msg as InitMsg}; use common::comp; use common_base::span; +use i18n::LocalizationHandle; use scene::Scene; use std::sync::Arc; use tokio::runtime; diff --git a/voxygen/src/menu/main/ui/connecting.rs b/voxygen/src/menu/main/ui/connecting.rs index 42c090a1c6..49651fdb21 100644 --- a/voxygen/src/menu/main/ui/connecting.rs +++ b/voxygen/src/menu/main/ui/connecting.rs @@ -1,13 +1,12 @@ use super::{ConnectionState, Imgs, Message}; -use crate::{ - i18n::Localization, - ui::{ - fonts::IcedFonts as Fonts, - ice::{component::neat_button, style, widget::Image, Element, IcedUi as Ui, Id}, - Graphic, - }, + +use crate::ui::{ + fonts::IcedFonts as Fonts, + ice::{component::neat_button, style, widget::Image, Element, IcedUi as Ui, Id}, + Graphic, }; use common::assets::{self, AssetExt}; +use i18n::Localization; use iced::{button, Align, Column, Container, Length, Row, Space, Text}; use serde::{Deserialize, Serialize}; diff --git a/voxygen/src/menu/main/ui/disclaimer.rs b/voxygen/src/menu/main/ui/disclaimer.rs index b7225a0edf..885b29bc15 100644 --- a/voxygen/src/menu/main/ui/disclaimer.rs +++ b/voxygen/src/menu/main/ui/disclaimer.rs @@ -1,6 +1,6 @@ use super::Message; +use i18n::{Localization}; use crate::{ - i18n::Localization, ui::{ fonts::IcedFonts as Fonts, ice::{component::neat_button, style, Element}, diff --git a/voxygen/src/menu/main/ui/login.rs b/voxygen/src/menu/main/ui/login.rs index cb8303b951..9234e713d6 100644 --- a/voxygen/src/menu/main/ui/login.rs +++ b/voxygen/src/menu/main/ui/login.rs @@ -1,19 +1,17 @@ use super::{Imgs, LoginInfo, Message, FILL_FRAC_ONE, FILL_FRAC_TWO}; -use crate::{ - i18n::Localization, - ui::{ - fonts::IcedFonts as Fonts, - ice::{ - component::neat_button, - style, - widget::{ - compound_graphic::{CompoundGraphic, Graphic}, - BackgroundContainer, Image, Padding, - }, - Element, +use crate::ui::{ + fonts::IcedFonts as Fonts, + ice::{ + component::neat_button, + style, + widget::{ + compound_graphic::{CompoundGraphic, Graphic}, + BackgroundContainer, Image, Padding, }, + Element, }, }; +use i18n::{LanguageMetadata, Localization}; use iced::{ button, scrollable, text_input, Align, Button, Column, Container, Length, Row, Scrollable, Space, Text, TextInput, @@ -61,7 +59,7 @@ impl Screen { i18n: &Localization, is_selecting_language: bool, selected_language_index: Option, - language_metadatas: &[crate::i18n::LanguageMetadata], + language_metadatas: &[LanguageMetadata], button_style: style::button::Style, version: &str, ) -> Element { @@ -223,7 +221,7 @@ impl LanguageSelectBanner { fonts: &Fonts, imgs: &Imgs, i18n: &Localization, - language_metadatas: &[crate::i18n::LanguageMetadata], + language_metadatas: &[LanguageMetadata], selected_language_index: Option, button_style: style::button::Style, ) -> Element { diff --git a/voxygen/src/menu/main/ui/mod.rs b/voxygen/src/menu/main/ui/mod.rs index 2cb8772994..a013750891 100644 --- a/voxygen/src/menu/main/ui/mod.rs +++ b/voxygen/src/menu/main/ui/mod.rs @@ -5,7 +5,6 @@ mod login; mod servers; use crate::{ - i18n::{LanguageMetadata, LocalizationHandle}, render::UiDrawer, ui::{ self, @@ -16,6 +15,7 @@ use crate::{ }, window, GlobalState, }; +use i18n::{LanguageMetadata, LocalizationHandle}; use iced::{text_input, Column, Container, HorizontalAlignment, Length, Row, Space}; //ImageFrame, Tooltip, use crate::settings::Settings; @@ -193,7 +193,7 @@ impl Controls { .iter() .position(|f| f == &login_info.server); - let language_metadatas = crate::i18n::list_localizations(); + let language_metadatas = i18n::list_localizations(); let selected_language_index = language_metadatas .iter() .position(|f| f.language_identifier == settings.language.selected_language); @@ -256,7 +256,7 @@ impl Controls { self.imgs.bg }; - let language_metadatas = crate::i18n::list_localizations(); + let language_metadatas = i18n::list_localizations(); // TODO: make any large text blocks scrollable so that if the area is to // small they can still be read @@ -315,7 +315,7 @@ impl Controls { ui: &mut Ui, ) { let servers = &settings.networking.servers; - let mut language_metadatas = crate::i18n::list_localizations(); + let mut language_metadatas = i18n::list_localizations(); match message { Message::Quit => events.push(Event::Quit), @@ -509,7 +509,7 @@ impl MainMenuUi { self.ui.clear_fonts(font); self.controls.fonts = Fonts::load(i18n.fonts(), &mut self.ui).expect("Impossible to load fonts!"); - let language_metadatas = crate::i18n::list_localizations(); + let language_metadatas = i18n::list_localizations(); self.controls.selected_language_index = language_metadatas .iter() .position(|f| f.language_identifier == settings.language.selected_language); diff --git a/voxygen/src/menu/main/ui/servers.rs b/voxygen/src/menu/main/ui/servers.rs index b07804ee63..4e4f20343f 100644 --- a/voxygen/src/menu/main/ui/servers.rs +++ b/voxygen/src/menu/main/ui/servers.rs @@ -1,11 +1,9 @@ use super::{Imgs, Message, FILL_FRAC_ONE}; -use crate::{ - i18n::Localization, - ui::{ - fonts::IcedFonts as Fonts, - ice::{component::neat_button, style, Element}, - }, +use crate::ui::{ + fonts::IcedFonts as Fonts, + ice::{component::neat_button, style, Element}, }; +use i18n::Localization; use iced::{ button, scrollable, Align, Button, Column, Container, Length, Row, Scrollable, Space, Text, }; diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index f64aed6221..3e7bda0b77 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -35,6 +35,7 @@ use common_net::{ use crate::{ audio::sfx::SfxEvent, + error::Error, game_input::GameInput, hud::{DebugInfo, Event as HudEvent, Hud, HudInfo, LootMessage, PromptDialogSettings}, key_state::KeyState, @@ -43,7 +44,7 @@ use crate::{ scene::{camera, terrain::Interaction, CameraMode, DebugShapeId, Scene, SceneData}, settings::Settings, window::{AnalogGameInput, Event}, - Direction, Error, GlobalState, PlayState, PlayStateResult, + Direction, GlobalState, PlayState, PlayStateResult, }; use hashbrown::HashMap; use settings_change::Language::ChangeLanguage; diff --git a/voxygen/src/session/settings_change.rs b/voxygen/src/session/settings_change.rs index 6f8239c141..62e18e8547 100644 --- a/voxygen/src/session/settings_change.rs +++ b/voxygen/src/session/settings_change.rs @@ -6,7 +6,6 @@ use crate::{ BarNumbers, BuffPosition, ChatTab, CrosshairType, Intro, PressBehavior, ScaleChange, ShortcutNumbers, XpBar, }, - i18n::{LanguageMetadata, LocalizationHandle}, render::RenderMode, settings::{ AudioSettings, ChatSettings, ControlSettings, Fps, GamepadSettings, GameplaySettings, @@ -15,6 +14,7 @@ use crate::{ window::FullScreenSettings, GlobalState, }; +use i18n::{LanguageMetadata, LocalizationHandle}; use vek::*; #[derive(Clone)] diff --git a/voxygen/src/settings/language.rs b/voxygen/src/settings/language.rs index b8e3f8b20e..28fd1840e3 100644 --- a/voxygen/src/settings/language.rs +++ b/voxygen/src/settings/language.rs @@ -1,4 +1,3 @@ -use crate::i18n; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, Serialize, Deserialize)] diff --git a/voxygen/src/ui/cache.rs b/voxygen/src/ui/cache.rs index dcf5041b8e..fd807d48e6 100644 --- a/voxygen/src/ui/cache.rs +++ b/voxygen/src/ui/cache.rs @@ -1,7 +1,7 @@ use super::graphic::{Graphic, GraphicCache, Id as GraphicId}; use crate::{ + error::Error, render::{Mesh, Renderer, Texture, UiTextureBindGroup, UiVertex}, - Error, }; use conrod_core::{text::GlyphCache, widget::Id}; use hashbrown::HashMap; diff --git a/voxygen/src/ui/fonts.rs b/voxygen/src/ui/fonts.rs index 1bd9ac45a1..fe3716542d 100644 --- a/voxygen/src/ui/fonts.rs +++ b/voxygen/src/ui/fonts.rs @@ -1,4 +1,4 @@ -use crate::{i18n, ui::ice::RawFont}; +use crate::ui::ice::RawFont; use common::assets::{self, AssetExt}; pub struct Font { diff --git a/voxygen/src/ui/ice/cache.rs b/voxygen/src/ui/ice/cache.rs index aeb629bc88..e7631e10a4 100644 --- a/voxygen/src/ui/ice/cache.rs +++ b/voxygen/src/ui/ice/cache.rs @@ -1,7 +1,7 @@ use super::graphic::{Graphic, GraphicCache, Id as GraphicId}; use crate::{ + error::Error, render::{Renderer, Texture, UiTextureBindGroup}, - Error, }; use common::assets::{self, AssetExt}; use glyph_brush::GlyphBrushBuilder; diff --git a/voxygen/src/ui/ice/mod.rs b/voxygen/src/ui/ice/mod.rs index 91393ad0cf..d28ef981d9 100644 --- a/voxygen/src/ui/ice/mod.rs +++ b/voxygen/src/ui/ice/mod.rs @@ -15,9 +15,9 @@ use super::{ scale::{Scale, ScaleMode}, }; use crate::{ + error::Error, render::{Renderer, UiDrawer}, window::Window, - Error, }; use common::slowjob::SlowJobPool; use common_base::span; diff --git a/voxygen/src/ui/ice/renderer/mod.rs b/voxygen/src/ui/ice/renderer/mod.rs index 51f4fbf494..2c6ff6014c 100644 --- a/voxygen/src/ui/ice/renderer/mod.rs +++ b/voxygen/src/ui/ice/renderer/mod.rs @@ -14,11 +14,11 @@ use super::{ Font, FontId, RawFont, Rotation, }; use crate::{ + error::Error, render::{ create_ui_quad, create_ui_quad_vert_gradient, DynamicModel, Mesh, Renderer, UiBoundLocals, UiDrawer, UiLocals, UiMode, UiVertex, }, - Error, }; use common::{slowjob::SlowJobPool, util::srgba_to_linear}; use common_base::span; diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index 574dd6ed8c..65b57fb139 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -28,12 +28,12 @@ pub use widgets::{ }; use crate::{ + error::Error, render::{ create_ui_quad, create_ui_tri, DynamicModel, Mesh, RenderError, Renderer, UiBoundLocals, UiDrawer, UiLocals, UiMode, UiVertex, }, window::Window, - Error, }; #[rustfmt::skip] use ::image::GenericImageView; diff --git a/voxygen/src/ui/widgets/item_tooltip.rs b/voxygen/src/ui/widgets/item_tooltip.rs index 4dcd6f7cf0..86c3ef1ad4 100644 --- a/voxygen/src/ui/widgets/item_tooltip.rs +++ b/voxygen/src/ui/widgets/item_tooltip.rs @@ -1,12 +1,9 @@ use super::image_frame::ImageFrame; -use crate::{ - hud::{ - get_quality_col, - img_ids::Imgs, - item_imgs::{animate_by_pulse, ItemImgs, ItemKey}, - util, - }, - i18n::Localization, +use crate::hud::{ + get_quality_col, + img_ids::Imgs, + item_imgs::{animate_by_pulse, ItemImgs, ItemKey}, + util, }; use client::Client; use common::{ @@ -22,6 +19,7 @@ use conrod_core::{ widget, widget_ids, Color, Colorable, FontSize, Positionable, Scalar, Sizeable, Ui, UiCell, Widget, WidgetCommon, WidgetStyle, }; +use i18n::Localization; use lazy_static::lazy_static; use std::time::{Duration, Instant}; diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index 3663e3443a..4f2c3da9d4 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -1,9 +1,10 @@ use crate::{ controller::*, + error::Error, game_input::GameInput, render::Renderer, settings::{ControlSettings, Settings}, - ui, Error, + ui, }; use common_base::span; use crossbeam_channel as channel; From c234f1d9266dc0c50b685e763fceffa87014d871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Thu, 29 Jul 2021 21:26:37 +0200 Subject: [PATCH 019/155] mark missing files as untranslated --- voxygen/i18n/src/analysis.rs | 25 +++++++++++++++++++------ voxygen/i18n/src/gitfragments.rs | 2 +- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/voxygen/i18n/src/analysis.rs b/voxygen/i18n/src/analysis.rs index e15d298839..28b055c908 100644 --- a/voxygen/i18n/src/analysis.rs +++ b/voxygen/i18n/src/analysis.rs @@ -69,6 +69,13 @@ fn compare_lang_with_reference( } }; + const MISSING: LocalizationEntryState = LocalizationEntryState { + key_line: None, + chuck_line_range: None, + commit_id: None, + state: Some(LocalizationState::NotFound), + }; + // match files for (ref_path, ref_fragment) in i18n_references.fragments.iter() { let cur_fragment = match current_i18n.fragments.get_mut(ref_path) { @@ -78,6 +85,17 @@ fn compare_lang_with_reference( "language {} is missing file: {:?}", current_i18n.manifest.metadata.language_identifier, ref_path ); + // add all keys as missing + let mut string_map = HashMap::new(); + for (ref_key, _) in ref_fragment.string_map.iter() { + string_map.insert(ref_key.to_owned(), MISSING.clone()); + } + current_i18n + .fragments + .insert(ref_path.to_owned(), RawFragment { + string_map, + vector_map: HashMap::new(), + }); continue; }, }; @@ -118,12 +136,7 @@ fn compare_lang_with_reference( None => { cur_fragment .string_map - .insert(ref_key.to_owned(), LocalizationEntryState { - key_line: None, - chuck_line_range: None, - commit_id: None, - state: Some(LocalizationState::NotFound), - }); + .insert(ref_key.to_owned(), MISSING.clone()); }, } } diff --git a/voxygen/i18n/src/gitfragments.rs b/voxygen/i18n/src/gitfragments.rs index e517360d42..ec77568837 100644 --- a/voxygen/i18n/src/gitfragments.rs +++ b/voxygen/i18n/src/gitfragments.rs @@ -19,7 +19,7 @@ pub(crate) const ALL_LOCALIZATION_STATES: [Option; 5] = [ None, ]; -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub(crate) struct LocalizationEntryState { pub(crate) key_line: Option, pub(crate) chuck_line_range: Option<(usize, usize)>, From 0b07b1409337096f7fcfb538eccf53d6c211b42a Mon Sep 17 00:00:00 2001 From: Thomas Kosel Date: Thu, 29 Jul 2021 22:38:20 +0200 Subject: [PATCH 020/155] moving CharacterState interpreting methods to character_state.rs --- common/src/comp/character_state.rs | 85 +++++++++++++++- common/systems/src/character_behavior.rs | 122 ++++------------------- 2 files changed, 103 insertions(+), 104 deletions(-) diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 8da7e8386c..6a3cd65939 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -1,8 +1,13 @@ use crate::{ combat::Attack, - comp::{tool::ToolKind, Density, Energy, InputAttr, InputKind, Ori, Pos, Vel}, + comp::{tool::ToolKind, ControlAction, Density, Energy, InputAttr, InputKind, Ori, Pos, Vel}, event::{LocalEvent, ServerEvent}, - states::{behavior::JoinData, utils::StageSection, *}, + states::{ + self, + behavior::{CharacterBehavior, JoinData}, + utils::StageSection, + *, + }, }; use serde::{Deserialize, Serialize}; use specs::{Component, DerefFlaggedStorage, VecStorage}; @@ -216,6 +221,82 @@ impl CharacterState { // Check if state is the same without looking at the inner data std::mem::discriminant(self) == std::mem::discriminant(other) } + + pub fn execute_behavior(&self, j: &JoinData) -> StateUpdate { + match &self { + CharacterState::Idle => states::idle::Data.behavior(&j), + CharacterState::Talk => states::talk::Data.behavior(&j), + CharacterState::Climb(data) => data.behavior(&j), + CharacterState::Glide(data) => data.behavior(&j), + CharacterState::GlideWield => states::glide_wield::Data.behavior(&j), + CharacterState::Stunned(data) => data.behavior(&j), + CharacterState::Sit => states::sit::Data::behavior(&states::sit::Data, &j), + CharacterState::Dance => states::dance::Data::behavior(&states::dance::Data, &j), + CharacterState::Sneak => states::sneak::Data::behavior(&states::sneak::Data, &j), + CharacterState::BasicBlock(data) => data.behavior(&j), + CharacterState::Roll(data) => data.behavior(&j), + CharacterState::Wielding => states::wielding::Data.behavior(&j), + CharacterState::Equipping(data) => data.behavior(&j), + CharacterState::ComboMelee(data) => data.behavior(&j), + CharacterState::BasicMelee(data) => data.behavior(&j), + CharacterState::BasicRanged(data) => data.behavior(&j), + CharacterState::Boost(data) => data.behavior(&j), + CharacterState::DashMelee(data) => data.behavior(&j), + CharacterState::LeapMelee(data) => data.behavior(&j), + CharacterState::SpinMelee(data) => data.behavior(&j), + CharacterState::ChargedMelee(data) => data.behavior(&j), + CharacterState::ChargedRanged(data) => data.behavior(&j), + CharacterState::RepeaterRanged(data) => data.behavior(&j), + CharacterState::Shockwave(data) => data.behavior(&j), + CharacterState::BasicBeam(data) => data.behavior(&j), + CharacterState::BasicAura(data) => data.behavior(&j), + CharacterState::Blink(data) => data.behavior(&j), + CharacterState::BasicSummon(data) => data.behavior(&j), + CharacterState::SelfBuff(data) => data.behavior(&j), + CharacterState::SpriteSummon(data) => data.behavior(&j), + CharacterState::UseItem(data) => data.behavior(&j), + } + } + + pub fn handle_action(&self, j: &JoinData, action: ControlAction) -> StateUpdate { + match &self { + CharacterState::Idle => states::idle::Data.handle_event(&j, action), + CharacterState::Talk => states::talk::Data.handle_event(&j, action), + CharacterState::Climb(data) => data.handle_event(&j, action), + CharacterState::Glide(data) => data.handle_event(&j, action), + CharacterState::GlideWield => states::glide_wield::Data.handle_event(&j, action), + CharacterState::Stunned(data) => data.handle_event(&j, action), + CharacterState::Sit => states::sit::Data::handle_event(&states::sit::Data, &j, action), + CharacterState::Dance => { + states::dance::Data::handle_event(&states::dance::Data, &j, action) + }, + CharacterState::Sneak => { + states::sneak::Data::handle_event(&states::sneak::Data, &j, action) + }, + CharacterState::BasicBlock(data) => data.handle_event(&j, action), + CharacterState::Roll(data) => data.handle_event(&j, action), + CharacterState::Wielding => states::wielding::Data.handle_event(&j, action), + CharacterState::Equipping(data) => data.handle_event(&j, action), + CharacterState::ComboMelee(data) => data.handle_event(&j, action), + CharacterState::BasicMelee(data) => data.handle_event(&j, action), + CharacterState::BasicRanged(data) => data.handle_event(&j, action), + CharacterState::Boost(data) => data.handle_event(&j, action), + CharacterState::DashMelee(data) => data.handle_event(&j, action), + CharacterState::LeapMelee(data) => data.handle_event(&j, action), + CharacterState::SpinMelee(data) => data.handle_event(&j, action), + CharacterState::ChargedMelee(data) => data.handle_event(&j, action), + CharacterState::ChargedRanged(data) => data.handle_event(&j, action), + CharacterState::RepeaterRanged(data) => data.handle_event(&j, action), + CharacterState::Shockwave(data) => data.handle_event(&j, action), + CharacterState::BasicBeam(data) => data.handle_event(&j, action), + CharacterState::BasicAura(data) => data.handle_event(&j, action), + CharacterState::Blink(data) => data.handle_event(&j, action), + CharacterState::BasicSummon(data) => data.handle_event(&j, action), + CharacterState::SelfBuff(data) => data.handle_event(&j, action), + CharacterState::SpriteSummon(data) => data.handle_event(&j, action), + CharacterState::UseItem(data) => data.handle_event(&j, action), + } + } } impl Default for CharacterState { diff --git a/common/systems/src/character_behavior.rs b/common/systems/src/character_behavior.rs index c1da0b563d..1b04200bbe 100644 --- a/common/systems/src/character_behavior.rs +++ b/common/systems/src/character_behavior.rs @@ -5,17 +5,14 @@ use specs::{ use common::{ comp::{ - self, inventory::item::MaterialStatManifest, Beam, Body, CharacterState, Combo, - ControlAction, Controller, Density, Energy, Health, Inventory, InventoryManip, Mass, Melee, - Mounting, Ori, PhysicsState, Poise, PoiseState, Pos, SkillSet, StateUpdate, Stats, Vel, + self, inventory::item::MaterialStatManifest, Beam, Body, CharacterState, Combo, Controller, + Density, Energy, Health, Inventory, InventoryManip, Mass, Melee, Mounting, Ori, + PhysicsState, Poise, PoiseState, Pos, SkillSet, StateUpdate, Stats, Vel, }, event::{Emitter, EventBus, LocalEvent, ServerEvent}, outcome::Outcome, resources::DeltaTime, - states::{ - self, - behavior::{CharacterBehavior, JoinData, JoinStruct}, - }, + states::behavior::{JoinData, JoinStruct}, terrain::TerrainGrid, uid::Uid, }; @@ -272,14 +269,13 @@ impl<'a> System<'a> for Sys { &read_data.dt, &read_data.msm, ); - let mut state_update = ::handle_action_of_current_state(action, &j); - - ::emit_state_updates( - &mut server_emitter, + let state_update = j.character.handle_action(&j, action); + ::publish_state_update( + &mut join_struct, + state_update, &mut local_emitter, - &mut state_update, + &mut server_emitter, ); - ::incorporate_update(&mut join_struct, state_update, &mut server_emitter); } // Mounted occurs after control actions have been handled @@ -299,105 +295,27 @@ impl<'a> System<'a> for Sys { &read_data.msm, ); - let mut state_update = ::execute_behavior_of_current_state(&j); - - ::emit_state_updates(&mut server_emitter, &mut local_emitter, &mut state_update); - ::incorporate_update(&mut join_struct, state_update, &mut server_emitter); + let state_update = j.character.execute_behavior(&j); + ::publish_state_update( + &mut join_struct, + state_update, + &mut local_emitter, + &mut server_emitter, + ); } } } impl Sys { - fn execute_behavior_of_current_state(j: &JoinData) -> StateUpdate { - match j.character { - CharacterState::Idle => states::idle::Data.behavior(&j), - CharacterState::Talk => states::talk::Data.behavior(&j), - CharacterState::Climb(data) => data.behavior(&j), - CharacterState::Glide(data) => data.behavior(&j), - CharacterState::GlideWield => states::glide_wield::Data.behavior(&j), - CharacterState::Stunned(data) => data.behavior(&j), - CharacterState::Sit => states::sit::Data::behavior(&states::sit::Data, &j), - CharacterState::Dance => states::dance::Data::behavior(&states::dance::Data, &j), - CharacterState::Sneak => states::sneak::Data::behavior(&states::sneak::Data, &j), - CharacterState::BasicBlock(data) => data.behavior(&j), - CharacterState::Roll(data) => data.behavior(&j), - CharacterState::Wielding => states::wielding::Data.behavior(&j), - CharacterState::Equipping(data) => data.behavior(&j), - CharacterState::ComboMelee(data) => data.behavior(&j), - CharacterState::BasicMelee(data) => data.behavior(&j), - CharacterState::BasicRanged(data) => data.behavior(&j), - CharacterState::Boost(data) => data.behavior(&j), - CharacterState::DashMelee(data) => data.behavior(&j), - CharacterState::LeapMelee(data) => data.behavior(&j), - CharacterState::SpinMelee(data) => data.behavior(&j), - CharacterState::ChargedMelee(data) => data.behavior(&j), - CharacterState::ChargedRanged(data) => data.behavior(&j), - CharacterState::RepeaterRanged(data) => data.behavior(&j), - CharacterState::Shockwave(data) => data.behavior(&j), - CharacterState::BasicBeam(data) => data.behavior(&j), - CharacterState::BasicAura(data) => data.behavior(&j), - CharacterState::Blink(data) => data.behavior(&j), - CharacterState::BasicSummon(data) => data.behavior(&j), - CharacterState::SelfBuff(data) => data.behavior(&j), - CharacterState::SpriteSummon(data) => data.behavior(&j), - CharacterState::UseItem(data) => data.behavior(&j), - } - } - - fn handle_action_of_current_state(action: ControlAction, j: &JoinData) -> StateUpdate { - match j.character { - CharacterState::Idle => states::idle::Data.handle_event(&j, action), - CharacterState::Talk => states::talk::Data.handle_event(&j, action), - CharacterState::Climb(data) => data.handle_event(&j, action), - CharacterState::Glide(data) => data.handle_event(&j, action), - CharacterState::GlideWield => states::glide_wield::Data.handle_event(&j, action), - CharacterState::Stunned(data) => data.handle_event(&j, action), - CharacterState::Sit => states::sit::Data::handle_event(&states::sit::Data, &j, action), - CharacterState::Dance => { - states::dance::Data::handle_event(&states::dance::Data, &j, action) - }, - CharacterState::Sneak => { - states::sneak::Data::handle_event(&states::sneak::Data, &j, action) - }, - CharacterState::BasicBlock(data) => data.handle_event(&j, action), - CharacterState::Roll(data) => data.handle_event(&j, action), - CharacterState::Wielding => states::wielding::Data.handle_event(&j, action), - CharacterState::Equipping(data) => data.handle_event(&j, action), - CharacterState::ComboMelee(data) => data.handle_event(&j, action), - CharacterState::BasicMelee(data) => data.handle_event(&j, action), - CharacterState::BasicRanged(data) => data.handle_event(&j, action), - CharacterState::Boost(data) => data.handle_event(&j, action), - CharacterState::DashMelee(data) => data.handle_event(&j, action), - CharacterState::LeapMelee(data) => data.handle_event(&j, action), - CharacterState::SpinMelee(data) => data.handle_event(&j, action), - CharacterState::ChargedMelee(data) => data.handle_event(&j, action), - CharacterState::ChargedRanged(data) => data.handle_event(&j, action), - CharacterState::RepeaterRanged(data) => data.handle_event(&j, action), - CharacterState::Shockwave(data) => data.handle_event(&j, action), - CharacterState::BasicBeam(data) => data.handle_event(&j, action), - CharacterState::BasicAura(data) => data.handle_event(&j, action), - CharacterState::Blink(data) => data.handle_event(&j, action), - CharacterState::BasicSummon(data) => data.handle_event(&j, action), - CharacterState::SelfBuff(data) => data.handle_event(&j, action), - CharacterState::SpriteSummon(data) => data.handle_event(&j, action), - CharacterState::UseItem(data) => data.handle_event(&j, action), - } - } - - fn emit_state_updates( - server_emitter: &mut Emitter, + fn publish_state_update( + join: &mut JoinStruct, + mut state_update: StateUpdate, local_emitter: &mut Emitter, - state_update: &mut StateUpdate, + server_emitter: &mut Emitter, ) { local_emitter.append(&mut state_update.local_events); server_emitter.append(&mut state_update.server_events); - } - fn incorporate_update( - join: &mut JoinStruct, - mut state_update: StateUpdate, - server_emitter: &mut Emitter, - ) { // TODO: if checking equality is expensive use optional field in StateUpdate if *join.char_state != state_update.character { *join.char_state = state_update.character From 005c33bb28b0f26b45aa5a31099d107eb60a28a6 Mon Sep 17 00:00:00 2001 From: Thomas Kosel Date: Thu, 29 Jul 2021 22:55:58 +0200 Subject: [PATCH 021/155] renaming methods to match the names of the methods called within --- common/src/comp/character_state.rs | 4 ++-- common/systems/src/character_behavior.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 6a3cd65939..3145f9d91a 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -222,7 +222,7 @@ impl CharacterState { std::mem::discriminant(self) == std::mem::discriminant(other) } - pub fn execute_behavior(&self, j: &JoinData) -> StateUpdate { + pub fn behavior(&self, j: &JoinData) -> StateUpdate { match &self { CharacterState::Idle => states::idle::Data.behavior(&j), CharacterState::Talk => states::talk::Data.behavior(&j), @@ -258,7 +258,7 @@ impl CharacterState { } } - pub fn handle_action(&self, j: &JoinData, action: ControlAction) -> StateUpdate { + pub fn handle_event(&self, j: &JoinData, action: ControlAction) -> StateUpdate { match &self { CharacterState::Idle => states::idle::Data.handle_event(&j, action), CharacterState::Talk => states::talk::Data.handle_event(&j, action), diff --git a/common/systems/src/character_behavior.rs b/common/systems/src/character_behavior.rs index 1b04200bbe..9b0b0958e9 100644 --- a/common/systems/src/character_behavior.rs +++ b/common/systems/src/character_behavior.rs @@ -269,7 +269,7 @@ impl<'a> System<'a> for Sys { &read_data.dt, &read_data.msm, ); - let state_update = j.character.handle_action(&j, action); + let state_update = j.character.handle_event(&j, action); ::publish_state_update( &mut join_struct, state_update, @@ -295,7 +295,7 @@ impl<'a> System<'a> for Sys { &read_data.msm, ); - let state_update = j.character.execute_behavior(&j); + let state_update = j.character.behavior(&j); ::publish_state_update( &mut join_struct, state_update, From 3735688e4ce94320585a5aa16b81ef619b22c145 Mon Sep 17 00:00:00 2001 From: Thomas Kosel Date: Thu, 29 Jul 2021 23:14:46 +0200 Subject: [PATCH 022/155] changing to Self to be a little more speaking and less riddles. --- common/systems/src/character_behavior.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/systems/src/character_behavior.rs b/common/systems/src/character_behavior.rs index 9b0b0958e9..930a243636 100644 --- a/common/systems/src/character_behavior.rs +++ b/common/systems/src/character_behavior.rs @@ -270,7 +270,7 @@ impl<'a> System<'a> for Sys { &read_data.msm, ); let state_update = j.character.handle_event(&j, action); - ::publish_state_update( + Self::publish_state_update( &mut join_struct, state_update, &mut local_emitter, @@ -296,7 +296,7 @@ impl<'a> System<'a> for Sys { ); let state_update = j.character.behavior(&j); - ::publish_state_update( + Self::publish_state_update( &mut join_struct, state_update, &mut local_emitter, From 14eb0f9aa258561e06e22fa23c7ddbc4a7aed9ea Mon Sep 17 00:00:00 2001 From: Monty Marz Date: Thu, 29 Jul 2021 22:38:35 +0000 Subject: [PATCH 023/155] Remove sceptre, add swords --- CHANGELOG.md | 6 + .../common/items/weapons/sword_1h/starter.ron | 21 ++++ assets/common/recipe_book.ron | 11 +- .../ui/char_select/portraits/danari_f.png | 4 +- .../ui/char_select/portraits/danari_m.png | 4 +- assets/voxygen/element/weapons/swords.png | 3 + assets/voxygen/i18n/en/common.ron | 6 +- assets/voxygen/item_image_manifest.ron | 4 + .../voxygen/voxel/biped_weapon_manifest.ron | 4 + .../voxygen/voxel/weapon/sword_1h/starter.vox | 3 + client/src/bin/bot/main.rs | 1 + client/src/lib.rs | 15 ++- common/net/src/msg/client.rs | 3 +- server/src/character_creator.rs | 68 +++++++---- server/src/sys/msg/character_screen.rs | 23 +++- voxygen/src/menu/char_selection/mod.rs | 9 +- voxygen/src/menu/char_selection/ui/mod.rs | 111 +++++++++++------- 17 files changed, 215 insertions(+), 81 deletions(-) create mode 100644 assets/common/items/weapons/sword_1h/starter.ron create mode 100644 assets/voxygen/element/weapons/swords.png create mode 100644 assets/voxygen/voxel/weapon/sword_1h/starter.vox diff --git a/CHANGELOG.md b/CHANGELOG.md index 4845b4b3ab..a748274fc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Quotes and escape codes can be used in command arguments - Toggle chat with a shortcut (default is F5) - Pets are now saved on logout 🐕 🦎 🐼 +- Dualwielded, one-handed swords as starting weapons (Will be replaced by daggers in the future!) +- Healing sceptre crafting recipe ### Changed @@ -41,10 +43,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Trades now consider if items can stack in full inventories. - The types of animals that can be tamed as pets are now limited to certain species, pending further balancing of pets + ### Removed - Enemies no longer spawn in dungeon boss room - Melee critical hit no longer applies after reduction by armour +- Enemies no more spawn in dungeon boss room +- Melee critical hit no more applies after reduction by armour +- Removed Healing Sceptre as a starting weapon as it is considered an advanced weapon ### Fixed diff --git a/assets/common/items/weapons/sword_1h/starter.ron b/assets/common/items/weapons/sword_1h/starter.ron new file mode 100644 index 0000000000..665c22a547 --- /dev/null +++ b/assets/common/items/weapons/sword_1h/starter.ron @@ -0,0 +1,21 @@ +ItemDef( + name: "Damaged Gladius", + description: "This blade has seen better days.", + kind: Tool(( + kind: Sword, + hands: One, + stats: Direct(( + equip_time_secs: 0.3, + power: 0.5, + effect_power: 1.0, + speed: 1.0, + crit_chance: 0.16, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + )), + )), + quality: Low, + tags: [], + ability_spec: None, +) diff --git a/assets/common/recipe_book.ron b/assets/common/recipe_book.ron index 5a1f2a8515..b46eece6a9 100644 --- a/assets/common/recipe_book.ron +++ b/assets/common/recipe_book.ron @@ -506,6 +506,15 @@ craft_sprite: Some(CraftingBench), is_recycling: false, ), + "Healing Sceptre": ( + output: ("common.items.weapons.sceptre.starter_sceptre", 1), + inputs: [ + (Item("common.items.crafting_ing.twigs"), 10), + (Item("common.items.crafting_ing.stones"), 0), + ], + craft_sprite: None, + is_recycling: false, + ), "Soothing Loop": ( output: ("common.items.weapons.sceptre.loops0", 1), inputs: [ @@ -514,7 +523,7 @@ (Item("common.items.mineral.gem.ruby"), 4), (Item("common.items.tool.craftsman_hammer"), 0), ], - craft_sprite: None, + craft_sprite: Some(CraftingBench), is_recycling: false, ), "Hunting Bow": ( diff --git a/assets/voxygen/element/ui/char_select/portraits/danari_f.png b/assets/voxygen/element/ui/char_select/portraits/danari_f.png index 503e55cb56..a7dd41216b 100644 --- a/assets/voxygen/element/ui/char_select/portraits/danari_f.png +++ b/assets/voxygen/element/ui/char_select/portraits/danari_f.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8877b0f6b59742996a64e9e35f07028e15c2e2df17eb7f0b80a1714cc7b30c96 -size 6323 +oid sha256:b3fe6ed254e8d1fc4dbdec0014070bd8a421e924f581f59642837b999f47fef3 +size 685 diff --git a/assets/voxygen/element/ui/char_select/portraits/danari_m.png b/assets/voxygen/element/ui/char_select/portraits/danari_m.png index 739e877c1d..c1845faeb4 100644 --- a/assets/voxygen/element/ui/char_select/portraits/danari_m.png +++ b/assets/voxygen/element/ui/char_select/portraits/danari_m.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e5ab138c073d970481e9213ba9f7c4c681011eba92114faef37c7c7edfde387 -size 12016 +oid sha256:d0a3c0ecf9309e439361d80b93f5292941fc677603e43531f628a024fe5917b3 +size 676 diff --git a/assets/voxygen/element/weapons/swords.png b/assets/voxygen/element/weapons/swords.png new file mode 100644 index 0000000000..fa2a4f1ade --- /dev/null +++ b/assets/voxygen/element/weapons/swords.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d48c06c9dab55e392528037e8efbbae35c8586ece413976cdc72c0d84f4ad117 +size 316 diff --git a/assets/voxygen/i18n/en/common.ron b/assets/voxygen/i18n/en/common.ron index 1dd6bf2c10..efbffbcda5 100644 --- a/assets/voxygen/i18n/en/common.ron +++ b/assets/voxygen/i18n/en/common.ron @@ -61,12 +61,14 @@ Is the client up to date?"#, "common.species.danari": "Danari", "common.weapons.axe": "Axe", + "common.weapons.greatsword": "Greatsword", + "common.weapons.shortswords": "Shortswords", "common.weapons.sword": "Sword", - "common.weapons.staff": "Staff", + "common.weapons.staff": "Firestaff", "common.weapons.bow": "Bow", "common.weapons.hammer": "Hammer", "common.weapons.general": "General Combat", - "common.weapons.sceptre": "Sceptre", + "common.weapons.sceptre": "Healing Sceptre", "common.weapons.shield": "Shield", "common.weapons.spear": "Spear", "common.weapons.hammer_simple": "Simple Hammer", diff --git a/assets/voxygen/item_image_manifest.ron b/assets/voxygen/item_image_manifest.ron index 303028d56e..bf44608ff0 100644 --- a/assets/voxygen/item_image_manifest.ron +++ b/assets/voxygen/item_image_manifest.ron @@ -437,6 +437,10 @@ "voxel.weapon.sword_1h.cobalt-3", (1.0, -1.0, 0.0), (-135.0, 90.0, 0.0), 1.2, ), + Tool("common.items.weapons.sword_1h.starter"): VoxTrans( + "voxel.weapon.sword_1h.starter", + (-1.0, 1.0, 0.0), (-135.0, 90.0, 0.0), 1.2, + ), Tool("common.items.weapons.sword_1h.iron-0"): VoxTrans( "voxel.weapon.sword_1h.iron-0", (1.0, -1.0, 0.0), (-135.0, 90.0, 0.0), 1.2, diff --git a/assets/voxygen/voxel/biped_weapon_manifest.ron b/assets/voxygen/voxel/biped_weapon_manifest.ron index 74cca7017f..ffc7128cf7 100644 --- a/assets/voxygen/voxel/biped_weapon_manifest.ron +++ b/assets/voxygen/voxel/biped_weapon_manifest.ron @@ -224,6 +224,10 @@ vox_spec: ("weapon.sword_1h.iron-4", (-2.0, -4.5, -3.0)), color: None ), + "common.items.weapons.sword_1h.starter": ( + vox_spec: ("weapon.sword_1h.starter", (-2.0, -4.5, -3.0)), + color: None + ), "common.items.weapons.sword_1h.obsidian-0": ( vox_spec: ("weapon.sword_1h.obsidian-0", (-2.0, -4.5, -3.0)), color: None diff --git a/assets/voxygen/voxel/weapon/sword_1h/starter.vox b/assets/voxygen/voxel/weapon/sword_1h/starter.vox new file mode 100644 index 0000000000..82917f17e9 --- /dev/null +++ b/assets/voxygen/voxel/weapon/sword_1h/starter.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fcde6c25e14c7970ebb926528e0e0a2f715f200a6f88c65a2a29da90f62aa513 +size 1304 diff --git a/client/src/bin/bot/main.rs b/client/src/bin/bot/main.rs index c6a4f5b63a..d4362b9b12 100644 --- a/client/src/bin/bot/main.rs +++ b/client/src/bin/bot/main.rs @@ -174,6 +174,7 @@ impl BotClient { client.create_character( cred.username.clone(), Some("common.items.weapons.sword.starter".to_string()), + None, body.into(), ); client.load_character_list(); diff --git a/client/src/lib.rs b/client/src/lib.rs index 4a6a823c1e..ae69cbf55a 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -826,9 +826,20 @@ impl Client { } /// New character creation - pub fn create_character(&mut self, alias: String, tool: Option, body: comp::Body) { + pub fn create_character( + &mut self, + alias: String, + mainhand: Option, + offhand: Option, + body: comp::Body, + ) { self.character_list.loading = true; - self.send_msg(ClientGeneral::CreateCharacter { alias, tool, body }); + self.send_msg(ClientGeneral::CreateCharacter { + alias, + mainhand, + offhand, + body, + }); } /// Character deletion diff --git a/common/net/src/msg/client.rs b/common/net/src/msg/client.rs index 0cc811ceb9..4f7b18ffa0 100644 --- a/common/net/src/msg/client.rs +++ b/common/net/src/msg/client.rs @@ -51,7 +51,8 @@ pub enum ClientGeneral { RequestCharacterList, CreateCharacter { alias: String, - tool: Option, + mainhand: Option, + offhand: Option, body: comp::Body, }, DeleteCharacter(CharacterId), diff --git a/server/src/character_creator.rs b/server/src/character_creator.rs index 688b0829fd..9c193262df 100644 --- a/server/src/character_creator.rs +++ b/server/src/character_creator.rs @@ -4,45 +4,54 @@ use common::comp::{ }; use specs::{Entity, WriteExpect}; -const VALID_STARTER_ITEMS: [&str; 6] = [ - "common.items.weapons.hammer.starter_hammer", - "common.items.weapons.bow.starter", - "common.items.weapons.axe.starter_axe", - "common.items.weapons.staff.starter_staff", - "common.items.weapons.sword.starter", - "common.items.weapons.sceptre.starter_sceptre", +const VALID_STARTER_ITEMS: &[[Option<&str>; 2]] = &[ + [None, None], // Not used with an unmodified client but should still be allowed (zesterer) + [Some("common.items.weapons.hammer.starter_hammer"), None], + [Some("common.items.weapons.bow.starter"), None], + [Some("common.items.weapons.axe.starter_axe"), None], + [Some("common.items.weapons.staff.starter_staff"), None], + [Some("common.items.weapons.sword.starter"), None], + [ + Some("common.items.weapons.sword_1h.starter"), + Some("common.items.weapons.sword_1h.starter"), + ], ]; +#[derive(Debug)] +pub enum CreationError { + InvalidWeapon, + InvalidBody, +} + pub fn create_character( entity: Entity, player_uuid: String, character_alias: String, - character_tool: Option, + character_mainhand: Option, + character_offhand: Option, body: Body, character_updater: &mut WriteExpect<'_, CharacterUpdater>, -) { +) -> Result<(), CreationError> { // quick fix whitelist validation for now; eventually replace the // `Option` with an index into a server-provided list of starter // items, and replace `comp::body::Body` with `comp::body::humanoid::Body` // throughout the messages involved - let tool_id = match character_tool { - Some(tool_id) if VALID_STARTER_ITEMS.contains(&&*tool_id) => tool_id, - _ => return, - }; if !matches!(body, Body::Humanoid(_)) { - return; + return Err(CreationError::InvalidBody); } - - let stats = Stats::new(character_alias.to_string()); - let skill_set = SkillSet::default(); - + if !VALID_STARTER_ITEMS.contains(&[character_mainhand.as_deref(), character_offhand.as_deref()]) + { + return Err(CreationError::InvalidWeapon); + }; + // The client sends None if a weapon hand is empty let loadout = LoadoutBuilder::empty() .defaults() - .active_mainhand(Some(Item::new_from_asset_expect(&tool_id))) + .active_mainhand(character_mainhand.map(|x| Item::new_from_asset_expect(&x))) + .active_offhand(character_offhand.map(|x| Item::new_from_asset_expect(&x))) .build(); - let mut inventory = Inventory::new_with_loadout(loadout); - + let stats = Stats::new(character_alias.to_string()); + let skill_set = SkillSet::default(); // Default items for new characters inventory .push(Item::new_from_asset_expect( @@ -61,4 +70,21 @@ pub fn create_character( character_alias, (body, stats, skill_set, inventory, waypoint, Vec::new()), ); + Ok(()) +} + +// Error handling +impl core::fmt::Display for CreationError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + CreationError::InvalidWeapon => write!( + f, + "Invalid weapon.\nServer and client might be partially incompatible." + ), + CreationError::InvalidBody => write!( + f, + "Invalid Body.\nServer and client might be partially incompatible" + ), + } + } } diff --git a/server/src/sys/msg/character_screen.rs b/server/src/sys/msg/character_screen.rs index 5610bfedf2..b2b2618c5a 100644 --- a/server/src/sys/msg/character_screen.rs +++ b/server/src/sys/msg/character_screen.rs @@ -115,19 +115,34 @@ impl Sys { character_loader.load_character_list(entity, player.uuid().to_string()) } }, - ClientGeneral::CreateCharacter { alias, tool, body } => { + ClientGeneral::CreateCharacter { + alias, + mainhand, + offhand, + body, + } => { if let Err(error) = alias_validator.validate(&alias) { debug!(?error, ?alias, "denied alias as it contained a banned word"); client.send(ServerGeneral::CharacterActionError(error.to_string()))?; } else if let Some(player) = players.get(entity) { - character_creator::create_character( + if let Err(error) = character_creator::create_character( entity, player.uuid().to_string(), alias, - tool, + mainhand.clone(), + offhand.clone(), body, character_updater, - ); + ) { + debug!( + ?error, + ?mainhand, + ?offhand, + ?body, + "Denied creating character because of invalid input." + ); + client.send(ServerGeneral::CharacterActionError(error.to_string()))?; + } } }, ClientGeneral::DeleteCharacter(character_id) => { diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index e2c67b6c42..8941cfc8bf 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -109,10 +109,15 @@ impl PlayState for CharSelectionState { ui::Event::Logout => { return PlayStateResult::Pop; }, - ui::Event::AddCharacter { alias, tool, body } => { + ui::Event::AddCharacter { + alias, + mainhand, + offhand, + body, + } => { self.client .borrow_mut() - .create_character(alias, Some(tool), body); + .create_character(alias, mainhand, offhand, body); }, ui::Event::DeleteCharacter(character_id) => { self.client.borrow_mut().delete_character(character_id); diff --git a/voxygen/src/menu/char_selection/ui/mod.rs b/voxygen/src/menu/char_selection/ui/mod.rs index b26d7c8fbe..083086848c 100644 --- a/voxygen/src/menu/char_selection/ui/mod.rs +++ b/voxygen/src/menu/char_selection/ui/mod.rs @@ -52,7 +52,8 @@ const STARTER_BOW: &str = "common.items.weapons.bow.starter"; const STARTER_AXE: &str = "common.items.weapons.axe.starter_axe"; const STARTER_STAFF: &str = "common.items.weapons.staff.starter_staff"; const STARTER_SWORD: &str = "common.items.weapons.sword.starter"; -const STARTER_SCEPTRE: &str = "common.items.weapons.sceptre.starter_sceptre"; +const STARTER_SWORDS: &str = "common.items.weapons.sword_1h.starter"; + // TODO: what does this comment mean? // // Use in future MR to make this a starter weapon @@ -67,9 +68,9 @@ image_ids_ice! { slider_range: "voxygen.element.ui.generic.slider.track", slider_indicator: "voxygen.element.ui.generic.slider.indicator", - selection: "voxygen.element.ui.generic.frames.selection", - selection_hover: "voxygen.element.ui.generic.frames.selection_hover", - selection_press: "voxygen.element.ui.generic.frames.selection_press", + char_selection: "voxygen.element.ui.generic.frames.selection", + char_selection_hover: "voxygen.element.ui.generic.frames.selection_hover", + char_selection_press: "voxygen.element.ui.generic.frames.selection_press", delete_button: "voxygen.element.ui.char_select.icons.bin", delete_button_hover: "voxygen.element.ui.char_select.icons.bin_hover", @@ -78,7 +79,7 @@ image_ids_ice! { name_input: "voxygen.element.ui.generic.textbox", // Tool Icons - sceptre: "voxygen.element.weapons.sceptre", + swords: "voxygen.element.weapons.swords", sword: "voxygen.element.weapons.sword", axe: "voxygen.element.weapons.axe", hammer: "voxygen.element.weapons.hammer", @@ -124,7 +125,8 @@ pub enum Event { Play(CharacterId), AddCharacter { alias: String, - tool: String, + mainhand: Option, + offhand: Option, body: comp::Body, }, DeleteCharacter(CharacterId), @@ -148,7 +150,8 @@ enum Mode { name: String, body: humanoid::Body, inventory: Box, - tool: &'static str, + mainhand: Option<&'static str>, + offhand: Option<&'static str>, body_type_buttons: [button::State; 2], species_buttons: [button::State; 6], @@ -178,11 +181,15 @@ impl Mode { } pub fn create(name: String) -> Self { - let tool = STARTER_SWORD; + // TODO: Load these from the server (presumably from a .ron) to allow for easier + // modification of custom starting weapons + let mainhand = Some(STARTER_SWORD); + let offhand = None; let loadout = LoadoutBuilder::empty() .defaults() - .active_mainhand(Some(Item::new_from_asset_expect(tool))) + .active_mainhand(mainhand.map(Item::new_from_asset_expect)) + .active_offhand(offhand.map(Item::new_from_asset_expect)) .build(); let inventory = Box::new(Inventory::new_with_loadout(loadout)); @@ -191,7 +198,8 @@ impl Mode { name, body: humanoid::Body::random(), inventory, - tool, + mainhand, + offhand, body_type_buttons: Default::default(), species_buttons: Default::default(), tool_buttons: Default::default(), @@ -244,7 +252,7 @@ enum Message { Name(String), BodyType(humanoid::BodyType), Species(humanoid::Species), - Tool(&'static str), + Tool((Option<&'static str>, Option<&'static str>)), RandomizeCharacter, RandomizeName, CancelDeletion, @@ -468,12 +476,12 @@ impl Controls { .padding(10) .style( style::button::Style::new(if Some(i) == selected { - imgs.selection_hover + imgs.char_selection_hover } else { - imgs.selection + imgs.char_selection }) - .hover_image(imgs.selection_hover) - .press_image(imgs.selection_press) + .hover_image(imgs.char_selection_hover) + .press_image(imgs.char_selection_press) .image_color(Rgba::new( select_col.0, select_col.1, @@ -485,7 +493,7 @@ impl Controls { .height(Length::Fill) .on_press(Message::Select(character_id)), ) - .ratio_of_image(imgs.selection), + .ratio_of_image(imgs.char_selection), ) .padding(0) .align_x(Align::End) @@ -514,9 +522,9 @@ impl Controls { .center_y(), ) .style( - style::button::Style::new(imgs.selection) - .hover_image(imgs.selection_hover) - .press_image(imgs.selection_press) + style::button::Style::new(imgs.char_selection) + .hover_image(imgs.char_selection_hover) + .press_image(imgs.char_selection_press) .image_color(Rgba::new(color.0, color.1, color.2, 255)) .text_color(iced::Color::from_rgb8(color.0, color.1, color.2)) .disabled_text_color(iced::Color::from_rgb8( @@ -531,7 +539,7 @@ impl Controls { button } }) - .ratio_of_image(imgs.selection) + .ratio_of_image(imgs.char_selection) .into(), ); characters @@ -710,7 +718,8 @@ impl Controls { name, body, inventory: _, - tool, + mainhand, + offhand: _, ref mut scroll, ref mut body_type_buttons, ref mut species_buttons, @@ -863,30 +872,30 @@ impl Controls { ]) .spacing(1); - let [ref mut sword_button, ref mut sceptre_button, ref mut axe_button, ref mut hammer_button, ref mut bow_button, ref mut staff_button] = + let [ref mut sword_button, ref mut swords_button, ref mut axe_button, ref mut hammer_button, ref mut bow_button, ref mut staff_button] = tool_buttons; let tool = Column::with_children(vec![ Row::with_children(vec![ icon_button_tooltip( sword_button, - *tool == STARTER_SWORD, - Message::Tool(STARTER_SWORD), + *mainhand == Some(STARTER_SWORD), + Message::Tool((Some(STARTER_SWORD), None)), imgs.sword, - "common.weapons.sword", + "common.weapons.greatsword", ) .into(), icon_button_tooltip( hammer_button, - *tool == STARTER_HAMMER, - Message::Tool(STARTER_HAMMER), + *mainhand == Some(STARTER_HAMMER), + Message::Tool((Some(STARTER_HAMMER), None)), imgs.hammer, "common.weapons.hammer", ) .into(), icon_button_tooltip( axe_button, - *tool == STARTER_AXE, - Message::Tool(STARTER_AXE), + *mainhand == Some(STARTER_AXE), + Message::Tool((Some(STARTER_AXE), None)), imgs.axe, "common.weapons.axe", ) @@ -896,25 +905,26 @@ impl Controls { .into(), Row::with_children(vec![ icon_button_tooltip( - sceptre_button, - *tool == STARTER_SCEPTRE, - Message::Tool(STARTER_SCEPTRE), - imgs.sceptre, - "common.weapons.sceptre", + swords_button, + *mainhand == Some(STARTER_SWORDS), + Message::Tool((Some(STARTER_SWORDS), Some(STARTER_SWORDS))), + imgs.swords, + "common.weapons.greatsword + ", ) .into(), icon_button_tooltip( bow_button, - *tool == STARTER_BOW, - Message::Tool(STARTER_BOW), + *mainhand == Some(STARTER_BOW), + Message::Tool((Some(STARTER_BOW), None)), imgs.bow, "common.weapons.bow", ) .into(), icon_button_tooltip( staff_button, - *tool == STARTER_STAFF, - Message::Tool(STARTER_STAFF), + *mainhand == Some(STARTER_STAFF), + Message::Tool((Some(STARTER_STAFF), None)), imgs.staff, "common.weapons.staff", ) @@ -1076,8 +1086,8 @@ impl Controls { let column_content = vec![ body_type.into(), - species.into(), tool.into(), + species.into(), slider_options.into(), rand_character.into(), ]; @@ -1300,12 +1310,17 @@ impl Controls { }, Message::CreateCharacter => { if let Mode::Create { - name, body, tool, .. + name, + body, + mainhand, + offhand, + .. } = &self.mode { events.push(Event::AddCharacter { alias: name.clone(), - tool: String::from(*tool), + mainhand: mainhand.map(String::from), + offhand: offhand.map(String::from), body: comp::Body::Humanoid(*body), }); self.mode = Mode::select(Some(InfoContent::CreatingCharacter)); @@ -1330,13 +1345,21 @@ impl Controls { }, Message::Tool(value) => { if let Mode::Create { - tool, inventory, .. + mainhand, + offhand, + inventory, + .. } = &mut self.mode { - *tool = value; + *mainhand = value.0; + *offhand = value.1; inventory.replace_loadout_item( EquipSlot::ActiveMainhand, - Some(Item::new_from_asset_expect(*tool)), + mainhand.map(|specifier| Item::new_from_asset_expect(specifier)), + ); + inventory.replace_loadout_item( + EquipSlot::ActiveOffhand, + offhand.map(|specifier| Item::new_from_asset_expect(specifier)), ); } }, From c4ec279121cbc9a0ce23081d5f0cdcf037bd1d04 Mon Sep 17 00:00:00 2001 From: Imbris Date: Fri, 30 Jul 2021 01:01:17 -0400 Subject: [PATCH 024/155] Add feature to profile memory allocation with Tracy --- voxygen/Cargo.toml | 1 + voxygen/src/main.rs | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index c7504d5890..6ded232b41 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -28,6 +28,7 @@ hot-reloading = ["common/hot-reloading"] singleplayer = ["server"] simd = ["vek/platform_intrinsics"] tracy = ["profiling", "profiling/profile-with-tracy", "common-frontend/tracy", "client/tracy"] +tracy-memory = ["tracy"] # enables heap profiling with tracy plugins = ["client/plugins"] egui-ui = ["voxygen-egui", "egui", "egui_wgpu_backend", "egui_winit_platform"] diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index f7dff8f1c7..a668bd44df 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -2,6 +2,12 @@ #![feature(bool_to_option)] #![recursion_limit = "2048"] +// Allow profiling allocations with Tracy +#[cfg_attr(feature = "tracy-memory", global_allocator)] +#[cfg(feature = "tracy-memory")] +static GLOBAL: common_base::tracy_client::ProfiledAllocator = + common_base::tracy_client::ProfiledAllocator::new(std::alloc::System, 128); + use i18n::{self, LocalizationHandle}; use veloren_voxygen::{ audio::AudioFrontend, From 172bddf731c40c9df29306406098073d0e595b6b Mon Sep 17 00:00:00 2001 From: Imbris Date: Fri, 30 Jul 2021 01:22:00 -0400 Subject: [PATCH 025/155] Make admin add/remove command arguments positional again --- CHANGELOG.md | 1 + server-cli/src/cli.rs | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4845b4b3ab..f838d0d80f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Mushroom Curry gives long-lasting Regeneration buff - Trades now consider if items can stack in full inventories. - The types of animals that can be tamed as pets are now limited to certain species, pending further balancing of pets +- Made server-cli admin add/remove command use positional arguments again ### Removed diff --git a/server-cli/src/cli.rs b/server-cli/src/cli.rs index 421ac93b5d..c416e3db45 100644 --- a/server-cli/src/cli.rs +++ b/server-cli/src/cli.rs @@ -8,15 +8,13 @@ use tracing::error; pub enum Admin { /// Adds an admin Add { - #[structopt(short, long)] /// Name of the admin to whom to assign a role username: String, /// role to assign to the admin - #[structopt(short, long, possible_values = &comp::AdminRole::variants(), case_insensitive = true)] + #[structopt(possible_values = &comp::AdminRole::variants(), case_insensitive = true)] role: comp::AdminRole, }, Remove { - #[structopt(short, long)] /// Name of the admin from whom to remove any existing roles username: String, }, From 2bf8a8c55c726d35d317f2437fd0c36d2be83ae9 Mon Sep 17 00:00:00 2001 From: Thomas Kosel Date: Fri, 30 Jul 2021 10:12:20 +0200 Subject: [PATCH 026/155] improving code quality by removing superfluous & --- common/src/comp/character_state.rs | 124 ++++++++++++++--------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 3145f9d91a..a0f2be1ee5 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -224,77 +224,77 @@ impl CharacterState { pub fn behavior(&self, j: &JoinData) -> StateUpdate { match &self { - CharacterState::Idle => states::idle::Data.behavior(&j), - CharacterState::Talk => states::talk::Data.behavior(&j), - CharacterState::Climb(data) => data.behavior(&j), - CharacterState::Glide(data) => data.behavior(&j), - CharacterState::GlideWield => states::glide_wield::Data.behavior(&j), - CharacterState::Stunned(data) => data.behavior(&j), - CharacterState::Sit => states::sit::Data::behavior(&states::sit::Data, &j), - CharacterState::Dance => states::dance::Data::behavior(&states::dance::Data, &j), - CharacterState::Sneak => states::sneak::Data::behavior(&states::sneak::Data, &j), - CharacterState::BasicBlock(data) => data.behavior(&j), - CharacterState::Roll(data) => data.behavior(&j), - CharacterState::Wielding => states::wielding::Data.behavior(&j), - CharacterState::Equipping(data) => data.behavior(&j), - CharacterState::ComboMelee(data) => data.behavior(&j), - CharacterState::BasicMelee(data) => data.behavior(&j), - CharacterState::BasicRanged(data) => data.behavior(&j), - CharacterState::Boost(data) => data.behavior(&j), - CharacterState::DashMelee(data) => data.behavior(&j), - CharacterState::LeapMelee(data) => data.behavior(&j), - CharacterState::SpinMelee(data) => data.behavior(&j), - CharacterState::ChargedMelee(data) => data.behavior(&j), - CharacterState::ChargedRanged(data) => data.behavior(&j), - CharacterState::RepeaterRanged(data) => data.behavior(&j), - CharacterState::Shockwave(data) => data.behavior(&j), - CharacterState::BasicBeam(data) => data.behavior(&j), - CharacterState::BasicAura(data) => data.behavior(&j), - CharacterState::Blink(data) => data.behavior(&j), - CharacterState::BasicSummon(data) => data.behavior(&j), - CharacterState::SelfBuff(data) => data.behavior(&j), - CharacterState::SpriteSummon(data) => data.behavior(&j), - CharacterState::UseItem(data) => data.behavior(&j), + CharacterState::Idle => states::idle::Data.behavior(j), + CharacterState::Talk => states::talk::Data.behavior(j), + CharacterState::Climb(data) => data.behavior(j), + CharacterState::Glide(data) => data.behavior(j), + CharacterState::GlideWield => states::glide_wield::Data.behavior(j), + CharacterState::Stunned(data) => data.behavior(j), + CharacterState::Sit => states::sit::Data::behavior(&states::sit::Data, j), + CharacterState::Dance => states::dance::Data::behavior(&states::dance::Data, j), + CharacterState::Sneak => states::sneak::Data::behavior(&states::sneak::Data, j), + CharacterState::BasicBlock(data) => data.behavior(j), + CharacterState::Roll(data) => data.behavior(j), + CharacterState::Wielding => states::wielding::Data.behavior(j), + CharacterState::Equipping(data) => data.behavior(j), + CharacterState::ComboMelee(data) => data.behavior(j), + CharacterState::BasicMelee(data) => data.behavior(j), + CharacterState::BasicRanged(data) => data.behavior(j), + CharacterState::Boost(data) => data.behavior(j), + CharacterState::DashMelee(data) => data.behavior(j), + CharacterState::LeapMelee(data) => data.behavior(j), + CharacterState::SpinMelee(data) => data.behavior(j), + CharacterState::ChargedMelee(data) => data.behavior(j), + CharacterState::ChargedRanged(data) => data.behavior(j), + CharacterState::RepeaterRanged(data) => data.behavior(j), + CharacterState::Shockwave(data) => data.behavior(j), + CharacterState::BasicBeam(data) => data.behavior(j), + CharacterState::BasicAura(data) => data.behavior(j), + CharacterState::Blink(data) => data.behavior(j), + CharacterState::BasicSummon(data) => data.behavior(j), + CharacterState::SelfBuff(data) => data.behavior(j), + CharacterState::SpriteSummon(data) => data.behavior(j), + CharacterState::UseItem(data) => data.behavior(j), } } pub fn handle_event(&self, j: &JoinData, action: ControlAction) -> StateUpdate { match &self { - CharacterState::Idle => states::idle::Data.handle_event(&j, action), - CharacterState::Talk => states::talk::Data.handle_event(&j, action), - CharacterState::Climb(data) => data.handle_event(&j, action), - CharacterState::Glide(data) => data.handle_event(&j, action), - CharacterState::GlideWield => states::glide_wield::Data.handle_event(&j, action), - CharacterState::Stunned(data) => data.handle_event(&j, action), - CharacterState::Sit => states::sit::Data::handle_event(&states::sit::Data, &j, action), + CharacterState::Idle => states::idle::Data.handle_event(j, action), + CharacterState::Talk => states::talk::Data.handle_event(j, action), + CharacterState::Climb(data) => data.handle_event(j, action), + CharacterState::Glide(data) => data.handle_event(j, action), + CharacterState::GlideWield => states::glide_wield::Data.handle_event(j, action), + CharacterState::Stunned(data) => data.handle_event(j, action), + CharacterState::Sit => states::sit::Data::handle_event(&states::sit::Data, j, action), CharacterState::Dance => { - states::dance::Data::handle_event(&states::dance::Data, &j, action) + states::dance::Data::handle_event(&states::dance::Data, j, action) }, CharacterState::Sneak => { - states::sneak::Data::handle_event(&states::sneak::Data, &j, action) + states::sneak::Data::handle_event(&states::sneak::Data, j, action) }, - CharacterState::BasicBlock(data) => data.handle_event(&j, action), - CharacterState::Roll(data) => data.handle_event(&j, action), - CharacterState::Wielding => states::wielding::Data.handle_event(&j, action), - CharacterState::Equipping(data) => data.handle_event(&j, action), - CharacterState::ComboMelee(data) => data.handle_event(&j, action), - CharacterState::BasicMelee(data) => data.handle_event(&j, action), - CharacterState::BasicRanged(data) => data.handle_event(&j, action), - CharacterState::Boost(data) => data.handle_event(&j, action), - CharacterState::DashMelee(data) => data.handle_event(&j, action), - CharacterState::LeapMelee(data) => data.handle_event(&j, action), - CharacterState::SpinMelee(data) => data.handle_event(&j, action), - CharacterState::ChargedMelee(data) => data.handle_event(&j, action), - CharacterState::ChargedRanged(data) => data.handle_event(&j, action), - CharacterState::RepeaterRanged(data) => data.handle_event(&j, action), - CharacterState::Shockwave(data) => data.handle_event(&j, action), - CharacterState::BasicBeam(data) => data.handle_event(&j, action), - CharacterState::BasicAura(data) => data.handle_event(&j, action), - CharacterState::Blink(data) => data.handle_event(&j, action), - CharacterState::BasicSummon(data) => data.handle_event(&j, action), - CharacterState::SelfBuff(data) => data.handle_event(&j, action), - CharacterState::SpriteSummon(data) => data.handle_event(&j, action), - CharacterState::UseItem(data) => data.handle_event(&j, action), + CharacterState::BasicBlock(data) => data.handle_event(j, action), + CharacterState::Roll(data) => data.handle_event(j, action), + CharacterState::Wielding => states::wielding::Data.handle_event(j, action), + CharacterState::Equipping(data) => data.handle_event(j, action), + CharacterState::ComboMelee(data) => data.handle_event(j, action), + CharacterState::BasicMelee(data) => data.handle_event(j, action), + CharacterState::BasicRanged(data) => data.handle_event(j, action), + CharacterState::Boost(data) => data.handle_event(j, action), + CharacterState::DashMelee(data) => data.handle_event(j, action), + CharacterState::LeapMelee(data) => data.handle_event(j, action), + CharacterState::SpinMelee(data) => data.handle_event(j, action), + CharacterState::ChargedMelee(data) => data.handle_event(j, action), + CharacterState::ChargedRanged(data) => data.handle_event(j, action), + CharacterState::RepeaterRanged(data) => data.handle_event(j, action), + CharacterState::Shockwave(data) => data.handle_event(j, action), + CharacterState::BasicBeam(data) => data.handle_event(j, action), + CharacterState::BasicAura(data) => data.handle_event(j, action), + CharacterState::Blink(data) => data.handle_event(j, action), + CharacterState::BasicSummon(data) => data.handle_event(j, action), + CharacterState::SelfBuff(data) => data.handle_event(j, action), + CharacterState::SpriteSummon(data) => data.handle_event(j, action), + CharacterState::UseItem(data) => data.handle_event(j, action), } } } From a3851c921493b59324448108e8121b2734731a70 Mon Sep 17 00:00:00 2001 From: Snowram Date: Sat, 31 Jul 2021 00:09:54 +0200 Subject: [PATCH 027/155] Retry release jobs on failure --- .gitlab/CI/release.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitlab/CI/release.yml b/.gitlab/CI/release.yml index 87484d7816..2a67b406ad 100644 --- a/.gitlab/CI/release.yml +++ b/.gitlab/CI/release.yml @@ -14,6 +14,8 @@ - if: $CI_PIPELINE_SOURCE != "merge_request_event" && $CI_PIPELINE_SOURCE != "schedule" && ($CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+/ || $CI_COMMIT_REF_NAME =~ /^r[0-9]+\.[0-9]+/) when: on_success - when: never + retry: + max: 1 # Template to only run if pushes to master or a tag happened for scheduled builds .release-nightly-tmp-fix-airshipper: @@ -22,3 +24,5 @@ - if: $CI_PIPELINE_SOURCE == "schedule" && ($CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+/ || $CI_COMMIT_REF_NAME =~ /^r[0-9]+\.[0-9]+/) when: on_success - when: never + retry: + max: 1 From 119c72f5d8940c280eb5521205b774b3475e3d4b Mon Sep 17 00:00:00 2001 From: Imbris Date: Fri, 30 Jul 2021 22:10:12 -0400 Subject: [PATCH 028/155] Fix typo in log message and remove prefixed '_' from a few used variables --- common/frontend/src/lib.rs | 16 +++++++++------- server/src/lib.rs | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/common/frontend/src/lib.rs b/common/frontend/src/lib.rs index cf3a72766b..6b78cf750e 100644 --- a/common/frontend/src/lib.rs +++ b/common/frontend/src/lib.rs @@ -39,7 +39,10 @@ where { // To hold the guards that we create, they will cause the logs to be // flushed when they're dropped. - let mut _guards: Vec = vec![]; + #[cfg(not(feature = "tracy"))] + let mut guards: Vec = Vec::new(); + #[cfg(feature = "tracy")] + let guards: Vec = Vec::new(); // We will do lower logging than the default (INFO) by INCLUSION. This // means that if you need lower level logging for a specific module, then @@ -100,8 +103,8 @@ where let registry = registry.with(tracing_tracy::TracyLayer::new().with_stackdepth(0)); #[cfg(not(feature = "tracy"))] let registry = { - let (non_blocking, _stdio_guard) = tracing_appender::non_blocking(terminal.make_writer()); - _guards.push(_stdio_guard); + let (non_blocking, stdio_guard) = tracing_appender::non_blocking(terminal.make_writer()); + guards.push(stdio_guard); registry.with(tracing_subscriber::fmt::layer().with_writer(non_blocking)) }; @@ -111,9 +114,8 @@ where match fs::create_dir_all(path) { Ok(_) => { let file_appender = tracing_appender::rolling::daily(path, file); - let (non_blocking_file, _file_guard) = - tracing_appender::non_blocking(file_appender); - _guards.push(_file_guard); + let (non_blocking_file, file_guard) = tracing_appender::non_blocking(file_appender); + guards.push(file_guard); file_setup = true; registry .with(tracing_subscriber::fmt::layer().with_writer(non_blocking_file)) @@ -146,7 +148,7 @@ where }; // Return the guards - _guards + guards } pub fn init_stdout(log_path_file: Option<(&Path, &str)>) -> Vec { diff --git a/server/src/lib.rs b/server/src/lib.rs index b70cc13247..33d2c7fffc 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -173,7 +173,7 @@ impl Server { data_dir: &std::path::Path, runtime: Arc, ) -> Result { - info!("Server is data dir is: {}", data_dir.display()); + info!("Server data dir is: {}", data_dir.display()); if settings.auth_server_address.is_none() { info!("Authentication is disabled"); } From 89eee332c9eedad9938c3ec744442637b8f9a508 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 31 Jul 2021 01:03:12 -0400 Subject: [PATCH 029/155] Replace `stamina -> energy` in code, i18n keys, and asset names --- .../{stamina_plus.png => energy_plus.png} | 0 .../ui/bag/icons/{stamina.png => energy.png} | 0 .../{stamina_bg.png => energy_bg.png} | 0 .../{stamina_frame.png => energy_frame.png} | 0 assets/voxygen/i18n/PL/buff.ron | 2 +- assets/voxygen/i18n/PL/hud/bag.ron | 2 +- assets/voxygen/i18n/PL/skills.ron | 12 ++--- assets/voxygen/i18n/cz_CZ/_manifest.ron | 16 +++---- assets/voxygen/i18n/de_DE/buff.ron | 2 +- assets/voxygen/i18n/de_DE/hud/bag.ron | 2 +- assets/voxygen/i18n/de_DE/skills.ron | 12 ++--- assets/voxygen/i18n/en/buff.ron | 2 +- assets/voxygen/i18n/en/hud/bag.ron | 2 +- assets/voxygen/i18n/en/skills.ron | 12 ++--- assets/voxygen/i18n/es_ES/buff.ron | 2 +- assets/voxygen/i18n/es_ES/hud/bag.ron | 2 +- assets/voxygen/i18n/es_ES/skills.ron | 12 ++--- assets/voxygen/i18n/fr_FR/buff.ron | 2 +- assets/voxygen/i18n/fr_FR/hud/bag.ron | 2 +- assets/voxygen/i18n/fr_FR/skills.ron | 12 ++--- assets/voxygen/i18n/hu_HU/buff.ron | 2 +- assets/voxygen/i18n/hu_HU/hud/bag.ron | 2 +- assets/voxygen/i18n/hu_HU/skills.ron | 12 ++--- assets/voxygen/i18n/it_IT/buff.ron | 2 +- assets/voxygen/i18n/it_IT/hud/bag.ron | 2 +- assets/voxygen/i18n/it_IT/skills.ron | 12 ++--- assets/voxygen/i18n/ja_JP/buff.ron | 2 +- assets/voxygen/i18n/ja_JP/hud/bag.ron | 2 +- assets/voxygen/i18n/ja_JP/skills.ron | 12 ++--- assets/voxygen/i18n/pt_BR/buff.ron | 2 +- assets/voxygen/i18n/pt_BR/hud/bag.ron | 2 +- assets/voxygen/i18n/pt_BR/skills.ron | 12 ++--- assets/voxygen/i18n/ru_RU/skills.ron | 12 ++--- assets/voxygen/i18n/sv/buff.ron | 2 +- assets/voxygen/i18n/sv/hud/bag.ron | 2 +- assets/voxygen/i18n/sv/skills.ron | 12 ++--- assets/voxygen/i18n/uk_UA/buff.ron | 2 +- assets/voxygen/i18n/uk_UA/hud/bag.ron | 2 +- assets/voxygen/i18n/uk_UA/skills.ron | 12 ++--- assets/voxygen/i18n/zh_CN/buff.ron | 2 +- assets/voxygen/i18n/zh_CN/hud/bag.ron | 2 +- assets/voxygen/i18n/zh_CN/skills.ron | 12 ++--- common/src/comp/buff.rs | 4 +- voxygen/src/hud/bag.rs | 10 ++-- voxygen/src/hud/buffs.rs | 6 +-- voxygen/src/hud/diary.rs | 8 ++-- voxygen/src/hud/group.rs | 10 ++-- voxygen/src/hud/img_ids.rs | 8 ++-- voxygen/src/hud/mod.rs | 2 +- voxygen/src/hud/skillbar.rs | 48 +++++++++---------- voxygen/src/hud/util.rs | 2 +- 51 files changed, 159 insertions(+), 159 deletions(-) rename assets/voxygen/element/skills/skilltree/{stamina_plus.png => energy_plus.png} (100%) rename assets/voxygen/element/ui/bag/icons/{stamina.png => energy.png} (100%) rename assets/voxygen/element/ui/skillbar/{stamina_bg.png => energy_bg.png} (100%) rename assets/voxygen/element/ui/skillbar/{stamina_frame.png => energy_frame.png} (100%) diff --git a/assets/voxygen/element/skills/skilltree/stamina_plus.png b/assets/voxygen/element/skills/skilltree/energy_plus.png similarity index 100% rename from assets/voxygen/element/skills/skilltree/stamina_plus.png rename to assets/voxygen/element/skills/skilltree/energy_plus.png diff --git a/assets/voxygen/element/ui/bag/icons/stamina.png b/assets/voxygen/element/ui/bag/icons/energy.png similarity index 100% rename from assets/voxygen/element/ui/bag/icons/stamina.png rename to assets/voxygen/element/ui/bag/icons/energy.png diff --git a/assets/voxygen/element/ui/skillbar/stamina_bg.png b/assets/voxygen/element/ui/skillbar/energy_bg.png similarity index 100% rename from assets/voxygen/element/ui/skillbar/stamina_bg.png rename to assets/voxygen/element/ui/skillbar/energy_bg.png diff --git a/assets/voxygen/element/ui/skillbar/stamina_frame.png b/assets/voxygen/element/ui/skillbar/energy_frame.png similarity index 100% rename from assets/voxygen/element/ui/skillbar/stamina_frame.png rename to assets/voxygen/element/ui/skillbar/energy_frame.png diff --git a/assets/voxygen/i18n/PL/buff.ron b/assets/voxygen/i18n/PL/buff.ron index f0c8fd9ba8..283575691e 100644 --- a/assets/voxygen/i18n/PL/buff.ron +++ b/assets/voxygen/i18n/PL/buff.ron @@ -26,7 +26,7 @@ "buff.desc.burn": "Palisz się żywcem", // Buffs stats "buff.stat.health": "Odnawia {str_total} Zdrowia", - "buff.stat.increase_max_stamina": "Podnosi Maksymalną Wytrzymałość o {strength}", + "buff.stat.increase_max_energy": "Podnosi Maksymalną Wytrzymałość o {strength}", "buff.stat.increase_max_health": "Podnosi Maksymalne Zdrowie o {strength}", "buff.stat.invulnerability": "Daje nietykalność", // Text diff --git a/assets/voxygen/i18n/PL/hud/bag.ron b/assets/voxygen/i18n/PL/hud/bag.ron index 819ff405d4..1ef6272b84 100644 --- a/assets/voxygen/i18n/PL/hud/bag.ron +++ b/assets/voxygen/i18n/PL/hud/bag.ron @@ -24,7 +24,7 @@ "hud.bag.offhand": "Ręka poboczna", "hud.bag.bag": "Torba", "hud.bag.health": "Zdrowie", - "hud.bag.stamina": "Energia", + "hud.bag.energy": "Energia", "hud.bag.combat_rating": "Combat Rating", "hud.bag.protection": "Ochrona", "hud.bag.combat_rating_desc": "Liczone na postawie Twojego\nekwipunku i zdrowia.", diff --git a/assets/voxygen/i18n/PL/skills.ron b/assets/voxygen/i18n/PL/skills.ron index cf9473ea72..0186674aab 100644 --- a/assets/voxygen/i18n/PL/skills.ron +++ b/assets/voxygen/i18n/PL/skills.ron @@ -9,8 +9,8 @@ // General "hud.skill.inc_health_title": "Zwiększ Zdrowie", "hud.skill.inc_health": "Zwiększa Maksymalne Zdrowie o {boost}{SP}", - "hud.skill.inc_stam_title": "Zwiększ Wytrzymałość", - "hud.skill.inc_stam": "Zwiększ Maksymalną Wytrzymałość o {boost}{SP}", + "hud.skill.inc_energy_title": "Zwiększ Wytrzymałość", + "hud.skill.inc_energy": "Zwiększ Maksymalną Wytrzymałość o {boost}{SP}", "hud.skill.unlck_sword_title": "Odblokuj miecz", "hud.skill.unlck_sword": "Odblokowuje umiejętności powiązane z mieczem{SP}", "hud.skill.unlck_axe_title": "Odblokuj topór", @@ -25,8 +25,8 @@ "hud.skill.unlck_sceptre": "Odblokowuje umiejętności powiązane z kosturem druida{SP}", "hud.skill.dodge_title": "Unik (przewrót)", "hud.skill.dodge": "Umożliwia unikanie ataków przeciwników (dodaje klatki nieśmiertelności){SP}", - "hud.skill.roll_stamina_title": "Przewrót - koszt", - "hud.skill.roll_stamina": "Przewrót kosztuje {boost}% mniej wytrzymałości{SP}", + "hud.skill.roll_energy_title": "Przewrót - koszt", + "hud.skill.roll_energy": "Przewrót kosztuje {boost}% mniej wytrzymałości{SP}", "hud.skill.roll_speed_title": "Przewrót - prędkość", "hud.skill.roll_speed": "Przewrót jest {boost}% szybszy{SP}", "hud.skill.roll_dur_title": "Przewrót - długość (czas)", @@ -93,8 +93,8 @@ "hud.skill.st_flamethrower_damage" : "Zwiększa obrażenia o {boost}%{SP}", "hud.skill.st_explosion_radius_title" : "Eksplozja - rozmiar", "hud.skill.st_explosion_radius" : "Rozmiar ma znaczenie, szczególnie gdy walczysz z wieloma przeciwnikami,\nzwiększa wielkość eksplozji o {boost}%{SP}", - "hud.skill.st_stamina_regen_title" : "Regeneracja Wytrzymałości", - "hud.skill.st_stamina_regen" : "Zwiększa regenerację Wytrzymałości o {boost}%{SP}", + "hud.skill.st_energy_regen_title" : "Regeneracja Wytrzymałości", + "hud.skill.st_energy_regen" : "Zwiększa regenerację Wytrzymałości o {boost}%{SP}", "hud.skill.st_fireball_title" : "Kula ognia", "hud.skill.st_fireball" : "Walisz z różdżki wybuchającymi fajerbolami", "hud.skill.st_damage_title" : "Obrażenia", diff --git a/assets/voxygen/i18n/cz_CZ/_manifest.ron b/assets/voxygen/i18n/cz_CZ/_manifest.ron index d5a6c1bef5..62e7bce880 100644 --- a/assets/voxygen/i18n/cz_CZ/_manifest.ron +++ b/assets/voxygen/i18n/cz_CZ/_manifest.ron @@ -262,7 +262,7 @@ Užijte si svůj pobyt ve světě Veloren!"#, "hud.bag.glider": "Glider", "hud.bag.bag": "Batoh", "hud.bag.health": "Život", - "hud.bag.stamina": "Výdrž", + "hud.bag.energy": "Výdrž", "hud.bag.combat_rating": "Bojové hodnocení", "hud.bag.protection": "Ochrana", "hud.bag.combat_rating_desc": "Vypočítáno z života/zbroje.", @@ -315,8 +315,8 @@ Užijte si svůj pobyt ve světě Veloren!"#, // General "hud.skill.inc_health_title": "Zvýší Zdraví", "hud.skill.inc_health": "Zvýší maximální zdraví o 5{SP}", - "hud.skill.inc_stam_title": "Zvýší Výdrž", - "hud.skill.inc_stam": "Zvýší Výdrž o 5{SP}", + "hud.skill.inc_energy_title": "Zvýší Výdrž", + "hud.skill.inc_energy": "Zvýší Výdrž o 5{SP}", "hud.skill.unlck_sword_title": "Odemknutí Meče", "hud.skill.unlck_sword": "Odemkne strom dovedností pro meče{SP}", "hud.skill.unlck_axe_title": "Odemknutí Sekery", @@ -331,8 +331,8 @@ Užijte si svůj pobyt ve světě Veloren!"#, "hud.skill.unlck_sceptre": "Odemkne strom dovedností pro žezlo{SP}", "hud.skill.dodge_title": "Vyhnutí", "hud.skill.dodge": "Vyhnese útokům zblízka{SP}", - "hud.skill.roll_stamina_title": "Menší spotřeba Výdrže pro Kotrmelec", - "hud.skill.roll_stamina": "Kotrmelec použije o 20% méně Výdrže{SP}", + "hud.skill.roll_energy_title": "Menší spotřeba Výdrže pro Kotrmelec", + "hud.skill.roll_energy": "Kotrmelec použije o 20% méně Výdrže{SP}", "hud.skill.roll_speed_title": "Rychlost Kotrmelce", "hud.skill.roll_speed": "Kotrmelec je o 20% rychlejší{SP}", "hud.skill.roll_dur_title": "Délka Kotrmelce", @@ -399,8 +399,8 @@ Užijte si svůj pobyt ve světě Veloren!"#, "hud.skill.st_flamethrower_damage" : "Zvýší poškození o 30%{SP}", "hud.skill.st_explosion_radius_title" : "Rozsah Exploze", "hud.skill.st_explosion_radius" : "Cím větší, tím lepší. Zvětší Rádius Exploze o 10%{SP}", - "hud.skill.st_stamina_regen_title" : "Obnova Výdrže", - "hud.skill.st_stamina_regen" : "Zvýší generaci výdrže o 20%{SP}", + "hud.skill.st_energy_regen_title" : "Obnova Výdrže", + "hud.skill.st_energy_regen" : "Zvýší generaci výdrže o 20%{SP}", "hud.skill.st_fireball_title" : "Ohnivá Koule", "hud.skill.st_fireball" : "Hrajte aport s nepřáteli", "hud.skill.st_damage_title" : "Poškození", @@ -778,7 +778,7 @@ Kdykoli se budeš cítit připraven, pokus se získat ještě lepší vybavení "buff.desc.cursed": "Jsi prokletý.", // Buffs stats "buff.stat.health": "Obnoví {str_total} Životů", - "buff.stat.increase_max_stamina": "Zvedne Maximalní Výdrž o {strength}", + "buff.stat.increase_max_energy": "Zvedne Maximalní Výdrž o {strength}", "buff.stat.increase_max_health": "Zvedne Maximální počet životů o {strength}", "buff.stat.invulnerability": "Zaručuje Nezranitelnost", // Text diff --git a/assets/voxygen/i18n/de_DE/buff.ron b/assets/voxygen/i18n/de_DE/buff.ron index f42d807832..f2e149b547 100644 --- a/assets/voxygen/i18n/de_DE/buff.ron +++ b/assets/voxygen/i18n/de_DE/buff.ron @@ -26,7 +26,7 @@ "buff.desc.cursed": "Du bist verflucht.", // Buffs stats "buff.stat.health": "Stellt {str_total} Leben wiederher", - "buff.stat.increase_max_stamina": "Erhöt die maximale Ausdauer um {strength}", + "buff.stat.increase_max_energy": "Erhöt die maximale Ausdauer um {strength}", "buff.stat.increase_max_health": "Erhöht die maximale Lebensenergie um {strength}", "buff.stat.invulnerability": "Gewährt Unverwundbarkeit", // Text diff --git a/assets/voxygen/i18n/de_DE/hud/bag.ron b/assets/voxygen/i18n/de_DE/hud/bag.ron index fafb68eb3e..24c2252fea 100644 --- a/assets/voxygen/i18n/de_DE/hud/bag.ron +++ b/assets/voxygen/i18n/de_DE/hud/bag.ron @@ -26,7 +26,7 @@ "hud.bag.offhand": "Nebenhand", "hud.bag.bag": "Beutel", "hud.bag.health": "Leben", - "hud.bag.stamina": "Ausdauer", + "hud.bag.energy": "Ausdauer", "hud.bag.combat_rating": "Kampfwertung", "hud.bag.protection": "Schutz", "hud.bag.stun_res": "Betäubungsresistenz", diff --git a/assets/voxygen/i18n/de_DE/skills.ron b/assets/voxygen/i18n/de_DE/skills.ron index d8915a90a4..edf044c638 100644 --- a/assets/voxygen/i18n/de_DE/skills.ron +++ b/assets/voxygen/i18n/de_DE/skills.ron @@ -11,8 +11,8 @@ // General "hud.skill.inc_health_title": "Leben erhöhen", "hud.skill.inc_health": "Erhöht max. Leben um {boost}{SP}", - "hud.skill.inc_stam_title": "Ausdauer", - "hud.skill.inc_stam": "Erhöht die max. Ausdauer um {boost}{SP}", + "hud.skill.inc_energy_title": "Ausdauer", + "hud.skill.inc_energy": "Erhöht die max. Ausdauer um {boost}{SP}", "hud.skill.unlck_sword_title": "Schwert freischalten", "hud.skill.unlck_sword": "Schaltet den Schwert-Fähigkeitenbaum frei{SP}", "hud.skill.unlck_axe_title": "Axt freischalten", @@ -27,8 +27,8 @@ "hud.skill.unlck_sceptre": "Schaltet den Zepter-Fähigkeitenbaum frei{SP}", "hud.skill.dodge_title": "Ausweichen", "hud.skill.dodge": "Weicht Nahkampfattacken aus{SP}", - "hud.skill.roll_stamina_title": "Ausdauerkosten beim Rollen", - "hud.skill.roll_stamina": "Rollen nutzt {boost}% weniger Ausdauer{SP}", + "hud.skill.roll_energy_title": "Ausdauerkosten beim Rollen", + "hud.skill.roll_energy": "Rollen nutzt {boost}% weniger Ausdauer{SP}", "hud.skill.roll_speed_title": "Rollgeschwindigkeit", "hud.skill.roll_speed": "Rolle um {boost}% schneller{SP}", "hud.skill.roll_dur_title": "Rolldauer", @@ -95,8 +95,8 @@ "hud.skill.st_flamethrower_damage" : "Erhöht den Schaden um {boost}%{SP}", "hud.skill.st_explosion_radius_title" : "Explosionsradius", "hud.skill.st_explosion_radius" : "Größer ist besser, erhöht den Radius der Explosion um {boost}%{SP}", - "hud.skill.st_stamina_regen_title" : "Ausdauerregeneration", - "hud.skill.st_stamina_regen" : "Erhöht den Ausdauergewinn um {boost}%{SP}", + "hud.skill.st_energy_regen_title" : "Ausdauerregeneration", + "hud.skill.st_energy_regen" : "Erhöht den Ausdauergewinn um {boost}%{SP}", "hud.skill.st_fireball_title" : "Feuerball", "hud.skill.st_fireball" : "Sende brennende Kugeln in Richtung deiner Feinde", "hud.skill.st_damage_title" : "Schaden", diff --git a/assets/voxygen/i18n/en/buff.ron b/assets/voxygen/i18n/en/buff.ron index e2c4ed10c6..1e41ca4b08 100644 --- a/assets/voxygen/i18n/en/buff.ron +++ b/assets/voxygen/i18n/en/buff.ron @@ -38,7 +38,7 @@ "buff.desc.ensnared": "Vines grasp at your legs, impeding your movement.", // Buffs stats "buff.stat.health": "Restores {str_total} Health", - "buff.stat.increase_max_stamina": "Raises Maximum Stamina by {strength}", + "buff.stat.increase_max_energy": "Raises Maximum Stamina by {strength}", "buff.stat.increase_max_health": "Raises Maximum Health by {strength}", "buff.stat.invulnerability": "Grants invulnerability", // Text diff --git a/assets/voxygen/i18n/en/hud/bag.ron b/assets/voxygen/i18n/en/hud/bag.ron index b8a0271369..ef65866ccd 100644 --- a/assets/voxygen/i18n/en/hud/bag.ron +++ b/assets/voxygen/i18n/en/hud/bag.ron @@ -30,7 +30,7 @@ "hud.bag.swap_equipped_weapons_desc": "Press {key}", "hud.bag.bag": "Bag", "hud.bag.health": "Health", - "hud.bag.stamina": "Stamina", + "hud.bag.energy": "Stamina", "hud.bag.combat_rating": "Combat Rating", "hud.bag.protection": "Protection", "hud.bag.stun_res": "Stun Resilience", diff --git a/assets/voxygen/i18n/en/skills.ron b/assets/voxygen/i18n/en/skills.ron index 472af3e40e..1c8b9eaa4d 100644 --- a/assets/voxygen/i18n/en/skills.ron +++ b/assets/voxygen/i18n/en/skills.ron @@ -11,8 +11,8 @@ // General "hud.skill.inc_health_title": "Increase Health", "hud.skill.inc_health": "Increases max health by {boost}{SP}", - "hud.skill.inc_stam_title": "Increase Stamina", - "hud.skill.inc_stam": "Increases max stamina by {boost}{SP}", + "hud.skill.inc_energy_title": "Increase Stamina", + "hud.skill.inc_energy": "Increases max stamina by {boost}{SP}", "hud.skill.unlck_sword_title": "Unlock Sword", "hud.skill.unlck_sword": "Unlocks sword skill tree{SP}", "hud.skill.unlck_axe_title": "Unlock Axe", @@ -27,8 +27,8 @@ "hud.skill.unlck_sceptre": "Unlocks sceptre skill tree{SP}", "hud.skill.dodge_title": "Dodge", "hud.skill.dodge": "Dodge rolls are triggered with middle-click, and grant temporary immunity to melee attacks (iframes) while you're rolling.", - "hud.skill.roll_stamina_title": "Roll Stamina Cost", - "hud.skill.roll_stamina": "Rolling uses {boost}% less stamina{SP}", + "hud.skill.roll_energy_title": "Roll Stamina Cost", + "hud.skill.roll_energy": "Rolling uses {boost}% less stamina{SP}", "hud.skill.roll_speed_title": "Rolling Speed", "hud.skill.roll_speed": "Roll {boost}% faster{SP}", "hud.skill.roll_dur_title": "Rolling Duration", @@ -97,8 +97,8 @@ "hud.skill.st_flamethrower_damage" : "Increases damage by {boost}%{SP}", "hud.skill.st_explosion_radius_title" : "Explosion Radius", "hud.skill.st_explosion_radius" : "Bigger is better, increases explosion radius by {boost}%{SP}", - "hud.skill.st_stamina_regen_title" : "Stamina Regen", - "hud.skill.st_stamina_regen" : "Increases stamina gain by {boost}%{SP}", + "hud.skill.st_energy_regen_title" : "Stamina Regen", + "hud.skill.st_energy_regen" : "Increases stamina gain by {boost}%{SP}", "hud.skill.st_fireball_title" : "Fireball", "hud.skill.st_fireball" : "Shoots a fireball that explodes on impact", "hud.skill.st_damage_title" : "Damage", diff --git a/assets/voxygen/i18n/es_ES/buff.ron b/assets/voxygen/i18n/es_ES/buff.ron index 6cf979b30c..014a67c146 100644 --- a/assets/voxygen/i18n/es_ES/buff.ron +++ b/assets/voxygen/i18n/es_ES/buff.ron @@ -26,7 +26,7 @@ "buff.desc.cursed": "Estás maldito.", // Buffs stats "buff.stat.health": "Restaura {str_total} salud", - "buff.stat.increase_max_stamina": "Aumenta la resistencia máxima en {strength}", + "buff.stat.increase_max_energy": "Aumenta la resistencia máxima en {strength}", "buff.stat.increase_max_health": "Aumenta la salud máxima en {strength}", "buff.stat.invulnerability": "Ofrece invulnerabilidad", // Text diff --git a/assets/voxygen/i18n/es_ES/hud/bag.ron b/assets/voxygen/i18n/es_ES/hud/bag.ron index db22d86dfb..c0b84fe65d 100644 --- a/assets/voxygen/i18n/es_ES/hud/bag.ron +++ b/assets/voxygen/i18n/es_ES/hud/bag.ron @@ -26,7 +26,7 @@ "hud.bag.offhand": "Mano secundaria", "hud.bag.bag": "Mochila", "hud.bag.health": "Vida", - "hud.bag.stamina": "Resistencia", + "hud.bag.energy": "Resistencia", "hud.bag.combat_rating": "Puntuación de combate", "hud.bag.protection": "Protección", "hud.bag.combat_rating_desc": "Calculado por tu\nequipamiento y vida", diff --git a/assets/voxygen/i18n/es_ES/skills.ron b/assets/voxygen/i18n/es_ES/skills.ron index 05bf911f4f..6fdf55cab1 100644 --- a/assets/voxygen/i18n/es_ES/skills.ron +++ b/assets/voxygen/i18n/es_ES/skills.ron @@ -11,8 +11,8 @@ // General "hud.skill.inc_health_title": "Aumentar la salud", "hud.skill.inc_health": "Aumenta la salud máxima en {boost}{SP}", - "hud.skill.inc_stam_title": "Aumenta la resistencia", - "hud.skill.inc_stam": "Aumenta la resistencia máxima en {boost}{SP}", + "hud.skill.inc_energy_title": "Aumenta la resistencia", + "hud.skill.inc_energy": "Aumenta la resistencia máxima en {boost}{SP}", "hud.skill.unlck_sword_title": "Desbloquear la espada", "hud.skill.unlck_sword": "Desbloquea el árbol de habilidades de la espada{SP}", "hud.skill.unlck_axe_title": "Desbloquear el hacha", @@ -27,8 +27,8 @@ "hud.skill.unlck_sceptre": "Desbloquea el árbol de habilidades del cetro{SP}", "hud.skill.dodge_title": "Esquivar", "hud.skill.dodge": "Esquivar evita los ataques cuerpo a cuerpo{SP}", - "hud.skill.roll_stamina_title": "Coste de resistencia Rodar", - "hud.skill.roll_stamina": "Rodar usa un {boost}% menos de resistencia{SP}", + "hud.skill.roll_energy_title": "Coste de resistencia Rodar", + "hud.skill.roll_energy": "Rodar usa un {boost}% menos de resistencia{SP}", "hud.skill.roll_speed_title": "Velocidad al rodar", "hud.skill.roll_speed": "Rodar es un {boost}% más rápido{SP}", "hud.skill.roll_dur_title": "Duración de rodar", @@ -95,8 +95,8 @@ "hud.skill.st_flamethrower_damage" : "Aumenta el daño en un {boost}%{SP}", "hud.skill.st_explosion_radius_title" : "Radio de explosión", "hud.skill.st_explosion_radius" : "Más grande es mejor, aumenta el radio de explosión en un {boost}%{SP}", - "hud.skill.st_stamina_regen_title" : "Regeneración de resistencia", - "hud.skill.st_stamina_regen" : "Aumenta la regeneración de resistencia en un {boost}%{SP}", + "hud.skill.st_energy_regen_title" : "Regeneración de resistencia", + "hud.skill.st_energy_regen" : "Aumenta la regeneración de resistencia en un {boost}%{SP}", "hud.skill.st_fireball_title" : "Bola de fuego", "hud.skill.st_fireball" : "Juega a perseguir a los enemigos", "hud.skill.st_damage_title" : "Daño", diff --git a/assets/voxygen/i18n/fr_FR/buff.ron b/assets/voxygen/i18n/fr_FR/buff.ron index d764b7968a..86d5d45b15 100644 --- a/assets/voxygen/i18n/fr_FR/buff.ron +++ b/assets/voxygen/i18n/fr_FR/buff.ron @@ -26,7 +26,7 @@ "buff.desc.cursed": "Vous êtes maudit.", // Buffs stats "buff.stat.health": "Restaure {str_total} points de vie", - "buff.stat.increase_max_stamina": "Augmente la vigueur maximale de {strength}", + "buff.stat.increase_max_energy": "Augmente la vigueur maximale de {strength}", "buff.stat.increase_max_health": "Augmente la santé maximale de {strength}", "buff.stat.invulnerability": "Rend invincible", // Text diff --git a/assets/voxygen/i18n/fr_FR/hud/bag.ron b/assets/voxygen/i18n/fr_FR/hud/bag.ron index 7865db0406..020f1ef603 100644 --- a/assets/voxygen/i18n/fr_FR/hud/bag.ron +++ b/assets/voxygen/i18n/fr_FR/hud/bag.ron @@ -26,7 +26,7 @@ "hud.bag.offhand": "Main Secondaire", "hud.bag.bag": "Sac", "hud.bag.health": "Santé", - "hud.bag.stamina": "Vigueur", + "hud.bag.energy": "Vigueur", "hud.bag.combat_rating": "Niveau de Combat", "hud.bag.protection": "Protection", "hud.bag.combat_rating_desc": "Calculé depuis votre\néquipement et votre santé", diff --git a/assets/voxygen/i18n/fr_FR/skills.ron b/assets/voxygen/i18n/fr_FR/skills.ron index 3fa6636704..5008c09588 100644 --- a/assets/voxygen/i18n/fr_FR/skills.ron +++ b/assets/voxygen/i18n/fr_FR/skills.ron @@ -11,8 +11,8 @@ // General "hud.skill.inc_health_title": "Augmentation de Santé", "hud.skill.inc_health": "Augmente les points de vie max de {boost}{SP}", - "hud.skill.inc_stam_title": "Augmentation d'Endurance", - "hud.skill.inc_stam": "Augmente les points d'endurance max de {boost}{SP}", + "hud.skill.inc_energy_title": "Augmentation d'Endurance", + "hud.skill.inc_energy": "Augmente les points d'endurance max de {boost}{SP}", "hud.skill.unlck_sword_title": "Maniement de l'Épée", "hud.skill.unlck_sword": "Débloque l'arbre de compétence pour l'épée{SP}", "hud.skill.unlck_axe_title": "Maniement de la Hache", @@ -27,8 +27,8 @@ "hud.skill.unlck_sceptre": "Débloque l'arbre de compétence pour le sceptre{SP}", "hud.skill.dodge_title": "Roulade", "hud.skill.dodge": "Esquivez les attaques de mélée en faisant des roulades{SP}", - "hud.skill.roll_stamina_title": "Coût d'Endurance de la Roulade", - "hud.skill.roll_stamina": "Rouler coûte {boost}% moins d'endurance{SP}", + "hud.skill.roll_energy_title": "Coût d'Endurance de la Roulade", + "hud.skill.roll_energy": "Rouler coûte {boost}% moins d'endurance{SP}", "hud.skill.roll_speed_title": "Vitesse de la Roulade", "hud.skill.roll_speed": "Rouler {boost}% plus vite{SP}", "hud.skill.roll_dur_title": "Durée de la Roulade", @@ -95,8 +95,8 @@ "hud.skill.st_flamethrower_damage" : "Augmente de {boost}% les dégâts{SP}", "hud.skill.st_explosion_radius_title" : "Portée de l'Explosion", "hud.skill.st_explosion_radius" : "Augmente la portée d'explosion de {boost}%{SP}", - "hud.skill.st_stamina_regen_title" : "Régénération d'Endurance des Boules de feu", - "hud.skill.st_stamina_regen" : "Augmente de {boost}% la régénération d'endurance{SP}", + "hud.skill.st_energy_regen_title" : "Régénération d'Endurance des Boules de feu", + "hud.skill.st_energy_regen" : "Augmente de {boost}% la régénération d'endurance{SP}", "hud.skill.st_fireball_title" : "Boule de Feu", "hud.skill.st_fireball" : "Joue à la balle avec les ennemis", "hud.skill.st_damage_title" : "Dégâts des boules de feu", diff --git a/assets/voxygen/i18n/hu_HU/buff.ron b/assets/voxygen/i18n/hu_HU/buff.ron index 7b1633b8d2..5a0f8eee85 100644 --- a/assets/voxygen/i18n/hu_HU/buff.ron +++ b/assets/voxygen/i18n/hu_HU/buff.ron @@ -38,7 +38,7 @@ "buff.desc.ensnared": "Indák kapaszkodnak a lábadba, így szinte lehetetlenné vált számodra a mozgás.", // Buffs stats "buff.stat.health": "{str_total} életerőt tölt vissza", - "buff.stat.increase_max_stamina": "Megnöveli a maximális energiát ennyivel: {strength}", + "buff.stat.increase_max_energy": "Megnöveli a maximális energiát ennyivel: {strength}", "buff.stat.increase_max_health": "Megnöveli a maximális életerőt ennyivel: {strength}", "buff.stat.invulnerability": "Sebezhetetlenné tesz", // Text diff --git a/assets/voxygen/i18n/hu_HU/hud/bag.ron b/assets/voxygen/i18n/hu_HU/hud/bag.ron index fec5dfa1f6..ca11e5a763 100644 --- a/assets/voxygen/i18n/hu_HU/hud/bag.ron +++ b/assets/voxygen/i18n/hu_HU/hud/bag.ron @@ -30,7 +30,7 @@ "hud.bag.swap_equipped_weapons_desc": "Nyomd meg a(z) '{key}' gombot", "hud.bag.bag": "Holmitartó", "hud.bag.health": "Életerő", - "hud.bag.stamina": "Energia", + "hud.bag.energy": "Energia", "hud.bag.combat_rating": "Küzdelmi érték", "hud.bag.protection": "Védelem", "hud.bag.stun_res": "Megszédíthetőség", diff --git a/assets/voxygen/i18n/hu_HU/skills.ron b/assets/voxygen/i18n/hu_HU/skills.ron index e3926b27c8..4cee0264a8 100644 --- a/assets/voxygen/i18n/hu_HU/skills.ron +++ b/assets/voxygen/i18n/hu_HU/skills.ron @@ -11,8 +11,8 @@ // General "hud.skill.inc_health_title": "Életerő növelése", "hud.skill.inc_health": "Maximális életerő növelése {boost} ponttal{SP}", - "hud.skill.inc_stam_title": "Energia növelése", - "hud.skill.inc_stam": "Maximális energia növelése {boost} ponttal{SP}", + "hud.skill.inc_energy_title": "Energia növelése", + "hud.skill.inc_energy": "Maximális energia növelése {boost} ponttal{SP}", "hud.skill.unlck_sword_title": "Kard feloldása", "hud.skill.unlck_sword": "Kard képességfájának feloldása{SP}", "hud.skill.unlck_axe_title": "Fejsze feloldása", @@ -27,8 +27,8 @@ "hud.skill.unlck_sceptre": "Varázsjogar képességfájának feloldása{SP}", "hud.skill.dodge_title": "Kitérés", "hud.skill.dodge": "A kitérőbukfencet görgőkattintással lehet aktiválni. A gurulás ideje alatt nem lehet megsebezni téged közelharci támadással.", - "hud.skill.roll_stamina_title": "Bukfencezés energiaigénye", - "hud.skill.roll_stamina": "A bukfencezés {boost}%-kal kevesebb energiát használ{SP}", + "hud.skill.roll_energy_title": "Bukfencezés energiaigénye", + "hud.skill.roll_energy": "A bukfencezés {boost}%-kal kevesebb energiát használ{SP}", "hud.skill.roll_speed_title": "Bukfencezés sebessége", "hud.skill.roll_speed": "{boost}%-kal gyorsabb bukfencezés{SP}", "hud.skill.roll_dur_title": "Bukfencezés időtartama", @@ -95,8 +95,8 @@ "hud.skill.st_flamethrower_damage" : "Megnöveli a sebzést {boost}%-kal{SP}", "hud.skill.st_explosion_radius_title" : "Robbanás sugara", "hud.skill.st_explosion_radius" : "Nagyobb a jobb, megnöveli a robbanás sugarát {boost}%-kal{SP}", - "hud.skill.st_stamina_regen_title" : "Energia visszatöltődés", - "hud.skill.st_stamina_regen" : "Megnöveli az energia visszatöltődést {boost}%-kal{SP}", + "hud.skill.st_energy_regen_title" : "Energia visszatöltődés", + "hud.skill.st_energy_regen" : "Megnöveli az energia visszatöltődést {boost}%-kal{SP}", "hud.skill.st_fireball_title" : "Tűzgolyó", "hud.skill.st_fireball" : "Egy tűzgolyót lő ki, amely becsapódáskor felrobban", "hud.skill.st_damage_title" : "Sebzés", diff --git a/assets/voxygen/i18n/it_IT/buff.ron b/assets/voxygen/i18n/it_IT/buff.ron index 3bed46b05c..254bb051d5 100644 --- a/assets/voxygen/i18n/it_IT/buff.ron +++ b/assets/voxygen/i18n/it_IT/buff.ron @@ -32,7 +32,7 @@ "buff.desc.crippled": "Il tuo movimento è storpio dal momento che le tue gambe sono gravemente ferite.", // Buffs stats "buff.stat.health": "Rigenera {str_total} di Salute", - "buff.stat.increase_max_stamina": "Aumenta la Stamina Massima di {strength}", + "buff.stat.increase_max_energy": "Aumenta la Stamina Massima di {strength}", "buff.stat.increase_max_health": "Aumenta la Salute Massima di {strength}", "buff.stat.invulnerability": "Dona invulnerabilità", // Text diff --git a/assets/voxygen/i18n/it_IT/hud/bag.ron b/assets/voxygen/i18n/it_IT/hud/bag.ron index c763a7bb66..517ee552f6 100644 --- a/assets/voxygen/i18n/it_IT/hud/bag.ron +++ b/assets/voxygen/i18n/it_IT/hud/bag.ron @@ -26,7 +26,7 @@ "hud.bag.offhand": "Mano Secondaria", "hud.bag.bag": "Borsa", "hud.bag.health": "Salute", - "hud.bag.stamina": "Stamina", + "hud.bag.energy": "Stamina", "hud.bag.combat_rating": "Grado di Combattimento", "hud.bag.protection": "Protezione", "hud.bag.stun_res": "Resilienza allo Stordimento", diff --git a/assets/voxygen/i18n/it_IT/skills.ron b/assets/voxygen/i18n/it_IT/skills.ron index 98f6c0a93f..8e0f41e237 100644 --- a/assets/voxygen/i18n/it_IT/skills.ron +++ b/assets/voxygen/i18n/it_IT/skills.ron @@ -11,8 +11,8 @@ // General "hud.skill.inc_health_title": "Aumenta Salute", "hud.skill.inc_health": "Incrementa la salute massima di {boost}{SP}", - "hud.skill.inc_stam_title": "Aumenta Stamina", - "hud.skill.inc_stam": "Incrementa la stamina massima di {boost}{SP}", + "hud.skill.inc_energy_title": "Aumenta Stamina", + "hud.skill.inc_energy": "Incrementa la stamina massima di {boost}{SP}", "hud.skill.unlck_sword_title": "Sblocca Spada", "hud.skill.unlck_sword": "Sblocca l'albero di abilità per la spada{SP}", "hud.skill.unlck_axe_title": "Sblocca Ascia", @@ -27,8 +27,8 @@ "hud.skill.unlck_sceptre": "Sblocca l'albero di abilità per lo scettro{SP}", "hud.skill.dodge_title": "Schivata", "hud.skill.dodge": "Le rotolate per schivare vengono attivate col click del tasto centrale del mouse, e concede immunità temporanea ad attacchi ravvicinati (iframes) mentre stai rotolando.", - "hud.skill.roll_stamina_title": "Costo di Stamina Rotolata", - "hud.skill.roll_stamina": "Rotolare usa il {boost}% in meno di stamina{SP}", + "hud.skill.roll_energy_title": "Costo di Stamina Rotolata", + "hud.skill.roll_energy": "Rotolare usa il {boost}% in meno di stamina{SP}", "hud.skill.roll_speed_title": "Velocità Rotolata", "hud.skill.roll_speed": "Rotola il {boost}% più velocemente{SP}", "hud.skill.roll_dur_title": "Durata Rotolata", @@ -95,8 +95,8 @@ "hud.skill.st_flamethrower_damage" : "Incrementa il danno del {boost}%{SP}", "hud.skill.st_explosion_radius_title" : "Portata Esplosione", "hud.skill.st_explosion_radius" : "Più grande è meglio, aumenta la portata dell'esplosione del {boost}%{SP}", - "hud.skill.st_stamina_regen_title" : "Rigenerazione Stamina", - "hud.skill.st_stamina_regen" : "Incrementa la stamina ottenuta del {boost}%{SP}", + "hud.skill.st_energy_regen_title" : "Rigenerazione Stamina", + "hud.skill.st_energy_regen" : "Incrementa la stamina ottenuta del {boost}%{SP}", "hud.skill.st_fireball_title" : "Palla di Fuoco", "hud.skill.st_fireball" : "Spara una palla di fuoco che esplode all'impatto", "hud.skill.st_damage_title" : "Danno", diff --git a/assets/voxygen/i18n/ja_JP/buff.ron b/assets/voxygen/i18n/ja_JP/buff.ron index da5885664c..1cb53bbdd0 100644 --- a/assets/voxygen/i18n/ja_JP/buff.ron +++ b/assets/voxygen/i18n/ja_JP/buff.ron @@ -26,7 +26,7 @@ "buff.desc.cursed": "あなたは呪われた。", // Buffs stats "buff.stat.health": "体力を{str_total}回復", - "buff.stat.increase_max_stamina": "スタミナ最大値を{strength}上げる", + "buff.stat.increase_max_energy": "スタミナ最大値を{strength}上げる", "buff.stat.increase_max_health": "体力最大値を{strength}上げる", "buff.stat.invulnerability": "不死身になる", // Text diff --git a/assets/voxygen/i18n/ja_JP/hud/bag.ron b/assets/voxygen/i18n/ja_JP/hud/bag.ron index 5492894b4d..e25c97ff1c 100644 --- a/assets/voxygen/i18n/ja_JP/hud/bag.ron +++ b/assets/voxygen/i18n/ja_JP/hud/bag.ron @@ -26,7 +26,7 @@ "hud.bag.offhand": "非利き手", "hud.bag.bag": "バッグ", "hud.bag.health": "体力", - "hud.bag.stamina": "スタミナ", + "hud.bag.energy": "スタミナ", "hud.bag.combat_rating": "戦闘レート", "hud.bag.protection": "防御力", "hud.bag.combat_rating_desc": "装備と体力から\n計算されます", diff --git a/assets/voxygen/i18n/ja_JP/skills.ron b/assets/voxygen/i18n/ja_JP/skills.ron index 6f94dc94f4..1ce14d2843 100644 --- a/assets/voxygen/i18n/ja_JP/skills.ron +++ b/assets/voxygen/i18n/ja_JP/skills.ron @@ -11,8 +11,8 @@ // General "hud.skill.inc_health_title": "体力追加", "hud.skill.inc_health": "体力の最大値を{boost}増加 {SP}", - "hud.skill.inc_stam_title": "スタミナ追加", - "hud.skill.inc_stam": "スタミナ最大値を{boost}増加 {SP}", + "hud.skill.inc_energy_title": "スタミナ追加", + "hud.skill.inc_energy": "スタミナ最大値を{boost}増加 {SP}", "hud.skill.unlck_sword_title": "剣解除", "hud.skill.unlck_sword": "剣のスキルツリーを解除 {SP}", "hud.skill.unlck_axe_title": "斧解除", @@ -27,8 +27,8 @@ "hud.skill.unlck_sceptre": "セプターのスキルツリーを解除 {SP}", "hud.skill.dodge_title": "回避", "hud.skill.dodge": "近接攻撃を素早く避ける {SP}", - "hud.skill.roll_stamina_title": "ローリング スタミナコスト", - "hud.skill.roll_stamina": "ローリングのスタミナ消費を{boost}%減少 {SP}", + "hud.skill.roll_energy_title": "ローリング スタミナコスト", + "hud.skill.roll_energy": "ローリングのスタミナ消費を{boost}%減少 {SP}", "hud.skill.roll_speed_title": "ローリング 速度", "hud.skill.roll_speed": "ローリングの速度を{boost}%加速 {SP}", "hud.skill.roll_dur_title": "ローリング 時間", @@ -95,8 +95,8 @@ "hud.skill.st_flamethrower_damage" : "ダメージを{boost}%増加 {SP}", "hud.skill.st_explosion_radius_title" : "エクスプロージョン 範囲", "hud.skill.st_explosion_radius" : "大きいのはいいですよね。爆発半径を{boost}%増加 {SP}", - "hud.skill.st_stamina_regen_title" : "スタミナ 再生", - "hud.skill.st_stamina_regen" : "スタミナ獲得量を{boost}%増加 {SP}", + "hud.skill.st_energy_regen_title" : "スタミナ 再生", + "hud.skill.st_energy_regen" : "スタミナ獲得量を{boost}%増加 {SP}", "hud.skill.st_fireball_title" : "ファイアーボール", "hud.skill.st_fireball" : "敵と一緒に遊びましょう", "hud.skill.st_damage_title" : "ダメージ", diff --git a/assets/voxygen/i18n/pt_BR/buff.ron b/assets/voxygen/i18n/pt_BR/buff.ron index 41010940af..19ae344942 100644 --- a/assets/voxygen/i18n/pt_BR/buff.ron +++ b/assets/voxygen/i18n/pt_BR/buff.ron @@ -38,7 +38,7 @@ "buff.desc.ensnared": "Trepadeiras agarram suas pernas, impedindo seus movimentos.", // Buffs stats "buff.stat.health": "Restaura {str_total} de Vida", - "buff.stat.increase_max_stamina": "Aumenta a Stamina Máxima em {strength}", + "buff.stat.increase_max_energy": "Aumenta a Stamina Máxima em {strength}", "buff.stat.increase_max_health": "Aumenta a Vida Máxima em {strength}", "buff.stat.invulnerability": "Concede invulnerabilidade", // Text diff --git a/assets/voxygen/i18n/pt_BR/hud/bag.ron b/assets/voxygen/i18n/pt_BR/hud/bag.ron index 175bc7e44e..11cbfcb6b4 100644 --- a/assets/voxygen/i18n/pt_BR/hud/bag.ron +++ b/assets/voxygen/i18n/pt_BR/hud/bag.ron @@ -30,7 +30,7 @@ "hud.bag.swap_equipped_weapons_desc": "Pressione {key}", "hud.bag.bag": "Mochila", "hud.bag.health": "Vida", - "hud.bag.stamina": "Stamina", + "hud.bag.energy": "Stamina", "hud.bag.combat_rating": "Pontuação de Combate", "hud.bag.protection": "Proteção", "hud.bag.stun_res": "Resistência à paralisia", diff --git a/assets/voxygen/i18n/pt_BR/skills.ron b/assets/voxygen/i18n/pt_BR/skills.ron index 493f6f139d..a2ea312e52 100644 --- a/assets/voxygen/i18n/pt_BR/skills.ron +++ b/assets/voxygen/i18n/pt_BR/skills.ron @@ -11,8 +11,8 @@ // Geral "hud.skill.inc_health_title": "Aumentar Saúde", "hud.skill.inc_health": "Aumentar saúde máxima por {boost}{SP}", - "hud.skill.inc_stam_title": "Aumentar Stamina", - "hud.skill.inc_stam": "Aumentar stamina máxima por {boost}{SP}", + "hud.skill.inc_energy_title": "Aumentar Stamina", + "hud.skill.inc_energy": "Aumentar stamina máxima por {boost}{SP}", "hud.skill.unlck_sword_title": "Desbloquear Espada", "hud.skill.unlck_sword": "Desbloquear habilidades de espada{SP}", "hud.skill.unlck_axe_title": "Desbloquear Machado", @@ -27,8 +27,8 @@ "hud.skill.unlck_sceptre": "Desbloquear Habilidades de Cetro{SP}", "hud.skill.dodge_title": "Esquiva", "hud.skill.dodge": "Esquivar evita ataques corpo a corpo{SP}", - "hud.skill.roll_stamina_title": "Custo de Stamina da Rolagem", - "hud.skill.roll_stamina": "Rolar usa {boost}% menos de stamina{SP}", + "hud.skill.roll_energy_title": "Custo de Stamina da Rolagem", + "hud.skill.roll_energy": "Rolar usa {boost}% menos de stamina{SP}", "hud.skill.roll_speed_title": "Velocidade da Rolagem", "hud.skill.roll_speed": "Rola {boost}% mais rápido{SP}", "hud.skill.roll_dur_title": "Duração da Rolagem", @@ -95,8 +95,8 @@ "hud.skill.st_flamethrower_damage" : "Aumenta o dano em {boost}%{SP}", "hud.skill.st_explosion_radius_title" : "Raio da Explosão", "hud.skill.st_explosion_radius" : "Quanto maior melhor, e o raio da explosão é aumentado em {boost}%{SP}", - "hud.skill.st_stamina_regen_title" : "Regeneração de stamina", - "hud.skill.st_stamina_regen" : "Aumenta o ganho de stamina em {boost}%{SP}", + "hud.skill.st_energy_regen_title" : "Regeneração de stamina", + "hud.skill.st_energy_regen" : "Aumenta o ganho de stamina em {boost}%{SP}", "hud.skill.st_fireball_title" : "Bola de fogo", "hud.skill.st_fireball" : "Brinque de perseguir seus inimigos", "hud.skill.st_damage_title" : "Dano", diff --git a/assets/voxygen/i18n/ru_RU/skills.ron b/assets/voxygen/i18n/ru_RU/skills.ron index e8de3706c2..1da764c4ff 100644 --- a/assets/voxygen/i18n/ru_RU/skills.ron +++ b/assets/voxygen/i18n/ru_RU/skills.ron @@ -11,8 +11,8 @@ // General "hud.skill.inc_health_title": "Повышение здоровья", "hud.skill.inc_health": "Увеличивает максимальное здоровье на {boost}{SP}", - "hud.skill.inc_stam_title": "Повышение Выносливости", - "hud.skill.inc_stam": "Увеличивает максимальную выносливость на {boost}{SP}", + "hud.skill.inc_energy_title": "Повышение Выносливости", + "hud.skill.inc_energy": "Увеличивает максимальную выносливость на {boost}{SP}", "hud.skill.unlck_sword_title": "Разблокировать меч", "hud.skill.unlck_sword": "Разблокировать древо навыков владения мечом{SP}", "hud.skill.unlck_axe_title": "Разблокировать топор", @@ -27,8 +27,8 @@ "hud.skill.unlck_sceptre": "Разблокировать древо навыков владения скипетром{SP}", "hud.skill.dodge_title": "Перекат", "hud.skill.dodge": "Перекат активируется средним щелчком мыши. Во время переката вы игнорируете урон ближнего боя.", - "hud.skill.roll_stamina_title": "Стоимость активации переката", - "hud.skill.roll_stamina": "Перекат использует на {boost}% меньше выносливости{SP}", + "hud.skill.roll_energy_title": "Стоимость активации переката", + "hud.skill.roll_energy": "Перекат использует на {boost}% меньше выносливости{SP}", "hud.skill.roll_speed_title": "Скорость переката", "hud.skill.roll_speed": "Перекат на {boost}% быстрее{SP}", "hud.skill.roll_dur_title": "Продолжительность переката", @@ -95,8 +95,8 @@ "hud.skill.st_flamethrower_damage" : "Урон больше на {boost}%{SP}", "hud.skill.st_explosion_radius_title" : "Радиус взрыва", "hud.skill.st_explosion_radius" : "Радиус взрыва больше на {boost}%{SP}", - "hud.skill.st_stamina_regen_title" : "Востановление выносливости", - "hud.skill.st_stamina_regen" : "Увеличивает прирост выносливости на {boost}%{SP}", + "hud.skill.st_energy_regen_title" : "Востановление выносливости", + "hud.skill.st_energy_regen" : "Увеличивает прирост выносливости на {boost}%{SP}", "hud.skill.st_fireball_title" : "Огненый шар", "hud.skill.st_fireball" : "Стреляет огненным шаром, который взрывается при ударе", "hud.skill.st_damage_title" : "Урон", diff --git a/assets/voxygen/i18n/sv/buff.ron b/assets/voxygen/i18n/sv/buff.ron index ea29b691d8..efc98bfbb6 100644 --- a/assets/voxygen/i18n/sv/buff.ron +++ b/assets/voxygen/i18n/sv/buff.ron @@ -38,7 +38,7 @@ "buff.desc.ensnared": "Rankor greppar tag i dina ben vilket begränsar dina rörelser.", // Buffs stats "buff.stat.health": "Återger {str_total} hälsa", - "buff.stat.increase_max_stamina": "Ökar max-uthålligheten med {strength}", + "buff.stat.increase_max_energy": "Ökar max-uthålligheten med {strength}", "buff.stat.increase_max_health": "Ökar maxhälsan med {strength}", "buff.stat.invulnerability": "Ger osårbarhet", // Text diff --git a/assets/voxygen/i18n/sv/hud/bag.ron b/assets/voxygen/i18n/sv/hud/bag.ron index 26be317f5e..42f8d8f7ba 100644 --- a/assets/voxygen/i18n/sv/hud/bag.ron +++ b/assets/voxygen/i18n/sv/hud/bag.ron @@ -30,7 +30,7 @@ "hud.bag.swap_equipped_weapons_desc": "Tryck {key}", "hud.bag.bag": "Säck", "hud.bag.health": "Hälsa", - "hud.bag.stamina": "Uthållighet", + "hud.bag.energy": "Uthållighet", "hud.bag.combat_rating": "Stridsduglighet", "hud.bag.protection": "Skydd", "hud.bag.stun_res": "Motståndskraft mot medvetslöshet", diff --git a/assets/voxygen/i18n/sv/skills.ron b/assets/voxygen/i18n/sv/skills.ron index 2605641c13..067a7b3965 100644 --- a/assets/voxygen/i18n/sv/skills.ron +++ b/assets/voxygen/i18n/sv/skills.ron @@ -11,8 +11,8 @@ // General "hud.skill.inc_health_title": "Mer hälsa", "hud.skill.inc_health": "Ökar maxhälsan med {boost}{SP}", - "hud.skill.inc_stam_title": "Ökad uthållighet", - "hud.skill.inc_stam": "Ökar max-uthålligheten med {boost}{SP}", + "hud.skill.inc_energy_title": "Ökad uthållighet", + "hud.skill.inc_energy": "Ökar max-uthålligheten med {boost}{SP}", "hud.skill.unlck_sword_title": "Lås upp svärd", "hud.skill.unlck_sword": "Låser upp färdighetsträdet för svärd{SP}", "hud.skill.unlck_axe_title": "Lås upp yxa", @@ -27,8 +27,8 @@ "hud.skill.unlck_sceptre": "Låser upp färdighetsträdet för spira{SP}", "hud.skill.dodge_title": "Ducka", "hud.skill.dodge": "Rulla åt sidan genom att mittenklicka och bli immun mot närstridsattacker under tiden du rullar.", - "hud.skill.roll_stamina_title": "Uthållighetskostnad för rullning", - "hud.skill.roll_stamina": "Rullning kostar {boost}% mindre uthållighet{SP}", + "hud.skill.roll_energy_title": "Uthållighetskostnad för rullning", + "hud.skill.roll_energy": "Rullning kostar {boost}% mindre uthållighet{SP}", "hud.skill.roll_speed_title": "Rullningshastighet", "hud.skill.roll_speed": "Ralla {boost}% fortare{SP}", "hud.skill.roll_dur_title": "Rullningstid", @@ -97,8 +97,8 @@ "hud.skill.st_flamethrower_damage" : "Orsakar {boost}% mer skada{SP}", "hud.skill.st_explosion_radius_title" : "Explosionsradie", "hud.skill.st_explosion_radius" : "Större är bättre, explosionsradien ökar med {boost}%{SP}", - "hud.skill.st_stamina_regen_title" : "Engergiåterhämtning", - "hud.skill.st_stamina_regen" : "Återhämta ytterligare {boost}% energi{SP}", + "hud.skill.st_energy_regen_title" : "Engergiåterhämtning", + "hud.skill.st_energy_regen" : "Återhämta ytterligare {boost}% energi{SP}", "hud.skill.st_fireball_title" : "Eldklot", "hud.skill.st_fireball" : "Skjuter ett eldklot som exploderar vid träff", "hud.skill.st_damage_title" : "Skada", diff --git a/assets/voxygen/i18n/uk_UA/buff.ron b/assets/voxygen/i18n/uk_UA/buff.ron index ce75cce748..ceb08de5bc 100644 --- a/assets/voxygen/i18n/uk_UA/buff.ron +++ b/assets/voxygen/i18n/uk_UA/buff.ron @@ -52,7 +52,7 @@ // Stats "buff.stat.health": "Відновлює {str_total} ОЗ", "buff.stat.increase_max_health": "Підвищує Максимальне Здоров'я на {strength}", - "buff.stat.increase_max_stamina": "Підвищує Максимальну Енергію на {strength}", + "buff.stat.increase_max_energy": "Підвищує Максимальну Енергію на {strength}", "buff.stat.invulnerability": "Дає невразливість", // Text "buff.text.for_seconds": "протягом {dur_secs} сек.", diff --git a/assets/voxygen/i18n/uk_UA/hud/bag.ron b/assets/voxygen/i18n/uk_UA/hud/bag.ron index f8c3ca571a..1a286d1a60 100644 --- a/assets/voxygen/i18n/uk_UA/hud/bag.ron +++ b/assets/voxygen/i18n/uk_UA/hud/bag.ron @@ -39,7 +39,7 @@ // Stats "hud.bag.health": "Здоров'я", - "hud.bag.stamina": "Енергія", + "hud.bag.energy": "Енергія", "hud.bag.combat_rating": "Бойовий рейтинг", "hud.bag.combat_rating_desc": "Розрахований з огляду на ваше\nспорядження і здоров'я", "hud.bag.protection": "Захист", diff --git a/assets/voxygen/i18n/uk_UA/skills.ron b/assets/voxygen/i18n/uk_UA/skills.ron index ab26355d0c..3c64c7c95a 100644 --- a/assets/voxygen/i18n/uk_UA/skills.ron +++ b/assets/voxygen/i18n/uk_UA/skills.ron @@ -11,8 +11,8 @@ // General "hud.skill.inc_health_title": "Збільшення здоров'я", "hud.skill.inc_health": "Збільшує максимальне здоров'я на {boost}{SP}", - "hud.skill.inc_stam_title": "Збільшення енергії", - "hud.skill.inc_stam": "Збільшує максимальну енергію на {boost}{SP}", + "hud.skill.inc_energy_title": "Збільшення енергії", + "hud.skill.inc_energy": "Збільшує максимальну енергію на {boost}{SP}", "hud.skill.unlck_sword_title": "Меч", "hud.skill.unlck_sword": "Відкриває дерево навичок володіння мечем{SP}", "hud.skill.unlck_axe_title": "Сокира", @@ -27,8 +27,8 @@ "hud.skill.unlck_sceptre": "Відкриває дерево навичок володіння цілющим скіпетром{SP}", "hud.skill.dodge_title": "Ухил", "hud.skill.dodge": "Станьте невразливим до ближніх атак під час перекиду{SP}", - "hud.skill.roll_stamina_title": "Енергоспоживання перекиду", - "hud.skill.roll_stamina": "Перекид споживає на {boost}% менше енергії{SP}", + "hud.skill.roll_energy_title": "Енергоспоживання перекиду", + "hud.skill.roll_energy": "Перекид споживає на {boost}% менше енергії{SP}", "hud.skill.roll_speed_title": "Швидкість перекиду", "hud.skill.roll_speed": "Перекид виконується на {boost}% швидше{SP}", "hud.skill.roll_dur_title": "Тривалість перекиду", @@ -116,8 +116,8 @@ "hud.skill.st_fireball_title": "Вогнений м'яч", "hud.skill.st_explosion_radius_title" : "Радіус вибуху", "hud.skill.st_explosion_radius" : "Більше - краще, збільшує радіус вибуху снарядів на {boost}%{SP}", - "hud.skill.st_stamina_regen_title" : "Відновлення енергії", - "hud.skill.st_stamina_regen" : "Збільшує відновлення енергії від заподіяних ушкоджень на {boost}%{SP}", + "hud.skill.st_energy_regen_title" : "Відновлення енергії", + "hud.skill.st_energy_regen" : "Збільшує відновлення енергії від заподіяних ушкоджень на {boost}%{SP}", "hud.skill.st_damage_title" : "Ушкодження снарядами", "hud.skill.st_damage" : "Збільшує ушкодження вогняними снарядами на {boost}%{SP}", // Bow diff --git a/assets/voxygen/i18n/zh_CN/buff.ron b/assets/voxygen/i18n/zh_CN/buff.ron index 64b0b7df0f..7efc477e8f 100644 --- a/assets/voxygen/i18n/zh_CN/buff.ron +++ b/assets/voxygen/i18n/zh_CN/buff.ron @@ -26,7 +26,7 @@ "buff.desc.cursed": "你被诅咒了.", // Buffs stats "buff.stat.health": "总共恢复 {str_total} 点生命值", - "buff.stat.increase_max_stamina": "提高{strength}点耐力值上限 ", + "buff.stat.increase_max_energy": "提高{strength}点耐力值上限 ", "buff.stat.increase_max_health": "提高{strength}点生命值上限", "buff.stat.invulnerability": "获得无敌状态", // Text diff --git a/assets/voxygen/i18n/zh_CN/hud/bag.ron b/assets/voxygen/i18n/zh_CN/hud/bag.ron index 32a3169e2a..45e6602221 100644 --- a/assets/voxygen/i18n/zh_CN/hud/bag.ron +++ b/assets/voxygen/i18n/zh_CN/hud/bag.ron @@ -26,7 +26,7 @@ "hud.bag.offhand": "副手", "hud.bag.bag": "背包", "hud.bag.health": "血量", - "hud.bag.stamina": "耐力", + "hud.bag.energy": "耐力", "hud.bag.combat_rating": "战力", "hud.bag.protection": "防御", "hud.bag.stun_res": "韧性恢复", diff --git a/assets/voxygen/i18n/zh_CN/skills.ron b/assets/voxygen/i18n/zh_CN/skills.ron index fd35f09502..7a3e1840bd 100644 --- a/assets/voxygen/i18n/zh_CN/skills.ron +++ b/assets/voxygen/i18n/zh_CN/skills.ron @@ -11,8 +11,8 @@ // General "hud.skill.inc_health_title": "增强生命", "hud.skill.inc_health": "最大生命值提高{boost}{SP}", - "hud.skill.inc_stam_title": "增强耐力/法力", - "hud.skill.inc_stam": "最大耐力提升{boost}{SP}", + "hud.skill.inc_energy_title": "增强耐力/法力", + "hud.skill.inc_energy": "最大耐力提升{boost}{SP}", "hud.skill.unlck_sword_title": "解锁双手剑专精", "hud.skill.unlck_sword": "解锁双手剑技能树{SP}", "hud.skill.unlck_axe_title": "解锁双手斧专精", @@ -27,8 +27,8 @@ "hud.skill.unlck_sceptre": "解锁生命权杖技能树{SP}", "hud.skill.dodge_title": "闪避", "hud.skill.dodge": "翻滚可以躲避敌人的攻击{SP}", - "hud.skill.roll_stamina_title": "体术(翻滚)", - "hud.skill.roll_stamina": "减少每次翻滚需要消耗的耐力{boost}%{SP}", + "hud.skill.roll_energy_title": "体术(翻滚)", + "hud.skill.roll_energy": "减少每次翻滚需要消耗的耐力{boost}%{SP}", "hud.skill.roll_speed_title": "迅捷", "hud.skill.roll_speed": "加快{boost}%的翻滚速度{SP}", "hud.skill.roll_dur_title": "飞身跃入", @@ -95,8 +95,8 @@ "hud.skill.st_flamethrower_damage" : "吐息造成的伤害提高{boost}%{SP}", "hud.skill.st_explosion_radius_title" : "爆破专家", "hud.skill.st_explosion_radius" : "火球爆炸的半径扩大{boost}%{SP}", - "hud.skill.st_stamina_regen_title" : "法力回复", - "hud.skill.st_stamina_regen" : "每次击中敌人回复的法力增加{boost}%{SP}", + "hud.skill.st_energy_regen_title" : "法力回复", + "hud.skill.st_energy_regen" : "每次击中敌人回复的法力增加{boost}%{SP}", "hud.skill.st_fireball_title" : "火球术", "hud.skill.st_fireball" : "发射火球攻击敌人", "hud.skill.st_damage_title" : "伤害提升", diff --git a/common/src/comp/buff.rs b/common/src/comp/buff.rs index 7e889c70ef..a8640f6a10 100644 --- a/common/src/comp/buff.rs +++ b/common/src/comp/buff.rs @@ -29,7 +29,7 @@ pub enum BuffKind { /// Applied when sitting at a campfire /// Strength is fraction of health resotred per second CampfireHeal, - /// Raises maximum stamina + /// Raises maximum energy /// Strength should be 10x the effect to max energy IncreaseMaxEnergy, /// Raises maximum health @@ -146,7 +146,7 @@ pub enum BuffEffect { }, /// Changes maximum health by a certain amount MaxHealthModifier { value: f32, kind: ModifierKind }, - /// Changes maximum stamina by a certain amount + /// Changes maximum energy by a certain amount MaxEnergyModifier { value: f32, kind: ModifierKind }, /// Reduces damage after armor is accounted for by this fraction DamageReduction(f32), diff --git a/voxygen/src/hud/bag.rs b/voxygen/src/hud/bag.rs index 4a21b416db..a3c676dc33 100644 --- a/voxygen/src/hud/bag.rs +++ b/voxygen/src/hud/bag.rs @@ -533,7 +533,7 @@ impl<'a> Bag<'a> { } const STATS: [&str; 5] = [ "Health", - "Stamina", + "Energy", "Protection", "Combat Rating", "Stun Resilience", @@ -809,7 +809,7 @@ impl<'a> Widget for Bag<'a> { for i in STATS.iter().copied().enumerate() { let btn = Button::image(match i.1 { "Health" => self.imgs.health_ico, - "Stamina" => self.imgs.stamina_ico, + "Energy" => self.imgs.energy_ico, "Combat Rating" => self.imgs.combat_rating_ico, "Protection" => self.imgs.protection_ico, "Stun Resilience" => self.imgs.stun_res_ico, @@ -828,7 +828,7 @@ impl<'a> Widget for Bag<'a> { as i32 ); let health_txt = format!("{}", (self.health.maximum() as f32 / 10.0) as usize); - let stamina_txt = format!("{}", (self.energy.maximum() as f32 / 10.0) as usize); + let energy_txt = format!("{}", (self.energy.maximum() as f32 / 10.0) as usize); let combat_rating_txt = format!("{}", (combat_rating * 10.0) as usize); let stun_res_txt = format!( "{}", @@ -841,7 +841,7 @@ impl<'a> Widget for Bag<'a> { }; let tooltip_head = match i.1 { "Health" => i18n.get("hud.bag.health"), - "Stamina" => i18n.get("hud.bag.stamina"), + "Energy" => i18n.get("hud.bag.energy"), "Combat Rating" => i18n.get("hud.bag.combat_rating"), "Protection" => i18n.get("hud.bag.protection"), "Stun Resilience" => i18n.get("hud.bag.stun_res"), @@ -863,7 +863,7 @@ impl<'a> Widget for Bag<'a> { .set(state.ids.stat_icons[i.0], ui); Text::new(match i.1 { "Health" => &health_txt, - "Stamina" => &stamina_txt, + "Energy" => &energy_txt, "Combat Rating" => &combat_rating_txt, "Protection" => &protection_txt, "Stun Resilience" => &stun_res_txt, diff --git a/voxygen/src/hud/buffs.rs b/voxygen/src/hud/buffs.rs index 393dd06fc0..da63a601c3 100644 --- a/voxygen/src/hud/buffs.rs +++ b/voxygen/src/hud/buffs.rs @@ -129,10 +129,10 @@ impl<'a> Widget for BuffsBar<'a> { let decayed_health = 1.0 - self.health.maximum() as f64 / self.health.base_max() as f64; let show_health = self.health.current() != self.health.maximum() || decayed_health > 0.0; - let show_stamina = self.energy.current() != self.energy.maximum(); - let offset = if show_stamina && show_health { + let show_energy = self.energy.current() != self.energy.maximum(); + let offset = if show_energy && show_health { 140.0 - } else if show_health || show_stamina { + } else if show_health || show_energy { 95.0 } else { 55.0 diff --git a/voxygen/src/hud/diary.rs b/voxygen/src/hud/diary.rs index da5af98b50..a53f4728c5 100644 --- a/voxygen/src/hud/diary.rs +++ b/voxygen/src/hud/diary.rs @@ -739,9 +739,9 @@ impl<'a> Widget for Diary<'a> { ); self.create_unlock_skill_button( Skill::General(EnergyIncrease), - self.imgs.stamina_plus_skill, + self.imgs.energy_plus_skill, state.skills_top_l[1], - "inc_stam", + "inc_energy", state.skill_general_stat_1, ui, &mut events, @@ -824,7 +824,7 @@ impl<'a> Widget for Diary<'a> { Skill::Roll(RollSkill::Cost), self.imgs.utility_cost_skill, state.skills_bot_l[1], - "roll_stamina", + "roll_energy", state.skill_general_roll_1, ui, &mut events, @@ -1699,7 +1699,7 @@ impl<'a> Widget for Diary<'a> { Skill::Staff(BRegen), self.imgs.magic_energy_regen_skill, state.skills_top_l[2], - "st_stamina_regen", + "st_energy_regen", state.skill_staff_basic_2, ui, &mut events, diff --git a/voxygen/src/hud/group.rs b/voxygen/src/hud/group.rs index 71fb4a5f56..506501fe2b 100644 --- a/voxygen/src/hud/group.rs +++ b/voxygen/src/hud/group.rs @@ -53,7 +53,7 @@ widget_ids! { member_panels_txt[], member_health[], member_health_decay[], - member_stam[], + member_energy[], buffs[], buff_timers[], dead_txt[], @@ -297,10 +297,10 @@ impl<'a> Widget for Group<'a> { .resize(group_size, &mut ui.widget_id_generator()); }) }; - if state.ids.member_stam.len() < group_size { + if state.ids.member_energy.len() < group_size { state.update(|s| { s.ids - .member_stam + .member_energy .resize(group_size, &mut ui.widget_id_generator()) }) }; @@ -485,12 +485,12 @@ impl<'a> Widget for Group<'a> { .set(state.ids.member_panels_txt[i], ui); if let Some(energy) = energy { let stam_perc = energy.current() as f64 / energy.maximum() as f64; - // Stamina + // Energy Image::new(self.imgs.bar_content) .w_h(100.0 * stam_perc, 8.0) .color(Some(STAMINA_COLOR)) .top_left_with_margins_on(state.ids.member_panels_bg[i], 26.0, 2.0) - .set(state.ids.member_stam[i], ui); + .set(state.ids.member_energy[i], ui); } if let Some(buffs) = buffs { // Limit displayed buffs to 11 diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index 55eaa73b5a..ba0badbcbe 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -187,7 +187,7 @@ image_ids! { // Skilltree Icons health_plus_skill: "voxygen.element.skills.skilltree.health_plus", - stamina_plus_skill: "voxygen.element.skills.skilltree.stamina_plus", + energy_plus_skill: "voxygen.element.skills.skilltree.energy_plus", unlock_axe_skill: "voxygen.element.skills.skilltree.unlock_axe", unlock_bow_skill: "voxygen.element.skills.skilltree.unlock_bow", unlock_hammer_skill: "voxygen.element.skills.skilltree.unlock_hammer", @@ -318,8 +318,8 @@ image_ids! { health_bg: "voxygen.element.ui.skillbar.health_bg", health_frame: "voxygen.element.ui.skillbar.health_frame", decayed_bg: "voxygen.element.ui.skillbar.decayed_bg", - stamina_bg: "voxygen.element.ui.skillbar.stamina_bg", - stamina_frame: "voxygen.element.ui.skillbar.stamina_frame", + energy_bg: "voxygen.element.ui.skillbar.energy_bg", + energy_frame: "voxygen.element.ui.skillbar.energy_frame", m1_ico: "voxygen.element.ui.generic.icons.m1", m2_ico: "voxygen.element.ui.generic.icons.m2", m_scroll_ico: "voxygen.element.ui.generic.icons.m_scroll", @@ -476,7 +476,7 @@ image_ids! { mainhand_bg: "voxygen.element.ui.bag.backgrounds.mainhand", bag_bg: "voxygen.element.ui.bag.backgrounds.bag", offhand_bg: "voxygen.element.ui.bag.backgrounds.offhand", - stamina_ico: "voxygen.element.ui.bag.icons.stamina", + energy_ico: "voxygen.element.ui.bag.icons.energy", health_ico: "voxygen.element.ui.bag.icons.health", protection_ico: "voxygen.element.ui.bag.icons.protection", stun_res_ico: "voxygen.element.ui.bag.icons.stun_res", diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 4a3b4693ba..5250e94d69 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -3943,7 +3943,7 @@ pub fn get_buff_title(buff: BuffKind, localized_strings: &Localization) -> &str BuffKind::Potion { .. } => localized_strings.get("buff.title.potion"), BuffKind::CampfireHeal { .. } => localized_strings.get("buff.title.campfire_heal"), BuffKind::IncreaseMaxHealth { .. } => localized_strings.get("buff.title.IncreaseMaxHealth"), - BuffKind::IncreaseMaxEnergy { .. } => localized_strings.get("buff.title.staminaup"), + BuffKind::IncreaseMaxEnergy { .. } => localized_strings.get("buff.title.energyup"), BuffKind::Invulnerability => localized_strings.get("buff.title.invulnerability"), BuffKind::ProtectingWard => localized_strings.get("buff.title.protectingward"), BuffKind::Frenzied => localized_strings.get("buff.title.frenzied"), diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs index 07eae60057..d1777b47af 100644 --- a/voxygen/src/hud/skillbar.rs +++ b/voxygen/src/hud/skillbar.rs @@ -58,8 +58,8 @@ widget_ids! { frame, bg_health, frame_health, - bg_stamina, - frame_stamina, + bg_energy, + frame_energy, m1_ico, m2_ico, // Level @@ -76,12 +76,12 @@ widget_ids! { hp_txt_bg, hp_txt, decay_overlay, - // Stamina-Bar - stamina_alignment, - stamina_filling, - stamina_txt_alignment, - stamina_txt_bg, - stamina_txt, + // Energy-Bar + energy_alignment, + energy_filling, + energy_txt_alignment, + energy_txt_bg, + energy_txt, // Combo Counter combo_align, combo_bg, @@ -379,7 +379,7 @@ impl<'a> Skillbar<'a> { let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani); let bar_values = self.global_state.settings.interface.bar_numbers; let show_health = self.health.current() != self.health.maximum(); - let show_stamina = self.energy.current() != self.energy.maximum(); + let show_energy = self.energy.current() != self.energy.maximum(); let decayed_health = 1.0 - self.health.maximum() as f64 / self.health.base_max() as f64; if show_health && !self.health.is_dead || decayed_health > 0.0 { @@ -424,29 +424,29 @@ impl<'a> Skillbar<'a> { .middle_of(state.ids.bg_health) .set(state.ids.frame_health, ui); } - if show_stamina && !self.health.is_dead { + if show_energy && !self.health.is_dead { let offset = if show_health || decayed_health > 0.0 { 34.0 } else { 1.0 }; - Image::new(self.imgs.stamina_bg) + Image::new(self.imgs.energy_bg) .w_h(323.0, 16.0) .mid_top_with_margin_on(state.ids.frame, -offset) - .set(state.ids.bg_stamina, ui); + .set(state.ids.bg_energy, ui); Rectangle::fill_with([319.0, 10.0], color::TRANSPARENT) - .top_left_with_margins_on(state.ids.bg_stamina, 2.0, 2.0) - .set(state.ids.stamina_alignment, ui); + .top_left_with_margins_on(state.ids.bg_energy, 2.0, 2.0) + .set(state.ids.energy_alignment, ui); Image::new(self.imgs.bar_content) .w_h(319.0 * energy_percentage / 100.0, 10.0) .color(Some(STAMINA_COLOR)) - .top_left_with_margins_on(state.ids.stamina_alignment, 0.0, 0.0) - .set(state.ids.stamina_filling, ui); - Image::new(self.imgs.stamina_frame) + .top_left_with_margins_on(state.ids.energy_alignment, 0.0, 0.0) + .set(state.ids.energy_filling, ui); + Image::new(self.imgs.energy_frame) .w_h(323.0, 16.0) .color(Some(UI_HIGHLIGHT_0)) - .middle_of(state.ids.bg_stamina) - .set(state.ids.frame_stamina, ui); + .middle_of(state.ids.bg_energy) + .set(state.ids.frame_energy, ui); } // Bar Text let bar_text = if self.health.is_dead { @@ -491,17 +491,17 @@ impl<'a> Skillbar<'a> { .set(state.ids.hp_txt, ui); Text::new(&energy_txt) - .middle_of(state.ids.frame_stamina) + .middle_of(state.ids.frame_energy) .font_size(self.fonts.cyri.scale(12)) .font_id(self.fonts.cyri.conrod_id) .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) - .set(state.ids.stamina_txt_bg, ui); + .set(state.ids.energy_txt_bg, ui); Text::new(&energy_txt) - .bottom_left_with_margins_on(state.ids.stamina_txt_bg, 2.0, 2.0) + .bottom_left_with_margins_on(state.ids.energy_txt_bg, 2.0, 2.0) .font_size(self.fonts.cyri.scale(12)) .font_id(self.fonts.cyri.conrod_id) .color(TEXT_COLOR) - .set(state.ids.stamina_txt, ui); + .set(state.ids.energy_txt, ui); } } @@ -873,7 +873,7 @@ impl<'a> Widget for Skillbar<'a> { .mid_bottom_with_margin_on(ui.window, 10.0) .set(state.ids.frame, ui); - // Health and Stamina bar + // Health and Energy bar self.show_stat_bars(state, ui); // Slots diff --git a/voxygen/src/hud/util.rs b/voxygen/src/hud/util.rs index 0b7342abf1..3e368eacab 100644 --- a/voxygen/src/hud/util.rs +++ b/voxygen/src/hud/util.rs @@ -148,7 +148,7 @@ pub fn consumable_desc(effects: &[Effect], i18n: &Localization) -> Vec { .get("buff.stat.health") .replace("{str_total}", &str_total.to_string()), BuffKind::IncreaseMaxEnergy => i18n - .get("buff.stat.increase_max_stamina") + .get("buff.stat.increase_max_energy") .replace("{strength}", &strength.to_string()), BuffKind::IncreaseMaxHealth => i18n .get("buff.stat.increase_max_health") From c5c8ae4d302ffcd2212624c5e643df604f6a4a75 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 31 Jul 2021 01:05:07 -0400 Subject: [PATCH 030/155] Replace `stamina -> energy` in english localization strings --- CHANGELOG.md | 2 +- assets/voxygen/i18n/en/buff.ron | 2 +- assets/voxygen/i18n/en/hud/bag.ron | 4 ++-- assets/voxygen/i18n/en/skills.ron | 34 +++++++++++++++--------------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dd827d282..face6f139a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,7 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Trades now consider if items can stack in full inventories. - The types of animals that can be tamed as pets are now limited to certain species, pending further balancing of pets - Made server-cli admin add/remove command use positional arguments again - +- Usage of "stamina" replaced with "energy" ### Removed diff --git a/assets/voxygen/i18n/en/buff.ron b/assets/voxygen/i18n/en/buff.ron index 1e41ca4b08..8b63f58575 100644 --- a/assets/voxygen/i18n/en/buff.ron +++ b/assets/voxygen/i18n/en/buff.ron @@ -38,7 +38,7 @@ "buff.desc.ensnared": "Vines grasp at your legs, impeding your movement.", // Buffs stats "buff.stat.health": "Restores {str_total} Health", - "buff.stat.increase_max_energy": "Raises Maximum Stamina by {strength}", + "buff.stat.increase_max_energy": "Raises Maximum Energy by {strength}", "buff.stat.increase_max_health": "Raises Maximum Health by {strength}", "buff.stat.invulnerability": "Grants invulnerability", // Text diff --git a/assets/voxygen/i18n/en/hud/bag.ron b/assets/voxygen/i18n/en/hud/bag.ron index ef65866ccd..b427d18147 100644 --- a/assets/voxygen/i18n/en/hud/bag.ron +++ b/assets/voxygen/i18n/en/hud/bag.ron @@ -30,13 +30,13 @@ "hud.bag.swap_equipped_weapons_desc": "Press {key}", "hud.bag.bag": "Bag", "hud.bag.health": "Health", - "hud.bag.energy": "Stamina", + "hud.bag.energy": "Energy", "hud.bag.combat_rating": "Combat Rating", "hud.bag.protection": "Protection", "hud.bag.stun_res": "Stun Resilience", "hud.bag.combat_rating_desc": "Calculated from your\nequipment and health.", "hud.bag.protection_desc": "Damage reduction through armor", - "hud.bag.stun_res_desc": "Resilience against being stunned by consecutive hits.\nRegenerates like Stamina.", + "hud.bag.stun_res_desc": "Resilience against being stunned by consecutive hits.\nRegenerates like Energy.", "hud.bag.sort_by_name": "Sort by Name", "hud.bag.sort_by_quality": "Sort by Quality", "hud.bag.sort_by_category": "Sort by Category", diff --git a/assets/voxygen/i18n/en/skills.ron b/assets/voxygen/i18n/en/skills.ron index 1c8b9eaa4d..de0fd8aced 100644 --- a/assets/voxygen/i18n/en/skills.ron +++ b/assets/voxygen/i18n/en/skills.ron @@ -11,8 +11,8 @@ // General "hud.skill.inc_health_title": "Increase Health", "hud.skill.inc_health": "Increases max health by {boost}{SP}", - "hud.skill.inc_energy_title": "Increase Stamina", - "hud.skill.inc_energy": "Increases max stamina by {boost}{SP}", + "hud.skill.inc_energy_title": "Increase Energy", + "hud.skill.inc_energy": "Increases max energy by {boost}{SP}", "hud.skill.unlck_sword_title": "Unlock Sword", "hud.skill.unlck_sword": "Unlocks sword skill tree{SP}", "hud.skill.unlck_axe_title": "Unlock Axe", @@ -27,8 +27,8 @@ "hud.skill.unlck_sceptre": "Unlocks sceptre skill tree{SP}", "hud.skill.dodge_title": "Dodge", "hud.skill.dodge": "Dodge rolls are triggered with middle-click, and grant temporary immunity to melee attacks (iframes) while you're rolling.", - "hud.skill.roll_energy_title": "Roll Stamina Cost", - "hud.skill.roll_energy": "Rolling uses {boost}% less stamina{SP}", + "hud.skill.roll_energy_title": "Roll Energy Cost", + "hud.skill.roll_energy": "Rolling uses {boost}% less energy{SP}", "hud.skill.roll_speed_title": "Rolling Speed", "hud.skill.roll_speed": "Roll {boost}% faster{SP}", "hud.skill.roll_dur_title": "Rolling Duration", @@ -36,7 +36,7 @@ "hud.skill.climbing_title": "Climbing", "hud.skill.climbing": "Jumping higher", "hud.skill.climbing_cost_title": "Climbing Cost", - "hud.skill.climbing_cost": "Climbing uses {boost}% less stamina{SP}", + "hud.skill.climbing_cost": "Climbing uses {boost}% less energy{SP}", "hud.skill.climbing_speed_title": "Climbing Speed", "hud.skill.climbing_speed": "Climb {boost}% faster{SP}", "hud.skill.swim_title": "Swimming", @@ -52,14 +52,14 @@ "hud.skill.sc_lifesteal_range": "Your beam reaches {boost}% further{SP}", "hud.skill.sc_lifesteal_lifesteal_title": "Lifesteal", "hud.skill.sc_lifesteal_lifesteal": "Convert an additional {boost}% of damage into health{SP}", - "hud.skill.sc_lifesteal_regen_title": "Stamina Regen", - "hud.skill.sc_lifesteal_regen": "Replenish your stamina by an additional {boost}%{SP}", + "hud.skill.sc_lifesteal_regen_title": "Energy Regen", + "hud.skill.sc_lifesteal_regen": "Replenish your energy by an additional {boost}%{SP}", "hud.skill.sc_heal_title": "Healing Aura", "hud.skill.sc_heal": "Heal your allies using the blood of your enemies, requires combo to activate", "hud.skill.sc_heal_heal_title": "Heal", "hud.skill.sc_heal_heal": "Increases the amount you heal by {boost}%{SP}", - "hud.skill.sc_heal_cost_title": "Stamina Cost", - "hud.skill.sc_heal_cost": "Healing requires {boost}% less stamina{SP}", + "hud.skill.sc_heal_cost_title": "Energy Cost", + "hud.skill.sc_heal_cost": "Healing requires {boost}% less energy{SP}", "hud.skill.sc_heal_duration_title": "Duration", "hud.skill.sc_heal_duration": "The effects of your healing aura last {boost}% longer{SP}", "hud.skill.sc_heal_range_title": "Radius", @@ -72,7 +72,7 @@ "hud.skill.sc_wardaura_duration": "The effects of your ward last {boost}% longer{SP}", "hud.skill.sc_wardaura_range_title": "Radius", "hud.skill.sc_wardaura_range": "Your ward reaches {boost}% further{SP}", - "hud.skill.sc_wardaura_cost_title": "Stamina Cost", + "hud.skill.sc_wardaura_cost_title": "Energy Cost", "hud.skill.sc_wardaura_cost": "Creating the ward requries {boost}% less energy{SP}", // Staff "hud.skill.st_shockwave_range_title" : "Shockwave Range", @@ -97,8 +97,8 @@ "hud.skill.st_flamethrower_damage" : "Increases damage by {boost}%{SP}", "hud.skill.st_explosion_radius_title" : "Explosion Radius", "hud.skill.st_explosion_radius" : "Bigger is better, increases explosion radius by {boost}%{SP}", - "hud.skill.st_energy_regen_title" : "Stamina Regen", - "hud.skill.st_energy_regen" : "Increases stamina gain by {boost}%{SP}", + "hud.skill.st_energy_regen_title" : "Energy Regen", + "hud.skill.st_energy_regen" : "Increases energy gain by {boost}%{SP}", "hud.skill.st_fireball_title" : "Fireball", "hud.skill.st_fireball" : "Shoots a fireball that explodes on impact", "hud.skill.st_damage_title" : "Damage", @@ -111,7 +111,7 @@ "hud.skill.bow_charged_damage_title" : "Charged Damage", "hud.skill.bow_charged_damage" : "Increases damage by {boost}%{SP}", "hud.skill.bow_charged_energy_regen_title" : "Charged Regen", - "hud.skill.bow_charged_energy_regen" : "Increases stamina recovery by {boost}%{SP}", + "hud.skill.bow_charged_energy_regen" : "Increases energy recovery by {boost}%{SP}", "hud.skill.bow_charged_knockback_title" : "Charged Knockback", "hud.skill.bow_charged_knockback" : "Knock enemies further back by {boost}%{SP}", "hud.skill.bow_charged_speed_title" : "Charged Speed", @@ -162,7 +162,7 @@ "hud.skill.hmr_single_strike_title" : "Single Strike", "hud.skill.hmr_single_strike" : "As single as you are", "hud.skill.hmr_single_strike_regen_title" : "Single Strike Regen", - "hud.skill.hmr_single_strike_regen" : "Increases stamina gain with each successive strike{SP}", + "hud.skill.hmr_single_strike_regen" : "Increases energy gain with each successive strike{SP}", "hud.skill.hmr_single_strike_speed_title" : "Single Strike Speed", "hud.skill.hmr_single_strike_speed" : "Increases the attack speed with each successive strike{SP}", "hud.skill.hmr_single_strike_damage_title" : "Single Strike Damage", @@ -180,7 +180,7 @@ "hud.skill.sw_trip_str_sp_title": "Triple Strike Speed", "hud.skill.sw_trip_str_sp": "Increases attack speed gained by each successive strike{SP}", "hud.skill.sw_trip_str_reg_title": "Triple Strike Regen", - "hud.skill.sw_trip_str_reg": "Increases stamina gain on each successive strike{SP}", + "hud.skill.sw_trip_str_reg": "Increases energy gain on each successive strike{SP}", "hud.skill.sw_dash_title": "Dash", "hud.skill.sw_dash": "Pin through your enemies", "hud.skill.sw_dash_dmg_title": "Dash Damage", @@ -217,7 +217,7 @@ "hud.skill.axe_double_strike_speed_title": "Double Strike Speed", "hud.skill.axe_double_strike_speed": "Increases the attack speed with each successive strike{SP}", "hud.skill.axe_double_strike_regen_title": "Double Strike Regen", - "hud.skill.axe_double_strike_regen": "Increases stamina gain with each successive strike{SP}", + "hud.skill.axe_double_strike_regen": "Increases energy gain with each successive strike{SP}", "hud.skill.axe_spin_title": "Axe Spin", "hud.skill.axe_spin": "You spin it right round ...", "hud.skill.axe_infinite_axe_spin_title": "Infinite Axe Spin", @@ -229,7 +229,7 @@ "hud.skill.axe_spin_speed_title": "Spin Speed", "hud.skill.axe_spin_speed": "Increases your spin speed by {boost}%{SP}", "hud.skill.axe_spin_cost_title": "Spin Cost", - "hud.skill.axe_spin_cost": "Decreases stamina cost of spinning by {boost}%{SP}", + "hud.skill.axe_spin_cost": "Decreases energy cost of spinning by {boost}%{SP}", "hud.skill.axe_unlock_leap_title": "Unlock Leap", "hud.skill.axe_unlock_leap": "Unlocks a leap spin{SP}", "hud.skill.axe_leap_damage_title": "Leap Damage", From f3d0d3f46a03e778c29d59d00919345941bf21fa Mon Sep 17 00:00:00 2001 From: Monty Marz Date: Sat, 31 Jul 2021 18:17:34 +0200 Subject: [PATCH 031/155] fix i18n --- assets/voxygen/i18n/de_DE/common.ron | 2 ++ voxygen/src/menu/char_selection/ui/mod.rs | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/assets/voxygen/i18n/de_DE/common.ron b/assets/voxygen/i18n/de_DE/common.ron index 856412b251..5a25a5e77e 100644 --- a/assets/voxygen/i18n/de_DE/common.ron +++ b/assets/voxygen/i18n/de_DE/common.ron @@ -60,6 +60,8 @@ Ist das Spiel auf dem neusten Stand?"#, "common.weapons.axe": "Axt", "common.weapons.sword": "Schwert", + "common.weapons.greatsword": "Zweihänder", + "common.weapons.shortswords": "Kurzschwerter", "common.weapons.staff": "Stab", "common.weapons.bow": "Bogen", "common.weapons.hammer": "Hammer", diff --git a/voxygen/src/menu/char_selection/ui/mod.rs b/voxygen/src/menu/char_selection/ui/mod.rs index 083086848c..2561f3bb90 100644 --- a/voxygen/src/menu/char_selection/ui/mod.rs +++ b/voxygen/src/menu/char_selection/ui/mod.rs @@ -909,8 +909,7 @@ impl Controls { *mainhand == Some(STARTER_SWORDS), Message::Tool((Some(STARTER_SWORDS), Some(STARTER_SWORDS))), imgs.swords, - "common.weapons.greatsword - ", + "common.weapons.shortswords", ) .into(), icon_button_tooltip( From 422e1c30f480afa15d28674db6c7217a6ecd393d Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 31 Jul 2021 20:33:28 +0100 Subject: [PATCH 032/155] Added menacing, made agent code less hacky --- CHANGELOG.md | 1 + assets/voxygen/i18n/en/_manifest.ron | 14 +- common/src/comp/agent.rs | 146 +++++---- common/src/comp/controller.rs | 5 +- server/src/events/interaction.rs | 4 +- server/src/settings.rs | 1 + server/src/sys/agent.rs | 427 ++++++++++++++++----------- server/src/sys/terrain.rs | 2 +- 8 files changed, 356 insertions(+), 244 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dd827d282..7fe6a1ebd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Pets are now saved on logout 🐕 🦎 🐼 - Dualwielded, one-handed swords as starting weapons (Will be replaced by daggers in the future!) - Healing sceptre crafting recipe +- NPCs can now warn players before engaging in combat ### Changed diff --git a/assets/voxygen/i18n/en/_manifest.ron b/assets/voxygen/i18n/en/_manifest.ron index 087c8d13ef..07d2ef3c07 100644 --- a/assets/voxygen/i18n/en/_manifest.ron +++ b/assets/voxygen/i18n/en/_manifest.ron @@ -42,7 +42,7 @@ "You can type /region or /r to only chat with players a couple of hundred blocks around you.", "Admins can use the /build command to enter build mode.", "You can type /group or /g to only chat with players in your current group.", - "To send private messages type /tell followed by a player name and your message.", + "To send private messages type /tell followed by a player name and your message.", "Keep an eye out for food, chests and other loot spread all around the world!", "Inventory filled with food? Try crafting better food from it!", "Wondering what there is to do? Try out one of the dungeons marked on the map!", @@ -52,7 +52,7 @@ "Press 'L-Shift' to open your Glider and conquer the skies.", "Veloren is still in Pre-Alpha. We do our best to improve it every day!", "If you want to join the dev team or just have a chat with us, join our Discord server.", - "You can toggle showing your amount of health on the healthbar in the settings.", + "You can toggle showing your amount of health on the healthbar in the settings.", "Sit near a campfire (with the 'K' key) to slowly recover from your injuries.", "Need more bags or better armor to continue your journey? Press 'C' to open the crafting menu!", "Try jumping when rolling through creatures.", @@ -228,6 +228,14 @@ "I have destroyed my enemy!", "Finally at peace!", "... now what was I doing?", - ] + ], + "npc.speech.menacing": [ + "I'm warning you!", + "Any closer and I'll attack!", + "You don't scare me!", + "Get away from here!", + "Turn around if you want to live!", + "You're not welcome here!", + ], } ) diff --git a/common/src/comp/agent.rs b/common/src/comp/agent.rs index ba42292175..7226c44a9c 100644 --- a/common/src/comp/agent.rs +++ b/common/src/comp/agent.rs @@ -15,7 +15,6 @@ use super::dialogue::Subject; pub const DEFAULT_INTERACTION_TIME: f32 = 1.0; pub const TRADE_INTERACTION_TIME: f32 = 300.0; -pub const MAX_LISTEN_DIST: f32 = 100.0; #[derive(Copy, Clone, Debug, PartialEq, Deserialize)] pub enum Alignment { @@ -43,6 +42,8 @@ impl Alignment { // Always attacks pub fn hostile_towards(self, other: Alignment) -> bool { match (self, other) { + (Alignment::Passive, _) => false, + (_, Alignment::Passive) => false, (Alignment::Enemy, Alignment::Enemy) => false, (Alignment::Enemy, Alignment::Wild) => false, (Alignment::Wild, Alignment::Enemy) => false, @@ -167,85 +168,107 @@ impl Behavior { #[derive(Clone, Debug, Default)] pub struct Psyche { - pub aggro: f32, // 0.0 = always flees, 1.0 = always attacks, 0.5 = flee at 50% health + /// The proportion of health below which entities will start fleeing. + /// 0.0 = never flees, 1.0 = always flees, 0.5 = flee at 50% health. + pub flee_health: f32, + /// The distance below which the agent will see enemies if it has line of + /// sight. + pub sight_dist: f32, + /// The distance below which the agent can hear enemies without seeing them. + pub listen_dist: f32, + /// The distance below which the agent will attack enemies. Should be lower + /// than `sight_dist`. `None` implied that the agent is always aggro + /// towards enemies that it is aware of. + pub aggro_dist: Option, } impl<'a> From<&'a Body> for Psyche { fn from(body: &'a Body) -> Self { Self { - aggro: match body { + flee_health: match body { Body::Humanoid(humanoid) => match humanoid.species { - humanoid::Species::Danari => 0.9, - humanoid::Species::Dwarf => 0.8, - humanoid::Species::Elf => 0.7, - humanoid::Species::Human => 0.6, - humanoid::Species::Orc => 0.9, - humanoid::Species::Undead => 0.9, + humanoid::Species::Danari => 0.1, + humanoid::Species::Dwarf => 0.2, + humanoid::Species::Elf => 0.3, + humanoid::Species::Human => 0.4, + humanoid::Species::Orc => 0.1, + humanoid::Species::Undead => 0.1, }, Body::QuadrupedSmall(quadruped_small) => match quadruped_small.species { quadruped_small::Species::Pig => 0.5, - quadruped_small::Species::Fox => 0.3, + quadruped_small::Species::Fox => 0.7, quadruped_small::Species::Sheep => 0.5, - quadruped_small::Species::Boar => 0.8, - quadruped_small::Species::Jackalope => 0.4, - quadruped_small::Species::Skunk => 0.6, - quadruped_small::Species::Cat => 0.2, - quadruped_small::Species::Batfox => 0.6, - quadruped_small::Species::Raccoon => 0.4, - quadruped_small::Species::Quokka => 0.4, - quadruped_small::Species::Dodarock => 0.9, - quadruped_small::Species::Holladon => 1.0, - quadruped_small::Species::Hyena => 0.4, - quadruped_small::Species::Rabbit => 0.1, - quadruped_small::Species::Truffler => 0.8, - quadruped_small::Species::Frog => 0.4, - quadruped_small::Species::Hare => 0.2, + quadruped_small::Species::Boar => 0.2, + quadruped_small::Species::Jackalope => 0.6, + quadruped_small::Species::Skunk => 0.4, + quadruped_small::Species::Cat => 0.8, + quadruped_small::Species::Batfox => 0.4, + quadruped_small::Species::Raccoon => 0.6, + quadruped_small::Species::Quokka => 0.6, + quadruped_small::Species::Dodarock => 0.1, + quadruped_small::Species::Holladon => 0.0, + quadruped_small::Species::Hyena => 0.6, + quadruped_small::Species::Rabbit => 0.9, + quadruped_small::Species::Truffler => 0.2, + quadruped_small::Species::Frog => 0.6, + quadruped_small::Species::Hare => 0.8, quadruped_small::Species::Goat => 0.5, - _ => 0.0, + _ => 1.0, }, Body::QuadrupedMedium(quadruped_medium) => match quadruped_medium.species { - quadruped_medium::Species::Tuskram => 0.7, - quadruped_medium::Species::Frostfang => 0.9, - quadruped_medium::Species::Mouflon => 0.7, - quadruped_medium::Species::Catoblepas => 0.8, - quadruped_medium::Species::Deer => 0.6, - quadruped_medium::Species::Hirdrasil => 0.7, - quadruped_medium::Species::Donkey => 0.7, - quadruped_medium::Species::Camel => 0.7, - quadruped_medium::Species::Zebra => 0.7, - quadruped_medium::Species::Antelope => 0.6, - quadruped_medium::Species::Horse => 0.7, - quadruped_medium::Species::Cattle => 0.7, - quadruped_medium::Species::Darkhound => 0.9, - quadruped_medium::Species::Dreadhorn => 0.8, - quadruped_medium::Species::Snowleopard => 0.7, - quadruped_medium::Species::Llama => 0.6, - quadruped_medium::Species::Alpaca => 0.6, + quadruped_medium::Species::Tuskram => 0.3, + quadruped_medium::Species::Frostfang => 0.1, + quadruped_medium::Species::Mouflon => 0.3, + quadruped_medium::Species::Catoblepas => 0.2, + quadruped_medium::Species::Deer => 0.4, + quadruped_medium::Species::Hirdrasil => 0.3, + quadruped_medium::Species::Donkey => 0.3, + quadruped_medium::Species::Camel => 0.3, + quadruped_medium::Species::Zebra => 0.3, + quadruped_medium::Species::Antelope => 0.4, + quadruped_medium::Species::Horse => 0.3, + quadruped_medium::Species::Cattle => 0.3, + quadruped_medium::Species::Darkhound => 0.1, + quadruped_medium::Species::Dreadhorn => 0.2, + quadruped_medium::Species::Snowleopard => 0.3, + quadruped_medium::Species::Llama => 0.4, + quadruped_medium::Species::Alpaca => 0.4, _ => 0.5, }, Body::QuadrupedLow(quadruped_low) => match quadruped_low.species { - quadruped_low::Species::Salamander => 0.7, - quadruped_low::Species::Monitor => 0.7, - quadruped_low::Species::Asp => 0.9, - quadruped_low::Species::Pangolin => 0.4, - _ => 0.6, + quadruped_low::Species::Salamander => 0.3, + quadruped_low::Species::Monitor => 0.3, + quadruped_low::Species::Asp => 0.1, + quadruped_low::Species::Pangolin => 0.6, + _ => 0.4, }, Body::BipedSmall(_) => 0.5, Body::BirdMedium(_) => 0.5, - Body::BirdLarge(_) => 0.9, - Body::FishMedium(_) => 0.15, - Body::FishSmall(_) => 0.0, - Body::BipedLarge(_) => 1.0, - Body::Object(_) => 1.0, - Body::Golem(_) => 1.0, - Body::Theropod(_) => 1.0, - Body::Dragon(_) => 1.0, - Body::Ship(_) => 1.0, + Body::BirdLarge(_) => 0.1, + Body::FishMedium(_) => 0.85, + Body::FishSmall(_) => 1.0, + Body::BipedLarge(_) => 0.0, + Body::Object(_) => 0.0, + Body::Golem(_) => 0.0, + Body::Theropod(_) => 0.0, + Body::Dragon(_) => 0.0, + Body::Ship(_) => 0.0, + }, + sight_dist: 40.0, + listen_dist: 30.0, + aggro_dist: match body { + Body::Humanoid(_) => Some(20.0), + _ => None, // Always aggressive if detected }, } } } +impl Psyche { + /// The maximum distance that targets might be detected by this agent. + pub fn search_dist(&self) -> f32 { self.sight_dist.max(self.listen_dist) } +} + #[derive(Clone, Debug)] /// Events that affect agent behavior from other entities/players/environment pub enum AgentEvent { @@ -309,8 +332,12 @@ pub enum SoundKind { #[derive(Clone, Copy, Debug)] pub struct Target { pub target: EcsEntity, + /// Whether the target is hostile pub hostile: bool, + /// The time at which the target was selected pub selected_at: f64, + /// Whether the target has come close enough to trigger aggro. + pub aggro_on: bool, } #[allow(clippy::type_complexity)] @@ -345,7 +372,7 @@ impl Agent { } pub fn with_destination(mut self, pos: Vec3) -> Self { - self.psyche = Psyche { aggro: 1.0 }; + self.psyche.flee_health = 0.0; self.rtsim_controller = RtSimController::with_destination(pos); self.behavior.allow(BehaviorCapability::SPEAK); self @@ -369,7 +396,10 @@ impl Agent { Agent { patrol_origin, psyche: if no_flee { - Psyche { aggro: 1.0 } + Psyche { + flee_health: 0.0, + ..Psyche::from(body) + } } else { Psyche::from(body) }, diff --git a/common/src/comp/controller.rs b/common/src/comp/controller.rs index f07608a361..54604d49f1 100644 --- a/common/src/comp/controller.rs +++ b/common/src/comp/controller.rs @@ -242,7 +242,10 @@ impl ControllerInputs { impl Controller { /// Sets all inputs to default - pub fn reset(&mut self) { *self = Self::default(); } + pub fn reset(&mut self) { + self.inputs = Default::default(); + self.queued_inputs = Default::default(); + } pub fn clear_events(&mut self) { self.events.clear(); } diff --git a/server/src/events/interaction.rs b/server/src/events/interaction.rs index 11f1942349..4a3e6b2f0b 100644 --- a/server/src/events/interaction.rs +++ b/server/src/events/interaction.rs @@ -6,7 +6,7 @@ use common::{ assets, comp::{ self, - agent::{AgentEvent, Sound, SoundKind, MAX_LISTEN_DIST}, + agent::{AgentEvent, Sound, SoundKind}, dialogue::Subject, inventory::slot::EquipSlot, item, @@ -408,7 +408,7 @@ pub fn handle_sound(server: &mut Server, sound: &Sound) { let propagated_sound = sound.with_new_vol(sound.vol - vol_dropoff); let can_hear_sound = propagated_sound.vol > 0.00; - let should_hear_sound = agent_dist_sqrd < MAX_LISTEN_DIST.powi(2); + let should_hear_sound = agent_dist_sqrd < agent.psyche.listen_dist.powi(2); if can_hear_sound && should_hear_sound { agent diff --git a/server/src/settings.rs b/server/src/settings.rs index 8df943a502..ce66969277 100644 --- a/server/src/settings.rs +++ b/server/src/settings.rs @@ -159,6 +159,7 @@ impl Settings { max_players: 100, start_time: 9.0 * 3600.0, max_view_distance: None, + safe_spawn: false, client_timeout: Duration::from_secs(180), ..load // Fill in remaining fields from server_settings.ron. } diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index 0ca68b358a..77468133fb 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -3,8 +3,7 @@ use common::{ comp::{ self, agent::{ - AgentEvent, Sound, SoundKind, Target, DEFAULT_INTERACTION_TIME, MAX_LISTEN_DIST, - TRADE_INTERACTION_TIME, + AgentEvent, Sound, SoundKind, Target, DEFAULT_INTERACTION_TIME, TRADE_INTERACTION_TIME, }, buff::{BuffKind, Buffs}, compass::{Direction, Distance}, @@ -169,7 +168,6 @@ const PARTIAL_PATH_DIST: f32 = 50.0; const SEPARATION_DIST: f32 = 10.0; const SEPARATION_BIAS: f32 = 0.8; const MAX_FLEE_DIST: f32 = 20.0; -const SEARCH_DIST: f32 = 48.0; const SNEAK_COEFFICIENT: f32 = 0.25; const AVG_FOLLOW_DIST: f32 = 6.0; const RETARGETING_THRESHOLD_SECONDS: f64 = 10.0; @@ -270,7 +268,7 @@ impl<'a> System<'a> for Sys { ) }; - let event_emitter = event_bus.emitter(); + let mut event_emitter = event_bus.emitter(); if !matches!(char_state, CharacterState::LeapMelee(_)) { // Default to looking in orientation direction @@ -381,44 +379,45 @@ impl<'a> System<'a> for Sys { // are the only parts of this tree that should provide // inputs. - let idle = |agent: &mut Agent, controller, mut event_emitter| { - data.idle_tree(agent, controller, &read_data, &mut event_emitter); - }; - - let relax = |agent: &mut Agent, controller, event_emitter| { - agent.target = None; - idle(agent, controller, event_emitter); - }; - - let react_as_pet = - |agent: &mut Agent, target: EcsEntity, controller, event_emitter| { - if let Some(tgt_pos) = read_data.positions.get(target) { - let dist_sqrd = pos.0.distance_squared(tgt_pos.0); - // If really far away drop everything and follow - if dist_sqrd > (2.0 * MAX_FOLLOW_DIST).powi(2) { - agent.bearing = Vec2::zero(); - data.follow(agent, controller, &read_data.terrain, tgt_pos); - // Attack target's attacker - } else if entity_was_attacked(target, &read_data) { - data.attack_target_attacker(agent, &read_data, controller); - // Follow owner if too far away and not - // fighting - } else if dist_sqrd > MAX_FOLLOW_DIST.powi(2) { - data.follow(agent, controller, &read_data.terrain, tgt_pos); - - // Otherwise just idle - } else { - idle(agent, controller, event_emitter); - } - } + let idle = + |agent: &mut Agent, + controller: &mut Controller, + event_emitter: &mut Emitter| { + agent.target = None; + data.idle_tree(agent, controller, &read_data, event_emitter); }; + let react_as_pet = |agent: &mut Agent, + target: EcsEntity, + controller: &mut Controller, + event_emitter| { + if let Some(tgt_pos) = read_data.positions.get(target) { + let dist_sqrd = pos.0.distance_squared(tgt_pos.0); + // If really far away drop everything and follow + if dist_sqrd > (2.0 * MAX_FOLLOW_DIST).powi(2) { + agent.bearing = Vec2::zero(); + data.follow(agent, controller, &read_data.terrain, tgt_pos); + // Attack target's attacker + } else if entity_was_attacked(target, &read_data) { + data.attack_target_attacker(agent, &read_data, controller); + // Follow owner if too far away and not + // fighting + } else if dist_sqrd > MAX_FOLLOW_DIST.powi(2) { + data.follow(agent, controller, &read_data.terrain, tgt_pos); + + // Otherwise just idle + } else { + idle(agent, controller, event_emitter); + } + } + }; + let react_to_target = |agent: &mut Agent, target: EcsEntity, hostile: bool, - controller, - mut event_emitter| { + controller: &mut Controller, + event_emitter| { if let Some(tgt_health) = read_data.healths.get(target) { // If target is dead, leave it if tgt_health.is_dead { @@ -427,69 +426,27 @@ impl<'a> System<'a> for Sys { { rtsim_forget_enemy(&tgt_stats.name, agent); } - relax(agent, controller, event_emitter); + agent.target = None; // If the target is hostile // (either based on alignment or if // the target just attacked) } else if hostile { - data.hostile_tree( - agent, - controller, - &read_data, - &mut event_emitter, - ); + data.hostile_tree(agent, controller, &read_data, event_emitter); // Target is something worth following // methinks } else if let Some(Alignment::Owned(uid)) = data.alignment { if read_data.uids.get(target) == Some(uid) { react_as_pet(agent, target, controller, event_emitter); } else { - relax(agent, controller, event_emitter); + agent.target = None; + idle(agent, controller, event_emitter); }; } else { idle(agent, controller, event_emitter); } } else { - relax(agent, controller, event_emitter); - } - }; - - let react_to_damage = - |agent: &mut Agent, by: Uid, controller, event_emitter| { - if let Some(attacker) = - read_data.uid_allocator.retrieve_entity_internal(by.id()) - { - // If the target is dead or in a safezone, remove the - // target and idle. - if should_stop_attacking(attacker, &read_data) { - relax(agent, controller, event_emitter); - } else if let Some(tgt_pos) = read_data.positions.get(attacker) { - if agent.target.is_none() { - controller.push_event(ControlEvent::Utterance( - UtteranceKind::Angry, - )); - } - - agent.target = Some(Target { - target: attacker, - hostile: true, - selected_at: read_data.time.0, - }); - let target_data = TargetData { - pos: tgt_pos, - body: read_data.bodies.get(attacker), - scale: read_data.scales.get(attacker), - }; - data.attack(agent, controller, &target_data, &read_data); - // Remember this encounter if an RtSim entity - if let Some(tgt_stats) = - data.rtsim_entity.and(read_data.stats.get(attacker)) - { - rtsim_new_enemy(&tgt_stats.name, agent, &read_data); - } - } else { - relax(agent, controller, event_emitter); - } + agent.target = None; + idle(agent, controller, event_emitter); } }; @@ -507,25 +464,75 @@ impl<'a> System<'a> for Sys { data.fly_upward(controller) } else if is_falling_dangerous && data.glider_equipped { data.glider_fall(controller); - } else if let Some(target_info) = agent.target { - let Target { - target, hostile, .. - } = target_info; - react_to_target(agent, target, hostile, controller, event_emitter); } else { // Target an entity that's attacking us if the attack // was recent and we have a health component match health { Some(health) if health.last_change.0 < DAMAGE_MEMORY_DURATION => { if let Some(by) = health.last_change.1.cause.damage_by() { - react_to_damage(agent, by, controller, event_emitter); - } else { - relax(agent, controller, event_emitter); + if let Some(attacker) = + read_data.uid_allocator.retrieve_entity_internal(by.id()) + { + // If the target is dead or in a safezone, remove the + // target and idle. + if should_stop_attacking(attacker, &read_data) { + agent.target = None; + } else if let Some(tgt_pos) = + read_data.positions.get(attacker) + { + if agent.target.is_none() { + controller.push_event(ControlEvent::Utterance( + UtteranceKind::Angry, + )); + } + + // Determine whether the new target should be a priority + // over the old one + // (i.e: because it's either close or because they + // attacked us) + let more_dangerous_than_old_target = + agent.target.map_or(true, |old_tgt| { + if let Some(old_tgt_pos) = + read_data.positions.get(old_tgt.target) + { + !old_tgt.aggro_on + || old_tgt_pos.0.distance_squared(pos.0) + < tgt_pos.0.distance_squared(pos.0) + } else { + true + } + }); + + // Select the attacker as the new target + if more_dangerous_than_old_target { + agent.target = Some(Target { + target: attacker, + hostile: true, + selected_at: read_data.time.0, + aggro_on: true, + }); + } + + // Remember this attack if we're an RtSim entity + if let Some(tgt_stats) = + data.rtsim_entity.and(read_data.stats.get(attacker)) + { + rtsim_new_enemy(&tgt_stats.name, agent, &read_data); + } + } + } } }, - _ => { - idle(agent, controller, event_emitter); - }, + _ => {}, + } + + if let Some(target_info) = agent.target { + let Target { + target, hostile, .. + } = target_info; + react_to_target(agent, target, hostile, controller, &mut event_emitter); + } else { + idle(agent, controller, &mut event_emitter); } } @@ -572,7 +579,7 @@ impl<'a> AgentData<'a> { if agent.target.is_none() && thread_rng().gen_bool(0.1) { if let Some(Alignment::Owned(owner)) = self.alignment { if let Some(owner) = get_entity_by_id(owner.id(), read_data) { - agent.target = build_target(owner, false, read_data.time.0); + agent.target = build_target(owner, false, read_data.time.0, false); } } } @@ -647,19 +654,34 @@ impl<'a> AgentData<'a> { if let Some(Target { target, selected_at, + aggro_on, .. - }) = agent.target + }) = &mut agent.target { + let target = *target; + let selected_at = *selected_at; + if let Some(tgt_pos) = read_data.positions.get(target) { - let dist_sqrd = self.pos.0.distance_squared(tgt_pos.0); - // Should the agent flee? - if 1.0 - agent.psyche.aggro > self.damage && self.flees { + let dist_sq = self.pos.0.distance_squared(tgt_pos.0); + let in_aggro_range = agent + .psyche + .aggro_dist + .map_or(true, |ad| dist_sq < ad.powi(2)); + // If, at any point, the target comes closer than the aggro distance, switch to + // aggro mode + if in_aggro_range { + *aggro_on = true; + } + let aggro_on = *aggro_on; + + if self.damage.min(1.0) < agent.psyche.flee_health && self.flees { + // Should the agent flee? if agent.action_state.timer == 0.0 && can_speak(agent) { - let msg = "npc.speech.villager_under_attack".to_string(); - self.chat_general(msg, event_emitter); + self.chat_general("npc.speech.villager_under_attack", event_emitter); self.emit_villager_alarm(read_data.time.0, event_emitter); agent.action_state.timer = 0.01; - } else if agent.action_state.timer < FLEE_DURATION || dist_sqrd < MAX_FLEE_DIST + } else if agent.action_state.timer < FLEE_DURATION + || dist_sq < MAX_FLEE_DIST.powi(2) { self.flee(agent, controller, &read_data.terrain, tgt_pos); agent.action_state.timer += read_data.dt.0; @@ -668,32 +690,36 @@ impl<'a> AgentData<'a> { agent.target = None; self.idle(agent, controller, read_data); } - - // If not fleeing, attack the hostile entity! + } else if should_stop_attacking(target, read_data) { + if can_speak(agent) { + let msg = "npc.speech.villager_enemy_killed".to_string(); + event_emitter + .emit(ServerEvent::Chat(UnresolvedChatMsg::npc(*self.uid, msg))); + } + agent.target = None; + self.idle(agent, controller, read_data); } else { - // If the hostile entity is dead or has an invulnerability buff (eg, those - // applied in safezones), return to idle - if should_stop_attacking(target, read_data) { - if can_speak(agent) { - let msg = "npc.speech.villager_enemy_killed".to_string(); - event_emitter - .emit(ServerEvent::Chat(UnresolvedChatMsg::npc(*self.uid, msg))); - } - agent.target = None; - self.idle(agent, controller, read_data); - // Choose a new target every 10 seconds, but only for - // enemies - // TODO: This should be more principled. Consider factoring - // health, combat rating, wielded weapon, etc, into the - // decision to change target. - } else if read_data.time.0 - selected_at > RETARGETING_THRESHOLD_SECONDS - && matches!(self.alignment, Some(Alignment::Enemy)) + // Potentially choose a new target + if read_data.time.0 - selected_at > RETARGETING_THRESHOLD_SECONDS + && !in_aggro_range { self.choose_target(agent, controller, read_data, event_emitter); - } else { - // TODO Add utility for attacking vs leaving target alone + } + + if aggro_on { let target_data = build_target_data(target, tgt_pos, read_data); self.attack(agent, controller, &target_data, read_data); + } else { + // If we're not yet aggro-ed, strike a menacing pose + if thread_rng().gen::() < read_data.dt.0 * 0.25 { + self.chat_general_if_can_speak( + agent, + "npc.speech.menacing", + event_emitter, + ); + controller.push_event(ControlEvent::Utterance(UtteranceKind::Angry)); + } + self.menacing(agent, controller, read_data, target, tgt_pos); } } } @@ -969,9 +995,9 @@ impl<'a> AgentData<'a> { Some(AgentEvent::Talk(by, subject)) => { if can_speak(agent) { if let Some(target) = get_entity_by_id(by.id(), read_data) { - agent.target = build_target(target, false, read_data.time.0); + agent.target = build_target(target, false, read_data.time.0, false); - if self.look_toward(controller, read_data, &target) { + if self.look_toward(controller, read_data, target) { controller.actions.push(ControlAction::Stand); controller.actions.push(ControlAction::Talk); controller.push_event(ControlEvent::Utterance(UtteranceKind::Greeting)); @@ -1017,11 +1043,12 @@ impl<'a> AgentData<'a> { }; self.chat_general(msg, event_emitter); } else if agent.behavior.can_trade() { - let msg = "npc.speech.merchant_advertisement".to_string(); - self.chat_general(msg, event_emitter); + self.chat_general( + "npc.speech.merchant_advertisement", + event_emitter, + ); } else { - let msg = "npc.speech.villager".to_string(); - self.chat_general(msg, event_emitter); + self.chat_general("npc.speech.villager", event_emitter); } }, Subject::Trade => { @@ -1031,18 +1058,23 @@ impl<'a> AgentData<'a> { by, InviteKind::Trade, )); - let msg = - "npc.speech.merchant_advertisement".to_string(); - self.chat_general(msg, event_emitter); + self.chat_general( + "npc.speech.merchant_advertisement", + event_emitter, + ); } else { - let msg = "npc.speech.merchant_busy".to_string(); - self.chat_general(msg, event_emitter); + self.chat_general( + "npc.speech.merchant_busy", + event_emitter, + ); } } else { // TODO: maybe make some travellers willing to trade with // simpler goods like potions - let msg = "npc.speech.villager_decline_trade".to_string(); - self.chat_general(msg, event_emitter); + self.chat_general( + "npc.speech.villager_decline_trade", + event_emitter, + ); } }, Subject::Mood => { @@ -1156,7 +1188,7 @@ impl<'a> AgentData<'a> { controller.actions.push(ControlAction::Stand); controller.actions.push(ControlAction::Talk); if let Some(target) = get_entity_by_id(with.id(), read_data) { - agent.target = build_target(target, false, read_data.time.0); + agent.target = build_target(target, false, read_data.time.0, false); } controller .events @@ -1167,22 +1199,28 @@ impl<'a> AgentData<'a> { controller .events .push(ControlEvent::InviteResponse(InviteResponse::Decline)); - let msg = "npc.speech.merchant_busy".to_string(); - self.chat_general_if_can_speak(agent, msg, event_emitter); + self.chat_general_if_can_speak( + agent, + "npc.speech.merchant_busy", + event_emitter, + ); } } else { // TODO: Provide a hint where to find the closest merchant? controller .events .push(ControlEvent::InviteResponse(InviteResponse::Decline)); - let msg = "npc.speech.villager_decline_trade".to_string(); - self.chat_general_if_can_speak(agent, msg, event_emitter); + self.chat_general_if_can_speak( + agent, + "npc.speech.villager_decline_trade", + event_emitter, + ); } }, Some(AgentEvent::TradeAccepted(with)) => { if !agent.behavior.is(BehaviorState::TRADING) { if let Some(target) = get_entity_by_id(with.id(), read_data) { - agent.target = build_target(target, false, read_data.time.0); + agent.target = build_target(target, false, read_data.time.0, false); } agent.behavior.set(BehaviorState::TRADING); agent.behavior.set(BehaviorState::TRADING_ISSUER); @@ -1192,12 +1230,13 @@ impl<'a> AgentData<'a> { if agent.behavior.is(BehaviorState::TRADING) { match result { TradeResult::Completed => { - let msg = "npc.speech.merchant_trade_successful".to_string(); - self.chat_general(msg, event_emitter); + self.chat_general( + "npc.speech.merchant_trade_successful", + event_emitter, + ); }, _ => { - let msg = "npc.speech.merchant_trade_declined".to_string(); - self.chat_general(msg, event_emitter); + self.chat_general("npc.speech.merchant_trade_declined", event_emitter); }, } agent.behavior.unset(BehaviorState::TRADING); @@ -1268,7 +1307,7 @@ impl<'a> AgentData<'a> { // No new events, continue looking towards the last // interacting player for some time if let Some(Target { target, .. }) = &agent.target { - self.look_toward(controller, read_data, target); + self.look_toward(controller, read_data, *target); } else { agent.action_state.timer = 0.0; } @@ -1281,14 +1320,11 @@ impl<'a> AgentData<'a> { &self, controller: &mut Controller, read_data: &ReadData, - target: &EcsEntity, + target: EcsEntity, ) -> bool { - if let Some(tgt_pos) = read_data.positions.get(*target) { + if let Some(tgt_pos) = read_data.positions.get(target) { let eye_offset = self.body.map_or(0.0, |b| b.eye_height()); - let tgt_eye_offset = read_data - .bodies - .get(*target) - .map_or(0.0, |b| b.eye_height()); + let tgt_eye_offset = read_data.bodies.get(target).map_or(0.0, |b| b.eye_height()); if let Some(dir) = Dir::from_unnormalized( Vec3::new(tgt_pos.0.x, tgt_pos.0.y, tgt_pos.0.z + tgt_eye_offset) - Vec3::new(self.pos.0.x, self.pos.0.y, self.pos.0.z + eye_offset), @@ -1301,6 +1337,24 @@ impl<'a> AgentData<'a> { } } + fn menacing( + &self, + _agent: &mut Agent, + controller: &mut Controller, + read_data: &ReadData, + target: EcsEntity, + _tgt_pos: &Pos, + ) { + self.look_toward(controller, read_data, target); + controller.actions.push(ControlAction::Wield); + + let max_move = 0.5; + let move_dir_mag = controller.inputs.move_dir.magnitude(); + if move_dir_mag > max_move { + controller.inputs.move_dir = max_move * controller.inputs.move_dir / move_dir_mag; + } + } + fn flee( &self, agent: &mut Agent, @@ -1431,34 +1485,41 @@ impl<'a> AgentData<'a> { }) }; - let in_search_area = |e_pos: &Pos, e_char_state: Option<&CharacterState>| { - let mut search_dist = SEARCH_DIST; - if e_char_state.map_or(false, CharacterState::is_stealthy) { - // TODO: make sneak more effective based on a stat like e_stats.fitness - search_dist *= SNEAK_COEFFICIENT; - }; + let max_search_dist = agent.psyche.search_dist(); + let max_sight_dist = agent.psyche.sight_dist; + let max_listen_dist = agent.psyche.listen_dist; + let in_sight_dist = |e_pos: &Pos, e_char_state: Option<&CharacterState>| { + let search_dist = max_sight_dist + * if e_char_state.map_or(false, CharacterState::is_stealthy) { + // TODO: make sneak more effective based on a stat like e_stats.fitness + SNEAK_COEFFICIENT + } else { + 1.0 + }; e_pos.0.distance_squared(self.pos.0) < search_dist.powi(2) }; - let within_view = |e_pos: &Pos| { + let within_fov = |e_pos: &Pos| { (e_pos.0 - self.pos.0) .try_normalized() .map_or(true, |v| v.dot(*controller.inputs.look_dir) > 0.15) }; - let in_listen_area = |e_pos: &Pos, e_char_state: Option<&CharacterState>| { - let mut listen_dist = MAX_LISTEN_DIST; - if e_char_state.map_or(false, CharacterState::is_stealthy) { - // TODO: make sneak more effective based on a stat like e_stats.fitness - listen_dist *= SNEAK_COEFFICIENT; - } + let in_listen_dist = |e_pos: &Pos, e_char_state: Option<&CharacterState>| { + let listen_dist = max_listen_dist + * if e_char_state.map_or(false, CharacterState::is_stealthy) { + // TODO: make sneak more effective based on a stat like e_stats.fitness + SNEAK_COEFFICIENT + } else { + 1.0 + }; // TODO implement proper sound system for agents e_pos.0.distance_squared(self.pos.0) < listen_dist.powi(2) }; let within_reach = |e_pos: &Pos, e_char_state: Option<&CharacterState>| { - (in_search_area(e_pos, e_char_state) && within_view(e_pos)) - || in_listen_area(e_pos, e_char_state) + (in_sight_dist(e_pos, e_char_state) && within_fov(e_pos)) + || in_listen_dist(e_pos, e_char_state) }; let owners_hostile = |e_alignment: Option<&Alignment>| { @@ -1594,9 +1655,10 @@ impl<'a> AgentData<'a> { // TODO choose target by more than just distance let common::CachedSpatialGrid(grid) = self.cached_spatial_grid; let target = grid - .in_circle_aabr(self.pos.0.xy(), SEARCH_DIST) + .in_circle_aabr(self.pos.0.xy(), max_search_dist) .filter_map(worth_choosing) .filter_map(possible_target) + // TODO: This seems expensive. Cache this to avoid recomputing each tick .filter(|(_, e_pos)| can_see_them(e_pos)) .min_by_key(|(_, e_pos)| (e_pos.0.distance_squared(self.pos.0) * 100.0) as i32) .map(|(e, _)| e); @@ -1609,6 +1671,7 @@ impl<'a> AgentData<'a> { target, hostile: true, selected_at: read_data.time.0, + aggro_on: false, }); } @@ -4017,11 +4080,13 @@ impl<'a> AgentData<'a> { } else if is_village_guard { self.follow(agent, controller, &read_data.terrain, &sound_pos); } else if is_neutral { - let aggro = agent.psyche.aggro; + let flee_health = agent.psyche.flee_health; let close_enough = dist_sqrd < 35.0_f32.powi(2); let sound_was_loud = sound.vol >= 10.0; - if close_enough && (aggro <= 0.5 || (aggro <= 0.7 && sound_was_loud)) { + if close_enough + && (flee_health <= 0.7 || (flee_health <= 0.5 && sound_was_loud)) + { self.flee(agent, controller, &read_data.terrain, &sound_pos); } else { self.idle(agent, controller, read_data); @@ -4048,11 +4113,11 @@ impl<'a> AgentData<'a> { controller.push_event(ControlEvent::Utterance(UtteranceKind::Angry)); } - agent.target = build_target(attacker, true, read_data.time.0); + agent.target = build_target(attacker, true, read_data.time.0, true); if let Some(tgt_pos) = read_data.positions.get(attacker) { if should_stop_attacking(attacker, read_data) { - agent.target = build_target(target, false, read_data.time.0); + agent.target = build_target(target, false, read_data.time.0, false); self.idle(agent, controller, read_data); } else { @@ -4154,11 +4219,11 @@ impl<'a> AgentData<'a> { fn chat_general_if_can_speak( &self, agent: &Agent, - msg: String, + msg: impl ToString, event_emitter: &mut Emitter<'_, ServerEvent>, ) -> bool { if can_speak(agent) { - event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(*self.uid, msg))); + self.chat_general(msg, event_emitter); true } else { false @@ -4177,8 +4242,11 @@ impl<'a> AgentData<'a> { } } - fn chat_general(&self, msg: String, event_emitter: &mut Emitter<'_, ServerEvent>) { - event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(*self.uid, msg))); + fn chat_general(&self, msg: impl ToString, event_emitter: &mut Emitter<'_, ServerEvent>) { + event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc( + *self.uid, + msg.to_string(), + ))); } fn emit_villager_alarm(&self, time: f64, event_emitter: &mut Emitter<'_, ServerEvent>) { @@ -4304,11 +4372,12 @@ fn entity_was_attacked(entity: EcsEntity, read_data: &ReadData) -> bool { } } -fn build_target(target: EcsEntity, is_hostile: bool, time: f64) -> Option { +fn build_target(target: EcsEntity, is_hostile: bool, time: f64, aggro_on: bool) -> Option { Some(Target { target, hostile: is_hostile, selected_at: time, + aggro_on, }) } diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index 0f3ea5e3a5..589b742592 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -265,7 +265,7 @@ impl<'a> System<'a> for Sys { let poise = comp::Poise::new(body); let can_speak = match body { - comp::Body::Humanoid(_) => alignment == comp::Alignment::Npc, + comp::Body::Humanoid(_) => true, comp::Body::BirdMedium(bird_medium) => match bird_medium.species { // Parrots like to have a word in this, too... bird_medium::Species::Parrot => alignment == comp::Alignment::Npc, From 82489782b45b22391cb3d2bf5471ca0601e562c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Sat, 31 Jul 2021 21:34:29 +0100 Subject: [PATCH 033/155] Fix uniformity bug in ui shader --- assets/voxygen/shaders/ui-frag.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/voxygen/shaders/ui-frag.glsl b/assets/voxygen/shaders/ui-frag.glsl index d9010a2c90..549f60bfb3 100644 --- a/assets/voxygen/shaders/ui-frag.glsl +++ b/assets/voxygen/shaders/ui-frag.glsl @@ -21,11 +21,11 @@ layout(location = 0) out vec4 tgt_color; void main() { // Text if (f_mode == uint(0)) { - tgt_color = f_color * vec4(1.0, 1.0, 1.0, texture(sampler2D(t_tex, s_tex), f_uv).a); + tgt_color = f_color * vec4(1.0, 1.0, 1.0, textureLod(sampler2D(t_tex, s_tex), f_uv, 0).a); // Image // HACK: bit 0 is set for both ordinary and north-facing images. } else if ((f_mode & uint(1)) == uint(1)) { - tgt_color = f_color * texture(sampler2D(t_tex, s_tex), f_uv); + tgt_color = f_color * textureLod(sampler2D(t_tex, s_tex), f_uv, 0); // 2D Geometry } else if (f_mode == uint(2)) { tgt_color = f_color; From 2fd26bf41c163bd3d5b555a3a050cc217dfc8644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Sun, 1 Aug 2021 00:26:23 +0200 Subject: [PATCH 034/155] make folders POSIX style and move skills to hud --- assets/voxygen/i18n/de_DE/{ => hud}/skills.ron | 0 assets/voxygen/i18n/en/{ => hud}/skills.ron | 0 assets/voxygen/i18n/es_ES/{ => hud}/skills.ron | 0 assets/voxygen/i18n/fr_FR/{ => hud}/skills.ron | 0 assets/voxygen/i18n/hu_HU/{ => hud}/skills.ron | 0 assets/voxygen/i18n/it_IT/{ => hud}/skills.ron | 0 assets/voxygen/i18n/ja_JP/{ => hud}/skills.ron | 0 assets/voxygen/i18n/{nl => nl_NL}/_manifest.ron | 4 ++-- assets/voxygen/i18n/{PL => pl_PL}/_manifest.ron | 2 +- assets/voxygen/i18n/{PL => pl_PL}/buff.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/char_selection.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/common.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/esc_menu.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/gameinput.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/hud/bag.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/hud/char_window.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/hud/chat.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/hud/crafting.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/hud/group.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/hud/hud_settings.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/hud/map.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/hud/misc.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/hud/sct.ron | 0 assets/voxygen/i18n/{PL => pl_PL/hud}/skills.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/hud/social.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/hud/trade.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/main.ron | 0 assets/voxygen/i18n/{PL => pl_PL}/template.ron | 0 assets/voxygen/i18n/pt_BR/{ => hud}/skills.ron | 0 assets/voxygen/i18n/ru_RU/{ => hud}/skills.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/_manifest.ron | 4 ++-- assets/voxygen/i18n/{sv => sv_SE}/buff.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/char_selection.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/common.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/esc_menu.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/gameinput.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/hud/bag.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/hud/char_window.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/hud/chat.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/hud/crafting.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/hud/group.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/hud/hud_settings.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/hud/map.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/hud/misc.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/hud/sct.ron | 0 assets/voxygen/i18n/{sv => sv_SE/hud}/skills.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/hud/social.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/hud/trade.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/main.ron | 0 assets/voxygen/i18n/{sv => sv_SE}/template.ron | 0 assets/voxygen/i18n/uk_UA/{ => hud}/skills.ron | 0 assets/voxygen/i18n/zh_CN/{ => hud}/skills.ron | 0 52 files changed, 5 insertions(+), 5 deletions(-) rename assets/voxygen/i18n/de_DE/{ => hud}/skills.ron (100%) rename assets/voxygen/i18n/en/{ => hud}/skills.ron (100%) rename assets/voxygen/i18n/es_ES/{ => hud}/skills.ron (100%) rename assets/voxygen/i18n/fr_FR/{ => hud}/skills.ron (100%) rename assets/voxygen/i18n/hu_HU/{ => hud}/skills.ron (100%) rename assets/voxygen/i18n/it_IT/{ => hud}/skills.ron (100%) rename assets/voxygen/i18n/ja_JP/{ => hud}/skills.ron (100%) rename assets/voxygen/i18n/{nl => nl_NL}/_manifest.ron (99%) rename assets/voxygen/i18n/{PL => pl_PL}/_manifest.ron (99%) rename assets/voxygen/i18n/{PL => pl_PL}/buff.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/char_selection.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/common.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/esc_menu.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/gameinput.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/hud/bag.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/hud/char_window.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/hud/chat.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/hud/crafting.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/hud/group.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/hud/hud_settings.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/hud/map.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/hud/misc.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/hud/sct.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL/hud}/skills.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/hud/social.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/hud/trade.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/main.ron (100%) rename assets/voxygen/i18n/{PL => pl_PL}/template.ron (100%) rename assets/voxygen/i18n/pt_BR/{ => hud}/skills.ron (100%) rename assets/voxygen/i18n/ru_RU/{ => hud}/skills.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/_manifest.ron (99%) rename assets/voxygen/i18n/{sv => sv_SE}/buff.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/char_selection.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/common.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/esc_menu.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/gameinput.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/hud/bag.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/hud/char_window.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/hud/chat.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/hud/crafting.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/hud/group.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/hud/hud_settings.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/hud/map.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/hud/misc.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/hud/sct.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE/hud}/skills.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/hud/social.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/hud/trade.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/main.ron (100%) rename assets/voxygen/i18n/{sv => sv_SE}/template.ron (100%) rename assets/voxygen/i18n/uk_UA/{ => hud}/skills.ron (100%) rename assets/voxygen/i18n/zh_CN/{ => hud}/skills.ron (100%) diff --git a/assets/voxygen/i18n/de_DE/skills.ron b/assets/voxygen/i18n/de_DE/hud/skills.ron similarity index 100% rename from assets/voxygen/i18n/de_DE/skills.ron rename to assets/voxygen/i18n/de_DE/hud/skills.ron diff --git a/assets/voxygen/i18n/en/skills.ron b/assets/voxygen/i18n/en/hud/skills.ron similarity index 100% rename from assets/voxygen/i18n/en/skills.ron rename to assets/voxygen/i18n/en/hud/skills.ron diff --git a/assets/voxygen/i18n/es_ES/skills.ron b/assets/voxygen/i18n/es_ES/hud/skills.ron similarity index 100% rename from assets/voxygen/i18n/es_ES/skills.ron rename to assets/voxygen/i18n/es_ES/hud/skills.ron diff --git a/assets/voxygen/i18n/fr_FR/skills.ron b/assets/voxygen/i18n/fr_FR/hud/skills.ron similarity index 100% rename from assets/voxygen/i18n/fr_FR/skills.ron rename to assets/voxygen/i18n/fr_FR/hud/skills.ron diff --git a/assets/voxygen/i18n/hu_HU/skills.ron b/assets/voxygen/i18n/hu_HU/hud/skills.ron similarity index 100% rename from assets/voxygen/i18n/hu_HU/skills.ron rename to assets/voxygen/i18n/hu_HU/hud/skills.ron diff --git a/assets/voxygen/i18n/it_IT/skills.ron b/assets/voxygen/i18n/it_IT/hud/skills.ron similarity index 100% rename from assets/voxygen/i18n/it_IT/skills.ron rename to assets/voxygen/i18n/it_IT/hud/skills.ron diff --git a/assets/voxygen/i18n/ja_JP/skills.ron b/assets/voxygen/i18n/ja_JP/hud/skills.ron similarity index 100% rename from assets/voxygen/i18n/ja_JP/skills.ron rename to assets/voxygen/i18n/ja_JP/hud/skills.ron diff --git a/assets/voxygen/i18n/nl/_manifest.ron b/assets/voxygen/i18n/nl_NL/_manifest.ron similarity index 99% rename from assets/voxygen/i18n/nl/_manifest.ron rename to assets/voxygen/i18n/nl_NL/_manifest.ron index b6324abc02..c5890c9072 100644 --- a/assets/voxygen/i18n/nl/_manifest.ron +++ b/assets/voxygen/i18n/nl_NL/_manifest.ron @@ -12,11 +12,11 @@ /// /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for "global" English +/// Localization for netherlands Dutch ( metadata: ( language_name: "Nederlands", - language_identifier: "nl", + language_identifier: "nl_NL", ), convert_utf8_to_ascii: false, fonts: { diff --git a/assets/voxygen/i18n/PL/_manifest.ron b/assets/voxygen/i18n/pl_PL/_manifest.ron similarity index 99% rename from assets/voxygen/i18n/PL/_manifest.ron rename to assets/voxygen/i18n/pl_PL/_manifest.ron index 204f497d07..db841f3959 100644 --- a/assets/voxygen/i18n/PL/_manifest.ron +++ b/assets/voxygen/i18n/pl_PL/_manifest.ron @@ -2,7 +2,7 @@ ( metadata: ( language_name: "Polish", - language_identifier: "PL", + language_identifier: "pl_PL", ), convert_utf8_to_ascii: false, fonts: { diff --git a/assets/voxygen/i18n/PL/buff.ron b/assets/voxygen/i18n/pl_PL/buff.ron similarity index 100% rename from assets/voxygen/i18n/PL/buff.ron rename to assets/voxygen/i18n/pl_PL/buff.ron diff --git a/assets/voxygen/i18n/PL/char_selection.ron b/assets/voxygen/i18n/pl_PL/char_selection.ron similarity index 100% rename from assets/voxygen/i18n/PL/char_selection.ron rename to assets/voxygen/i18n/pl_PL/char_selection.ron diff --git a/assets/voxygen/i18n/PL/common.ron b/assets/voxygen/i18n/pl_PL/common.ron similarity index 100% rename from assets/voxygen/i18n/PL/common.ron rename to assets/voxygen/i18n/pl_PL/common.ron diff --git a/assets/voxygen/i18n/PL/esc_menu.ron b/assets/voxygen/i18n/pl_PL/esc_menu.ron similarity index 100% rename from assets/voxygen/i18n/PL/esc_menu.ron rename to assets/voxygen/i18n/pl_PL/esc_menu.ron diff --git a/assets/voxygen/i18n/PL/gameinput.ron b/assets/voxygen/i18n/pl_PL/gameinput.ron similarity index 100% rename from assets/voxygen/i18n/PL/gameinput.ron rename to assets/voxygen/i18n/pl_PL/gameinput.ron diff --git a/assets/voxygen/i18n/PL/hud/bag.ron b/assets/voxygen/i18n/pl_PL/hud/bag.ron similarity index 100% rename from assets/voxygen/i18n/PL/hud/bag.ron rename to assets/voxygen/i18n/pl_PL/hud/bag.ron diff --git a/assets/voxygen/i18n/PL/hud/char_window.ron b/assets/voxygen/i18n/pl_PL/hud/char_window.ron similarity index 100% rename from assets/voxygen/i18n/PL/hud/char_window.ron rename to assets/voxygen/i18n/pl_PL/hud/char_window.ron diff --git a/assets/voxygen/i18n/PL/hud/chat.ron b/assets/voxygen/i18n/pl_PL/hud/chat.ron similarity index 100% rename from assets/voxygen/i18n/PL/hud/chat.ron rename to assets/voxygen/i18n/pl_PL/hud/chat.ron diff --git a/assets/voxygen/i18n/PL/hud/crafting.ron b/assets/voxygen/i18n/pl_PL/hud/crafting.ron similarity index 100% rename from assets/voxygen/i18n/PL/hud/crafting.ron rename to assets/voxygen/i18n/pl_PL/hud/crafting.ron diff --git a/assets/voxygen/i18n/PL/hud/group.ron b/assets/voxygen/i18n/pl_PL/hud/group.ron similarity index 100% rename from assets/voxygen/i18n/PL/hud/group.ron rename to assets/voxygen/i18n/pl_PL/hud/group.ron diff --git a/assets/voxygen/i18n/PL/hud/hud_settings.ron b/assets/voxygen/i18n/pl_PL/hud/hud_settings.ron similarity index 100% rename from assets/voxygen/i18n/PL/hud/hud_settings.ron rename to assets/voxygen/i18n/pl_PL/hud/hud_settings.ron diff --git a/assets/voxygen/i18n/PL/hud/map.ron b/assets/voxygen/i18n/pl_PL/hud/map.ron similarity index 100% rename from assets/voxygen/i18n/PL/hud/map.ron rename to assets/voxygen/i18n/pl_PL/hud/map.ron diff --git a/assets/voxygen/i18n/PL/hud/misc.ron b/assets/voxygen/i18n/pl_PL/hud/misc.ron similarity index 100% rename from assets/voxygen/i18n/PL/hud/misc.ron rename to assets/voxygen/i18n/pl_PL/hud/misc.ron diff --git a/assets/voxygen/i18n/PL/hud/sct.ron b/assets/voxygen/i18n/pl_PL/hud/sct.ron similarity index 100% rename from assets/voxygen/i18n/PL/hud/sct.ron rename to assets/voxygen/i18n/pl_PL/hud/sct.ron diff --git a/assets/voxygen/i18n/PL/skills.ron b/assets/voxygen/i18n/pl_PL/hud/skills.ron similarity index 100% rename from assets/voxygen/i18n/PL/skills.ron rename to assets/voxygen/i18n/pl_PL/hud/skills.ron diff --git a/assets/voxygen/i18n/PL/hud/social.ron b/assets/voxygen/i18n/pl_PL/hud/social.ron similarity index 100% rename from assets/voxygen/i18n/PL/hud/social.ron rename to assets/voxygen/i18n/pl_PL/hud/social.ron diff --git a/assets/voxygen/i18n/PL/hud/trade.ron b/assets/voxygen/i18n/pl_PL/hud/trade.ron similarity index 100% rename from assets/voxygen/i18n/PL/hud/trade.ron rename to assets/voxygen/i18n/pl_PL/hud/trade.ron diff --git a/assets/voxygen/i18n/PL/main.ron b/assets/voxygen/i18n/pl_PL/main.ron similarity index 100% rename from assets/voxygen/i18n/PL/main.ron rename to assets/voxygen/i18n/pl_PL/main.ron diff --git a/assets/voxygen/i18n/PL/template.ron b/assets/voxygen/i18n/pl_PL/template.ron similarity index 100% rename from assets/voxygen/i18n/PL/template.ron rename to assets/voxygen/i18n/pl_PL/template.ron diff --git a/assets/voxygen/i18n/pt_BR/skills.ron b/assets/voxygen/i18n/pt_BR/hud/skills.ron similarity index 100% rename from assets/voxygen/i18n/pt_BR/skills.ron rename to assets/voxygen/i18n/pt_BR/hud/skills.ron diff --git a/assets/voxygen/i18n/ru_RU/skills.ron b/assets/voxygen/i18n/ru_RU/hud/skills.ron similarity index 100% rename from assets/voxygen/i18n/ru_RU/skills.ron rename to assets/voxygen/i18n/ru_RU/hud/skills.ron diff --git a/assets/voxygen/i18n/sv/_manifest.ron b/assets/voxygen/i18n/sv_SE/_manifest.ron similarity index 99% rename from assets/voxygen/i18n/sv/_manifest.ron rename to assets/voxygen/i18n/sv_SE/_manifest.ron index 73dd4fc971..200216b724 100644 --- a/assets/voxygen/i18n/sv/_manifest.ron +++ b/assets/voxygen/i18n/sv_SE/_manifest.ron @@ -1,10 +1,10 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for "global" Swedish +/// Localization for sweden Swedish ( metadata: ( language_name: "Svenska", - language_identifier: "sv", + language_identifier: "sv_SE", ), convert_utf8_to_ascii: false, fonts: { diff --git a/assets/voxygen/i18n/sv/buff.ron b/assets/voxygen/i18n/sv_SE/buff.ron similarity index 100% rename from assets/voxygen/i18n/sv/buff.ron rename to assets/voxygen/i18n/sv_SE/buff.ron diff --git a/assets/voxygen/i18n/sv/char_selection.ron b/assets/voxygen/i18n/sv_SE/char_selection.ron similarity index 100% rename from assets/voxygen/i18n/sv/char_selection.ron rename to assets/voxygen/i18n/sv_SE/char_selection.ron diff --git a/assets/voxygen/i18n/sv/common.ron b/assets/voxygen/i18n/sv_SE/common.ron similarity index 100% rename from assets/voxygen/i18n/sv/common.ron rename to assets/voxygen/i18n/sv_SE/common.ron diff --git a/assets/voxygen/i18n/sv/esc_menu.ron b/assets/voxygen/i18n/sv_SE/esc_menu.ron similarity index 100% rename from assets/voxygen/i18n/sv/esc_menu.ron rename to assets/voxygen/i18n/sv_SE/esc_menu.ron diff --git a/assets/voxygen/i18n/sv/gameinput.ron b/assets/voxygen/i18n/sv_SE/gameinput.ron similarity index 100% rename from assets/voxygen/i18n/sv/gameinput.ron rename to assets/voxygen/i18n/sv_SE/gameinput.ron diff --git a/assets/voxygen/i18n/sv/hud/bag.ron b/assets/voxygen/i18n/sv_SE/hud/bag.ron similarity index 100% rename from assets/voxygen/i18n/sv/hud/bag.ron rename to assets/voxygen/i18n/sv_SE/hud/bag.ron diff --git a/assets/voxygen/i18n/sv/hud/char_window.ron b/assets/voxygen/i18n/sv_SE/hud/char_window.ron similarity index 100% rename from assets/voxygen/i18n/sv/hud/char_window.ron rename to assets/voxygen/i18n/sv_SE/hud/char_window.ron diff --git a/assets/voxygen/i18n/sv/hud/chat.ron b/assets/voxygen/i18n/sv_SE/hud/chat.ron similarity index 100% rename from assets/voxygen/i18n/sv/hud/chat.ron rename to assets/voxygen/i18n/sv_SE/hud/chat.ron diff --git a/assets/voxygen/i18n/sv/hud/crafting.ron b/assets/voxygen/i18n/sv_SE/hud/crafting.ron similarity index 100% rename from assets/voxygen/i18n/sv/hud/crafting.ron rename to assets/voxygen/i18n/sv_SE/hud/crafting.ron diff --git a/assets/voxygen/i18n/sv/hud/group.ron b/assets/voxygen/i18n/sv_SE/hud/group.ron similarity index 100% rename from assets/voxygen/i18n/sv/hud/group.ron rename to assets/voxygen/i18n/sv_SE/hud/group.ron diff --git a/assets/voxygen/i18n/sv/hud/hud_settings.ron b/assets/voxygen/i18n/sv_SE/hud/hud_settings.ron similarity index 100% rename from assets/voxygen/i18n/sv/hud/hud_settings.ron rename to assets/voxygen/i18n/sv_SE/hud/hud_settings.ron diff --git a/assets/voxygen/i18n/sv/hud/map.ron b/assets/voxygen/i18n/sv_SE/hud/map.ron similarity index 100% rename from assets/voxygen/i18n/sv/hud/map.ron rename to assets/voxygen/i18n/sv_SE/hud/map.ron diff --git a/assets/voxygen/i18n/sv/hud/misc.ron b/assets/voxygen/i18n/sv_SE/hud/misc.ron similarity index 100% rename from assets/voxygen/i18n/sv/hud/misc.ron rename to assets/voxygen/i18n/sv_SE/hud/misc.ron diff --git a/assets/voxygen/i18n/sv/hud/sct.ron b/assets/voxygen/i18n/sv_SE/hud/sct.ron similarity index 100% rename from assets/voxygen/i18n/sv/hud/sct.ron rename to assets/voxygen/i18n/sv_SE/hud/sct.ron diff --git a/assets/voxygen/i18n/sv/skills.ron b/assets/voxygen/i18n/sv_SE/hud/skills.ron similarity index 100% rename from assets/voxygen/i18n/sv/skills.ron rename to assets/voxygen/i18n/sv_SE/hud/skills.ron diff --git a/assets/voxygen/i18n/sv/hud/social.ron b/assets/voxygen/i18n/sv_SE/hud/social.ron similarity index 100% rename from assets/voxygen/i18n/sv/hud/social.ron rename to assets/voxygen/i18n/sv_SE/hud/social.ron diff --git a/assets/voxygen/i18n/sv/hud/trade.ron b/assets/voxygen/i18n/sv_SE/hud/trade.ron similarity index 100% rename from assets/voxygen/i18n/sv/hud/trade.ron rename to assets/voxygen/i18n/sv_SE/hud/trade.ron diff --git a/assets/voxygen/i18n/sv/main.ron b/assets/voxygen/i18n/sv_SE/main.ron similarity index 100% rename from assets/voxygen/i18n/sv/main.ron rename to assets/voxygen/i18n/sv_SE/main.ron diff --git a/assets/voxygen/i18n/sv/template.ron b/assets/voxygen/i18n/sv_SE/template.ron similarity index 100% rename from assets/voxygen/i18n/sv/template.ron rename to assets/voxygen/i18n/sv_SE/template.ron diff --git a/assets/voxygen/i18n/uk_UA/skills.ron b/assets/voxygen/i18n/uk_UA/hud/skills.ron similarity index 100% rename from assets/voxygen/i18n/uk_UA/skills.ron rename to assets/voxygen/i18n/uk_UA/hud/skills.ron diff --git a/assets/voxygen/i18n/zh_CN/skills.ron b/assets/voxygen/i18n/zh_CN/hud/skills.ron similarity index 100% rename from assets/voxygen/i18n/zh_CN/skills.ron rename to assets/voxygen/i18n/zh_CN/hud/skills.ron From 49072702bcdb432f1d737c811d29754ecdb8f31d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Sun, 1 Aug 2021 09:31:03 +0200 Subject: [PATCH 035/155] fix #1258 --- assets/voxygen/i18n/cz_CZ/_manifest.ron | 870 ------------------ assets/voxygen/i18n/cz_CZ/buff.ron | 40 + assets/voxygen/i18n/cz_CZ/char_selection.ron | 34 + assets/voxygen/i18n/cz_CZ/common.ron | 106 +++ assets/voxygen/i18n/cz_CZ/esc_menu.ron | 13 + assets/voxygen/i18n/cz_CZ/gameinput.ron | 70 ++ assets/voxygen/i18n/cz_CZ/hud/bag.ron | 39 + assets/voxygen/i18n/cz_CZ/hud/char_window.ron | 20 + assets/voxygen/i18n/cz_CZ/hud/chat.ron | 38 + assets/voxygen/i18n/cz_CZ/hud/crafting.ron | 16 + assets/voxygen/i18n/cz_CZ/hud/group.ron | 24 + .../voxygen/i18n/cz_CZ/hud/hud_settings.ron | 108 +++ assets/voxygen/i18n/cz_CZ/hud/map.ron | 33 + .../template.ron => cz_CZ/hud/misc.ron} | 4 +- .../{it_IT/template.ron => cz_CZ/hud/sct.ron} | 3 +- assets/voxygen/i18n/cz_CZ/hud/skills.ron | 243 +++++ assets/voxygen/i18n/cz_CZ/hud/social.ron | 24 + assets/voxygen/i18n/cz_CZ/hud/trade.ron | 30 + assets/voxygen/i18n/cz_CZ/main.ron | 67 ++ assets/voxygen/i18n/en/hud/sct.ron | 2 +- assets/voxygen/i18n/en/hud/trade.ron | 34 +- assets/voxygen/i18n/es_ES/template.ron | 12 - assets/voxygen/i18n/es_LA/_manifest.ron | 152 +++ assets/voxygen/i18n/es_LA/buff.ron | 26 + assets/voxygen/i18n/es_LA/char_selection.ron | 32 + assets/voxygen/i18n/es_LA/common.ron | 71 ++ assets/voxygen/i18n/es_LA/esc_menu.ron | 13 + assets/voxygen/i18n/es_LA/gameinput.ron | 68 ++ assets/voxygen/i18n/es_LA/hud/bag.ron | 31 + assets/voxygen/i18n/es_LA/hud/char_window.ron | 22 + assets/voxygen/i18n/es_LA/hud/chat.ron | 36 + assets/voxygen/i18n/es_LA/hud/crafting.ron | 16 + assets/voxygen/i18n/es_LA/hud/group.ron | 23 + .../voxygen/i18n/es_LA/hud/hud_settings.ron | 101 ++ assets/voxygen/i18n/es_LA/hud/map.ron | 26 + assets/voxygen/i18n/es_LA/hud/misc.ron | 74 ++ assets/voxygen/i18n/es_LA/hud/sct.ron | 14 + assets/voxygen/i18n/es_LA/hud/skills.ron | 11 + assets/voxygen/i18n/es_LA/hud/social.ron | 22 + .../template.ron => es_LA/hud/trade.ron} | 4 +- assets/voxygen/i18n/es_LA/main.ron | 63 ++ assets/voxygen/i18n/es_la/_manifest.ron | 665 ------------- assets/voxygen/i18n/ja_JP/template.ron | 12 - assets/voxygen/i18n/nl_NL/_manifest.ron | 475 +--------- assets/voxygen/i18n/nl_NL/buff.ron | 11 + assets/voxygen/i18n/nl_NL/char_selection.ron | 32 + assets/voxygen/i18n/nl_NL/common.ron | 71 ++ assets/voxygen/i18n/nl_NL/esc_menu.ron | 13 + assets/voxygen/i18n/nl_NL/gameinput.ron | 66 ++ assets/voxygen/i18n/nl_NL/hud/bag.ron | 32 + assets/voxygen/i18n/nl_NL/hud/char_window.ron | 21 + assets/voxygen/i18n/nl_NL/hud/chat.ron | 32 + assets/voxygen/i18n/nl_NL/hud/crafting.ron | 16 + assets/voxygen/i18n/nl_NL/hud/group.ron | 23 + .../voxygen/i18n/nl_NL/hud/hud_settings.ron | 96 ++ assets/voxygen/i18n/nl_NL/hud/map.ron | 14 + assets/voxygen/i18n/nl_NL/hud/misc.ron | 78 ++ assets/voxygen/i18n/nl_NL/hud/sct.ron | 14 + assets/voxygen/i18n/nl_NL/hud/skills.ron | 11 + assets/voxygen/i18n/nl_NL/hud/social.ron | 22 + assets/voxygen/i18n/nl_NL/hud/trade.ron | 12 + assets/voxygen/i18n/nl_NL/main.ron | 59 ++ assets/voxygen/i18n/no_NB/_manifest.ron | 152 +++ assets/voxygen/i18n/no_NB/buff.ron | 25 + assets/voxygen/i18n/no_NB/char_selection.ron | 32 + assets/voxygen/i18n/no_NB/common.ron | 71 ++ assets/voxygen/i18n/no_NB/esc_menu.ron | 13 + assets/voxygen/i18n/no_NB/gameinput.ron | 67 ++ assets/voxygen/i18n/no_NB/hud/bag.ron | 32 + assets/voxygen/i18n/no_NB/hud/char_window.ron | 22 + assets/voxygen/i18n/no_NB/hud/chat.ron | 37 + assets/voxygen/i18n/no_NB/hud/crafting.ron | 16 + assets/voxygen/i18n/no_NB/hud/group.ron | 23 + .../voxygen/i18n/no_NB/hud/hud_settings.ron | 98 ++ assets/voxygen/i18n/no_NB/hud/map.ron | 14 + assets/voxygen/i18n/no_NB/hud/misc.ron | 76 ++ assets/voxygen/i18n/no_NB/hud/sct.ron | 14 + .../template.ron => no_NB/hud/skills.ron} | 2 +- assets/voxygen/i18n/no_NB/hud/social.ron | 22 + .../template.ron => no_NB/hud/trade.ron} | 4 +- assets/voxygen/i18n/no_NB/main.ron | 63 ++ assets/voxygen/i18n/no_nb/_manifest.ron | 644 ------------- assets/voxygen/i18n/pt_BR/template.ron | 12 - assets/voxygen/i18n/pt_PT/_manifest.ron | 352 ------- assets/voxygen/i18n/pt_PT/buff.ron | 11 + assets/voxygen/i18n/pt_PT/char_selection.ron | 29 + assets/voxygen/i18n/pt_PT/common.ron | 57 ++ assets/voxygen/i18n/pt_PT/esc_menu.ron | 13 + assets/voxygen/i18n/pt_PT/gameinput.ron | 11 + assets/voxygen/i18n/pt_PT/hud/bag.ron | 11 + assets/voxygen/i18n/pt_PT/hud/char_window.ron | 19 + assets/voxygen/i18n/pt_PT/hud/chat.ron | 11 + assets/voxygen/i18n/pt_PT/hud/crafting.ron | 11 + assets/voxygen/i18n/pt_PT/hud/group.ron | 11 + .../voxygen/i18n/pt_PT/hud/hud_settings.ron | 141 +++ assets/voxygen/i18n/pt_PT/hud/map.ron | 11 + assets/voxygen/i18n/pt_PT/hud/misc.ron | 76 ++ assets/voxygen/i18n/pt_PT/hud/sct.ron | 11 + assets/voxygen/i18n/pt_PT/hud/skills.ron | 11 + assets/voxygen/i18n/pt_PT/hud/social.ron | 18 + assets/voxygen/i18n/pt_PT/hud/trade.ron | 12 + assets/voxygen/i18n/pt_PT/main.ron | 58 ++ assets/voxygen/i18n/vi_VI/_manifest.ron | 113 --- assets/voxygen/i18n/vi_VI/buff.ron | 11 + assets/voxygen/i18n/vi_VI/char_selection.ron | 10 + assets/voxygen/i18n/vi_VI/common.ron | 73 ++ assets/voxygen/i18n/vi_VI/esc_menu.ron | 11 + assets/voxygen/i18n/vi_VI/gameinput.ron | 11 + assets/voxygen/i18n/vi_VI/hud/bag.ron | 11 + assets/voxygen/i18n/vi_VI/hud/char_window.ron | 11 + assets/voxygen/i18n/vi_VI/hud/chat.ron | 11 + assets/voxygen/i18n/vi_VI/hud/crafting.ron | 11 + assets/voxygen/i18n/vi_VI/hud/group.ron | 11 + .../voxygen/i18n/vi_VI/hud/hud_settings.ron | 11 + assets/voxygen/i18n/vi_VI/hud/map.ron | 11 + assets/voxygen/i18n/vi_VI/hud/misc.ron | 11 + assets/voxygen/i18n/vi_VI/hud/sct.ron | 11 + assets/voxygen/i18n/vi_VI/hud/skills.ron | 11 + assets/voxygen/i18n/vi_VI/hud/social.ron | 12 + assets/voxygen/i18n/vi_VI/hud/trade.ron | 12 + assets/voxygen/i18n/vi_VI/main.ron | 64 ++ assets/voxygen/i18n/zh_CN/template.ron | 12 - assets/voxygen/i18n/zh_TW/_manifest.ron | 338 ------- assets/voxygen/i18n/zh_TW/buff.ron | 11 + assets/voxygen/i18n/zh_TW/char_selection.ron | 29 + assets/voxygen/i18n/zh_TW/common.ron | 57 ++ assets/voxygen/i18n/zh_TW/esc_menu.ron | 13 + assets/voxygen/i18n/zh_TW/gameinput.ron | 11 + assets/voxygen/i18n/zh_TW/hud/bag.ron | 17 + assets/voxygen/i18n/zh_TW/hud/char_window.ron | 20 + assets/voxygen/i18n/zh_TW/hud/chat.ron | 11 + assets/voxygen/i18n/zh_TW/hud/crafting.ron | 11 + assets/voxygen/i18n/zh_TW/hud/group.ron | 11 + .../voxygen/i18n/zh_TW/hud/hud_settings.ron | 145 +++ assets/voxygen/i18n/zh_TW/hud/map.ron | 14 + assets/voxygen/i18n/zh_TW/hud/misc.ron | 65 ++ assets/voxygen/i18n/zh_TW/hud/sct.ron | 11 + assets/voxygen/i18n/zh_TW/hud/skills.ron | 11 + assets/voxygen/i18n/zh_TW/hud/social.ron | 18 + assets/voxygen/i18n/zh_TW/hud/trade.ron | 12 + assets/voxygen/i18n/zh_TW/main.ron | 53 ++ 141 files changed, 4493 insertions(+), 3527 deletions(-) create mode 100644 assets/voxygen/i18n/cz_CZ/buff.ron create mode 100644 assets/voxygen/i18n/cz_CZ/char_selection.ron create mode 100644 assets/voxygen/i18n/cz_CZ/common.ron create mode 100644 assets/voxygen/i18n/cz_CZ/esc_menu.ron create mode 100644 assets/voxygen/i18n/cz_CZ/gameinput.ron create mode 100644 assets/voxygen/i18n/cz_CZ/hud/bag.ron create mode 100644 assets/voxygen/i18n/cz_CZ/hud/char_window.ron create mode 100644 assets/voxygen/i18n/cz_CZ/hud/chat.ron create mode 100644 assets/voxygen/i18n/cz_CZ/hud/crafting.ron create mode 100644 assets/voxygen/i18n/cz_CZ/hud/group.ron create mode 100644 assets/voxygen/i18n/cz_CZ/hud/hud_settings.ron create mode 100644 assets/voxygen/i18n/cz_CZ/hud/map.ron rename assets/voxygen/i18n/{pl_PL/template.ron => cz_CZ/hud/misc.ron} (81%) rename assets/voxygen/i18n/{it_IT/template.ron => cz_CZ/hud/sct.ron} (81%) create mode 100644 assets/voxygen/i18n/cz_CZ/hud/skills.ron create mode 100644 assets/voxygen/i18n/cz_CZ/hud/social.ron create mode 100644 assets/voxygen/i18n/cz_CZ/hud/trade.ron create mode 100644 assets/voxygen/i18n/cz_CZ/main.ron delete mode 100644 assets/voxygen/i18n/es_ES/template.ron create mode 100644 assets/voxygen/i18n/es_LA/_manifest.ron create mode 100644 assets/voxygen/i18n/es_LA/buff.ron create mode 100644 assets/voxygen/i18n/es_LA/char_selection.ron create mode 100644 assets/voxygen/i18n/es_LA/common.ron create mode 100644 assets/voxygen/i18n/es_LA/esc_menu.ron create mode 100644 assets/voxygen/i18n/es_LA/gameinput.ron create mode 100644 assets/voxygen/i18n/es_LA/hud/bag.ron create mode 100644 assets/voxygen/i18n/es_LA/hud/char_window.ron create mode 100644 assets/voxygen/i18n/es_LA/hud/chat.ron create mode 100644 assets/voxygen/i18n/es_LA/hud/crafting.ron create mode 100644 assets/voxygen/i18n/es_LA/hud/group.ron create mode 100644 assets/voxygen/i18n/es_LA/hud/hud_settings.ron create mode 100644 assets/voxygen/i18n/es_LA/hud/map.ron create mode 100644 assets/voxygen/i18n/es_LA/hud/misc.ron create mode 100644 assets/voxygen/i18n/es_LA/hud/sct.ron create mode 100644 assets/voxygen/i18n/es_LA/hud/skills.ron create mode 100644 assets/voxygen/i18n/es_LA/hud/social.ron rename assets/voxygen/i18n/{sv_SE/template.ron => es_LA/hud/trade.ron} (77%) create mode 100644 assets/voxygen/i18n/es_LA/main.ron delete mode 100644 assets/voxygen/i18n/es_la/_manifest.ron delete mode 100644 assets/voxygen/i18n/ja_JP/template.ron create mode 100644 assets/voxygen/i18n/nl_NL/buff.ron create mode 100644 assets/voxygen/i18n/nl_NL/char_selection.ron create mode 100644 assets/voxygen/i18n/nl_NL/common.ron create mode 100644 assets/voxygen/i18n/nl_NL/esc_menu.ron create mode 100644 assets/voxygen/i18n/nl_NL/gameinput.ron create mode 100644 assets/voxygen/i18n/nl_NL/hud/bag.ron create mode 100644 assets/voxygen/i18n/nl_NL/hud/char_window.ron create mode 100644 assets/voxygen/i18n/nl_NL/hud/chat.ron create mode 100644 assets/voxygen/i18n/nl_NL/hud/crafting.ron create mode 100644 assets/voxygen/i18n/nl_NL/hud/group.ron create mode 100644 assets/voxygen/i18n/nl_NL/hud/hud_settings.ron create mode 100644 assets/voxygen/i18n/nl_NL/hud/map.ron create mode 100644 assets/voxygen/i18n/nl_NL/hud/misc.ron create mode 100644 assets/voxygen/i18n/nl_NL/hud/sct.ron create mode 100644 assets/voxygen/i18n/nl_NL/hud/skills.ron create mode 100644 assets/voxygen/i18n/nl_NL/hud/social.ron create mode 100644 assets/voxygen/i18n/nl_NL/hud/trade.ron create mode 100644 assets/voxygen/i18n/nl_NL/main.ron create mode 100644 assets/voxygen/i18n/no_NB/_manifest.ron create mode 100644 assets/voxygen/i18n/no_NB/buff.ron create mode 100644 assets/voxygen/i18n/no_NB/char_selection.ron create mode 100644 assets/voxygen/i18n/no_NB/common.ron create mode 100644 assets/voxygen/i18n/no_NB/esc_menu.ron create mode 100644 assets/voxygen/i18n/no_NB/gameinput.ron create mode 100644 assets/voxygen/i18n/no_NB/hud/bag.ron create mode 100644 assets/voxygen/i18n/no_NB/hud/char_window.ron create mode 100644 assets/voxygen/i18n/no_NB/hud/chat.ron create mode 100644 assets/voxygen/i18n/no_NB/hud/crafting.ron create mode 100644 assets/voxygen/i18n/no_NB/hud/group.ron create mode 100644 assets/voxygen/i18n/no_NB/hud/hud_settings.ron create mode 100644 assets/voxygen/i18n/no_NB/hud/map.ron create mode 100644 assets/voxygen/i18n/no_NB/hud/misc.ron create mode 100644 assets/voxygen/i18n/no_NB/hud/sct.ron rename assets/voxygen/i18n/{uk_UA/template.ron => no_NB/hud/skills.ron} (79%) create mode 100644 assets/voxygen/i18n/no_NB/hud/social.ron rename assets/voxygen/i18n/{hu_HU/template.ron => no_NB/hud/trade.ron} (79%) create mode 100644 assets/voxygen/i18n/no_NB/main.ron delete mode 100644 assets/voxygen/i18n/no_nb/_manifest.ron delete mode 100644 assets/voxygen/i18n/pt_BR/template.ron create mode 100644 assets/voxygen/i18n/pt_PT/buff.ron create mode 100644 assets/voxygen/i18n/pt_PT/char_selection.ron create mode 100644 assets/voxygen/i18n/pt_PT/common.ron create mode 100644 assets/voxygen/i18n/pt_PT/esc_menu.ron create mode 100644 assets/voxygen/i18n/pt_PT/gameinput.ron create mode 100644 assets/voxygen/i18n/pt_PT/hud/bag.ron create mode 100644 assets/voxygen/i18n/pt_PT/hud/char_window.ron create mode 100644 assets/voxygen/i18n/pt_PT/hud/chat.ron create mode 100644 assets/voxygen/i18n/pt_PT/hud/crafting.ron create mode 100644 assets/voxygen/i18n/pt_PT/hud/group.ron create mode 100644 assets/voxygen/i18n/pt_PT/hud/hud_settings.ron create mode 100644 assets/voxygen/i18n/pt_PT/hud/map.ron create mode 100644 assets/voxygen/i18n/pt_PT/hud/misc.ron create mode 100644 assets/voxygen/i18n/pt_PT/hud/sct.ron create mode 100644 assets/voxygen/i18n/pt_PT/hud/skills.ron create mode 100644 assets/voxygen/i18n/pt_PT/hud/social.ron create mode 100644 assets/voxygen/i18n/pt_PT/hud/trade.ron create mode 100644 assets/voxygen/i18n/pt_PT/main.ron create mode 100644 assets/voxygen/i18n/vi_VI/buff.ron create mode 100644 assets/voxygen/i18n/vi_VI/char_selection.ron create mode 100644 assets/voxygen/i18n/vi_VI/common.ron create mode 100644 assets/voxygen/i18n/vi_VI/esc_menu.ron create mode 100644 assets/voxygen/i18n/vi_VI/gameinput.ron create mode 100644 assets/voxygen/i18n/vi_VI/hud/bag.ron create mode 100644 assets/voxygen/i18n/vi_VI/hud/char_window.ron create mode 100644 assets/voxygen/i18n/vi_VI/hud/chat.ron create mode 100644 assets/voxygen/i18n/vi_VI/hud/crafting.ron create mode 100644 assets/voxygen/i18n/vi_VI/hud/group.ron create mode 100644 assets/voxygen/i18n/vi_VI/hud/hud_settings.ron create mode 100644 assets/voxygen/i18n/vi_VI/hud/map.ron create mode 100644 assets/voxygen/i18n/vi_VI/hud/misc.ron create mode 100644 assets/voxygen/i18n/vi_VI/hud/sct.ron create mode 100644 assets/voxygen/i18n/vi_VI/hud/skills.ron create mode 100644 assets/voxygen/i18n/vi_VI/hud/social.ron create mode 100644 assets/voxygen/i18n/vi_VI/hud/trade.ron create mode 100644 assets/voxygen/i18n/vi_VI/main.ron delete mode 100644 assets/voxygen/i18n/zh_CN/template.ron create mode 100644 assets/voxygen/i18n/zh_TW/buff.ron create mode 100644 assets/voxygen/i18n/zh_TW/char_selection.ron create mode 100644 assets/voxygen/i18n/zh_TW/common.ron create mode 100644 assets/voxygen/i18n/zh_TW/esc_menu.ron create mode 100644 assets/voxygen/i18n/zh_TW/gameinput.ron create mode 100644 assets/voxygen/i18n/zh_TW/hud/bag.ron create mode 100644 assets/voxygen/i18n/zh_TW/hud/char_window.ron create mode 100644 assets/voxygen/i18n/zh_TW/hud/chat.ron create mode 100644 assets/voxygen/i18n/zh_TW/hud/crafting.ron create mode 100644 assets/voxygen/i18n/zh_TW/hud/group.ron create mode 100644 assets/voxygen/i18n/zh_TW/hud/hud_settings.ron create mode 100644 assets/voxygen/i18n/zh_TW/hud/map.ron create mode 100644 assets/voxygen/i18n/zh_TW/hud/misc.ron create mode 100644 assets/voxygen/i18n/zh_TW/hud/sct.ron create mode 100644 assets/voxygen/i18n/zh_TW/hud/skills.ron create mode 100644 assets/voxygen/i18n/zh_TW/hud/social.ron create mode 100644 assets/voxygen/i18n/zh_TW/hud/trade.ron create mode 100644 assets/voxygen/i18n/zh_TW/main.ron diff --git a/assets/voxygen/i18n/cz_CZ/_manifest.ron b/assets/voxygen/i18n/cz_CZ/_manifest.ron index 62e7bce880..7af0195d63 100644 --- a/assets/voxygen/i18n/cz_CZ/_manifest.ron +++ b/assets/voxygen/i18n/cz_CZ/_manifest.ron @@ -28,876 +28,6 @@ ), }, string_map: { - // Texts used in multiple locations with the same formatting - "common.username": "jméno", - "common.singleplayer": "Hra jednoho hráče", - "common.multiplayer": "Hra více hráčů", - "common.servers": "Servery", - "common.quit": "Vypnout", - "common.settings": "Nastavení", - "common.languages": "Jazyky", - "common.interface": "Rozhraní", - "common.gameplay": "Hra", - "common.controls": "Ovládání", - "common.video": "Grafika", - "common.sound": "Zvuk", - "common.resume": "Pokračovat", - "common.characters": "Postavy", - "common.close": "Zavřít", - "common.yes": "Ano", - "common.no": "Ne", - "common.back": "Zpět", - "common.create": "Vytvořik", - "common.okay": "OK", - "common.add": "Přidat", - "common.accept": "Příjmout", - "common.decline": "Odmítnout", - "common.disclaimer": "Zřeknutí se odpovědnosti", - "common.cancel": "Zrušit", - "common.none": "Nic", - "common.error": "Chyba", - "common.fatal_error": "Fatalní Chyba", - "common.you": "ty", - "common.automatic": "Auto", - "common.random": "Náhodný", - "common.empty": "Prázdný", - - // Settings Window title - "common.interface_settings": "Rozhraní", - "common.gameplay_settings": "Hra", - "common.controls_settings": "Ovládání", - "common.video_settings": "Grafika", - "common.sound_settings": "Zvuk", - "common.language_settings": "Jazyk", - - // Message when connection to the server is lost - "common.connection_lost": r#"Spojení ztraceno! - Restartoval se server? - Je klient aktuální?"#, - - - "common.species.orc": "Ork", - "common.species.human": "Člověk", - "common.species.dwarf": "Trpaslík", - "common.species.elf": "Elf", - "common.species.undead": "Nemrtvý", - "common.species.danari": "Danari", - - "common.weapons.axe": "Sekera", - "common.weapons.sword": "Meč", - "common.weapons.staff": "Hůl", - "common.weapons.bow": "Luk", - "common.weapons.hammer": "Kladivo", - "common.weapons.general": "Všeobecný", - "common.weapons.sceptre": "Žezlo", - "common.weapons.shield": "Štít", - "common.weapons.spear": "Kopí", - "common.weapons.hammer_simple": "Jednoduché Kladivo", - "common.weapons.sword_simple": "Jednoduchý Meč", - "common.weapons.staff_simple": "Jednoduchá Hůl", - "common.weapons.axe_simple": "Jednoduchá Sekera", - "common.weapons.bow_simple": "Jednoduchý Luk", - "common.weapons.unique": "Unikátní", - "common.tool.debug": "Debug", - "common.tool.faming": "Farmářský Nástroj", - "common.tool.pick": "Krumpáč", - "common.kind.modular_component": "Modulární komponenta", - "common.kind.glider": "Kluzák", - "common.kind.consumable": "Spotřební", - "common.kind.throwable": "Lze házet", - "common.kind.utility": "Užitečné", - "common.kind.ingredient": "Ingredience", - "common.kind.lantern": "Lampa", - "common.hands.one": "Jednoruční", - "common.hands.two": "Dvojruční", - - "common.rand_appearance": "Náhodný vzhled", - "common.rand_name": "Náhodné Jméno", - - "common.stats.dps": "DPS", - "common.stats.power": "Moc", - "common.stats.speed": "Rychlost", - "common.stats.poise": "Postoj", - "common.stats.crit_chance": "Kritická šance", - "common.stats.crit_mult": "Crit Mult", - "common.stats.armor": "Zbroj", - "common.stats.poise_res": "Postojové res", - "common.stats.slots": "Sloty", - - /// End Common section - - - /// Start Main screen section - "main.connecting": "Připojování", - "main.creating_world": "Tvorba Světa", - - // Welcome notice that appears the first time Veloren is started - "main.notice": r#"Vítejte v alfa verzi Veloren! - -Než začnete, mějte na paměti, že: - -- Hra je v rané verzi alfa. Očekávejte chyby, extrémně nedokončený příběh, nedostatečně rozvinuté mechaniky a chybějící funkce. - -- Pokud se chcete podělit o svůj názor, máte návrhy nebo nápady nebo chcete nahlásit chybu, můžete nás kontaktovat prostřednictvím Redditu, GitLabu nebo Discordu. - -- Veloren je licencován pod licencí open source GPL 3. To znamená, že máte právo hru upravovat a distribuovat, jakkoliv chcete (pokud je vaše práce licencována také pod GPL 3). - -- Veloren je neziskový projekt, kde je každý pracující člověk dobrovolníkem. Pokud se vám tato hra líbí, připojte se k našemu týmu! - -Děkujeme za přečtení této zprávy a doufáme, že se vám tato hra bude líbit! - -~ Tvůrci Veloren"#, - - // Login process description - "main.login_process": r#"Informace o procesu přihlášení: - -Pokud máte problémy s přihlášením: - -Nezapomeňte, že k připojení na server -se zapnutým ověřením potřebujete účet. - -Účet si můžete vytvořit na webu: - -https://veloren.net/account/."#, - "main.login.server_not_found": "Server nenalezen", - "main.login.authentication_error": "Chyba ověření", - "main.login.server_full": "Server je plný", - "main.login.untrusted_auth_server": "Ověřovací server je nedůvěryhodný", - "main.login.outdated_client_or_server": "ServerWentMad: Pravděpodobně jsou verze nekompatibilní, zkontrolujte aktualizace!", - "main.login.network_wrong_version": "Server běží na jiné verzy hry. Aktualizuj si klienta.", - "main.login.timeout": "Timeout: Server neodpověděl včas. (Přetížení nebo chyby v síti).", - "main.login.server_shut_down": "Server Uzavřen", - "main.login.network_error": "Chyba sítě.", - "main.login.failed_sending_request": "Dotaz na ověřovací server se nezdařil", - "main.login.client_crashed": "Pád klienta", - "main.servers.select_server": "Výběr serveru", - "main.server": "Server", - "main.password": "Heslo", - "main.username": "Jméno", - "main.tip":"Rada:", - "main.login.invalid_character": "Vybraná postava je neplatná", - "main.login.not_on_whitelist": "Potřebuješ být ve whitelistu. Kontaktuj Admina serveru.", - "main.login.banned": "Byl/a si zabanován/á z tohoto důvodu", - "main.login.kicked": "Byl/a si vyhozen/á z tohoto důvodu", - "main.login.select_language": "Vyber si svůj Jazyk", - "main.login.insecure_auth_scheme": "Schéma ověření HTTP NENÍ podporováno. Je to nejisté! Pro účely vývoje je HTTP povolen pro „localhost“ nebo pro ladění", - "main.login.failed_auth_server_url_invalid": "Připojení k ověřovacímu serveru se nezdařilo.", - /// End Main screen section - - - /// Start HUD Section - - - "hud.press_key_to_show_keybindings_fmt": "Kliknutím {key} zobrazíte klávesy", - "hud.press_key_to_show_debug_info_fmt": "Kliknutím {key} zobrazíte rozšířené informace", - "hud.press_key_to_toggle_keybindings_fmt": "Kliknutím {key} přepnete klávesové zkratky", - "hud.press_key_to_toggle_debug_info_fmt": "Kliknutím {key} přepnete rozšířené informace", - - // Respawn message - "hud.press_key_to_respawn": r#"Kliknutím {key} se zrodíte u posledního navštíveného ohniště."#, - - // Welcome message - "hud.welcome": r#"Vítejte v alfa verzi Veloren! - - -Několik tipů, než začnete: - -Klepnutím na F1 zkontrolujte výchozí klíče. - -Napište /help v chatu a podívejte se na dostupné příkazy - - -Po celém světě jsou náhodně skryté truhly a další předměty s náhodnou kořistí! - -Klikněte pravým tlačítkem pro sebrání. - -Chcete-li použít nebo nasadit předmět, použijte klávesu „B“ k otevření inventáře. - -Poklepáním na položku ji můžete použít nebo nosit. - -Nepotřebné položky vytáhnete z oblasti inventáře, zahodíte je. - - -Noci ve Velorenu mohou být temné. - -Vybavte si lampu a rozsvíťte ji kliknutím na tlačítko „G“ - - -Chcete odemknout systémový kurzor ze hry? Klikněte na 'TAB' - - -Užijte si svůj pobyt ve světě Veloren!"#, - - // Chat - "hud.chat.online_msg": "[{name}] je online", - "hud.chat.offline_msg": "[{name}] šel/šla offline", - - "hud.chat.default_death_msg": "[{name}] zemřel", - "hud.chat.environmental_kill_msg": "[{name}] zemřel v {environment}", - "hud.chat.fall_kill_msg": "[{name}] zemřel z pádu", - "hud.chat.suicide_msg": "[{name}] zemřel díky svému zapříčinění", - - "hud.chat.pvp_buff_kill_msg": "[{victim}] zemřel z {buff} od [{attacker}]", - "hud.chat.pvp_melee_kill_msg": "[{attacker}] porazil [{victim}]", - "hud.chat.pvp_ranged_kill_msg": "[{attacker}] postřelil [{victim}]", - "hud.chat.pvp_explosion_kill_msg": "[{attacker}] odpálil [{victim}]", - "hud.chat.pvp_energy_kill_msg": "[{attacker}] zabil [{victim}] pomocí magie", - - "hud.chat.nonexistent_buff_kill_msg": "[{victim}] zemřel pomocí {buff}", - - "hud.chat.npc_buff_kill_msg": "[{victim}] died of {buff} od {attacker}", - "hud.chat.npc_melee_kill_msg": "{attacker} zabil [{victim}]", - "hud.chat.npc_ranged_kill_msg": "{attacker} postřelil [{victim}]", - "hud.chat.npc_explosion_kill_msg": "{attacker} odpálil [{victim}]", - "hud.chat.npc_energy_kill_msg": "{attacker} zabil [{victim}] pomocí magie", - "hud.chat.npc_other_kill_msg": "{attacker} zabil [{victim}]", - - "hud.chat.loot_msg": "Sebral si [{item}]", - "hud.chat.loot_fail": "Tvůj inventář je plný!", - "hud.chat.goodbye": "nashledanou!", - "hud.chat.connection_lost": "Spojení ztraceno. Odpojuji za {time} sekund.", - - - // Inventory - "hud.bag.glider": "Glider", - "hud.bag.bag": "Batoh", - "hud.bag.health": "Život", - "hud.bag.energy": "Výdrž", - "hud.bag.combat_rating": "Bojové hodnocení", - "hud.bag.protection": "Ochrana", - "hud.bag.combat_rating_desc": "Vypočítáno z života/zbroje.", - "hud.bag.protection_desc": "Redukce poškození přes brnení", - "hud.bag.inventory": "Inventář {playername}", - "hud.bag.stats_title": "Statistiky {playername}", - "hud.bag.exp": "Zkušenosti", - "hud.bag.armor": "Výzbroj", - "hud.bag.stats": "Statistiky", - "hud.bag.head": "Hlava", - "hud.bag.neck": "Krk", - "hud.bag.tabard": "Tabard", - "hud.bag.shoulders": "Ramena", - "hud.bag.chest": "Hruď", - "hud.bag.hands": "Ruce", - "hud.bag.lantern": "Lampa", - "hud.bag.belt": "Pas", - "hud.bag.ring": "Prsten", - "hud.bag.back": "Záda", - "hud.bag.legs": "Nohy", - "hud.bag.feet": "Chodidla", - "hud.bag.mainhand": "Hlavní Ruka", - "hud.bag.offhand": "Druhá Ruka", - - - // Map and Questlog - "hud.map.map_title": "Mapa", - "hud.map.qlog_title": "Úkoly", - "hud.map.difficulty": "Obtížnost", - "hud.map.towns": "Města", - "hud.map.castles": "Hrady", - "hud.map.dungeons": "Kobky", - "hud.map.caves": "Jeskyně", - "hud.map.cave": "Jeskyně", - "hud.map.trees": "Velké Stromy", - "hud.map.tree": "Velký Strom", - "hud.map.town": "Město", - "hud.map.castle": "Hrad", - "hud.map.dungeon": "Kobka", - "hud.map.difficulty_dungeon": "Kobka\n\nDifficulty: {difficulty}", - "hud.map.drag": "Pohybovat", - "hud.map.zoom": "Přiblížit", - "hud.map.recenter": "Recentrovat", - "hud.rank_up": "Nový Skillpoint", - "hud.skill.sp_available": "{number} SP dostupných", - "hud.skill.not_unlocked": "Není ještě odemčeno", - "hud.skill.req_sp": "\n\nVyžaduje {number} SP", - - // Skills - // General - "hud.skill.inc_health_title": "Zvýší Zdraví", - "hud.skill.inc_health": "Zvýší maximální zdraví o 5{SP}", - "hud.skill.inc_energy_title": "Zvýší Výdrž", - "hud.skill.inc_energy": "Zvýší Výdrž o 5{SP}", - "hud.skill.unlck_sword_title": "Odemknutí Meče", - "hud.skill.unlck_sword": "Odemkne strom dovedností pro meče{SP}", - "hud.skill.unlck_axe_title": "Odemknutí Sekery", - "hud.skill.unlck_axe": "Odemkne strom dovedností pro sekery{SP}", - "hud.skill.unlck_hammer_title": "Odemknutí Kladiva", - "hud.skill.unlck_hammer": "Odemkne strom dovedností pro kladivo{SP}", - "hud.skill.unlck_bow_title": "Odemknutí Luku", - "hud.skill.unlck_bow": "Odemkne strom dovedností pro luk{SP}", - "hud.skill.unlck_staff_title": "Odemknutí Hole", - "hud.skill.unlck_staff": "Odemkne strom dovedností pro hůl{SP}", - "hud.skill.unlck_sceptre_title": "Odemknutí Žezla", - "hud.skill.unlck_sceptre": "Odemkne strom dovedností pro žezlo{SP}", - "hud.skill.dodge_title": "Vyhnutí", - "hud.skill.dodge": "Vyhnese útokům zblízka{SP}", - "hud.skill.roll_energy_title": "Menší spotřeba Výdrže pro Kotrmelec", - "hud.skill.roll_energy": "Kotrmelec použije o 20% méně Výdrže{SP}", - "hud.skill.roll_speed_title": "Rychlost Kotrmelce", - "hud.skill.roll_speed": "Kotrmelec je o 20% rychlejší{SP}", - "hud.skill.roll_dur_title": "Délka Kotrmelce", - "hud.skill.roll_dur": "Kotrmelec je delší o 20%{SP}", - "hud.skill.climbing_title": "Lezení", - "hud.skill.climbing": "Skočíš výš", - "hud.skill.climbing_cost_title": "Lezení", - "hud.skill.climbing_cost": "Lezení spotřebuje o 20% méně Výdrže{SP}", - "hud.skill.climbing_speed_title": "Rychlost Lezení", - "hud.skill.climbing_speed": "Lezení je o 20% rychlejší{SP}", - "hud.skill.swim_title": "Plavání", - "hud.skill.swim": "Pohyb v mokrém prostředí", - "hud.skill.swim_speed_title": "Rychlost plávání", - "hud.skill.swim_speed": "Plaveš o 40% rychleji{SP}", - // Sceptre - "hud.skill.sc_lifesteal_title": "Paprsek Životokrádeže", - "hud.skill.sc_lifesteal": "Krade život z nepřátel", - "hud.skill.sc_lifesteal_damage_title": "Poškození", - "hud.skill.sc_lifesteal_damage": "Přídá o 20% více poškození{SP}", - "hud.skill.sc_lifesteal_range_title": "Dosah", - "hud.skill.sc_lifesteal_range": "Paprsek dosáhne o 25% dále{SP}", - "hud.skill.sc_lifesteal_lifesteal_title": "Životokrádež", - "hud.skill.sc_lifesteal_lifesteal": "Konverutuje o 30% více poškození na život{SP}", - "hud.skill.sc_lifesteal_regen_title": "Obnova Výdrže", - "hud.skill.sc_lifesteal_regen": "Doplní výdrž o 25%{SP}", - "hud.skill.sc_heal_title": "Paprsek Léčby", - "hud.skill.sc_heal": "Vyléčí vaše přátelé pomocí krve nepřátel", - "hud.skill.sc_heal_heal_title": "Léčba", - "hud.skill.sc_heal_heal": "Zvýší efektivnost Léčby o 20%{SP}", - "hud.skill.sc_heal_cost_title": "Spotřeba Výdrže", - "hud.skill.sc_heal_cost": "Léčení spotřebuje o 20% méně Výdrže{SP}", - "hud.skill.sc_heal_range_title": "Dosah", - "hud.skill.sc_heal_range": "Paprsek dosáhne dále o 25% {SP}", - "hud.skill.sc_wardaura_unlock_title": "Ochranářská Aura", - "hud.skill.sc_wardaura_unlock": "Dovolí ochránit přátele před útoky{SP}", - "hud.skill.sc_wardaura_strength_title": "Síla", - "hud.skill.sc_wardaura_strength": "Síla ochrany se zvýší o 20%{SP}", - "hud.skill.sc_wardaura_duration_title": "Délka", - "hud.skill.sc_wardaura_duration": "Efekt vaší ochrany potrvá o 30% déle{SP}", - "hud.skill.sc_wardaura_range_title": "Rádius", - "hud.skill.sc_wardaura_range": "Ochrana dosáhne o 25% dále{SP}", - "hud.skill.sc_wardaura_cost_title": "Spotřeba Výdrže", - "hud.skill.sc_wardaura_cost": "Tvorba ochrany stojí o 20% méně Energie{SP}", - // Staff - "hud.skill.st_shockwave_range_title" : "Dosah Rázové vlny", - "hud.skill.st_shockwave_range" : "Umožný hodit věci mimo dosah. Dosah se zvýšil o 20%{SP}", - "hud.skill.st_shockwave_cost_title" : "Spotřeba Rázové vlny", - "hud.skill.st_shockwave_cost" : "Snižuje spotřebu energie pro házení bezbraných vesničanů o 20%{SP}", - "hud.skill.st_shockwave_knockback_title" : "Ráz Rázové vlny", - "hud.skill.st_shockwave_knockback" : "Zvyšuje odhození o 30%{SP}", - "hud.skill.st_shockwave_damage_title" : "Poškození Rázové Vlny", - "hud.skill.st_shockwave_damage" : "Zvyšuje poškození o 30%{SP}", - "hud.skill.st_shockwave_unlock_title" : "Shockwave Unlock", - "hud.skill.st_shockwave_unlock" : "Umožnuje odhazovat objekty pomocí ohně{SP}", - "hud.skill.st_flamethrower_title" : "Plamenomet", - "hud.skill.st_flamethrower" : "Podpaluje, jdeme péct", - "hud.skill.st_flame_velocity_title" : "Rychlost metání", - "hud.skill.st_flame_velocity" : "Zvýší rychlost ohně o 25% {SP}", - "hud.skill.st_flamethrower_range_title" : "Dosah Plamenometu", - "hud.skill.st_flamethrower_range" : "Když plameny nedosáhnou, tak je potřeba je zvětšit o 25% {SP}", - "hud.skill.st_energy_drain_title" : "Spotřeba Energie", - "hud.skill.st_energy_drain" : "Zmenší spotřebu energie o 20%{SP}", - "hud.skill.st_flamethrower_damage_title" : "Poškození Plamenometem", - "hud.skill.st_flamethrower_damage" : "Zvýší poškození o 30%{SP}", - "hud.skill.st_explosion_radius_title" : "Rozsah Exploze", - "hud.skill.st_explosion_radius" : "Cím větší, tím lepší. Zvětší Rádius Exploze o 10%{SP}", - "hud.skill.st_energy_regen_title" : "Obnova Výdrže", - "hud.skill.st_energy_regen" : "Zvýší generaci výdrže o 20%{SP}", - "hud.skill.st_fireball_title" : "Ohnivá Koule", - "hud.skill.st_fireball" : "Hrajte aport s nepřáteli", - "hud.skill.st_damage_title" : "Poškození", - "hud.skill.st_damage" : "Zvětší Poškození o 20%{SP}", - "hud.skill.st_explosion_title" : "Exploze", - "hud.skill.st_explosion" : "Když oheň nestačí{SP}", - // Bow - "hud.skill.bow_projectile_speed_title" : "Rychlost Projektilu", - "hud.skill.bow_projectile_speed" : "Zvětšuje rozsah, rychlost o 30%{SP}", - "hud.skill.bow_arrow_count_title" : "Počet Šípů", - "hud.skill.bow_arrow_count" : "Vystřelí další šíp při odskoku{SP}", - "hud.skill.bow_repeater_cost_title" : "Zmenšení Spotřeby", - "hud.skill.bow_repeater_cost" : "Sníží spotřebu Energie o 30%{SP}", - "hud.skill.bow_repeater_glide_title" : "Plachtění Opakovače", - "hud.skill.bow_repeater_glide" : "Doplachti dál při opakování{SP}", - "hud.skill.bow_repeater_damage_title" : "Poškození během opakování", - "hud.skill.bow_repeater_damage" : "Zvýší poškození o 40%{SP}", - "hud.skill.bow_repeater_unlock_title" : "Odemčení Opakovače", - "hud.skill.bow_repeater_unlock" : "Odemkne možnost odskočit ve vzduchu a vystřelit haldu šípů{SP}", - "hud.skill.bow_charged_title" : "Silný Výstřel", - "hud.skill.bow_charged" : "Protože si počkal/a dýl", - "hud.skill.bow_charged_knockback_title" : "Nabitý Ráz", - "hud.skill.bow_charged_knockback" : "Odhoď neprátele o 25% dále{SP}", - "hud.skill.bow_charged_move_speed_title" : "Rychlost při míření", - "hud.skill.bow_charged_move_speed" : "Zvýší pohyb během natahování luku o 25%{SP}", - "hud.skill.bow_charged_speed_title" : "Nabitá rychlost ", - "hud.skill.bow_charged_speed" : "Zvýší jak rychle lze střílet o 10%{SP}", - "hud.skill.bow_charged_projectile_speed_title" : "Rychlost Nabitého Projektilu", - "hud.skill.bow_charged_projectile_speed" : "Rychlost projektilu se zvětší o 20% během nabijení{SP}", - "hud.skill.bow_charged_drain_title" : "Spotřeba během Nabijení", - "hud.skill.bow_charged_drain" : "Snižuje spotřebu nabití o 15%{SP}", - "hud.skill.bow_charged_damage_title" : "Nabitý Poškození", - "hud.skill.bow_charged_damage" : "Zvyšuje Poškození o 20%{SP}", - "hud.skill.bow_energy_regen_title" : "Regenerace Energie", - "hud.skill.bow_energy_regen" : "Zvyšuje zisk Energie o 40%{SP}", - "hud.skill.bow_title" : "Výstřel Šípu", - "hud.skill.bow" : "Nekoneční toulec, nepatří do ruky dětem", - "hud.skill.bow_damage_title" : "Poškození", - "hud.skill.bow_damage" : "Zvyšuje poškození o 25%{SP}", - // Hammer - "hud.skill.hmr_leap_radius_title" : "Rádius Vyšlehnutí", - "hud.skill.hmr_leap_radius" : "Zvětšuje rádius boucnutí do země by 1 meter{SP}", - "hud.skill.hmr_leap_distance_title" : "Vzdálenost Vyšlehnutí", - "hud.skill.hmr_leap_distance" : "Zvětší vzdálenost o 25%{SP}", - "hud.skill.hmr_leap_cost_title" : "Spotřeba při Vyšlehnutí", - "hud.skill.hmr_leap_cost" : "Sníží cenu skoku o 25%{SP}", - "hud.skill.hmr_leap_knockback_title" : "Odražení", - "hud.skill.hmr_leap_knockback" : "Zvyšuje odražení z Vyšlehnutí o 50%{SP}", - "hud.skill.hmr_leap_damage_title" : "Poškození Vyšlehnutí", - "hud.skill.hmr_leap_damage" : "Zvyšuje poškození při Vyšlehnutí 40%{SP}", - "hud.skill.hmr_unlock_leap_title" : "Odemknout Vyšlehnutí", - "hud.skill.hmr_unlock_leap" : "Unlocks a leap{SP}", - "hud.skill.hmr_charged_melee_title" : "Nabitý Rozkmit", - "hud.skill.hmr_charged_melee" : "Útok na blízko, ale silnější", - "hud.skill.hmr_charged_rate_title" : "Rychlost Nabití", - "hud.skill.hmr_charged_rate" : "Zvýší rychlost nabití o 25%{SP}", - "hud.skill.hmr_charged_melee_nrg_drain_title" : "Menší Spotřeba Energie", - "hud.skill.hmr_charged_melee_nrg_drain" : "Snižuje spotřebu energie během Srážky o 25%{SP}", - "hud.skill.hmr_charged_melee_damage_title" : "Poškození", - "hud.skill.hmr_charged_melee_damage" : "Zvětší poškození nabitého rozkmitu o 25%{SP}", - "hud.skill.hmr_charged_melee_knockback_title" : "Knockback", - "hud.skill.hmr_charged_melee_knockback" : "Masivně zvětšuje knockback Rozkmitu o 50%{SP}", - "hud.skill.hmr_single_strike_title" : "Jednoduchý Úder", - "hud.skill.hmr_single_strike" : "Jednoduchý jako ty", - "hud.skill.hmr_single_strike_regen_title" : "Regenerace Výdrže", - "hud.skill.hmr_single_strike_regen" : "Zvyšuje Výdrž při každém povedeném úderu{SP}", - "hud.skill.hmr_single_strike_speed_title" : "Rychlost Jednoduchého Útoku", - "hud.skill.hmr_single_strike_speed" : "Zvýší rychlost útoku pro Jednoduchý Útok při trefě{SP}", - "hud.skill.hmr_single_strike_damage_title" : "Poškození Jednoduchého Útoku", - "hud.skill.hmr_single_strike_damage" : "Při každém povedeném úderu zvyšuje Poškození{SP}", - "hud.skill.hmr_single_strike_knockback_title" : "Odražení pomocí Jednoduchého Útoku", - "hud.skill.hmr_single_strike_knockback" : "Zvyšuje potencial odhození o 50%{SP}", - "hud.skill." : "", - // Sword - "hud.skill.sw_trip_str_title": "Trojtý Úder", - "hud.skill.sw_trip_str": "Udeříš až 3x", - "hud.skill.sw_trip_str_combo_title": "Kombo Trojtého Úderu", - "hud.skill.sw_trip_str_combo": "Odemkne škálování kombíček na trojtým útoku{SP}", - "hud.skill.sw_trip_str_dmg_title": "Poškození Trojtým Úderem", - "hud.skill.sw_trip_str_dmg": "Zvyšuje poškození při každém podařeném úderu{SP}", - "hud.skill.sw_trip_str_sp_title": "Rychlost Trojtého Úderu", - "hud.skill.sw_trip_str_sp": "Zvýší rychlost útoku při každém úspešném úderu{SP}", - "hud.skill.sw_trip_str_reg_title": "Regenerace při Trojtém Úderu", - "hud.skill.sw_trip_str_reg": "Regeneruje Výdrž při každém úspešném úderu{SP}", - "hud.skill.sw_dash_title": "Dash", - "hud.skill.sw_dash": "Proběhni přes nepřátele", - "hud.skill.sw_dash_dmg_title": "Poškození Dashem", - "hud.skill.sw_dash_dmg": "Zvýší poškození o 20%{SP}", - "hud.skill.sw_dash_drain_title": "Menší spotřeba při Dashy", - "hud.skill.sw_dash_drain": "Sníží průběžnou spotřebu energie o 25%{SP}", - "hud.skill.sw_dash_cost_title": "Cena Dashe ", - "hud.skill.sw_dash_cost": "Sníží celkovou spotřebu energie o 25%{SP}", - "hud.skill.sw_dash_speed_title": "Rychlost Dashe", - "hud.skill.sw_dash_speed": "Zvýší rychlost při Dashování o 30%{SP}", - "hud.skill.sw_dash_inf_title": "Nekoneční Dash", - "hud.skill.sw_dash_inf": "Nechá tě používát Dash nekonečně dlouho, než ti dojde energie{SP}", - "hud.skill.sw_dash_scale_title": "Škálování Poškození při Dashy", - "hud.skill.sw_dash_scale": "Zvýší škálování poškození o 20%{SP}", - "hud.skill.sw_spin_title": "Odemknout Roztočení", - "hud.skill.sw_spin": "Odemkne roztočení{SP}", - "hud.skill.sw_spin_dmg_title": "Poškození Roztočení", - "hud.skill.sw_spin_dmg": "Zvýší poškození, které udělíš o 40%{SP}", - "hud.skill.sw_spin_spd_title": "Rychlost Roztočení", - "hud.skill.sw_spin_spd": "Zvýší rychlost roztočení o 25%{SP}", - "hud.skill.sw_spin_cost_title": "Cena Roztočení", - "hud.skill.sw_spin_cost": "Sníží cenu roztočení o 25%{SP}", - "hud.skill.sw_spin_spins_title": "Počet točení při Roztočení", - "hud.skill.sw_spin_spins": "Zvýší počet otoček během roztočení{SP}", - "hud.skill.sw_interrupt_title": "Překažení Útoků", - "hud.skill.sw_interrupt": "Dokáže ihned přerušit útok dalším útokem{SP}", - // Axe - "hud.skill.axe_double_strike_title": "Dvojtý Úder", - "hud.skill.axe_double_strike": "Skácej své nepřátele", - "hud.skill.axe_double_strike_combo_title": "Kombo Dvojtého Úderu", - "hud.skill.axe_double_strike_combo": "Odemkne Dvojtý Útok{SP}", - "hud.skill.axe_double_strike_damage_title": "Poškození Dvojtého Úderu", - "hud.skill.axe_double_strike_damage": "Zvyšuje poškození při každém podařeném úderu{SP}", - "hud.skill.axe_double_strike_speed_title": "Rychlost Dvojtého Úderu", - "hud.skill.axe_double_strike_speed": "Zvyšuje Rychlost Útoku při každém podařeném úderu{SP}", - "hud.skill.axe_double_strike_regen_title": "Regenerace při Dvojtém Útoku", - "hud.skill.axe_double_strike_regen": "Zvyšuje regeneraci Výdrže při každém podařeném úderu{SP}", - "hud.skill.axe_spin_title": "Roztočení Sekery", - "hud.skill.axe_spin": "Točíš se správným směrem...", - "hud.skill.axe_infinite_axe_spin_title": "Nekonečné Roztočení Sekery", - "hud.skill.axe_infinite_axe_spin": "Toč Sekeru dokaď máš Energii{SP}", - "hud.skill.axe_spin_damage_title": "Poškození Roztočení", - "hud.skill.axe_spin_damage": "Zvýší poškození, které udělíš o 30%{SP}", - "hud.skill.axe_spin_helicopter_title": "Vrtulníček", - "hud.skill.axe_spin_helicopter": "Při pádu budeš padat pomaleji při Roztočení Sekery{SP}", - "hud.skill.axe_spin_speed_title": "Rychlost Roztočení", - "hud.skill.axe_spin_speed": "Zvýší Rychlost Roztočení o 25%{SP}", - "hud.skill.axe_spin_cost_title": "Cena Roztočení", - "hud.skill.axe_spin_cost": "Sníží spotřebu výdrže o 25%{SP}", - "hud.skill.axe_unlock_leap_title": "Odemknout Vyšlehnutí", - "hud.skill.axe_unlock_leap": "Odemkne Vyšlehnutí{SP}", - "hud.skill.axe_leap_damage_title": "Poškození při Vyšlehnutí", - "hud.skill.axe_leap_damage": "Zvýší poškození Vyšlehnutí o 35%{SP}", - "hud.skill.axe_leap_knockback_title": "Odražení při Vyšlehnutí", - "hud.skill.axe_leap_knockback": "Při Vyšlehnutí, zvýší odražení o 40%{SP}", - "hud.skill.axe_leap_cost_title": "Cena Vyšlehnutí", - "hud.skill.axe_leap_cost": "Sníží cenu vyšlehnutí o 25%{SP}", - "hud.skill.axe_leap_distance_title": "Dosah Vyšlehnutí", - "hud.skill.axe_leap_distance": "Zvýší dosah o 20%{SP}", - - - // crafting - "hud.crafting": "Výroba", - "hud.crafting.recipes": "Recepty", - "hud.crafting.ingredients": "Ingredience:", - "hud.crafting.craft": "Vyrobit", - "hud.crafting.tool_cata": "Potřeba:", - - // Group - - "hud.group": "Skupina", - "hud.group.invite_to_join": "[{name}] tě pozval do skupiny!", - "hud.group.invite_to_trade": "[{name}] by chtěl s tebou obchodovat.", - "hud.group.invite": "Pozvat", - "hud.group.kick": "Vyhodit", - "hud.group.assign_leader": "Nastavit Vůdcem", - "hud.group.leave": "Opustit Skupinu", - "hud.group.dead" : "Mrtvý", - "hud.group.out_of_range": "Nedosažitelný", - "hud.group.add_friend": "Přidat Přítele", - "hud.group.link_group": "Propojit Skupiny", - "hud.group.in_menu": "V Menu", - "hud.group.members": "Členové Skupiny", - - - - - // Settings - "hud.settings.general": "Obecné", - "hud.settings.none": "Nic", - "hud.settings.press_behavior.toggle": "Přepnout", - "hud.settings.press_behavior.hold": "Podržet", - "hud.settings.help_window": "Okno nápovědy", - "hud.settings.debug_info": "Ladící informace", - "hud.settings.tips_on_startup": "Rady", - "hud.settings.ui_scale": "Velikost UI", - "hud.settings.relative_scaling": "Relativní škálování", - "hud.settings.custom_scaling": "Vlastní škálování", - "hud.settings.crosshair": "Zaměřování", - "hud.settings.transparency": "Průhlednost", - "hud.settings.hotbar": "Hotbar", - "hud.settings.toggle_shortcuts": "Povolit Zkratky", - "hud.settings.buffs_skillbar": "Buffy u Skillbaru", - "hud.settings.buffs_mmap": "Buffy u Minimapy", - "hud.settings.toggle_bar_experience": "Povolit Zkušenostní Bar", - "hud.settings.scrolling_combat_text": "Létajíci Combat Text", - "hud.settings.single_damage_number": "Jednotná čísla Poškození", - "hud.settings.cumulated_damage": "Seskupený Poškození", - "hud.settings.incoming_damage": "Příchozí Poškození", - "hud.settings.cumulated_incoming_damage": "Seskupený Příchozí Poškození", - "hud.settings.speech_bubble": "Povídací Bublina", - "hud.settings.speech_bubble_dark_mode": "Tmavá Povídací Bublina", - "hud.settings.speech_bubble_icon": "Ikona Povídací Bubliny", - "hud.settings.energybar_numbers": "Čísla u Baru Energie", - "hud.settings.values": "Hodnoty", - "hud.settings.percentages": "Procenta", - "hud.settings.chat": "Chat", - "hud.settings.background_transparency": "Průhlednost Pozadí", - "hud.settings.chat_character_name": "Jména Postav v Chatu", - "hud.settings.loading_tips": "Rady v Načítání", - "hud.settings.reset_interface": "Výchozí Nastavení", - - "hud.settings.pan_sensitivity": "Citlivost Rozhledu", - "hud.settings.zoom_sensitivity": "Citlivost Přiblížení", - "hud.settings.camera_clamp_angle": "Úhel pro vertikální režim upnutí kamery", - "hud.settings.invert_scroll_zoom": "Invertovat rolování zvětšení", - "hud.settings.invert_mouse_y_axis": "Obrátit osu Y myši", - "hud.settings.invert_controller_y_axis": "Obrátit osu Y ovladače", - "hud.settings.enable_mouse_smoothing": "Vyhlazení kamery", - "hud.settings.free_look_behavior": "Chování volného pohledu", - "hud.settings.auto_walk_behavior": "Chování Auto chůze", - "hud.settings.camera_clamp_behavior": "Chování připnuté kamery", - "hud.settings.stop_auto_walk_on_input": "Přestat Auto chodit při pohybu", - "hud.settings.reset_gameplay": "Výchozí Nastavení", - - "hud.settings.view_distance": "Vykreslovací Vzdálenost", - "hud.settings.sprites_view_distance": "Vykreslovací Vzdálenost Spritů", - "hud.settings.figures_view_distance": "Vykreslovací Vzdálenost Entit", - "hud.settings.maximum_fps": "Maximum FPS", - "hud.settings.fov": "Úhel pohledu (stupně)", - "hud.settings.gamma": "Gama", - "hud.settings.exposure": "Expozice", - "hud.settings.ambiance": "Jas prostředí", - "hud.settings.antialiasing_mode": "Režim AntiAliasing", - "hud.settings.upscale_factor": "Interní Rozlišení", - "hud.settings.cloud_rendering_mode": "Vykreslování Mraků", - "hud.settings.fluid_rendering_mode": "Vykreslování Vody", - "hud.settings.fluid_rendering_mode.cheap": "Levný", - "hud.settings.fluid_rendering_mode.shiny": "Blíštivý", - "hud.settings.cloud_rendering_mode.minimal": "Minimalní", - "hud.settings.cloud_rendering_mode.low": "Nizký", - "hud.settings.cloud_rendering_mode.medium": "Střední", - "hud.settings.cloud_rendering_mode.high": "Vysoký", - "hud.settings.cloud_rendering_mode.ultra": "Ultra", - "hud.settings.fullscreen": "Celá Obrazovka", - "hud.settings.fullscreen_mode": "Režim Celé obrazovky", - "hud.settings.fullscreen_mode.exclusive": "Exkluzivní", - "hud.settings.fullscreen_mode.borderless": "Bezokrajový", - "hud.settings.particles": "Částice", - "hud.settings.resolution": "Rozlišení", - "hud.settings.bit_depth": "Bitová Hloubka", - "hud.settings.refresh_rate": "Obnovovací Frekvence", - "hud.settings.lighting_rendering_mode": "Vykreslování Osvětlení", - "hud.settings.lighting_rendering_mode.ashikhmin": "Typ A - Vysoký ", - "hud.settings.lighting_rendering_mode.blinnphong": "Typ B - Střední", - "hud.settings.lighting_rendering_mode.lambertian": "Typ L - Levný", - "hud.settings.shadow_rendering_mode": "Vykreslování Stínů", - "hud.settings.shadow_rendering_mode.none": "Nic", - "hud.settings.shadow_rendering_mode.cheap": "Levný", - "hud.settings.shadow_rendering_mode.map": "Mapa", - "hud.settings.shadow_rendering_mode.map.resolution": "Rozlišení", - "hud.settings.lod_detail": "LoD Detail", - "hud.settings.save_window_size": "Pamatovat Okno", - "hud.settings.reset_graphics": "Výchozí Nastavení", - - - "hud.settings.music_volume": "Hlasitost Hudby", - "hud.settings.sound_effect_volume": "Hlasitost Efektů", - "hud.settings.audio_device": "Vstupní Zařízení", - "hud.settings.reset_sound": "Výchozí Nastavení", - - "hud.settings.awaitingkey": "Zmáčkni klávesu...", - "hud.settings.unbound": "Žádná", - "hud.settings.reset_keybinds": "Výchozí", - - /// Socialní - - "hud.social": "Společnost", - "hud.social.online": "Aktivní", - "hud.social.friends": "Přátelé", - "hud.social.not_yet_available": "Ještě není dostupné", - "hud.social.faction": "Cech", - "hud.social.play_online_fmt": "{nb_player} je aktivní", - "hud.social.name": "Jméno", - "hud.social.level": "Úroveň", - "hud.social.zone": "Zóna", - "hud.social.account": "Účet", - - /// Obchod - - "hud.trade.trade_window": "Obchod", - "hud.trade.phase1_description": "Přetáhněte položky.", - "hud.trade.phase2_description": "Obchod je nyní uzamčen, abyste měli\n čas jej zkontrolovat.", - /// Phase3 should only be visible for a few milliseconds if everything is working properly, but is included for completeness - "hud.trade.phase3_description": "Probíhá zpracování.", - "hud.trade.persons_offer": "Nabídka {playername}", - "hud.trade.has_accepted": "{playername}přijal obchod", - "hud.trade.accept": "Akceptovat", - "hud.trade.decline": "Odmítnout", - "hud.trade.invite_sent": "Žádost o obchod zaslána {playername}.", - "hud.trade.result.completed": "Obchod proběhl úspěšně.", - "hud.trade.result.declined": "Obchod odmítnut.", - "hud.trade.result.nospace": "Nedostatek místa pro dokončení.", - "hud.trade.buy_price": "Cena koupě", - "hud.trade.sell_price": "Cena prodeje", - "hud.trade.coin": "Peníze", - - - /// misc - - "hud.do_not_show_on_startup": "Nezobrazovat toto při spuštění", - "hud.show_tips": "Zobrazit Rady", - "hud.quests": "Úkoly", - "hud.you_died": "Umřel si", - "hud.waypoint_saved": "Waypoint uložen", - "hud.sp_arrow_txt": "SP", - - "hud.press_key_to_show_keybindings_fmt": "[{key}] Ovládání", - "hud.press_key_to_toggle_lantern_fmt": "[{key}] Lampa", - "hud.press_key_to_show_debug_info_fmt": "Zmáčkni {key} pro Ladící Menu", - "hud.press_key_to_toggle_keybindings_fmt": "Zmáčkni {key} pro Hastavení Ovládání", - "hud.press_key_to_toggle_debug_info_fmt": "Zmáčkni {key} pro Ladící Informace", - - // Respawn message - "hud.press_key_to_respawn": r#"Zmáčkni {key} pro oživení u posledního navštíveného ohně."#, - - // Tutorial Button - "hud.tutorial_btn": r#"Tutorial"#, - "hud.tutorial_click_here": r#"Zmáčkni [ {key} ] pro odemčení kurzoru a zmáčkni na toto tlačítko"#, - "hud.tutorial_elements": r#"Výroba"#, - -"hud.temp_quest_headline": r#"vítej Poutníku"#, -"hud.temp_quest_text": r#"Na začátek své cesty bys ses mohl prohledat tuto vesnici a sbírat zásoby. - -Je ti dovoleno vzít si to co potřebuješ na svou cestu! - -V pravém dolním rohu obrazovky najdete různé věci, jako je taška, nabídka tvorby a mapa. - -Nabídka Tvorby vám umožní vytvářet brnění, zbraně, jídlo a mnoho dalšího! - -Divoká zvířata po celém městě jsou skvělým zdrojem koženého odpadu, který vytváří určitou ochranu před nebezpečím tam venku. - -Kdykoli se budeš cítit připraven, pokus se získat ještě lepší vybavení z mnoha výzev vyznačených na mapě! -"#, - - "hud.spell": "Dovednosti", - // Diary - "hud.diary": "Deník", - - "hud.free_look_indicator": "Volný pohled je povolený. Můžeš ho vypnout pomocí {key} .", - "hud.camera_clamp_indicator": "Vertikální upnutá kamera je zaplá, Můžeš to vypnout pomocí {key}", - "hud.auto_walk_indicator": "Auto Chůze je zaplá", - - // SCT outputs - "hud.sct.experience": "{amount} Zkušeností", - "hud.sct.block": "BLOKOVÁNO", - - /// End HUD section - - - // Buffs - "buff.remove": "Klikni pro zrušení", - "buff.title.missing": "Chybějící název", - "buff.desc.missing": "Chybějící popis", - "buff.title.heal": "Léčba", - "buff.desc.heal": "Přídá život během určitého času.", - "buff.title.potion": "Lektvar", - "buff.desc.potion": "Piju...", - "buff.title.saturation": "Nasycení", - "buff.desc.saturation": "Přídá život během času ze Spotřebních.", - "buff.title.campfire_heal": "Léčba Táborákem", - "buff.desc.campfire_heal": "Odpočinek u ohně léčí 1% za sekundu.", - "buff.title.invulnerability": "Nezranitelnost", - "buff.desc.invulnerability": "Žádný útok tě nezraní.", - "buff.title.protectingward": "Ochraná Vizita", - "buff.desc.protectingward": "Jsi chráněn, nějak, před útoky.", - // Debuffs - "buff.title.bleed": "Krvácení", - "buff.desc.bleed": "Způsobuje pravidelné poškození.", - "buff.title.cursed": "Prokletí", - "buff.desc.cursed": "Jsi prokletý.", - // Buffs stats - "buff.stat.health": "Obnoví {str_total} Životů", - "buff.stat.increase_max_energy": "Zvedne Maximalní Výdrž o {strength}", - "buff.stat.increase_max_health": "Zvedne Maximální počet životů o {strength}", - "buff.stat.invulnerability": "Zaručuje Nezranitelnost", - // Text - "buff.text.over_seconds": "více než {dur_secs} sekund", - "buff.text.for_seconds": "po dobu {dur_secs} sekund", - - /// Start GameInput section - - "gameinput.primary": "Základní Útok", - "gameinput.secondary": "Druhý Útok/Blok/Míření", - "gameinput.slot1": "Hotbar Slot 1", - "gameinput.slot2": "Hotbar Slot 2", - "gameinput.slot3": "Hotbar Slot 3", - "gameinput.slot4": "Hotbar Slot 4", - "gameinput.slot5": "Hotbar Slot 5", - "gameinput.slot6": "Hotbar Slot 6", - "gameinput.slot7": "Hotbar Slot 7", - "gameinput.slot8": "Hotbar Slot 8", - "gameinput.slot9": "Hotbar Slot 9", - "gameinput.slot10": "Hotbar Slot 10", - "gameinput.swaploadout": "Výměna Vybavení", - "gameinput.togglecursor": "Povolit Kurzor", - "gameinput.help": "Povolit Okno Nápovědy", - "gameinput.toggleinterface": "Povolit Rozhraní", - "gameinput.toggledebug": "Povolit FPS a Debug info", - "gameinput.screenshot": "Pořídit Snímek Obrazovky", - "gameinput.toggleingameui": "Povolit Jména", - "gameinput.fullscreen": "Povolit Celou Obrazovku", - "gameinput.moveforward": "Pohyb Dopředu", - "gameinput.moveleft": "Pohyb Doleva", - "gameinput.moveright": "Pohyb Doprava", - "gameinput.moveback": "Pohyb Dozádu", - "gameinput.jump": "Skok", - "gameinput.glide": "Kluzák", - "gameinput.roll": "Kotrmelec", - "gameinput.climb": "Lézt", - "gameinput.climbdown": "Lézt Dolů", - "gameinput.wallleap": "Wall Leap", - "gameinput.togglelantern": "Lucerna", - "gameinput.mount": "Nasednout", - "gameinput.chat": "Chat", - "gameinput.command": "Príkaz", - "gameinput.escape": "Nabídka", - "gameinput.map": "Mapa", - "gameinput.bag": "Taška", - "gameinput.trade": "Obchod", - "gameinput.social": "Společenost", - "gameinput.sit": "Sednout", - "gameinput.spellbook": "Dovednosti", - "gameinput.settings": "Nastavení", - "gameinput.respawn": "Oživení", - "gameinput.charge": "Charge", - "gameinput.togglewield": "Vzít zbraň do ruky", - "gameinput.interact": "Interagovat", - "gameinput.freelook": "Volný Pohled", - "gameinput.autowalk": "Auto Chůze", - "gameinput.cameraclamp": "Připnutí Kamery", - "gameinput.dance": "Tanec", - "gameinput.select": "Vybrat Entitu", - "gameinput.acceptgroupinvite": "Příjmout pozvání do Skupiny", - "gameinput.declinegroupinvite": "Odmítnout pozvání do Skupiny", - "gameinput.cyclecamera": "Druhy kamer", - "gameinput.crafting": "Tvorba", - "gameinput.fly": "Létání", - "gameinput.sneak": "Plížení", - "gameinput.swimdown": "Plavat Dolů", - "gameinput.swimup": "Plavat Nahoru", - - - /// End GameInput section - - - /// Start chracter selection section - "char_selection.loading_characters": "Načítání postavy...", - "char_selection.delete_permanently": "Chcete smazat tuto postavu?", - "char_selection.deleting_character": "Probíhá mazání postavy...", - "char_selection.change_server": "Změnit server", - "char_selection.enter_world": "Vstup do světa", - "char_selection.logout": "Odhlásit", - "char_selection.create_new_character": "Nová Postava", - "char_selection.creating_character": "Probíhá tvorba nové postavy", - "char_selection.character_creation": "Tvůrce postavy", - "char_selection.human_default": "Výchozí postava", - "char_selection.level_fmt": "úroveň {level_nb}", - "char_selection.uncanny_valley": "Divočina", - "char_selection.plains_of_uncertainty": "Pole nejistoty", - "char_selection.beard": "Brada", - "char_selection.hair_style": "Styl vlasů", - "char_selection.hair_color": "Barva vlasů", - "char_selection.chest_color": "Barva hrudníku", - "char_selection.eye_color": "Barva očí", - "char_selection.skin": "Kůže", - "char_selection.eyebrows": "Obočí", - "char_selection.accessories": "Doplňky", - "char_selection.create_new_charater": "Nová postava", - "char_selection.eyeshape": "Tvar očí", - "char_selection.create_info_name": "Tvá postava potřebuje jméno!", - - /// End chracter selection section - - - /// Start character window section - "character_window.character_name": "Jméno postavy", - // Charater stats - "character_window.character_stats": r#"Síla - -Zdatnost - -Síla vůle -"#, - - - /// ???Start character window section - - - /// Start Escape Menu Section - "esc_menu.logout": "Odhlásit", - "esc_menu.quit_game": "Opustit hru", - /// End Escape Menu Section }, vector_map: { diff --git a/assets/voxygen/i18n/cz_CZ/buff.ron b/assets/voxygen/i18n/cz_CZ/buff.ron new file mode 100644 index 0000000000..4f8a6f8f01 --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/buff.ron @@ -0,0 +1,40 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish +( + string_map: { + // Buffs + "buff.remove": "Klikni pro zrušení", + "buff.title.missing": "Chybějící název", + "buff.desc.missing": "Chybějící popis", + "buff.title.heal": "Léčba", + "buff.desc.heal": "Přídá život během určitého času.", + "buff.title.potion": "Lektvar", + "buff.desc.potion": "Piju...", + "buff.title.saturation": "Nasycení", + "buff.desc.saturation": "Přídá život během času ze Spotřebních.", + "buff.title.campfire_heal": "Léčba Táborákem", + "buff.desc.campfire_heal": "Odpočinek u ohně léčí 1% za sekundu.", + "buff.title.invulnerability": "Nezranitelnost", + "buff.desc.invulnerability": "Žádný útok tě nezraní.", + "buff.title.protectingward": "Ochraná Vizita", + "buff.desc.protectingward": "Jsi chráněn, nějak, před útoky.", + // Debuffs + "buff.title.bleed": "Krvácení", + "buff.desc.bleed": "Způsobuje pravidelné poškození.", + "buff.title.cursed": "Prokletí", + "buff.desc.cursed": "Jsi prokletý.", + // Buffs stats + "buff.stat.health": "Obnoví {str_total} Životů", + "buff.stat.increase_max_energy": "Zvedne Maximalní Výdrž o {strength}", + "buff.stat.increase_max_health": "Zvedne Maximální počet životů o {strength}", + "buff.stat.invulnerability": "Zaručuje Nezranitelnost", + // Text + "buff.text.over_seconds": "více než {dur_secs} sekund", + "buff.text.for_seconds": "po dobu {dur_secs} sekund", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/cz_CZ/char_selection.ron b/assets/voxygen/i18n/cz_CZ/char_selection.ron new file mode 100644 index 0000000000..92608387fa --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/char_selection.ron @@ -0,0 +1,34 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish +( + string_map: { + "char_selection.loading_characters": "Načítání postavy...", + "char_selection.delete_permanently": "Chcete smazat tuto postavu?", + "char_selection.deleting_character": "Probíhá mazání postavy...", + "char_selection.change_server": "Změnit server", + "char_selection.enter_world": "Vstup do světa", + "char_selection.logout": "Odhlásit", + "char_selection.create_new_character": "Nová Postava", + "char_selection.creating_character": "Probíhá tvorba nové postavy", + "char_selection.character_creation": "Tvůrce postavy", + "char_selection.human_default": "Výchozí postava", + "char_selection.level_fmt": "úroveň {level_nb}", + "char_selection.uncanny_valley": "Divočina", + "char_selection.plains_of_uncertainty": "Pole nejistoty", + "char_selection.beard": "Brada", + "char_selection.hair_style": "Styl vlasů", + "char_selection.hair_color": "Barva vlasů", + "char_selection.chest_color": "Barva hrudníku", + "char_selection.eye_color": "Barva očí", + "char_selection.skin": "Kůže", + "char_selection.eyebrows": "Obočí", + "char_selection.accessories": "Doplňky", + "char_selection.create_new_charater": "Nová postava", + "char_selection.eyeshape": "Tvar očí", + "char_selection.create_info_name": "Tvá postava potřebuje jméno!", + }, + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/cz_CZ/common.ron b/assets/voxygen/i18n/cz_CZ/common.ron new file mode 100644 index 0000000000..a89b149269 --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/common.ron @@ -0,0 +1,106 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish +( + string_map: { + // Texts used in multiple locations with the same formatting + "common.username": "jméno", + "common.singleplayer": "Hra jednoho hráče", + "common.multiplayer": "Hra více hráčů", + "common.servers": "Servery", + "common.quit": "Vypnout", + "common.settings": "Nastavení", + "common.languages": "Jazyky", + "common.interface": "Rozhraní", + "common.gameplay": "Hra", + "common.controls": "Ovládání", + "common.video": "Grafika", + "common.sound": "Zvuk", + "common.resume": "Pokračovat", + "common.characters": "Postavy", + "common.close": "Zavřít", + "common.yes": "Ano", + "common.no": "Ne", + "common.back": "Zpět", + "common.create": "Vytvořik", + "common.okay": "OK", + "common.add": "Přidat", + "common.accept": "Příjmout", + "common.decline": "Odmítnout", + "common.disclaimer": "Zřeknutí se odpovědnosti", + "common.cancel": "Zrušit", + "common.none": "Nic", + "common.error": "Chyba", + "common.fatal_error": "Fatalní Chyba", + "common.you": "ty", + "common.automatic": "Auto", + "common.random": "Náhodný", + "common.empty": "Prázdný", + + // Settings Window title + "common.interface_settings": "Rozhraní", + "common.gameplay_settings": "Hra", + "common.controls_settings": "Ovládání", + "common.video_settings": "Grafika", + "common.sound_settings": "Zvuk", + "common.language_settings": "Jazyk", + + // Message when connection to the server is lost + "common.connection_lost": r#"Spojení ztraceno! + Restartoval se server? + Je klient aktuální?"#, + + + "common.species.orc": "Ork", + "common.species.human": "Člověk", + "common.species.dwarf": "Trpaslík", + "common.species.elf": "Elf", + "common.species.undead": "Nemrtvý", + "common.species.danari": "Danari", + + "common.weapons.axe": "Sekera", + "common.weapons.sword": "Meč", + "common.weapons.staff": "Hůl", + "common.weapons.bow": "Luk", + "common.weapons.hammer": "Kladivo", + "common.weapons.general": "Všeobecný", + "common.weapons.sceptre": "Žezlo", + "common.weapons.shield": "Štít", + "common.weapons.spear": "Kopí", + "common.weapons.hammer_simple": "Jednoduché Kladivo", + "common.weapons.sword_simple": "Jednoduchý Meč", + "common.weapons.staff_simple": "Jednoduchá Hůl", + "common.weapons.axe_simple": "Jednoduchá Sekera", + "common.weapons.bow_simple": "Jednoduchý Luk", + "common.weapons.unique": "Unikátní", + "common.tool.debug": "Debug", + "common.tool.faming": "Farmářský Nástroj", + "common.tool.pick": "Krumpáč", + "common.kind.modular_component": "Modulární komponenta", + "common.kind.glider": "Kluzák", + "common.kind.consumable": "Spotřební", + "common.kind.throwable": "Lze házet", + "common.kind.utility": "Užitečné", + "common.kind.ingredient": "Ingredience", + "common.kind.lantern": "Lampa", + "common.hands.one": "Jednoruční", + "common.hands.two": "Dvojruční", + + "common.rand_appearance": "Náhodný vzhled", + "common.rand_name": "Náhodné Jméno", + + "common.stats.dps": "DPS", + "common.stats.power": "Moc", + "common.stats.speed": "Rychlost", + "common.stats.poise": "Postoj", + "common.stats.crit_chance": "Kritická šance", + "common.stats.crit_mult": "Crit Mult", + "common.stats.armor": "Zbroj", + "common.stats.poise_res": "Postojové res", + "common.stats.slots": "Sloty", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/cz_CZ/esc_menu.ron b/assets/voxygen/i18n/cz_CZ/esc_menu.ron new file mode 100644 index 0000000000..e3b27c71a7 --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/esc_menu.ron @@ -0,0 +1,13 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish +( + string_map: { + "esc_menu.logout": "Odhlásit", + "esc_menu.quit_game": "Opustit hru", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/cz_CZ/gameinput.ron b/assets/voxygen/i18n/cz_CZ/gameinput.ron new file mode 100644 index 0000000000..0a46dd928a --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/gameinput.ron @@ -0,0 +1,70 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish +( + string_map: { + "gameinput.primary": "Základní Útok", + "gameinput.secondary": "Druhý Útok/Blok/Míření", + "gameinput.slot1": "Hotbar Slot 1", + "gameinput.slot2": "Hotbar Slot 2", + "gameinput.slot3": "Hotbar Slot 3", + "gameinput.slot4": "Hotbar Slot 4", + "gameinput.slot5": "Hotbar Slot 5", + "gameinput.slot6": "Hotbar Slot 6", + "gameinput.slot7": "Hotbar Slot 7", + "gameinput.slot8": "Hotbar Slot 8", + "gameinput.slot9": "Hotbar Slot 9", + "gameinput.slot10": "Hotbar Slot 10", + "gameinput.swaploadout": "Výměna Vybavení", + "gameinput.togglecursor": "Povolit Kurzor", + "gameinput.help": "Povolit Okno Nápovědy", + "gameinput.toggleinterface": "Povolit Rozhraní", + "gameinput.toggledebug": "Povolit FPS a Debug info", + "gameinput.screenshot": "Pořídit Snímek Obrazovky", + "gameinput.toggleingameui": "Povolit Jména", + "gameinput.fullscreen": "Povolit Celou Obrazovku", + "gameinput.moveforward": "Pohyb Dopředu", + "gameinput.moveleft": "Pohyb Doleva", + "gameinput.moveright": "Pohyb Doprava", + "gameinput.moveback": "Pohyb Dozádu", + "gameinput.jump": "Skok", + "gameinput.glide": "Kluzák", + "gameinput.roll": "Kotrmelec", + "gameinput.climb": "Lézt", + "gameinput.climbdown": "Lézt Dolů", + "gameinput.wallleap": "Wall Leap", + "gameinput.togglelantern": "Lucerna", + "gameinput.mount": "Nasednout", + "gameinput.chat": "Chat", + "gameinput.command": "Príkaz", + "gameinput.escape": "Nabídka", + "gameinput.map": "Mapa", + "gameinput.bag": "Taška", + "gameinput.trade": "Obchod", + "gameinput.social": "Společenost", + "gameinput.sit": "Sednout", + "gameinput.spellbook": "Dovednosti", + "gameinput.settings": "Nastavení", + "gameinput.respawn": "Oživení", + "gameinput.charge": "Charge", + "gameinput.togglewield": "Vzít zbraň do ruky", + "gameinput.interact": "Interagovat", + "gameinput.freelook": "Volný Pohled", + "gameinput.autowalk": "Auto Chůze", + "gameinput.cameraclamp": "Připnutí Kamery", + "gameinput.dance": "Tanec", + "gameinput.select": "Vybrat Entitu", + "gameinput.acceptgroupinvite": "Příjmout pozvání do Skupiny", + "gameinput.declinegroupinvite": "Odmítnout pozvání do Skupiny", + "gameinput.cyclecamera": "Druhy kamer", + "gameinput.crafting": "Tvorba", + "gameinput.fly": "Létání", + "gameinput.sneak": "Plížení", + "gameinput.swimdown": "Plavat Dolů", + "gameinput.swimup": "Plavat Nahoru", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/cz_CZ/hud/bag.ron b/assets/voxygen/i18n/cz_CZ/hud/bag.ron new file mode 100644 index 0000000000..0f124dcbb3 --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/hud/bag.ron @@ -0,0 +1,39 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish +( + string_map: { + // Inventory + "hud.bag.glider": "Glider", + "hud.bag.bag": "Batoh", + "hud.bag.health": "Život", + "hud.bag.energy": "Výdrž", + "hud.bag.combat_rating": "Bojové hodnocení", + "hud.bag.protection": "Ochrana", + "hud.bag.combat_rating_desc": "Vypočítáno z života/zbroje.", + "hud.bag.protection_desc": "Redukce poškození přes brnení", + "hud.bag.inventory": "Inventář {playername}", + "hud.bag.stats_title": "Statistiky {playername}", + "hud.bag.exp": "Zkušenosti", + "hud.bag.armor": "Výzbroj", + "hud.bag.stats": "Statistiky", + "hud.bag.head": "Hlava", + "hud.bag.neck": "Krk", + "hud.bag.tabard": "Tabard", + "hud.bag.shoulders": "Ramena", + "hud.bag.chest": "Hruď", + "hud.bag.hands": "Ruce", + "hud.bag.lantern": "Lampa", + "hud.bag.belt": "Pas", + "hud.bag.ring": "Prsten", + "hud.bag.back": "Záda", + "hud.bag.legs": "Nohy", + "hud.bag.feet": "Chodidla", + "hud.bag.mainhand": "Hlavní Ruka", + "hud.bag.offhand": "Druhá Ruka", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/cz_CZ/hud/char_window.ron b/assets/voxygen/i18n/cz_CZ/hud/char_window.ron new file mode 100644 index 0000000000..0bb5977f09 --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/hud/char_window.ron @@ -0,0 +1,20 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish +( + string_map: { + /// Start character window section + "character_window.character_name": "Jméno postavy", + // Charater stats + "character_window.character_stats": r#"Síla + +Zdatnost + +Síla vůle +"#, + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/cz_CZ/hud/chat.ron b/assets/voxygen/i18n/cz_CZ/hud/chat.ron new file mode 100644 index 0000000000..d630f34e6c --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/hud/chat.ron @@ -0,0 +1,38 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish +( + string_map: { + "hud.chat.online_msg": "[{name}] je online", + "hud.chat.offline_msg": "[{name}] šel/šla offline", + + "hud.chat.default_death_msg": "[{name}] zemřel", + "hud.chat.environmental_kill_msg": "[{name}] zemřel v {environment}", + "hud.chat.fall_kill_msg": "[{name}] zemřel z pádu", + "hud.chat.suicide_msg": "[{name}] zemřel díky svému zapříčinění", + + "hud.chat.pvp_buff_kill_msg": "[{victim}] zemřel z {buff} od [{attacker}]", + "hud.chat.pvp_melee_kill_msg": "[{attacker}] porazil [{victim}]", + "hud.chat.pvp_ranged_kill_msg": "[{attacker}] postřelil [{victim}]", + "hud.chat.pvp_explosion_kill_msg": "[{attacker}] odpálil [{victim}]", + "hud.chat.pvp_energy_kill_msg": "[{attacker}] zabil [{victim}] pomocí magie", + + "hud.chat.nonexistent_buff_kill_msg": "[{victim}] zemřel pomocí {buff}", + + "hud.chat.npc_buff_kill_msg": "[{victim}] died of {buff} od {attacker}", + "hud.chat.npc_melee_kill_msg": "{attacker} zabil [{victim}]", + "hud.chat.npc_ranged_kill_msg": "{attacker} postřelil [{victim}]", + "hud.chat.npc_explosion_kill_msg": "{attacker} odpálil [{victim}]", + "hud.chat.npc_energy_kill_msg": "{attacker} zabil [{victim}] pomocí magie", + "hud.chat.npc_other_kill_msg": "{attacker} zabil [{victim}]", + + "hud.chat.loot_msg": "Sebral si [{item}]", + "hud.chat.loot_fail": "Tvůj inventář je plný!", + "hud.chat.goodbye": "nashledanou!", + "hud.chat.connection_lost": "Spojení ztraceno. Odpojuji za {time} sekund.", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/cz_CZ/hud/crafting.ron b/assets/voxygen/i18n/cz_CZ/hud/crafting.ron new file mode 100644 index 0000000000..42bd9cc4e0 --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/hud/crafting.ron @@ -0,0 +1,16 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish +( + string_map: { + "hud.crafting": "Výroba", + "hud.crafting.recipes": "Recepty", + "hud.crafting.ingredients": "Ingredience:", + "hud.crafting.craft": "Vyrobit", + "hud.crafting.tool_cata": "Potřeba:", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/cz_CZ/hud/group.ron b/assets/voxygen/i18n/cz_CZ/hud/group.ron new file mode 100644 index 0000000000..62e496b1a7 --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/hud/group.ron @@ -0,0 +1,24 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish +( + string_map: { + "hud.group": "Skupina", + "hud.group.invite_to_join": "[{name}] tě pozval do skupiny!", + "hud.group.invite_to_trade": "[{name}] by chtěl s tebou obchodovat.", + "hud.group.invite": "Pozvat", + "hud.group.kick": "Vyhodit", + "hud.group.assign_leader": "Nastavit Vůdcem", + "hud.group.leave": "Opustit Skupinu", + "hud.group.dead" : "Mrtvý", + "hud.group.out_of_range": "Nedosažitelný", + "hud.group.add_friend": "Přidat Přítele", + "hud.group.link_group": "Propojit Skupiny", + "hud.group.in_menu": "V Menu", + "hud.group.members": "Členové Skupiny", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/cz_CZ/hud/hud_settings.ron b/assets/voxygen/i18n/cz_CZ/hud/hud_settings.ron new file mode 100644 index 0000000000..3244bafc62 --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/hud/hud_settings.ron @@ -0,0 +1,108 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish +( + string_map: { + // Settings + "hud.settings.general": "Obecné", + "hud.settings.none": "Nic", + "hud.settings.press_behavior.toggle": "Přepnout", + "hud.settings.press_behavior.hold": "Podržet", + "hud.settings.help_window": "Okno nápovědy", + "hud.settings.debug_info": "Ladící informace", + "hud.settings.tips_on_startup": "Rady", + "hud.settings.ui_scale": "Velikost UI", + "hud.settings.relative_scaling": "Relativní škálování", + "hud.settings.custom_scaling": "Vlastní škálování", + "hud.settings.crosshair": "Zaměřování", + "hud.settings.transparency": "Průhlednost", + "hud.settings.hotbar": "Hotbar", + "hud.settings.toggle_shortcuts": "Povolit Zkratky", + "hud.settings.buffs_skillbar": "Buffy u Skillbaru", + "hud.settings.buffs_mmap": "Buffy u Minimapy", + "hud.settings.toggle_bar_experience": "Povolit Zkušenostní Bar", + "hud.settings.scrolling_combat_text": "Létajíci Combat Text", + "hud.settings.single_damage_number": "Jednotná čísla Poškození", + "hud.settings.cumulated_damage": "Seskupený Poškození", + "hud.settings.incoming_damage": "Příchozí Poškození", + "hud.settings.cumulated_incoming_damage": "Seskupený Příchozí Poškození", + "hud.settings.speech_bubble": "Povídací Bublina", + "hud.settings.speech_bubble_dark_mode": "Tmavá Povídací Bublina", + "hud.settings.speech_bubble_icon": "Ikona Povídací Bubliny", + "hud.settings.energybar_numbers": "Čísla u Baru Energie", + "hud.settings.values": "Hodnoty", + "hud.settings.percentages": "Procenta", + "hud.settings.chat": "Chat", + "hud.settings.background_transparency": "Průhlednost Pozadí", + "hud.settings.chat_character_name": "Jména Postav v Chatu", + "hud.settings.loading_tips": "Rady v Načítání", + "hud.settings.reset_interface": "Výchozí Nastavení", + + "hud.settings.pan_sensitivity": "Citlivost Rozhledu", + "hud.settings.zoom_sensitivity": "Citlivost Přiblížení", + "hud.settings.camera_clamp_angle": "Úhel pro vertikální režim upnutí kamery", + "hud.settings.invert_scroll_zoom": "Invertovat rolování zvětšení", + "hud.settings.invert_mouse_y_axis": "Obrátit osu Y myši", + "hud.settings.invert_controller_y_axis": "Obrátit osu Y ovladače", + "hud.settings.enable_mouse_smoothing": "Vyhlazení kamery", + "hud.settings.free_look_behavior": "Chování volného pohledu", + "hud.settings.auto_walk_behavior": "Chování Auto chůze", + "hud.settings.camera_clamp_behavior": "Chování připnuté kamery", + "hud.settings.stop_auto_walk_on_input": "Přestat Auto chodit při pohybu", + "hud.settings.reset_gameplay": "Výchozí Nastavení", + + "hud.settings.view_distance": "Vykreslovací Vzdálenost", + "hud.settings.sprites_view_distance": "Vykreslovací Vzdálenost Spritů", + "hud.settings.figures_view_distance": "Vykreslovací Vzdálenost Entit", + "hud.settings.maximum_fps": "Maximum FPS", + "hud.settings.fov": "Úhel pohledu (stupně)", + "hud.settings.gamma": "Gama", + "hud.settings.exposure": "Expozice", + "hud.settings.ambiance": "Jas prostředí", + "hud.settings.antialiasing_mode": "Režim AntiAliasing", + "hud.settings.upscale_factor": "Interní Rozlišení", + "hud.settings.cloud_rendering_mode": "Vykreslování Mraků", + "hud.settings.fluid_rendering_mode": "Vykreslování Vody", + "hud.settings.fluid_rendering_mode.cheap": "Levný", + "hud.settings.fluid_rendering_mode.shiny": "Blíštivý", + "hud.settings.cloud_rendering_mode.minimal": "Minimalní", + "hud.settings.cloud_rendering_mode.low": "Nizký", + "hud.settings.cloud_rendering_mode.medium": "Střední", + "hud.settings.cloud_rendering_mode.high": "Vysoký", + "hud.settings.cloud_rendering_mode.ultra": "Ultra", + "hud.settings.fullscreen": "Celá Obrazovka", + "hud.settings.fullscreen_mode": "Režim Celé obrazovky", + "hud.settings.fullscreen_mode.exclusive": "Exkluzivní", + "hud.settings.fullscreen_mode.borderless": "Bezokrajový", + "hud.settings.particles": "Částice", + "hud.settings.resolution": "Rozlišení", + "hud.settings.bit_depth": "Bitová Hloubka", + "hud.settings.refresh_rate": "Obnovovací Frekvence", + "hud.settings.lighting_rendering_mode": "Vykreslování Osvětlení", + "hud.settings.lighting_rendering_mode.ashikhmin": "Typ A - Vysoký ", + "hud.settings.lighting_rendering_mode.blinnphong": "Typ B - Střední", + "hud.settings.lighting_rendering_mode.lambertian": "Typ L - Levný", + "hud.settings.shadow_rendering_mode": "Vykreslování Stínů", + "hud.settings.shadow_rendering_mode.none": "Nic", + "hud.settings.shadow_rendering_mode.cheap": "Levný", + "hud.settings.shadow_rendering_mode.map": "Mapa", + "hud.settings.shadow_rendering_mode.map.resolution": "Rozlišení", + "hud.settings.lod_detail": "LoD Detail", + "hud.settings.save_window_size": "Pamatovat Okno", + "hud.settings.reset_graphics": "Výchozí Nastavení", + + + "hud.settings.music_volume": "Hlasitost Hudby", + "hud.settings.sound_effect_volume": "Hlasitost Efektů", + "hud.settings.audio_device": "Vstupní Zařízení", + "hud.settings.reset_sound": "Výchozí Nastavení", + + "hud.settings.awaitingkey": "Zmáčkni klávesu...", + "hud.settings.unbound": "Žádná", + "hud.settings.reset_keybinds": "Výchozí", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/cz_CZ/hud/map.ron b/assets/voxygen/i18n/cz_CZ/hud/map.ron new file mode 100644 index 0000000000..347327577e --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/hud/map.ron @@ -0,0 +1,33 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish +( + string_map: { + // Map and Questlog + "hud.map.map_title": "Mapa", + "hud.map.qlog_title": "Úkoly", + "hud.map.difficulty": "Obtížnost", + "hud.map.towns": "Města", + "hud.map.castles": "Hrady", + "hud.map.dungeons": "Kobky", + "hud.map.caves": "Jeskyně", + "hud.map.cave": "Jeskyně", + "hud.map.trees": "Velké Stromy", + "hud.map.tree": "Velký Strom", + "hud.map.town": "Město", + "hud.map.castle": "Hrad", + "hud.map.dungeon": "Kobka", + "hud.map.difficulty_dungeon": "Kobka\n\nDifficulty: {difficulty}", + "hud.map.drag": "Pohybovat", + "hud.map.zoom": "Přiblížit", + "hud.map.recenter": "Recentrovat", + "hud.rank_up": "Nový Skillpoint", + "hud.skill.sp_available": "{number} SP dostupných", + "hud.skill.not_unlocked": "Není ještě odemčeno", + "hud.skill.req_sp": "\n\nVyžaduje {number} SP", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/pl_PL/template.ron b/assets/voxygen/i18n/cz_CZ/hud/misc.ron similarity index 81% rename from assets/voxygen/i18n/pl_PL/template.ron rename to assets/voxygen/i18n/cz_CZ/hud/misc.ron index d104f24ca9..32d330c9fa 100644 --- a/assets/voxygen/i18n/pl_PL/template.ron +++ b/assets/voxygen/i18n/cz_CZ/hud/misc.ron @@ -1,9 +1,11 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish ( string_map: { - }, + vector_map: { } ) diff --git a/assets/voxygen/i18n/it_IT/template.ron b/assets/voxygen/i18n/cz_CZ/hud/sct.ron similarity index 81% rename from assets/voxygen/i18n/it_IT/template.ron rename to assets/voxygen/i18n/cz_CZ/hud/sct.ron index f93a64c33e..32d330c9fa 100644 --- a/assets/voxygen/i18n/it_IT/template.ron +++ b/assets/voxygen/i18n/cz_CZ/hud/sct.ron @@ -1,9 +1,8 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for italian +/// Localization for Polish ( string_map: { - }, diff --git a/assets/voxygen/i18n/cz_CZ/hud/skills.ron b/assets/voxygen/i18n/cz_CZ/hud/skills.ron new file mode 100644 index 0000000000..542c4c501d --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/hud/skills.ron @@ -0,0 +1,243 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish +( + string_map: { + // General + "hud.skill.inc_health_title": "Zvýší Zdraví", + "hud.skill.inc_health": "Zvýší maximální zdraví o 5{SP}", + "hud.skill.inc_energy_title": "Zvýší Výdrž", + "hud.skill.inc_energy": "Zvýší Výdrž o 5{SP}", + "hud.skill.unlck_sword_title": "Odemknutí Meče", + "hud.skill.unlck_sword": "Odemkne strom dovedností pro meče{SP}", + "hud.skill.unlck_axe_title": "Odemknutí Sekery", + "hud.skill.unlck_axe": "Odemkne strom dovedností pro sekery{SP}", + "hud.skill.unlck_hammer_title": "Odemknutí Kladiva", + "hud.skill.unlck_hammer": "Odemkne strom dovedností pro kladivo{SP}", + "hud.skill.unlck_bow_title": "Odemknutí Luku", + "hud.skill.unlck_bow": "Odemkne strom dovedností pro luk{SP}", + "hud.skill.unlck_staff_title": "Odemknutí Hole", + "hud.skill.unlck_staff": "Odemkne strom dovedností pro hůl{SP}", + "hud.skill.unlck_sceptre_title": "Odemknutí Žezla", + "hud.skill.unlck_sceptre": "Odemkne strom dovedností pro žezlo{SP}", + "hud.skill.dodge_title": "Vyhnutí", + "hud.skill.dodge": "Vyhnese útokům zblízka{SP}", + "hud.skill.roll_energy_title": "Menší spotřeba Výdrže pro Kotrmelec", + "hud.skill.roll_energy": "Kotrmelec použije o 20% méně Výdrže{SP}", + "hud.skill.roll_speed_title": "Rychlost Kotrmelce", + "hud.skill.roll_speed": "Kotrmelec je o 20% rychlejší{SP}", + "hud.skill.roll_dur_title": "Délka Kotrmelce", + "hud.skill.roll_dur": "Kotrmelec je delší o 20%{SP}", + "hud.skill.climbing_title": "Lezení", + "hud.skill.climbing": "Skočíš výš", + "hud.skill.climbing_cost_title": "Lezení", + "hud.skill.climbing_cost": "Lezení spotřebuje o 20% méně Výdrže{SP}", + "hud.skill.climbing_speed_title": "Rychlost Lezení", + "hud.skill.climbing_speed": "Lezení je o 20% rychlejší{SP}", + "hud.skill.swim_title": "Plavání", + "hud.skill.swim": "Pohyb v mokrém prostředí", + "hud.skill.swim_speed_title": "Rychlost plávání", + "hud.skill.swim_speed": "Plaveš o 40% rychleji{SP}", + // Sceptre + "hud.skill.sc_lifesteal_title": "Paprsek Životokrádeže", + "hud.skill.sc_lifesteal": "Krade život z nepřátel", + "hud.skill.sc_lifesteal_damage_title": "Poškození", + "hud.skill.sc_lifesteal_damage": "Přídá o 20% více poškození{SP}", + "hud.skill.sc_lifesteal_range_title": "Dosah", + "hud.skill.sc_lifesteal_range": "Paprsek dosáhne o 25% dále{SP}", + "hud.skill.sc_lifesteal_lifesteal_title": "Životokrádež", + "hud.skill.sc_lifesteal_lifesteal": "Konverutuje o 30% více poškození na život{SP}", + "hud.skill.sc_lifesteal_regen_title": "Obnova Výdrže", + "hud.skill.sc_lifesteal_regen": "Doplní výdrž o 25%{SP}", + "hud.skill.sc_heal_title": "Paprsek Léčby", + "hud.skill.sc_heal": "Vyléčí vaše přátelé pomocí krve nepřátel", + "hud.skill.sc_heal_heal_title": "Léčba", + "hud.skill.sc_heal_heal": "Zvýší efektivnost Léčby o 20%{SP}", + "hud.skill.sc_heal_cost_title": "Spotřeba Výdrže", + "hud.skill.sc_heal_cost": "Léčení spotřebuje o 20% méně Výdrže{SP}", + "hud.skill.sc_heal_range_title": "Dosah", + "hud.skill.sc_heal_range": "Paprsek dosáhne dále o 25% {SP}", + "hud.skill.sc_wardaura_unlock_title": "Ochranářská Aura", + "hud.skill.sc_wardaura_unlock": "Dovolí ochránit přátele před útoky{SP}", + "hud.skill.sc_wardaura_strength_title": "Síla", + "hud.skill.sc_wardaura_strength": "Síla ochrany se zvýší o 20%{SP}", + "hud.skill.sc_wardaura_duration_title": "Délka", + "hud.skill.sc_wardaura_duration": "Efekt vaší ochrany potrvá o 30% déle{SP}", + "hud.skill.sc_wardaura_range_title": "Rádius", + "hud.skill.sc_wardaura_range": "Ochrana dosáhne o 25% dále{SP}", + "hud.skill.sc_wardaura_cost_title": "Spotřeba Výdrže", + "hud.skill.sc_wardaura_cost": "Tvorba ochrany stojí o 20% méně Energie{SP}", + // Staff + "hud.skill.st_shockwave_range_title" : "Dosah Rázové vlny", + "hud.skill.st_shockwave_range" : "Umožný hodit věci mimo dosah. Dosah se zvýšil o 20%{SP}", + "hud.skill.st_shockwave_cost_title" : "Spotřeba Rázové vlny", + "hud.skill.st_shockwave_cost" : "Snižuje spotřebu energie pro házení bezbraných vesničanů o 20%{SP}", + "hud.skill.st_shockwave_knockback_title" : "Ráz Rázové vlny", + "hud.skill.st_shockwave_knockback" : "Zvyšuje odhození o 30%{SP}", + "hud.skill.st_shockwave_damage_title" : "Poškození Rázové Vlny", + "hud.skill.st_shockwave_damage" : "Zvyšuje poškození o 30%{SP}", + "hud.skill.st_shockwave_unlock_title" : "Shockwave Unlock", + "hud.skill.st_shockwave_unlock" : "Umožnuje odhazovat objekty pomocí ohně{SP}", + "hud.skill.st_flamethrower_title" : "Plamenomet", + "hud.skill.st_flamethrower" : "Podpaluje, jdeme péct", + "hud.skill.st_flame_velocity_title" : "Rychlost metání", + "hud.skill.st_flame_velocity" : "Zvýší rychlost ohně o 25% {SP}", + "hud.skill.st_flamethrower_range_title" : "Dosah Plamenometu", + "hud.skill.st_flamethrower_range" : "Když plameny nedosáhnou, tak je potřeba je zvětšit o 25% {SP}", + "hud.skill.st_energy_drain_title" : "Spotřeba Energie", + "hud.skill.st_energy_drain" : "Zmenší spotřebu energie o 20%{SP}", + "hud.skill.st_flamethrower_damage_title" : "Poškození Plamenometem", + "hud.skill.st_flamethrower_damage" : "Zvýší poškození o 30%{SP}", + "hud.skill.st_explosion_radius_title" : "Rozsah Exploze", + "hud.skill.st_explosion_radius" : "Cím větší, tím lepší. Zvětší Rádius Exploze o 10%{SP}", + "hud.skill.st_energy_regen_title" : "Obnova Výdrže", + "hud.skill.st_energy_regen" : "Zvýší generaci výdrže o 20%{SP}", + "hud.skill.st_fireball_title" : "Ohnivá Koule", + "hud.skill.st_fireball" : "Hrajte aport s nepřáteli", + "hud.skill.st_damage_title" : "Poškození", + "hud.skill.st_damage" : "Zvětší Poškození o 20%{SP}", + "hud.skill.st_explosion_title" : "Exploze", + "hud.skill.st_explosion" : "Když oheň nestačí{SP}", + // Bow + "hud.skill.bow_projectile_speed_title" : "Rychlost Projektilu", + "hud.skill.bow_projectile_speed" : "Zvětšuje rozsah, rychlost o 30%{SP}", + "hud.skill.bow_arrow_count_title" : "Počet Šípů", + "hud.skill.bow_arrow_count" : "Vystřelí další šíp při odskoku{SP}", + "hud.skill.bow_repeater_cost_title" : "Zmenšení Spotřeby", + "hud.skill.bow_repeater_cost" : "Sníží spotřebu Energie o 30%{SP}", + "hud.skill.bow_repeater_glide_title" : "Plachtění Opakovače", + "hud.skill.bow_repeater_glide" : "Doplachti dál při opakování{SP}", + "hud.skill.bow_repeater_damage_title" : "Poškození během opakování", + "hud.skill.bow_repeater_damage" : "Zvýší poškození o 40%{SP}", + "hud.skill.bow_repeater_unlock_title" : "Odemčení Opakovače", + "hud.skill.bow_repeater_unlock" : "Odemkne možnost odskočit ve vzduchu a vystřelit haldu šípů{SP}", + "hud.skill.bow_charged_title" : "Silný Výstřel", + "hud.skill.bow_charged" : "Protože si počkal/a dýl", + "hud.skill.bow_charged_knockback_title" : "Nabitý Ráz", + "hud.skill.bow_charged_knockback" : "Odhoď neprátele o 25% dále{SP}", + "hud.skill.bow_charged_move_speed_title" : "Rychlost při míření", + "hud.skill.bow_charged_move_speed" : "Zvýší pohyb během natahování luku o 25%{SP}", + "hud.skill.bow_charged_speed_title" : "Nabitá rychlost ", + "hud.skill.bow_charged_speed" : "Zvýší jak rychle lze střílet o 10%{SP}", + "hud.skill.bow_charged_projectile_speed_title" : "Rychlost Nabitého Projektilu", + "hud.skill.bow_charged_projectile_speed" : "Rychlost projektilu se zvětší o 20% během nabijení{SP}", + "hud.skill.bow_charged_drain_title" : "Spotřeba během Nabijení", + "hud.skill.bow_charged_drain" : "Snižuje spotřebu nabití o 15%{SP}", + "hud.skill.bow_charged_damage_title" : "Nabitý Poškození", + "hud.skill.bow_charged_damage" : "Zvyšuje Poškození o 20%{SP}", + "hud.skill.bow_energy_regen_title" : "Regenerace Energie", + "hud.skill.bow_energy_regen" : "Zvyšuje zisk Energie o 40%{SP}", + "hud.skill.bow_title" : "Výstřel Šípu", + "hud.skill.bow" : "Nekoneční toulec, nepatří do ruky dětem", + "hud.skill.bow_damage_title" : "Poškození", + "hud.skill.bow_damage" : "Zvyšuje poškození o 25%{SP}", + // Hammer + "hud.skill.hmr_leap_radius_title" : "Rádius Vyšlehnutí", + "hud.skill.hmr_leap_radius" : "Zvětšuje rádius boucnutí do země by 1 meter{SP}", + "hud.skill.hmr_leap_distance_title" : "Vzdálenost Vyšlehnutí", + "hud.skill.hmr_leap_distance" : "Zvětší vzdálenost o 25%{SP}", + "hud.skill.hmr_leap_cost_title" : "Spotřeba při Vyšlehnutí", + "hud.skill.hmr_leap_cost" : "Sníží cenu skoku o 25%{SP}", + "hud.skill.hmr_leap_knockback_title" : "Odražení", + "hud.skill.hmr_leap_knockback" : "Zvyšuje odražení z Vyšlehnutí o 50%{SP}", + "hud.skill.hmr_leap_damage_title" : "Poškození Vyšlehnutí", + "hud.skill.hmr_leap_damage" : "Zvyšuje poškození při Vyšlehnutí 40%{SP}", + "hud.skill.hmr_unlock_leap_title" : "Odemknout Vyšlehnutí", + "hud.skill.hmr_unlock_leap" : "Unlocks a leap{SP}", + "hud.skill.hmr_charged_melee_title" : "Nabitý Rozkmit", + "hud.skill.hmr_charged_melee" : "Útok na blízko, ale silnější", + "hud.skill.hmr_charged_rate_title" : "Rychlost Nabití", + "hud.skill.hmr_charged_rate" : "Zvýší rychlost nabití o 25%{SP}", + "hud.skill.hmr_charged_melee_nrg_drain_title" : "Menší Spotřeba Energie", + "hud.skill.hmr_charged_melee_nrg_drain" : "Snižuje spotřebu energie během Srážky o 25%{SP}", + "hud.skill.hmr_charged_melee_damage_title" : "Poškození", + "hud.skill.hmr_charged_melee_damage" : "Zvětší poškození nabitého rozkmitu o 25%{SP}", + "hud.skill.hmr_charged_melee_knockback_title" : "Knockback", + "hud.skill.hmr_charged_melee_knockback" : "Masivně zvětšuje knockback Rozkmitu o 50%{SP}", + "hud.skill.hmr_single_strike_title" : "Jednoduchý Úder", + "hud.skill.hmr_single_strike" : "Jednoduchý jako ty", + "hud.skill.hmr_single_strike_regen_title" : "Regenerace Výdrže", + "hud.skill.hmr_single_strike_regen" : "Zvyšuje Výdrž při každém povedeném úderu{SP}", + "hud.skill.hmr_single_strike_speed_title" : "Rychlost Jednoduchého Útoku", + "hud.skill.hmr_single_strike_speed" : "Zvýší rychlost útoku pro Jednoduchý Útok při trefě{SP}", + "hud.skill.hmr_single_strike_damage_title" : "Poškození Jednoduchého Útoku", + "hud.skill.hmr_single_strike_damage" : "Při každém povedeném úderu zvyšuje Poškození{SP}", + "hud.skill.hmr_single_strike_knockback_title" : "Odražení pomocí Jednoduchého Útoku", + "hud.skill.hmr_single_strike_knockback" : "Zvyšuje potencial odhození o 50%{SP}", + "hud.skill." : "", + // Sword + "hud.skill.sw_trip_str_title": "Trojtý Úder", + "hud.skill.sw_trip_str": "Udeříš až 3x", + "hud.skill.sw_trip_str_combo_title": "Kombo Trojtého Úderu", + "hud.skill.sw_trip_str_combo": "Odemkne škálování kombíček na trojtým útoku{SP}", + "hud.skill.sw_trip_str_dmg_title": "Poškození Trojtým Úderem", + "hud.skill.sw_trip_str_dmg": "Zvyšuje poškození při každém podařeném úderu{SP}", + "hud.skill.sw_trip_str_sp_title": "Rychlost Trojtého Úderu", + "hud.skill.sw_trip_str_sp": "Zvýší rychlost útoku při každém úspešném úderu{SP}", + "hud.skill.sw_trip_str_reg_title": "Regenerace při Trojtém Úderu", + "hud.skill.sw_trip_str_reg": "Regeneruje Výdrž při každém úspešném úderu{SP}", + "hud.skill.sw_dash_title": "Dash", + "hud.skill.sw_dash": "Proběhni přes nepřátele", + "hud.skill.sw_dash_dmg_title": "Poškození Dashem", + "hud.skill.sw_dash_dmg": "Zvýší poškození o 20%{SP}", + "hud.skill.sw_dash_drain_title": "Menší spotřeba při Dashy", + "hud.skill.sw_dash_drain": "Sníží průběžnou spotřebu energie o 25%{SP}", + "hud.skill.sw_dash_cost_title": "Cena Dashe ", + "hud.skill.sw_dash_cost": "Sníží celkovou spotřebu energie o 25%{SP}", + "hud.skill.sw_dash_speed_title": "Rychlost Dashe", + "hud.skill.sw_dash_speed": "Zvýší rychlost při Dashování o 30%{SP}", + "hud.skill.sw_dash_inf_title": "Nekoneční Dash", + "hud.skill.sw_dash_inf": "Nechá tě používát Dash nekonečně dlouho, než ti dojde energie{SP}", + "hud.skill.sw_dash_scale_title": "Škálování Poškození při Dashy", + "hud.skill.sw_dash_scale": "Zvýší škálování poškození o 20%{SP}", + "hud.skill.sw_spin_title": "Odemknout Roztočení", + "hud.skill.sw_spin": "Odemkne roztočení{SP}", + "hud.skill.sw_spin_dmg_title": "Poškození Roztočení", + "hud.skill.sw_spin_dmg": "Zvýší poškození, které udělíš o 40%{SP}", + "hud.skill.sw_spin_spd_title": "Rychlost Roztočení", + "hud.skill.sw_spin_spd": "Zvýší rychlost roztočení o 25%{SP}", + "hud.skill.sw_spin_cost_title": "Cena Roztočení", + "hud.skill.sw_spin_cost": "Sníží cenu roztočení o 25%{SP}", + "hud.skill.sw_spin_spins_title": "Počet točení při Roztočení", + "hud.skill.sw_spin_spins": "Zvýší počet otoček během roztočení{SP}", + "hud.skill.sw_interrupt_title": "Překažení Útoků", + "hud.skill.sw_interrupt": "Dokáže ihned přerušit útok dalším útokem{SP}", + // Axe + "hud.skill.axe_double_strike_title": "Dvojtý Úder", + "hud.skill.axe_double_strike": "Skácej své nepřátele", + "hud.skill.axe_double_strike_combo_title": "Kombo Dvojtého Úderu", + "hud.skill.axe_double_strike_combo": "Odemkne Dvojtý Útok{SP}", + "hud.skill.axe_double_strike_damage_title": "Poškození Dvojtého Úderu", + "hud.skill.axe_double_strike_damage": "Zvyšuje poškození při každém podařeném úderu{SP}", + "hud.skill.axe_double_strike_speed_title": "Rychlost Dvojtého Úderu", + "hud.skill.axe_double_strike_speed": "Zvyšuje Rychlost Útoku při každém podařeném úderu{SP}", + "hud.skill.axe_double_strike_regen_title": "Regenerace při Dvojtém Útoku", + "hud.skill.axe_double_strike_regen": "Zvyšuje regeneraci Výdrže při každém podařeném úderu{SP}", + "hud.skill.axe_spin_title": "Roztočení Sekery", + "hud.skill.axe_spin": "Točíš se správným směrem...", + "hud.skill.axe_infinite_axe_spin_title": "Nekonečné Roztočení Sekery", + "hud.skill.axe_infinite_axe_spin": "Toč Sekeru dokaď máš Energii{SP}", + "hud.skill.axe_spin_damage_title": "Poškození Roztočení", + "hud.skill.axe_spin_damage": "Zvýší poškození, které udělíš o 30%{SP}", + "hud.skill.axe_spin_helicopter_title": "Vrtulníček", + "hud.skill.axe_spin_helicopter": "Při pádu budeš padat pomaleji při Roztočení Sekery{SP}", + "hud.skill.axe_spin_speed_title": "Rychlost Roztočení", + "hud.skill.axe_spin_speed": "Zvýší Rychlost Roztočení o 25%{SP}", + "hud.skill.axe_spin_cost_title": "Cena Roztočení", + "hud.skill.axe_spin_cost": "Sníží spotřebu výdrže o 25%{SP}", + "hud.skill.axe_unlock_leap_title": "Odemknout Vyšlehnutí", + "hud.skill.axe_unlock_leap": "Odemkne Vyšlehnutí{SP}", + "hud.skill.axe_leap_damage_title": "Poškození při Vyšlehnutí", + "hud.skill.axe_leap_damage": "Zvýší poškození Vyšlehnutí o 35%{SP}", + "hud.skill.axe_leap_knockback_title": "Odražení při Vyšlehnutí", + "hud.skill.axe_leap_knockback": "Při Vyšlehnutí, zvýší odražení o 40%{SP}", + "hud.skill.axe_leap_cost_title": "Cena Vyšlehnutí", + "hud.skill.axe_leap_cost": "Sníží cenu vyšlehnutí o 25%{SP}", + "hud.skill.axe_leap_distance_title": "Dosah Vyšlehnutí", + "hud.skill.axe_leap_distance": "Zvýší dosah o 20%{SP}", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/cz_CZ/hud/social.ron b/assets/voxygen/i18n/cz_CZ/hud/social.ron new file mode 100644 index 0000000000..721d48c464 --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/hud/social.ron @@ -0,0 +1,24 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish +( + string_map: { + /// Socialní + + "hud.social": "Společnost", + "hud.social.online": "Aktivní", + "hud.social.friends": "Přátelé", + "hud.social.not_yet_available": "Ještě není dostupné", + "hud.social.faction": "Cech", + "hud.social.play_online_fmt": "{nb_player} je aktivní", + "hud.social.name": "Jméno", + "hud.social.level": "Úroveň", + "hud.social.zone": "Zóna", + "hud.social.account": "Účet", + }, + + + vector_map: { + } +) + diff --git a/assets/voxygen/i18n/cz_CZ/hud/trade.ron b/assets/voxygen/i18n/cz_CZ/hud/trade.ron new file mode 100644 index 0000000000..c40c8d6228 --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/hud/trade.ron @@ -0,0 +1,30 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish +( + string_map: { + /// Obchod + + "hud.trade.trade_window": "Obchod", + "hud.trade.phase1_description": "Přetáhněte položky.", + "hud.trade.phase2_description": "Obchod je nyní uzamčen, abyste měli\n čas jej zkontrolovat.", + /// Phase3 should only be visible for a few milliseconds if everything is working properly, but is included for completeness + "hud.trade.phase3_description": "Probíhá zpracování.", + "hud.trade.persons_offer": "Nabídka {playername}", + "hud.trade.has_accepted": "{playername}přijal obchod", + "hud.trade.accept": "Akceptovat", + "hud.trade.decline": "Odmítnout", + "hud.trade.invite_sent": "Žádost o obchod zaslána {playername}.", + "hud.trade.result.completed": "Obchod proběhl úspěšně.", + "hud.trade.result.declined": "Obchod odmítnut.", + "hud.trade.result.nospace": "Nedostatek místa pro dokončení.", + "hud.trade.buy_price": "Cena koupě", + "hud.trade.sell_price": "Cena prodeje", + "hud.trade.coin": "Peníze", + }, + + + vector_map: { + } +) + diff --git a/assets/voxygen/i18n/cz_CZ/main.ron b/assets/voxygen/i18n/cz_CZ/main.ron new file mode 100644 index 0000000000..42cb2c172a --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/main.ron @@ -0,0 +1,67 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Polish +( + string_map: { + /// Start Main screen section + "main.connecting": "Připojování", + "main.creating_world": "Tvorba Světa", + + // Welcome notice that appears the first time Veloren is started + "main.notice": r#"Vítejte v alfa verzi Veloren! + +Než začnete, mějte na paměti, že: + +- Hra je v rané verzi alfa. Očekávejte chyby, extrémně nedokončený příběh, nedostatečně rozvinuté mechaniky a chybějící funkce. + +- Pokud se chcete podělit o svůj názor, máte návrhy nebo nápady nebo chcete nahlásit chybu, můžete nás kontaktovat prostřednictvím Redditu, GitLabu nebo Discordu. + +- Veloren je licencován pod licencí open source GPL 3. To znamená, že máte právo hru upravovat a distribuovat, jakkoliv chcete (pokud je vaše práce licencována také pod GPL 3). + +- Veloren je neziskový projekt, kde je každý pracující člověk dobrovolníkem. Pokud se vám tato hra líbí, připojte se k našemu týmu! + +Děkujeme za přečtení této zprávy a doufáme, že se vám tato hra bude líbit! + +~ Tvůrci Veloren"#, + + // Login process description + "main.login_process": r#"Informace o procesu přihlášení: + +Pokud máte problémy s přihlášením: + +Nezapomeňte, že k připojení na server +se zapnutým ověřením potřebujete účet. + +Účet si můžete vytvořit na webu: + +https://veloren.net/account/."#, + "main.login.server_not_found": "Server nenalezen", + "main.login.authentication_error": "Chyba ověření", + "main.login.server_full": "Server je plný", + "main.login.untrusted_auth_server": "Ověřovací server je nedůvěryhodný", + "main.login.outdated_client_or_server": "ServerWentMad: Pravděpodobně jsou verze nekompatibilní, zkontrolujte aktualizace!", + "main.login.network_wrong_version": "Server běží na jiné verzy hry. Aktualizuj si klienta.", + "main.login.timeout": "Timeout: Server neodpověděl včas. (Přetížení nebo chyby v síti).", + "main.login.server_shut_down": "Server Uzavřen", + "main.login.network_error": "Chyba sítě.", + "main.login.failed_sending_request": "Dotaz na ověřovací server se nezdařil", + "main.login.client_crashed": "Pád klienta", + "main.servers.select_server": "Výběr serveru", + "main.server": "Server", + "main.password": "Heslo", + "main.username": "Jméno", + "main.tip":"Rada:", + "main.login.invalid_character": "Vybraná postava je neplatná", + "main.login.not_on_whitelist": "Potřebuješ být ve whitelistu. Kontaktuj Admina serveru.", + "main.login.banned": "Byl/a si zabanován/á z tohoto důvodu", + "main.login.kicked": "Byl/a si vyhozen/á z tohoto důvodu", + "main.login.select_language": "Vyber si svůj Jazyk", + "main.login.insecure_auth_scheme": "Schéma ověření HTTP NENÍ podporováno. Je to nejisté! Pro účely vývoje je HTTP povolen pro „localhost“ nebo pro ladění", + "main.login.failed_auth_server_url_invalid": "Připojení k ověřovacímu serveru se nezdařilo.", + /// End Main screen section + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/en/hud/sct.ron b/assets/voxygen/i18n/en/hud/sct.ron index e044a9ebb4..62e47bc983 100644 --- a/assets/voxygen/i18n/en/hud/sct.ron +++ b/assets/voxygen/i18n/en/hud/sct.ron @@ -6,7 +6,7 @@ // SCT outputs "hud.sct.experience": "{amount} Exp", "hud.sct.block": "BLOCKED", - }, + }, vector_map: { diff --git a/assets/voxygen/i18n/en/hud/trade.ron b/assets/voxygen/i18n/en/hud/trade.ron index 3298ff71aa..5a855ed754 100644 --- a/assets/voxygen/i18n/en/hud/trade.ron +++ b/assets/voxygen/i18n/en/hud/trade.ron @@ -4,23 +4,23 @@ ( string_map: { "hud.trade.trade_window": "Trade window", - "hud.trade.phase1_description": "Drag the items you want to trade\n into the corresponding area.", - "hud.trade.phase2_description": "The trade is now locked to give you\n time to review it.", - /// Phase3 should only be visible for a few milliseconds if everything is working properly, but is included for completeness - "hud.trade.phase3_description": "Trade is being processed.", - "hud.trade.persons_offer": "{playername}'s offer", - "hud.trade.has_accepted": "{playername}\nhas accepted", - "hud.trade.accept": "Accept", - "hud.trade.decline": "Decline", - "hud.trade.invite_sent": "Trade request sent to {playername}.", - "hud.trade.result.completed": "Trade completed successfully.", - "hud.trade.result.declined": "Trade declined.", - "hud.trade.result.nospace": "Not enough space to complete the trade.", - "hud.trade.buy_price": "Buy price", - "hud.trade.sell_price": "Sell Price", - "hud.trade.coin": "coin(s)", - "hud.trade.tooltip_hint_1": "", - "hud.trade.tooltip_hint_2": "", + "hud.trade.phase1_description": "Drag the items you want to trade\n into the corresponding area.", + "hud.trade.phase2_description": "The trade is now locked to give you\n time to review it.", + /// Phase3 should only be visible for a few milliseconds if everything is working properly, but is included for completeness + "hud.trade.phase3_description": "Trade is being processed.", + "hud.trade.persons_offer": "{playername}'s offer", + "hud.trade.has_accepted": "{playername}\nhas accepted", + "hud.trade.accept": "Accept", + "hud.trade.decline": "Decline", + "hud.trade.invite_sent": "Trade request sent to {playername}.", + "hud.trade.result.completed": "Trade completed successfully.", + "hud.trade.result.declined": "Trade declined.", + "hud.trade.result.nospace": "Not enough space to complete the trade.", + "hud.trade.buy_price": "Buy price", + "hud.trade.sell_price": "Sell Price", + "hud.trade.coin": "coin(s)", + "hud.trade.tooltip_hint_1": "", + "hud.trade.tooltip_hint_2": "", }, diff --git a/assets/voxygen/i18n/es_ES/template.ron b/assets/voxygen/i18n/es_ES/template.ron deleted file mode 100644 index 0ce3ada5d1..0000000000 --- a/assets/voxygen/i18n/es_ES/template.ron +++ /dev/null @@ -1,12 +0,0 @@ -/// WARNING: Localization files shall be saved in UTF-8 format without BOM - -/// Localization for Spanish (Spain) -( - string_map: { - - }, - - - vector_map: { - } -) \ No newline at end of file diff --git a/assets/voxygen/i18n/es_LA/_manifest.ron b/assets/voxygen/i18n/es_LA/_manifest.ron new file mode 100644 index 0000000000..5dc84fde14 --- /dev/null +++ b/assets/voxygen/i18n/es_LA/_manifest.ron @@ -0,0 +1,152 @@ +/// Translation document instructions +/// +/// In order to keep localization documents readible please follow the following +/// rules: +/// - separate the string map sections using a commentary describing the purpose +/// of the next section +/// - prepend multi-line strings with a commentary +/// - append one blank lines after a multi-line strings and two after sections +/// +/// To add a new language in Veloren, just write an additional `.ron` file in +/// `assets/voxygen/i18n` and that's it! +/// +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for "latinoamericano" Latin-American +( + metadata: ( + language_name: "Español Latino", + language_identifier: "es_LA", + ), + convert_utf8_to_ascii: false, + fonts: { + "opensans": Font ( + asset_key: "voxygen.font.OpenSans-Regular", + scale_ratio: 1.0, + ), + "metamorph": Font ( + asset_key: "voxygen.font.Metamorphous-Regular", + scale_ratio: 1.0, + ), + "alkhemi": Font ( + asset_key: "voxygen.font.Alkhemikal", + scale_ratio: 1.0, + ), + "wizard": Font ( + asset_key: "voxygen.font.wizard", + scale_ratio: 1.0, + ), + "cyri": Font ( + asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", + scale_ratio: 1.0, + ), + }, + string_map: { + + }, + + + vector_map: { + "loading.tips": [ + "Presiona 'G' para encender tu linterna.", + "Presiona 'F1' para ver los controles predeterminados.", + "Puedes escribir /say o /s para chatear solo con jugadores alrededor tuyo.", + "Puedes escribr /region o /r para chatear solo con jugadores que están a unos cien bloques alrededor tuyo.", + "Para enviar mensajes privados escribe /tell seguido de el nombre de un jugador y luego tu mensaje.", + "NPCs con el mismo nivel pueden tener una dificultad diferente.", + "Observa el terreno en búsqueda de comida, cofres y botines!", + "¿Inventario lleno de comida? Intenta craftear mejor comida con ella!", + "¿Te preguntas dónde debes hacerlo? Los Dungeons están marcados con puntos marrones en el mapa!", + "No te olvides de ajustar los gráficos de tu pc. Presiona 'N' para abrir la configuración.", + "Jugar con otros es divertido! Presiona 'O' para ver quien esta conectado.", + "Un NPC con un craneo debajo de su barra de vida es bastante más poderoso comparado contigo.", + "Presiona 'J' para bailar. Fiesta!", + "Presiona 'Shift-Izquierdo' para abrir tu planeador y conquistar los cielos.", + "Veloren está aún en Alfa temprana. Hacemos lo mejor para mejorar día a día!", + "Si te quieres unir al equipo de desarrolladores o solo chatear con nosotros, únete a nuestro servidor en Discord.", + "Puedes elegir mostrar tu cantidad de vida en la barra de vida en la configuración.", + "Para ver tus estadísticas, haz click en el botón 'Estadísticas' en el inventario.", + ], + "npc.speech.villager_under_attack": [ + "Ayuda, ¡Me están atacando!", + "¡Ayuda! ¡Me están atacando!", + "¡Auch! ¡Me están atacando!", + "¡Auch! ¡Me están atacando! ¡Ayuda!", + "¡Ayudenme! ¡Me están atacando!", + "¡Me están atacando! ¡Ayuda!", + "¡Me están atacando! ¡Ayudenme!", + "¡Ayuda!", + "¡Ayuda! ¡Ayuda!", + "¡Ayuda! ¡Ayuda! ¡Ayuda!", + "¡Me están atacando!", + "¡AAAHH! ¡Me están atacando!", + "¡AAAHH! ¡Me están atacando! ¡Ayuda!", + "Ayuda! Nos están atacando!", + "¡Ayuda! ¡Asesino!", + "¡Ayuda! ¡Hay un asesino suelto!", + "¡Ayuda! ¡están intentando matarme!", + "Guardias, ¡Me están atacando!", + "¡Guardias! ¡Me están atacando!", + "¡Me están atacando! ¡Guardias!", + "¡Ayuda! ¡Guardias! ¡Me están atacando!", + "¡Guardias! ¡Vengan rapido!", + "¡Guardias, Guardias!", + "¡Guardias! ¡Me esta atacando un villano!", + "¡Guardias, eliminen a este desagradable villano!", + "¡Guardias! ¡Ahi esta el asesino!", + "¡Guardias! ¡Ayúdenme!", + "No te saldrás con la tuya, ¡Guardias!", + "¡Eres despreciable!", + "¡Ayúdenme!", + "¡Ayuda! ¡Porfavor!", + "¡Auch! ¡Guardias! ¡Ayuda!", + "¡Vienen por mi!", + "¡Ayuda! ¡Ayuda! Estoy siendo atacado", + "Ah, se nota que la violencia es parte del sistema.", + "¡Esto no es más que un rasguño!", + "Deja de hacer eso!", + "¿Qué te hice para merecer esto?", + "Por favor, para de atacarme!", + "Hey! Mira hacia adonde apuntas con esa cosa", + "Desgraciado, vete de aqui!", + "Para ya! Vete!", + "Me estas haciendo enojar!", + "Hey!¿Quién te piensas que eres?", + "Te arrancaré la cabeza por eso!", + "Detente, por favor! No llevo nada de valor!", + "Te voy a mandar a mi hermano, el es más grande que yo!", + "Nooo, le contaré a mi madre!", + "Maldito seas!", + "Por favor no lo hagas.", + "Eso no fue agradable!", + "Tu arma funciona, ahora aléjala!", + "Si claro...", + "Por favor, tengo familia!", + "Soy demasiado jóven para morir!", + "¿Podemos hablar sobre esto?", + "La violencia no resuelve nada!", + "Este día se esta convirtiendo en uno muy feo...", + "Hey, eso dolió!", + "Ayy!", + "Qué violento!", + "Detente, te lo suplico!", + "Ojala te enfermes!", + "Esto no es divertido.", + "¡¿Cómo te atreves?!", + "Vas a pagar por eso!", + "Sigue con eso y lo lamentarás!", + "No hagas que te lastime!", + "Tiene que ser un malentendido!", + "No necesitas hacer esto!", + "Vete, demonio!", + "Eso realmente dolió!", + "¿Por qué harias eso?", + "Por todos los Santos, para!", + "Me habrás confudido con alguien más!", + "No me merezco esto!", + "Por favor, no lo hagas de nuevo", + "Guardias, tiren este monstruo al lago", + "Invocaré mis demonios en ti!", + ], + } +) diff --git a/assets/voxygen/i18n/es_LA/buff.ron b/assets/voxygen/i18n/es_LA/buff.ron new file mode 100644 index 0000000000..1752e1a8c5 --- /dev/null +++ b/assets/voxygen/i18n/es_LA/buff.ron @@ -0,0 +1,26 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + "buff.remove": "Click para quitar", + "buff.title.missing": "Sin Título", + "buff.desc.missing": "Sin Descripción", + // Buffs + "buff.title.heal": "Curación", + "buff.desc.heal": "Recupera vida durante un tiempo.", + "buff.title.potion": "Poción", + "buff.desc.potion": "Bebiendo...", + "buff.title.saturation": "Saturación", + "buff.desc.saturation": "Recupera vida durante un tiempo por objetos.", + "buff.title.campfire_heal": "Curación de fogata", + "buff.desc.campfire_heal": "Descansar en una fogata recupera {rate}% por segundo.", + // Debuffs + "buff.title.bleed": "Sangrando", + "buff.desc.bleed": "Inflinge daño regularmente.", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/es_LA/char_selection.ron b/assets/voxygen/i18n/es_LA/char_selection.ron new file mode 100644 index 0000000000..19fa8c4fbf --- /dev/null +++ b/assets/voxygen/i18n/es_LA/char_selection.ron @@ -0,0 +1,32 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + "char_selection.loading_characters": "Cargando personajes...", + "char_selection.delete_permanently": "¿Borrar este Personaje permanentemente?", + "char_selection.deleting_character": "Borrando Personaje...", + "char_selection.change_server": "Cambiar Servidor", + "char_selection.enter_world": "Entrar al Mundo", + "char_selection.logout": "Cerrar Sesión", + "char_selection.create_new_character": "Crear Nuevo Personaje", + "char_selection.creating_character": "Creando Personaje...", + "char_selection.character_creation": "Creación de Personaje", + + "char_selection.human_default": "Humano por defecto", + "char_selection.level_fmt": "Nivel {level_nb}", + "char_selection.uncanny_valley": "Valle Misterioso", + "char_selection.plains_of_uncertainty": "Planicies de la Incertidumbre", + "char_selection.beard": "Barba", + "char_selection.hair_style": "Peinado", + "char_selection.hair_color": "Color de Pelo", + "char_selection.eye_color": "Color de Ojos", + "char_selection.skin": "Color de Piel", + "char_selection.eyeshape": "Detalles de los Ojos", + "char_selection.accessories": "Accesorios", + "char_selection.create_info_name": "Tu Personaje necesita un nombre!", + }, + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/es_LA/common.ron b/assets/voxygen/i18n/es_LA/common.ron new file mode 100644 index 0000000000..92e4272b23 --- /dev/null +++ b/assets/voxygen/i18n/es_LA/common.ron @@ -0,0 +1,71 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + // Texts used in multiple locations with the same formatting + "common.username": "Usuario", + "common.singleplayer": "Un Jugador", + "common.multiplayer": "Multijugador", + "common.servers": "Servidores", + "common.quit": "Salir", + "common.settings": "Configuración", + "common.languages": "Idiomas", //this one is repeated in en.ron (53 and 59) + "common.interface": "Interfaz", + "common.gameplay": "Jugabilidad", + "common.controls": "Controles", + "common.video": "Gráficos", + "common.sound": "Sonido", + "common.resume": "Continuar", + "common.characters": "Personajes", + "common.close": "Cerrar", + "common.yes": "Sí", + "common.no": "No", + "common.back": "Volver", + "common.create": "Crear", + "common.okay": "Ok", + "common.add": "Agregar", + "common.accept": "Aceptar", + "common.decline": "Rechazar", + "common.disclaimer": "Cuidado", + "common.cancel": "Cancelar", + "common.none": "Ninguno", + "common.error": "Error", + "common.fatal_error": "Error Fatal", + "common.you": "Tú", + "common.automatic": "Automático", + "common.random": "Aleatorio", + // Settings Window title + "common.interface_settings": "Ajustes de Interfaz", + "common.gameplay_settings": "Ajustes de Jugabilidad", + "common.controls_settings": "Ajustes de Controles", + "common.video_settings": "Ajustes de Graficos", + "common.sound_settings": "Ajustes de Sonido", + "common.language_settings": "Ajustes de Idiomas", + + // Message when connection to the server is lost + "common.connection_lost": r#"Conexión perdida! +Se reinició el servidor? +El cliente está actualizado?"#, + + + "common.species.orc": "Orco", + "common.species.human": "Humano", + "common.species.dwarf": "Enano", + "common.species.elf": "Elfo", + "common.species.undead": "No-Muerto", + "common.species.danari": "Danari", + + "common.weapons.axe": "Hacha", + "common.weapons.sword": "Espada", + "common.weapons.staff": "Vara Mágica", + "common.weapons.bow": "Arco", + "common.weapons.hammer": "Martillo", + "common.weapons.sceptre": "Cetro curativo", + "common.rand_appearance": "Nombre y Apariencia Aleatoria", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/es_LA/esc_menu.ron b/assets/voxygen/i18n/es_LA/esc_menu.ron new file mode 100644 index 0000000000..b17495ff1c --- /dev/null +++ b/assets/voxygen/i18n/es_LA/esc_menu.ron @@ -0,0 +1,13 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + "esc_menu.logout": "Cerrar Sesión", + "esc_menu.quit_game": "Salir del Juego", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/es_LA/gameinput.ron b/assets/voxygen/i18n/es_LA/gameinput.ron new file mode 100644 index 0000000000..d85d2495e6 --- /dev/null +++ b/assets/voxygen/i18n/es_LA/gameinput.ron @@ -0,0 +1,68 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + "gameinput.primary": "Ataque Básico", + "gameinput.secondary": "Ataque Secundario/Bloquear/Apuntar", + "gameinput.slot1": "Ranura de Inventario Rápido 1", + "gameinput.slot2": "Ranura de Inventario Rápido 2", + "gameinput.slot3": "Ranura de Inventario Rápido 3", + "gameinput.slot4": "Ranura de Inventario Rápido 4", + "gameinput.slot5": "Ranura de Inventario Rápido 5", + "gameinput.slot6": "Ranura de Inventario Rápido 6", + "gameinput.slot7": "Ranura de Inventario Rápido 7", + "gameinput.slot8": "Ranura de Inventario Rápido 8", + "gameinput.slot9": "Ranura de Inventario Rápido 9", + "gameinput.slot10": "Ranura de Inventario Rápido 10", + "gameinput.swaploadout": "Cambiar Equipamiento", + "gameinput.togglecursor": "Mostrar Cursor", + "gameinput.help": "Mostrar Ventana de Ayuda", + "gameinput.toggleinterface": "Mostrar Interfaz", + "gameinput.toggledebug": "Mostrar FPS y la Info de Depuración", + "gameinput.screenshot": "Tomar Captura de Pantalla", + "gameinput.toggleingameui": "Mostrar Nombres", + "gameinput.fullscreen": "Pantalla Completa", + "gameinput.moveforward": "Moverse hacia Adelante", + "gameinput.moveleft": "Moverse hacia la Izquierda", + "gameinput.moveright": "Moverse hacia la Derecha", + "gameinput.moveback": "Moverse hacia Atras", + "gameinput.jump": "Saltar", + "gameinput.glide": "Planeador", + "gameinput.roll": "Rodar", + "gameinput.climb": "Trepar", + "gameinput.climbdown": "Descender", + "gameinput.wallleap": "Saltar a la Pared", + "gameinput.togglelantern": "Encender Farol", + "gameinput.mount": "Montar", + "gameinput.chat": "Abrir Chat", + "gameinput.enter": "Entrar", + "gameinput.command": "Insertar Comandos", + "gameinput.escape": "Escapar", + "gameinput.map": "Mapa", + "gameinput.bag": "Mochila", + "gameinput.social": "Lista de jugadores", + "gameinput.sit": "Sentarse", + "gameinput.spellbook": "Hechizos", + "gameinput.settings": "Configuración", + "gameinput.respawn": "Reaparecer", + "gameinput.charge": "Cargar", + "gameinput.togglewield": "Alternar empuñadura", + "gameinput.interact": "Interactuar", + "gameinput.freelook": "Vista Libre", + "gameinput.autowalk": "Caminata Automática", + "gameinput.dance": "Bailar", + "gameinput.select": "Seleccione la Entidad", + "gameinput.acceptgroupinvite": "Aceptar invitación al grupo", + "gameinput.declinegroupinvite": "Rechazar invitación al grupo", + "gameinput.crafting": "Craftear", + "gameinput.fly": "Volar", + "gameinput.sneak": "Agacharse", + "gameinput.swimdown": "Sumergirse", + "gameinput.swimup": "Nadar hacia arriba", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/es_LA/hud/bag.ron b/assets/voxygen/i18n/es_LA/hud/bag.ron new file mode 100644 index 0000000000..45224648ad --- /dev/null +++ b/assets/voxygen/i18n/es_LA/hud/bag.ron @@ -0,0 +1,31 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + "hud.bag.inventory": "Inventario de {playername}", + "hud.bag.stats_title": "Estadísticas de {playername}", + "hud.bag.exp": "Exp", + "hud.bag.armor": "Armadura", + "hud.bag.stats": "Estadísticas", + "hud.bag.head": "Cabeza", + "hud.bag.neck": "Cuello", + "hud.bag.tabard": "Tabardo", + "hud.bag.shoulders": "Hombros", + "hud.bag.chest": "Torso", + "hud.bag.hands": "Manos", + "hud.bag.lantern": "Linterna", + "hud.bag.glider": "Planeador", + "hud.bag.belt": "Cinturón", + "hud.bag.ring": "Anillo", + "hud.bag.back": "Espalda", + "hud.bag.legs": "Piernas", + "hud.bag.feet": "Pies", + "hud.bag.mainhand": "Mano Principal", + "hud.bag.offhand": "Mano Secundaria", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/es_LA/hud/char_window.ron b/assets/voxygen/i18n/es_LA/hud/char_window.ron new file mode 100644 index 0000000000..402e5073eb --- /dev/null +++ b/assets/voxygen/i18n/es_LA/hud/char_window.ron @@ -0,0 +1,22 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + /// Start character window section + "character_window.character_name": "Nombre de Personaje", + // Character stats + "character_window.character_stats": r#"Resistencia + +Estado Físico + +Valentía + +Protección +"#, + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/es_LA/hud/chat.ron b/assets/voxygen/i18n/es_LA/hud/chat.ron new file mode 100644 index 0000000000..2be6aea288 --- /dev/null +++ b/assets/voxygen/i18n/es_LA/hud/chat.ron @@ -0,0 +1,36 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + "hud.chat.online_msg": "[{name}] se ha conectado.", + "hud.chat.offline_msg": "[{name}] se ha desconectado.", + + "hud.chat.default_death_msg": "[{name}] murió", + "hud.chat.environmental_kill_msg": "[{name}] murió en {environment}", + "hud.chat.fall_kill_msg": "[{name}] murió por daño de caída", + "hud.chat.suicide_msg": "[{name}] murió por heridas autoinfligidas", + + "hud.chat.pvp_melee_kill_msg": "[{attacker}] derrotó a [{victim}]", + "hud.chat.pvp_ranged_kill_msg": "[{attacker}] le disparó a [{victim}]", + "hud.chat.pvp_explosion_kill_msg": "[{attacker}] hizo explotar a [{victim}]", + "hud.chat.pvp_energy_kill_msg": "[{attacker}] usó magia para matar a [{victim}]", + "hud.chat.pvp_buff_kill_msg": "[{attacker}] mató a [{victim}]", + + + "hud.chat.npc_melee_kill_msg": "{attacker} mató a [{victim}]", + "hud.chat.npc_ranged_kill_msg": "{attacker} le disparó a [{victim}]", + "hud.chat.npc_explosion_kill_msg": "{attacker} hizo explotar a [{victim}]", + "hud.chat.npc_energy_kill_msg": "{attacker} usó magia para matar a [{victim}]", + "hud.chat.npc_other_kill_msg": "{attacker} mató a [{victim}]", + + "hud.chat.loot_msg": "Recogiste [{item}]", + "hud.chat.loot_fail": "Tu inventario está lleno!", + "hud.chat.goodbye": "Adiós!", + "hud.chat.connection_lost": "Conexión perdida. Expulsando en {time} segundos.", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/es_LA/hud/crafting.ron b/assets/voxygen/i18n/es_LA/hud/crafting.ron new file mode 100644 index 0000000000..4f959ad3a3 --- /dev/null +++ b/assets/voxygen/i18n/es_LA/hud/crafting.ron @@ -0,0 +1,16 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + "hud.crafting": "Crafteo", + "hud.crafting.recipes": "Recetas", + "hud.crafting.ingredients": "Ingredientes:", + "hud.crafting.craft": "Fabricar", + "hud.crafting.tool_cata": "Requisitos:", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/es_LA/hud/group.ron b/assets/voxygen/i18n/es_LA/hud/group.ron new file mode 100644 index 0000000000..59059f49a4 --- /dev/null +++ b/assets/voxygen/i18n/es_LA/hud/group.ron @@ -0,0 +1,23 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + "hud.group": "Grupo", + "hud.group.invite_to_join": "[{name}] Te invito a su Grupo!", + "hud.group.invite": "Invitar", + "hud.group.kick": "Echar", + "hud.group.assign_leader": "Asignar Lider", + "hud.group.leave": "Salir del Grupo", + "hud.group.dead" : "Muerto", + "hud.group.out_of_range": "Fuera de Alcance", + "hud.group.add_friend": "Agregar a Amigos", + "hud.group.link_group": "Conectar Grupos", + "hud.group.in_menu": "Eligiendo Personaje", + "hud.group.members": "Miembros del Grupo", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/es_LA/hud/hud_settings.ron b/assets/voxygen/i18n/es_LA/hud/hud_settings.ron new file mode 100644 index 0000000000..27691237b3 --- /dev/null +++ b/assets/voxygen/i18n/es_LA/hud/hud_settings.ron @@ -0,0 +1,101 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + "hud.settings.general": "General", + "hud.settings.none": "Ninguno", + "hud.settings.press_behavior.toggle": "Alternar", + "hud.settings.press_behavior.hold": "Mantener", + "hud.settings.help_window": "Ventana de Ayuda", + "hud.settings.debug_info": "Info de Depuración", + "hud.settings.tips_on_startup": "Consejos de Inicio", + "hud.settings.ui_scale": "Escala de la Interfaz", + "hud.settings.relative_scaling": "Escalado Relativo", + "hud.settings.custom_scaling": "Escalado Personalizado", + "hud.settings.crosshair": "Mira", + "hud.settings.transparency": "Transparencia", + "hud.settings.hotbar": "Inventario Rápido", + "hud.settings.toggle_shortcuts": "Alternar Atajos", + "hud.settings.buffs_skillbar": "Buffs en la barra de habilidades.", + "hud.settings.buffs_mmap": "Buffs en el Minimapa", + "hud.settings.toggle_bar_experience": "Alternar Barra de Experiencia", + "hud.settings.scrolling_combat_text": "Texto de Combate con Desplazamiento", + "hud.settings.single_damage_number": "Números de Daño Singular", + "hud.settings.cumulated_damage": "Daño Acumulado", + "hud.settings.incoming_damage": "Daño Recibido", + "hud.settings.cumulated_incoming_damage": "Daño Recibido Acumulado", + "hud.settings.speech_bubble": "Burbuja de Diálogo", + "hud.settings.speech_bubble_dark_mode": "Burbuja de Diálogo en Modo Oscuro", + "hud.settings.speech_bubble_icon": "Burbuja de Diálogo en Modo Oscuro", + "hud.settings.energybar_numbers": "Números de la Barra de Energia", + "hud.settings.values": "Valores", + "hud.settings.percentages": "Porcentajes", + "hud.settings.chat": "Chat", + "hud.settings.background_transparency": "Transparencia del Fondo", + "hud.settings.chat_character_name": "Nombres de Personajes en el chat", + "hud.settings.loading_tips": "Consejos en Pantalla de Carga", + + "hud.settings.pan_sensitivity": "Sensibilidad de Desplazamiento de la Cámara", + "hud.settings.zoom_sensitivity": "Sensibilidad del Zoom", + "hud.settings.invert_scroll_zoom": "Invertir Desplazamiento de Zoom", + "hud.settings.invert_mouse_y_axis": "Invertir eje Y del Ratón", + "hud.settings.enable_mouse_smoothing": "Suavizado de la Cámara", + "hud.settings.free_look_behavior": "Modo de vista libre", + "hud.settings.auto_walk_behavior": "Modo de caminata automática", + "hud.settings.stop_auto_walk_on_input": "Frenar caminata automática", + + "hud.settings.view_distance": "Distancia de Visión", + "hud.settings.sprites_view_distance": "Distancia de Visión de Sprites", + "hud.settings.figures_view_distance": "Distancia de Visión de Entidades", + "hud.settings.maximum_fps": "FPS Máximos", + "hud.settings.fov": "Campo de Visión (grados)", + "hud.settings.gamma": "Gama", + "hud.settings.exposure": "Exposición", + "hud.settings.ambiance": "Brillo del Ambiente", + "hud.settings.antialiasing_mode": "Modo Anti-Aliasing", + "hud.settings.upscale_factor": "Factor de Escala", + "hud.settings.cloud_rendering_mode": "Modo de Renderizado de Nubes", + "hud.settings.fluid_rendering_mode": "Modo de Renderizado del Agua", + "hud.settings.fluid_rendering_mode.cheap": "Bajo", + "hud.settings.fluid_rendering_mode.shiny": "Alto", + "hud.settings.cloud_rendering_mode.minimal": "Mínimo", + "hud.settings.cloud_rendering_mode.low": "Bajo", + "hud.settings.cloud_rendering_mode.medium": "Medio", + "hud.settings.cloud_rendering_mode.high": "Alto", + "hud.settings.cloud_rendering_mode.ultra": "Ultra", + "hud.settings.fullscreen": "Pantalla Completa", + "hud.settings.fullscreen_mode": "Modo de Pantalla Completa", + "hud.settings.fullscreen_mode.exclusive": "Completo", + "hud.settings.fullscreen_mode.borderless": "Con Bordes", + "hud.settings.particles": "Particulas", + "hud.settings.resolution": "Resolución", + "hud.settings.bit_depth": "Profundidad de Bits", + "hud.settings.refresh_rate": "Taza de Refresco", + "hud.settings.save_window_size": " Guardar tamaño de ventana", + "hud.settings.lighting_rendering_mode": "Renderizado de la luz de la Linterna", + "hud.settings.lighting_rendering_mode.ashikhmin": "Tipo A - Alto", + "hud.settings.lighting_rendering_mode.blinnphong": "Tipo B - Medio", + "hud.settings.lighting_rendering_mode.lambertian": "Tipo L - Bajo", + "hud.settings.shadow_rendering_mode": "Renderizado de Sombras", + "hud.settings.shadow_rendering_mode.none": "Ninguno", + "hud.settings.shadow_rendering_mode.cheap": "Bajo", + "hud.settings.shadow_rendering_mode.map": "Alto", + "hud.settings.shadow_rendering_mode.map.resolution": "Resolución", + "hud.settings.lod_detail": "Detalle de LoD", + "hud.settings.save_window_size": "Recordar tamaño de ventana", //It's repeated in en.ron (359 and 370) + + + "hud.settings.music_volume": "Volumen de Música", + "hud.settings.sound_effect_volume": "Volumen de Efectos de Sonido", + "hud.settings.audio_device": "Dispositivo de Audio", + + "hud.settings.awaitingkey": "Presiona una tecla...", + "hud.settings.unbound": "Ninguno", + "hud.settings.reset_keybinds": "Reestablecer Controles", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/es_LA/hud/map.ron b/assets/voxygen/i18n/es_LA/hud/map.ron new file mode 100644 index 0000000000..e4992d5bfc --- /dev/null +++ b/assets/voxygen/i18n/es_LA/hud/map.ron @@ -0,0 +1,26 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + "hud.map.map_title": "Mapa", + "hud.map.qlog_title": "Misiones", + "hud.map.difficulty": "Dificultad", + "hud.map.towns": "Pueblos", + "hud.map.castles": "Castillos", + "hud.map.dungeons": "Calabozos", + "hud.map.caves": "Cuevas", + "hud.map.cave": "Cueva", + "hud.map.town": "Pueblo", + "hud.map.castle": "Castillo", + "hud.map.dungeon": "Calabozo", + "hud.map.difficulty_dungeon": "Dificultad de\n\nCalabozo: {difficulty}", + "hud.map.drag": "Arrastrar", + "hud.map.zoom": "Zoom", + "hud.map.recenter": "Centrar", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/es_LA/hud/misc.ron b/assets/voxygen/i18n/es_LA/hud/misc.ron new file mode 100644 index 0000000000..9fc5821904 --- /dev/null +++ b/assets/voxygen/i18n/es_LA/hud/misc.ron @@ -0,0 +1,74 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + "hud.do_not_show_on_startup": "No muestres esto al iniciar", + "hud.show_tips": "Mostrar Consejos", + "hud.quests": "Misiones", + "hud.you_died": "Moriste", + "hud.waypoint_saved": "Marcador Guardado", + + "hud.press_key_to_show_keybindings_fmt": "Presiona {key} para mostrar los controles del teclado", + "hud.press_key_to_toggle_lantern_fmt": "[{key}] Linterna", + "hud.press_key_to_show_debug_info_fmt": "Presiona {key} para mostrar información de depuración", + "hud.press_key_to_toggle_keybindings_fmt": "Presiona {key} para alternar los controles del teclado", + "hud.press_key_to_toggle_debug_info_fmt": "Presiona {key} para alternar la información de depuración", + + // Respawn message + "hud.press_key_to_respawn": r#"Presiona {key} para reaparecer en la ultima fogata que visitaste."#, + + // Welcome message + "hud.welcome": r#"Bienvenido a la alfa de Veloren! + + +Algunos consejos antes de que empieces: + + +Presiona F1 para ver los controles del teclado disponibles. + +Escribe /help en el chat para ver los comandos del chat + + +Hay cofres y otros objetos que aparecen al azar en el Mundo! + +Presiona E para recogerlos. + +Para usar lo que consigas de los cofres abre tu inventario con 'B'. + +Doble click en los objetos en tu bolsa para usarlos o equiparlos. + +Deshazte de ellos haciendo click en ellos y luego arrastralos fuera de la bolsa. + + +Las noches pueden volverse bastante oscuras en Veloren. + +Enciende tu Linterna escribiendo /lantern en el chat o presionando la G. + + +Quieres liberar tu cursor para cerrar esta ventana? Presiona TAB! + + +Disfruta tu estadía en el Mundo de Veloren."#, + +"hud.temp_quest_headline": r#"Por favor, ayúdanos Viajero!"#, +"hud.temp_quest_text": r#"Calabozos llenos de cultistas malvados +han emergido alrededor de nuestros pacíficos pueblos! + + +Consigue alguien que te acompañe, re-abastecete con comida +y derrota sus viles lideres y acólitos. + + +Tal vez incluso obtengas uno de sus +objetos infundidos con magia?"#, + "hud.spell": "Hechizos", + + "hud.free_look_indicator": "Vista libre activa", + "hud.auto_walk_indicator": "Caminata automática activa", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/es_LA/hud/sct.ron b/assets/voxygen/i18n/es_LA/hud/sct.ron new file mode 100644 index 0000000000..88760ebbfb --- /dev/null +++ b/assets/voxygen/i18n/es_LA/hud/sct.ron @@ -0,0 +1,14 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + // SCT outputs + "hud.sct.experience": "{amount} Exp", + "hud.sct.block": "BLOQUEADO", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/es_LA/hud/skills.ron b/assets/voxygen/i18n/es_LA/hud/skills.ron new file mode 100644 index 0000000000..f5c5c45d15 --- /dev/null +++ b/assets/voxygen/i18n/es_LA/hud/skills.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/es_LA/hud/social.ron b/assets/voxygen/i18n/es_LA/hud/social.ron new file mode 100644 index 0000000000..2a4fb78afd --- /dev/null +++ b/assets/voxygen/i18n/es_LA/hud/social.ron @@ -0,0 +1,22 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + "hud.social": "Lista de jugadores", + "hud.social.online": "En Línea", + "hud.social.friends": "Amigos", + "hud.social.not_yet_available": "Aún no esta disponible", + "hud.social.faction": "Facción", + "hud.social.play_online_fmt": "{nb_player} jugador(es) en línea", + "hud.social.name": "Nombre", + "hud.social.level": "Nivel", + "hud.social.zone": "Zona", + "hud.social.account": "Cuenta", + }, + + + vector_map: { + } +) + diff --git a/assets/voxygen/i18n/sv_SE/template.ron b/assets/voxygen/i18n/es_LA/hud/trade.ron similarity index 77% rename from assets/voxygen/i18n/sv_SE/template.ron rename to assets/voxygen/i18n/es_LA/hud/trade.ron index 014f73c1cc..7f309aea52 100644 --- a/assets/voxygen/i18n/sv_SE/template.ron +++ b/assets/voxygen/i18n/es_LA/hud/trade.ron @@ -1,12 +1,12 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for "global" Swedish +/// Localization for Latin-American ( string_map: { - }, vector_map: { } ) + diff --git a/assets/voxygen/i18n/es_LA/main.ron b/assets/voxygen/i18n/es_LA/main.ron new file mode 100644 index 0000000000..0c3dfda33c --- /dev/null +++ b/assets/voxygen/i18n/es_LA/main.ron @@ -0,0 +1,63 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Latin-American +( + string_map: { + "main.username": "Usuario", + "main.server": "Servidor", + "main.password": "Contraseña", + "main.connecting": "Conectando", + "main.creating_world": "Creando Mundo", + "main.tip": "Consejo:", + + // Welcome notice that appears the first time Veloren is started + "main.notice": r#"Bienvenido a la version alfa de Veloren! + +Antes de que te diviertas, por favor ten en cuenta lo siguiente: + +- Esta es una alfa muy temprana, espera fallos, jugabilidad extremadamente incompleta, mecánicas sin pulir y características faltantes. + +- Si tienes críticas constructivas o reportes de fallos, puedes contactarnos por reddit, GitLab, o por el server de Discord de nuestra comunidad. + +- Veloren esta licenciado bajo la licencia GPL 3 open-source (código abierto). Eso significa que tienes la libertad de jugar, modificar, y redistribuir el Juego como + desees (siempre y cuando dicho trabajo también este licenciado como GPL 3). + +- Veloren es un proyecto en comunidad sin ánimo de lucro, y todos los que trabajan en el son voluntarios. +Si te gusta lo que ves, eres bienvenido a unirte a los equipos de desarrollo o de arte! + +Gracias por tomarte el tiempo de leer este mensaje, esperamos que disfrutes el juego! + +~ Los Desarrolladores de Veloren"#, + + // Login process description + "main.login_process": r#"Información sobre el proceso para Iniciar Sesión: + +Por favor ten en cuenta que ahora necesitas una cuenta +para jugar en servidores con autenticación activada. + +Puedes crearte una cuenta en + +https://veloren.net/account/."#, + "main.login.server_not_found": "No se encontró el servidor", + "main.login.authentication_error": "Error de autenticación en el servidor", + "main.login.server_full": "El servidor está lleno", + "main.login.untrusted_auth_server": "El servidor de autenticación no es confiable", + "main.login.outdated_client_or_server": "ServidorEnloquecido: Probablemente las versiones son incompatibles, intenta actualizar tu cliente.", + "main.login.timeout": "Tiempo de espera agotado: El servidor no respondio a tiempo. (Puede estar sobrecargado o tener problemas de red).", + "main.login.server_shut_down": "El servidor se apagó", + "main.login.network_error": "Error de red", + "main.login.failed_sending_request": "El pedido al servidor de autenticacion fallo", + "main.login.invalid_character": "El personaje seleccionado no es válido", + "main.login.client_crashed": "El cliente crasheó", + "main.login.not_on_whitelist": "No estás en la lista. Contacta al Dueño del Servidor si quieres unirte.", + "main.login.banned": "Usted ha sido baneado por la siguiente razón", + "main.login.kicked": "Te han echado por la siguiente razón", + "main.login.select_language": "Elige un idioma", + + "main.servers.select_server": "Elige un servidor", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/es_la/_manifest.ron b/assets/voxygen/i18n/es_la/_manifest.ron deleted file mode 100644 index f746bc9812..0000000000 --- a/assets/voxygen/i18n/es_la/_manifest.ron +++ /dev/null @@ -1,665 +0,0 @@ -/// Translation document instructions -/// -/// In order to keep localization documents readible please follow the following -/// rules: -/// - separate the string map sections using a commentary describing the purpose -/// of the next section -/// - prepend multi-line strings with a commentary -/// - append one blank lines after a multi-line strings and two after sections -/// -/// To add a new language in Veloren, just write an additional `.ron` file in -/// `assets/voxygen/i18n` and that's it! -/// -/// WARNING: Localization files shall be saved in UTF-8 format without BOM - -/// Localization for "latinoamericano" Latin-American -( - metadata: ( - language_name: "Español Latino", - language_identifier: "es_la", - ), - convert_utf8_to_ascii: false, - fonts: { - "opensans": Font ( - asset_key: "voxygen.font.OpenSans-Regular", - scale_ratio: 1.0, - ), - "metamorph": Font ( - asset_key: "voxygen.font.Metamorphous-Regular", - scale_ratio: 1.0, - ), - "alkhemi": Font ( - asset_key: "voxygen.font.Alkhemikal", - scale_ratio: 1.0, - ), - "wizard": Font ( - asset_key: "voxygen.font.wizard", - scale_ratio: 1.0, - ), - "cyri": Font ( - asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", - scale_ratio: 1.0, - ), - }, - string_map: { - /// Start Common section - // Texts used in multiple locations with the same formatting - "common.username": "Usuario", - "common.singleplayer": "Un Jugador", - "common.multiplayer": "Multijugador", - "common.servers": "Servidores", - "common.quit": "Salir", - "common.settings": "Configuración", - "common.languages": "Idiomas", //this one is repeated in en.ron (53 and 59) - "common.interface": "Interfaz", - "common.gameplay": "Jugabilidad", - "common.controls": "Controles", - "common.video": "Gráficos", - "common.sound": "Sonido", - "common.resume": "Continuar", - "common.characters": "Personajes", - "common.close": "Cerrar", - "common.yes": "Sí", - "common.no": "No", - "common.back": "Volver", - "common.create": "Crear", - "common.okay": "Ok", - "common.add": "Agregar", - "common.accept": "Aceptar", - "common.decline": "Rechazar", - "common.disclaimer": "Cuidado", - "common.cancel": "Cancelar", - "common.none": "Ninguno", - "common.error": "Error", - "common.fatal_error": "Error Fatal", - "common.you": "Tú", - "common.automatic": "Automático", - "common.random": "Aleatorio", - // Settings Window title - "common.interface_settings": "Ajustes de Interfaz", - "common.gameplay_settings": "Ajustes de Jugabilidad", - "common.controls_settings": "Ajustes de Controles", - "common.video_settings": "Ajustes de Graficos", - "common.sound_settings": "Ajustes de Sonido", - "common.language_settings": "Ajustes de Idiomas", - - // Message when connection to the server is lost - "common.connection_lost": r#"Conexión perdida! -Se reinició el servidor? -El cliente está actualizado?"#, - - - "common.species.orc": "Orco", - "common.species.human": "Humano", - "common.species.dwarf": "Enano", - "common.species.elf": "Elfo", - "common.species.undead": "No-Muerto", - "common.species.danari": "Danari", - - "common.weapons.axe": "Hacha", - "common.weapons.sword": "Espada", - "common.weapons.staff": "Vara Mágica", - "common.weapons.bow": "Arco", - "common.weapons.hammer": "Martillo", - "common.weapons.sceptre": "Cetro curativo", - "common.rand_appearance": "Nombre y Apariencia Aleatoria", - /// End Common section - - - /// Start Main screen section - "main.username": "Usuario", - "main.server": "Servidor", - "main.password": "Contraseña", - "main.connecting": "Conectando", - "main.creating_world": "Creando Mundo", - "main.tip": "Consejo:", - - // Welcome notice that appears the first time Veloren is started - "main.notice": r#"Bienvenido a la version alfa de Veloren! - -Antes de que te diviertas, por favor ten en cuenta lo siguiente: - -- Esta es una alfa muy temprana, espera fallos, jugabilidad extremadamente incompleta, mecánicas sin pulir y características faltantes. - -- Si tienes críticas constructivas o reportes de fallos, puedes contactarnos por reddit, GitLab, o por el server de Discord de nuestra comunidad. - -- Veloren esta licenciado bajo la licencia GPL 3 open-source (código abierto). Eso significa que tienes la libertad de jugar, modificar, y redistribuir el Juego como - desees (siempre y cuando dicho trabajo también este licenciado como GPL 3). - -- Veloren es un proyecto en comunidad sin ánimo de lucro, y todos los que trabajan en el son voluntarios. -Si te gusta lo que ves, eres bienvenido a unirte a los equipos de desarrollo o de arte! - -Gracias por tomarte el tiempo de leer este mensaje, esperamos que disfrutes el juego! - -~ Los Desarrolladores de Veloren"#, - - // Login process description - "main.login_process": r#"Información sobre el proceso para Iniciar Sesión: - -Por favor ten en cuenta que ahora necesitas una cuenta -para jugar en servidores con autenticación activada. - -Puedes crearte una cuenta en - -https://veloren.net/account/."#, - "main.login.server_not_found": "No se encontró el servidor", - "main.login.authentication_error": "Error de autenticación en el servidor", - "main.login.server_full": "El servidor está lleno", - "main.login.untrusted_auth_server": "El servidor de autenticación no es confiable", - "main.login.outdated_client_or_server": "ServidorEnloquecido: Probablemente las versiones son incompatibles, intenta actualizar tu cliente.", - "main.login.timeout": "Tiempo de espera agotado: El servidor no respondio a tiempo. (Puede estar sobrecargado o tener problemas de red).", - "main.login.server_shut_down": "El servidor se apagó", - "main.login.network_error": "Error de red", - "main.login.failed_sending_request": "El pedido al servidor de autenticacion fallo", - "main.login.invalid_character": "El personaje seleccionado no es válido", - "main.login.client_crashed": "El cliente crasheó", - "main.login.not_on_whitelist": "No estás en la lista. Contacta al Dueño del Servidor si quieres unirte.", - "main.login.banned": "Usted ha sido baneado por la siguiente razón", - "main.login.kicked": "Te han echado por la siguiente razón", - "main.login.select_language": "Elige un idioma", - - "main.servers.select_server": "Elige un servidor", - - /// End Main screen section - - - /// Start HUD Section - "hud.do_not_show_on_startup": "No muestres esto al iniciar", - "hud.show_tips": "Mostrar Consejos", - "hud.quests": "Misiones", - "hud.you_died": "Moriste", - "hud.waypoint_saved": "Marcador Guardado", - - "hud.press_key_to_show_keybindings_fmt": "Presiona {key} para mostrar los controles del teclado", - "hud.press_key_to_toggle_lantern_fmt": "[{key}] Linterna", - "hud.press_key_to_show_debug_info_fmt": "Presiona {key} para mostrar información de depuración", - "hud.press_key_to_toggle_keybindings_fmt": "Presiona {key} para alternar los controles del teclado", - "hud.press_key_to_toggle_debug_info_fmt": "Presiona {key} para alternar la información de depuración", - - // Chat outputs - "hud.chat.online_msg": "[{name}] se ha conectado.", - "hud.chat.offline_msg": "[{name}] se ha desconectado.", - - "hud.chat.default_death_msg": "[{name}] murió", - "hud.chat.environmental_kill_msg": "[{name}] murió en {environment}", - "hud.chat.fall_kill_msg": "[{name}] murió por daño de caída", - "hud.chat.suicide_msg": "[{name}] murió por heridas autoinfligidas", - - "hud.chat.pvp_melee_kill_msg": "[{attacker}] derrotó a [{victim}]", - "hud.chat.pvp_ranged_kill_msg": "[{attacker}] le disparó a [{victim}]", - "hud.chat.pvp_explosion_kill_msg": "[{attacker}] hizo explotar a [{victim}]", - "hud.chat.pvp_energy_kill_msg": "[{attacker}] usó magia para matar a [{victim}]", - "hud.chat.pvp_buff_kill_msg": "[{attacker}] mató a [{victim}]", - - - "hud.chat.npc_melee_kill_msg": "{attacker} mató a [{victim}]", - "hud.chat.npc_ranged_kill_msg": "{attacker} le disparó a [{victim}]", - "hud.chat.npc_explosion_kill_msg": "{attacker} hizo explotar a [{victim}]", - "hud.chat.npc_energy_kill_msg": "{attacker} usó magia para matar a [{victim}]", - "hud.chat.npc_other_kill_msg": "{attacker} mató a [{victim}]", - - "hud.chat.loot_msg": "Recogiste [{item}]", - "hud.chat.loot_fail": "Tu inventario está lleno!", - "hud.chat.goodbye": "Adiós!", - "hud.chat.connection_lost": "Conexión perdida. Expulsando en {time} segundos.", - - // SCT outputs - "hud.sct.experience": "{amount} Exp", - "hud.sct.block": "BLOQUEADO", - - // Respawn message - "hud.press_key_to_respawn": r#"Presiona {key} para reaparecer en la ultima fogata que visitaste."#, - - // Welcome message - "hud.welcome": r#"Bienvenido a la alfa de Veloren! - - -Algunos consejos antes de que empieces: - - -Presiona F1 para ver los controles del teclado disponibles. - -Escribe /help en el chat para ver los comandos del chat - - -Hay cofres y otros objetos que aparecen al azar en el Mundo! - -Presiona E para recogerlos. - -Para usar lo que consigas de los cofres abre tu inventario con 'B'. - -Doble click en los objetos en tu bolsa para usarlos o equiparlos. - -Deshazte de ellos haciendo click en ellos y luego arrastralos fuera de la bolsa. - - -Las noches pueden volverse bastante oscuras en Veloren. - -Enciende tu Linterna escribiendo /lantern en el chat o presionando la G. - - -Quieres liberar tu cursor para cerrar esta ventana? Presiona TAB! - - -Disfruta tu estadía en el Mundo de Veloren."#, - -"hud.temp_quest_headline": r#"Por favor, ayúdanos Viajero!"#, -"hud.temp_quest_text": r#"Calabozos llenos de cultistas malvados -han emergido alrededor de nuestros pacíficos pueblos! - - -Consigue alguien que te acompañe, re-abastecete con comida -y derrota sus viles lideres y acólitos. - - -Tal vez incluso obtengas uno de sus -objetos infundidos con magia?"#, - - - - // Inventory - "hud.bag.inventory": "Inventario de {playername}", - "hud.bag.stats_title": "Estadísticas de {playername}", - "hud.bag.exp": "Exp", - "hud.bag.armor": "Armadura", - "hud.bag.stats": "Estadísticas", - "hud.bag.head": "Cabeza", - "hud.bag.neck": "Cuello", - "hud.bag.tabard": "Tabardo", - "hud.bag.shoulders": "Hombros", - "hud.bag.chest": "Torso", - "hud.bag.hands": "Manos", - "hud.bag.lantern": "Linterna", - "hud.bag.glider": "Planeador", - "hud.bag.belt": "Cinturón", - "hud.bag.ring": "Anillo", - "hud.bag.back": "Espalda", - "hud.bag.legs": "Piernas", - "hud.bag.feet": "Pies", - "hud.bag.mainhand": "Mano Principal", - "hud.bag.offhand": "Mano Secundaria", - - - // Map and Questlog - "hud.map.map_title": "Mapa", - "hud.map.qlog_title": "Misiones", - - // Settings - "hud.settings.general": "General", - "hud.settings.none": "Ninguno", - "hud.settings.press_behavior.toggle": "Alternar", - "hud.settings.press_behavior.hold": "Mantener", - "hud.settings.help_window": "Ventana de Ayuda", - "hud.settings.debug_info": "Info de Depuración", - "hud.settings.tips_on_startup": "Consejos de Inicio", - "hud.settings.ui_scale": "Escala de la Interfaz", - "hud.settings.relative_scaling": "Escalado Relativo", - "hud.settings.custom_scaling": "Escalado Personalizado", - "hud.settings.crosshair": "Mira", - "hud.settings.transparency": "Transparencia", - "hud.settings.hotbar": "Inventario Rápido", - "hud.settings.toggle_shortcuts": "Alternar Atajos", - "hud.settings.buffs_skillbar": "Buffs en la barra de habilidades.", - "hud.settings.buffs_mmap": "Buffs en el Minimapa", - "hud.settings.toggle_bar_experience": "Alternar Barra de Experiencia", - "hud.settings.scrolling_combat_text": "Texto de Combate con Desplazamiento", - "hud.settings.single_damage_number": "Números de Daño Singular", - "hud.settings.cumulated_damage": "Daño Acumulado", - "hud.settings.incoming_damage": "Daño Recibido", - "hud.settings.cumulated_incoming_damage": "Daño Recibido Acumulado", - "hud.settings.speech_bubble": "Burbuja de Diálogo", - "hud.settings.speech_bubble_dark_mode": "Burbuja de Diálogo en Modo Oscuro", - "hud.settings.speech_bubble_icon": "Burbuja de Diálogo en Modo Oscuro", - "hud.settings.energybar_numbers": "Números de la Barra de Energia", - "hud.settings.values": "Valores", - "hud.settings.percentages": "Porcentajes", - "hud.settings.chat": "Chat", - "hud.settings.background_transparency": "Transparencia del Fondo", - "hud.settings.chat_character_name": "Nombres de Personajes en el chat", - "hud.settings.loading_tips": "Consejos en Pantalla de Carga", - - "hud.settings.pan_sensitivity": "Sensibilidad de Desplazamiento de la Cámara", - "hud.settings.zoom_sensitivity": "Sensibilidad del Zoom", - "hud.settings.invert_scroll_zoom": "Invertir Desplazamiento de Zoom", - "hud.settings.invert_mouse_y_axis": "Invertir eje Y del Ratón", - "hud.settings.enable_mouse_smoothing": "Suavizado de la Cámara", - "hud.settings.free_look_behavior": "Modo de vista libre", - "hud.settings.auto_walk_behavior": "Modo de caminata automática", - "hud.settings.stop_auto_walk_on_input": "Frenar caminata automática", - - "hud.settings.view_distance": "Distancia de Visión", - "hud.settings.sprites_view_distance": "Distancia de Visión de Sprites", - "hud.settings.figures_view_distance": "Distancia de Visión de Entidades", - "hud.settings.maximum_fps": "FPS Máximos", - "hud.settings.fov": "Campo de Visión (grados)", - "hud.settings.gamma": "Gama", - "hud.settings.exposure": "Exposición", - "hud.settings.ambiance": "Brillo del Ambiente", - "hud.settings.antialiasing_mode": "Modo Anti-Aliasing", - "hud.settings.upscale_factor": "Factor de Escala", - "hud.settings.cloud_rendering_mode": "Modo de Renderizado de Nubes", - "hud.settings.fluid_rendering_mode": "Modo de Renderizado del Agua", - "hud.settings.fluid_rendering_mode.cheap": "Bajo", - "hud.settings.fluid_rendering_mode.shiny": "Alto", - "hud.settings.cloud_rendering_mode.minimal": "Mínimo", - "hud.settings.cloud_rendering_mode.low": "Bajo", - "hud.settings.cloud_rendering_mode.medium": "Medio", - "hud.settings.cloud_rendering_mode.high": "Alto", - "hud.settings.cloud_rendering_mode.ultra": "Ultra", - "hud.settings.fullscreen": "Pantalla Completa", - "hud.settings.fullscreen_mode": "Modo de Pantalla Completa", - "hud.settings.fullscreen_mode.exclusive": "Completo", - "hud.settings.fullscreen_mode.borderless": "Con Bordes", - "hud.settings.particles": "Particulas", - "hud.settings.resolution": "Resolución", - "hud.settings.bit_depth": "Profundidad de Bits", - "hud.settings.refresh_rate": "Taza de Refresco", - "hud.settings.save_window_size": " Guardar tamaño de ventana", - "hud.settings.lighting_rendering_mode": "Renderizado de la luz de la Linterna", - "hud.settings.lighting_rendering_mode.ashikhmin": "Tipo A - Alto", - "hud.settings.lighting_rendering_mode.blinnphong": "Tipo B - Medio", - "hud.settings.lighting_rendering_mode.lambertian": "Tipo L - Bajo", - "hud.settings.shadow_rendering_mode": "Renderizado de Sombras", - "hud.settings.shadow_rendering_mode.none": "Ninguno", - "hud.settings.shadow_rendering_mode.cheap": "Bajo", - "hud.settings.shadow_rendering_mode.map": "Alto", - "hud.settings.shadow_rendering_mode.map.resolution": "Resolución", - "hud.settings.lod_detail": "Detalle de LoD", - "hud.settings.save_window_size": "Recordar tamaño de ventana", //It's repeated in en.ron (359 and 370) - - - "hud.settings.music_volume": "Volumen de Música", - "hud.settings.sound_effect_volume": "Volumen de Efectos de Sonido", - "hud.settings.audio_device": "Dispositivo de Audio", - - "hud.settings.awaitingkey": "Presiona una tecla...", - "hud.settings.unbound": "Ninguno", - "hud.settings.reset_keybinds": "Reestablecer Controles", - - "hud.social": "Lista de jugadores", - "hud.social.online": "En Línea", - "hud.social.friends": "Amigos", - "hud.social.not_yet_available": "Aún no esta disponible", - "hud.social.faction": "Facción", - "hud.social.play_online_fmt": "{nb_player} jugador(es) en línea", - "hud.social.name": "Nombre", - "hud.social.level": "Nivel", - "hud.social.zone": "Zona", - "hud.social.account": "Cuenta", - - - "hud.crafting": "Crafteo", - "hud.crafting.recipes": "Recetas", - "hud.crafting.ingredients": "Ingredientes:", - "hud.crafting.craft": "Fabricar", - "hud.crafting.tool_cata": "Requisitos:", - - "hud.group": "Grupo", - "hud.group.invite_to_join": "[{name}] Te invito a su Grupo!", - "hud.group.invite": "Invitar", - "hud.group.kick": "Echar", - "hud.group.assign_leader": "Asignar Lider", - "hud.group.leave": "Salir del Grupo", - "hud.group.dead" : "Muerto", - "hud.group.out_of_range": "Fuera de Alcance", - "hud.group.add_friend": "Agregar a Amigos", - "hud.group.link_group": "Conectar Grupos", - "hud.group.in_menu": "Eligiendo Personaje", - "hud.group.members": "Miembros del Grupo", - - "hud.spell": "Hechizos", - - "hud.free_look_indicator": "Vista libre activa", - "hud.auto_walk_indicator": "Caminata automática activa", - - "hud.map.difficulty": "Dificultad", - "hud.map.towns": "Pueblos", - "hud.map.castles": "Castillos", - "hud.map.dungeons": "Calabozos", - "hud.map.caves": "Cuevas", - "hud.map.cave": "Cueva", - "hud.map.town": "Pueblo", - "hud.map.castle": "Castillo", - "hud.map.dungeon": "Calabozo", - "hud.map.difficulty_dungeon": "Dificultad de\n\nCalabozo: {difficulty}", - "hud.map.drag": "Arrastrar", - "hud.map.zoom": "Zoom", - "hud.map.recenter": "Centrar", - - /// End HUD section - - - /// Start GameInput section - - "gameinput.primary": "Ataque Básico", - "gameinput.secondary": "Ataque Secundario/Bloquear/Apuntar", - "gameinput.slot1": "Ranura de Inventario Rápido 1", - "gameinput.slot2": "Ranura de Inventario Rápido 2", - "gameinput.slot3": "Ranura de Inventario Rápido 3", - "gameinput.slot4": "Ranura de Inventario Rápido 4", - "gameinput.slot5": "Ranura de Inventario Rápido 5", - "gameinput.slot6": "Ranura de Inventario Rápido 6", - "gameinput.slot7": "Ranura de Inventario Rápido 7", - "gameinput.slot8": "Ranura de Inventario Rápido 8", - "gameinput.slot9": "Ranura de Inventario Rápido 9", - "gameinput.slot10": "Ranura de Inventario Rápido 10", - "gameinput.swaploadout": "Cambiar Equipamiento", - "gameinput.togglecursor": "Mostrar Cursor", - "gameinput.help": "Mostrar Ventana de Ayuda", - "gameinput.toggleinterface": "Mostrar Interfaz", - "gameinput.toggledebug": "Mostrar FPS y la Info de Depuración", - "gameinput.screenshot": "Tomar Captura de Pantalla", - "gameinput.toggleingameui": "Mostrar Nombres", - "gameinput.fullscreen": "Pantalla Completa", - "gameinput.moveforward": "Moverse hacia Adelante", - "gameinput.moveleft": "Moverse hacia la Izquierda", - "gameinput.moveright": "Moverse hacia la Derecha", - "gameinput.moveback": "Moverse hacia Atras", - "gameinput.jump": "Saltar", - "gameinput.glide": "Planeador", - "gameinput.roll": "Rodar", - "gameinput.climb": "Trepar", - "gameinput.climbdown": "Descender", - "gameinput.wallleap": "Saltar a la Pared", - "gameinput.togglelantern": "Encender Farol", - "gameinput.mount": "Montar", - "gameinput.chat": "Abrir Chat", - "gameinput.enter": "Entrar", - "gameinput.command": "Insertar Comandos", - "gameinput.escape": "Escapar", - "gameinput.map": "Mapa", - "gameinput.bag": "Mochila", - "gameinput.social": "Lista de jugadores", - "gameinput.sit": "Sentarse", - "gameinput.spellbook": "Hechizos", - "gameinput.settings": "Configuración", - "gameinput.respawn": "Reaparecer", - "gameinput.charge": "Cargar", - "gameinput.togglewield": "Alternar empuñadura", - "gameinput.interact": "Interactuar", - "gameinput.freelook": "Vista Libre", - "gameinput.autowalk": "Caminata Automática", - "gameinput.dance": "Bailar", - "gameinput.select": "Seleccione la Entidad", - "gameinput.acceptgroupinvite": "Aceptar invitación al grupo", - "gameinput.declinegroupinvite": "Rechazar invitación al grupo", - "gameinput.crafting": "Craftear", - "gameinput.fly": "Volar", - "gameinput.sneak": "Agacharse", - "gameinput.swimdown": "Sumergirse", - "gameinput.swimup": "Nadar hacia arriba", - - /// End GameInput section - - - /// Start chracter selection section - "char_selection.loading_characters": "Cargando personajes...", - "char_selection.delete_permanently": "¿Borrar este Personaje permanentemente?", - "char_selection.deleting_character": "Borrando Personaje...", - "char_selection.change_server": "Cambiar Servidor", - "char_selection.enter_world": "Entrar al Mundo", - "char_selection.logout": "Cerrar Sesión", - "char_selection.create_new_character": "Crear Nuevo Personaje", - "char_selection.creating_character": "Creando Personaje...", - "char_selection.character_creation": "Creación de Personaje", - - "char_selection.human_default": "Humano por defecto", - "char_selection.level_fmt": "Nivel {level_nb}", - "char_selection.uncanny_valley": "Valle Misterioso", - "char_selection.plains_of_uncertainty": "Planicies de la Incertidumbre", - "char_selection.beard": "Barba", - "char_selection.hair_style": "Peinado", - "char_selection.hair_color": "Color de Pelo", - "char_selection.eye_color": "Color de Ojos", - "char_selection.skin": "Color de Piel", - "char_selection.eyeshape": "Detalles de los Ojos", - "char_selection.accessories": "Accesorios", - "char_selection.create_info_name": "Tu Personaje necesita un nombre!", - - /// End chracter selection section - - - /// Start character window section - "character_window.character_name": "Nombre de Personaje", - // Character stats - "character_window.character_stats": r#"Resistencia - -Estado Físico - -Valentía - -Protección -"#, - /// End character window section - - - /// Start Escape Menu Section - "esc_menu.logout": "Cerrar Sesión", - "esc_menu.quit_game": "Salir del Juego", - /// End Escape Menu Section - - /// Buffs and Debuffs - "buff.remove": "Click para quitar", - "buff.title.missing": "Sin Título", - "buff.desc.missing": "Sin Descripción", - // Buffs - "buff.title.heal": "Curación", - "buff.desc.heal": "Recupera vida durante un tiempo.", - "buff.title.potion": "Poción", - "buff.desc.potion": "Bebiendo...", - "buff.title.saturation": "Saturación", - "buff.desc.saturation": "Recupera vida durante un tiempo por objetos.", - "buff.title.campfire_heal": "Curación de fogata", - "buff.desc.campfire_heal": "Descansar en una fogata recupera {rate}% por segundo.", - // Debuffs - "buff.title.bleed": "Sangrando", - "buff.desc.bleed": "Inflinge daño regularmente.", - - - }, - - - vector_map: { - "loading.tips": [ - "Presiona 'G' para encender tu linterna.", - "Presiona 'F1' para ver los controles predeterminados.", - "Puedes escribir /say o /s para chatear solo con jugadores alrededor tuyo.", - "Puedes escribr /region o /r para chatear solo con jugadores que están a unos cien bloques alrededor tuyo.", - "Para enviar mensajes privados escribe /tell seguido de el nombre de un jugador y luego tu mensaje.", - "NPCs con el mismo nivel pueden tener una dificultad diferente.", - "Observa el terreno en búsqueda de comida, cofres y botines!", - "¿Inventario lleno de comida? Intenta craftear mejor comida con ella!", - "¿Te preguntas dónde debes hacerlo? Los Dungeons están marcados con puntos marrones en el mapa!", - "No te olvides de ajustar los gráficos de tu pc. Presiona 'N' para abrir la configuración.", - "Jugar con otros es divertido! Presiona 'O' para ver quien esta conectado.", - "Un NPC con un craneo debajo de su barra de vida es bastante más poderoso comparado contigo.", - "Presiona 'J' para bailar. Fiesta!", - "Presiona 'Shift-Izquierdo' para abrir tu planeador y conquistar los cielos.", - "Veloren está aún en Alfa temprana. Hacemos lo mejor para mejorar día a día!", - "Si te quieres unir al equipo de desarrolladores o solo chatear con nosotros, únete a nuestro servidor en Discord.", - "Puedes elegir mostrar tu cantidad de vida en la barra de vida en la configuración.", - "Para ver tus estadísticas, haz click en el botón 'Estadísticas' en el inventario.", - ], - "npc.speech.villager_under_attack": [ - "Ayuda, ¡Me están atacando!", - "¡Ayuda! ¡Me están atacando!", - "¡Auch! ¡Me están atacando!", - "¡Auch! ¡Me están atacando! ¡Ayuda!", - "¡Ayudenme! ¡Me están atacando!", - "¡Me están atacando! ¡Ayuda!", - "¡Me están atacando! ¡Ayudenme!", - "¡Ayuda!", - "¡Ayuda! ¡Ayuda!", - "¡Ayuda! ¡Ayuda! ¡Ayuda!", - "¡Me están atacando!", - "¡AAAHH! ¡Me están atacando!", - "¡AAAHH! ¡Me están atacando! ¡Ayuda!", - "Ayuda! Nos están atacando!", - "¡Ayuda! ¡Asesino!", - "¡Ayuda! ¡Hay un asesino suelto!", - "¡Ayuda! ¡están intentando matarme!", - "Guardias, ¡Me están atacando!", - "¡Guardias! ¡Me están atacando!", - "¡Me están atacando! ¡Guardias!", - "¡Ayuda! ¡Guardias! ¡Me están atacando!", - "¡Guardias! ¡Vengan rapido!", - "¡Guardias, Guardias!", - "¡Guardias! ¡Me esta atacando un villano!", - "¡Guardias, eliminen a este desagradable villano!", - "¡Guardias! ¡Ahi esta el asesino!", - "¡Guardias! ¡Ayúdenme!", - "No te saldrás con la tuya, ¡Guardias!", - "¡Eres despreciable!", - "¡Ayúdenme!", - "¡Ayuda! ¡Porfavor!", - "¡Auch! ¡Guardias! ¡Ayuda!", - "¡Vienen por mi!", - "¡Ayuda! ¡Ayuda! Estoy siendo atacado", - "Ah, se nota que la violencia es parte del sistema.", - "¡Esto no es más que un rasguño!", - "Deja de hacer eso!", - "¿Qué te hice para merecer esto?", - "Por favor, para de atacarme!", - "Hey! Mira hacia adonde apuntas con esa cosa", - "Desgraciado, vete de aqui!", - "Para ya! Vete!", - "Me estas haciendo enojar!", - "Hey!¿Quién te piensas que eres?", - "Te arrancaré la cabeza por eso!", - "Detente, por favor! No llevo nada de valor!", - "Te voy a mandar a mi hermano, el es más grande que yo!", - "Nooo, le contaré a mi madre!", - "Maldito seas!", - "Por favor no lo hagas.", - "Eso no fue agradable!", - "Tu arma funciona, ahora aléjala!", - "Si claro...", - "Por favor, tengo familia!", - "Soy demasiado jóven para morir!", - "¿Podemos hablar sobre esto?", - "La violencia no resuelve nada!", - "Este día se esta convirtiendo en uno muy feo...", - "Hey, eso dolió!", - "Ayy!", - "Qué violento!", - "Detente, te lo suplico!", - "Ojala te enfermes!", - "Esto no es divertido.", - "¡¿Cómo te atreves?!", - "Vas a pagar por eso!", - "Sigue con eso y lo lamentarás!", - "No hagas que te lastime!", - "Tiene que ser un malentendido!", - "No necesitas hacer esto!", - "Vete, demonio!", - "Eso realmente dolió!", - "¿Por qué harias eso?", - "Por todos los Santos, para!", - "Me habrás confudido con alguien más!", - "No me merezco esto!", - "Por favor, no lo hagas de nuevo", - "Guardias, tiren este monstruo al lago", - "Invocaré mis demonios en ti!", - ], - } -) diff --git a/assets/voxygen/i18n/ja_JP/template.ron b/assets/voxygen/i18n/ja_JP/template.ron deleted file mode 100644 index 02abc19286..0000000000 --- a/assets/voxygen/i18n/ja_JP/template.ron +++ /dev/null @@ -1,12 +0,0 @@ -/// 警告: ローカライズファイルは、UTF-8のBOM無しで保存する必要があります - -/// Localization for 日本語 Japanese -( - string_map: { - - }, - - - vector_map: { - } -) diff --git a/assets/voxygen/i18n/nl_NL/_manifest.ron b/assets/voxygen/i18n/nl_NL/_manifest.ron index c5890c9072..d1081e1d97 100644 --- a/assets/voxygen/i18n/nl_NL/_manifest.ron +++ b/assets/voxygen/i18n/nl_NL/_manifest.ron @@ -42,477 +42,10 @@ ), }, string_map: { - /// Start Common section - // Texts used in multiple locations with the same formatting - "common.username": "Spelernaam", - "common.singleplayer": "Alleen spelen", - "common.multiplayer": "Samen spelen", - "common.servers": "Servers", - "common.quit": "Afsluiten", - "common.settings": "Instellingen", - "common.languages": "Talen", - "common.interface": "Interface", - "common.gameplay": "Gameplay", - "common.controls": "Besturing", - "common.video": "Grafische weergave", - "common.sound": "Geluid", - "common.languages": "Talen", - "common.resume": "Verder spelen", - "common.characters": "Karakters", - "common.close": "Sluiten", - "common.yes": "Ja", - "common.no": "Nee", - "common.back": "Terug", - "common.create": "Aanmaken", - "common.okay": "Oké", - "common.accept": "Aanvaarden", - "common.decline": "Afwijzen", - "common.disclaimer": "Disclaimer", - "common.cancel": "Annuleren", - "common.none": "Geen", - "common.error": "Fout", - "common.fatal_error": "Fatale fout", - "common.you": "Jij", - "common.automatic": "Auto", - "common.random": "Willekeurig", - // Settings Window title - "common.interface_settings": "Interface Instellingen", - "common.gameplay_settings": "Gameplay Instellingen", - "common.controls_settings": "Besturing Instellingen", - "common.video_settings": "Grafische instellingen", - "common.sound_settings": "Geluids instellingen", - "common.language_settings": "Taal instellingen", - - // Message when connection to the server is lost - "common.connection_lost": r#"Verbinding verloren! -Is de server opniew opgestart? -Is je client nog up to date?"#, - - - "common.species.orc": "Orc", - "common.species.human": "Mens", - "common.species.dwarf": "Dwerg", - "common.species.elf": "Elf", - "common.species.undead": "Ondood", - "common.species.danari": "Danari", - - "common.weapons.axe": "Bijl", - "common.weapons.sword": "Zwaard", - "common.weapons.staff": "Staf", - "common.weapons.bow": "Boog", - "common.weapons.hammer": "Hamer", - "common.weapons.sceptre": "Genezende scepter", - "common.rand_appearance": "Willekeurig uiterlijk en naam", - /// End Common section - - - /// Start Main screen section - "main.connecting": "Verbinden", - "main.creating_world": "Wereld aan het maken", - "main.tip": "Tip:", - - // Welcome notice that appears the first time Veloren is started - "main.notice": r#"Welkom bij de Alpha versie van Veloren! - -Voordat de fun begint zijn hier enkele dingen om rekening mee te houden: - -- Dit is een hele vroege alpha. Verwacht bugs, extreem onafgemaakte gameplay, ruwe spelmechanics en missende functies. - -- Als je constructieve feedback hebt of bugs wil melden, kan je ons contacteren via Reddit, Gitlab of onze community Discord. - -- Veloren is onder de GPL 3 open-source licentie gelicensieerd. Dat betekent dat je vrij bent om het spel te spelen, bewerken en doorgeven op welke manier -je ook wil (zo lang afgeleide werken ook onder GPL 3 gelicensieerd zijn) - -- Veloren is een non-profit community project, en iedereen dat er aan meehelpt is een vrijwilliger. -Als je interesse hebt kan je je aansluiten bij onze ontwikkeling- of ontwerpteams! - -Bedankt voor de tijd te nemen om deze melding te lezen, we hopen dat je van het spel zult genieten! -Thanks for taking the time to read this notice, we hope you enjoy the game! - -~ De Veloren ontwikkelaars"#, - - // Login process description - "main.login_process": r#"Information over het loginproces: - -Hou er rekening mee dat je tegenwoordig een account nodig hebt -om op servers met authenticatie te spelen - -Je kan een account maken op - -https://veloren.net/account/."#, - "main.login.server_not_found": "Server nie gevonden", - "main.login.authentication_error": "Authenticatie mislukt", - "main.login.server_full": "Server zit vol", - "main.login.untrusted_auth_server": "Onvertrouwde authenticatie server", - "main.login.outdated_client_or_server": "Versieprobleem: De versie tussen de client en de server komen niet overeen. Check of er updates zijn/", - "main.login.timeout": "Timeout: De server deed er te lang over om te antwoorden. (Overblast of netwerk problemen).", - "main.login.server_shut_down": "Server is afgesloten", - "main.login.network_error": "Network problemen", - "main.login.failed_sending_request": "Kon verzoek niet naar authenticatie server sturen", - "main.login.invalid_character": "Het geselecteerde karakter is ongeldig", - "main.login.client_crashed": "Client is gecrashed", - "main.login.not_on_whitelist": "Je moet op de whitelist staan om deze wereld te joinen", - "main.login.banned": "Je bent verbannen voor de volgende reden", - "main.login.kicked": "Je bent gekicked voor de volgende reden", - "main.login.select_language": "Kies een taal", - - - /// End Main screen section - - - /// Start HUD Section - "hud.do_not_show_on_startup": "Niet meer bij opstarten tonen", - "hud.show_tips": "Tips tonen", - "hud.quests": "Quests", - "hud.you_died": "Je bent gedood", - "hud.waypoint_saved": "Waypoint Opgeslagen", - - "hud.press_key_to_show_keybindings_fmt": "[{key}] Besturing", - "hud.press_key_to_toggle_lantern_fmt": "[{key}] Lantaarn", - "hud.press_key_to_show_debug_info_fmt": "Druk op {key} om debug info te tonen", - "hud.press_key_to_toggle_keybindings_fmt": "Druk op {key} om te de besturing aan/uit te zetten", - "hud.press_key_to_toggle_debug_info_fmt": "Druk op {key} om debug info aan/uit te zetten", - - // Chat outputs - "hud.chat.online_msg": "[{name}] is nu online", - "hud.chat.offline_msg": "[{name}] is offline gegaan", - - "hud.chat.default_death_msg": "[{name}] is gestorven", - "hud.chat.environmental_kill_msg": "[{name}] is gestorven in {environment}", - "hud.chat.fall_kill_msg": "[{name}] is gestorven door te vallen", - "hud.chat.suicide_msg": "[{name}] is gestorven door zelf toegebrachte verwondingen", - - "hud.chat.pvp_melee_kill_msg": "[{attacker}] versloeg [{victim}]", - "hud.chat.pvp_ranged_kill_msg": "[{attacker}] schoot [{victim}] neer", - "hud.chat.pvp_explosion_kill_msg": "[{attacker}] blies [{victim}] op", - "hud.chat.pvp_energy_kill_msg": "[{attacker}] gebruikte magie om [{victim}] te vermoorden", - - "hud.chat.npc_melee_kill_msg": "{attacker} dode [{victim}]", - "hud.chat.npc_ranged_kill_msg": "{attacker} schoot [{victim}]", - "hud.chat.npc_explosion_kill_msg": "{attacker} blies [{victim}] op", - - "hud.chat.loot_msg": "Je raapte [{item}] op", - "hud.chat.loot_fail": "Jouw inventory is vol!", - "hud.chat.goodbye": "Vaarwel!", - "hud.chat.connection_lost": "Verbinding verloren. Je wordt in {time} seconden gekicked.", - - // SCT outputs - "hud.sct.experience": "{amount} Exp", - "hud.sct.block": "GEBLOCKED", - - // Respawn message - "hud.press_key_to_respawn": r#"Druk op {key} om te respawnen bij het laatste kampvuur dat je bezocht."#, - - // Welcome message - "hud.welcome": r#"Welcome bij de Veloren Alpha! - -Wat tips voor je start: - - -Druk op F1 om de besturing te zien. - -Type /help in chat om de chat commando's te zien. - - -Er verschijnen kisten en andere objecten willekeurig in de wereld! - -Gebruik rechtermuisknop om ze te verzamelen! - -Om effectief hetgene dat je van de kisten krijgt te gebruiken, open je je inventory met 'B'. - -Dubbelklik op de voorwerpen in je rugzak om ze aan te doen of te gebruiken. - -Gooi dingen weg door ze eenmaal aan te klikken en dan buiten je rugzak te klikken. - - -Nachten kunnen vrij donker worden in Veloren. - -Gebruik je lantaarn door 'G' te drukken - - -Wil je je cursor gebruiken om dit venster te sluiten? Druk TAB! - - -Geniet van je verblijf in de wereld van Veloren."#, - -"hud.temp_quest_headline": r#"Help ons alsjeblieft, reiziger!"#, -"hud.temp_quest_text": r#"Kerkers vol met kwaaraardige sektes -komen overal tevoorschijn rond onze vreedzame dorpen! - - -Verzamel wat gezelschap, vul je voedselrantsoenen aan -en versla hun kwaadaardige leiders en volgelingen. - - -Misschien kan je zelfs een van hun -Maybe you can even obtain one of their -met magie gevulde objecten bemachtigen?"#, - - - - // Inventory - "hud.bag.inventory": "{playername}'s Rugzak", - "hud.bag.stats_title": "{playername}'s Stats", - "hud.bag.exp": "Exp", - "hud.bag.armor": "Armor", - "hud.bag.stats": "Stats", - "hud.bag.head": "Hoofd", - "hud.bag.neck": "Nek", - "hud.bag.tabard": "Tabberd", - "hud.bag.shoulders": "Schouders", - "hud.bag.chest": "Borstkas", - "hud.bag.hands": "Handen", - "hud.bag.lantern": "Lantaarn", - "hud.bag.glider": "Deltavlieger", - "hud.bag.belt": "Riem", - "hud.bag.ring": "Ring", - "hud.bag.back": "Rug", - "hud.bag.legs": "Benen", - "hud.bag.feet": "Voeten", - "hud.bag.mainhand": "Dominante hand", - "hud.bag.offhand": "Tweede hand", - - - // Map and Questlog - "hud.map.map_title": "Kaart", - "hud.map.qlog_title": "Quests", - - // Settings - "hud.settings.general": "Algemeen", - "hud.settings.none": "Geen", - "hud.settings.press_behavior.toggle": "Omschakelbaar", - "hud.settings.press_behavior.hold": "Inhouden", - "hud.settings.help_window": "Help Venster", - "hud.settings.debug_info": "Debug Informatie", - "hud.settings.tips_on_startup": "Tips-Bij-Opstarten", - "hud.settings.ui_scale": "UI-Schaal", - "hud.settings.relative_scaling": "Relatief Schalen", - "hud.settings.custom_scaling": "Aangepast Schalen", - "hud.settings.crosshair": "Richtkruis", - "hud.settings.transparency": "Doorschijnbaarheid", - "hud.settings.hotbar": "Hotbar", - "hud.settings.toggle_shortcuts": "Toon Sneltoetsen", - "hud.settings.toggle_bar_experience": "Toon Experience Balk", - "hud.settings.scrolling_combat_text": "Pop-up Gevechtstext", - "hud.settings.single_damage_number": "Aparte Schade Getallen", - "hud.settings.cumulated_damage": "Cumulatieve Schade Getallen", - "hud.settings.incoming_damage": "Inkomende Schade Getallen", - "hud.settings.cumulated_incoming_damage": "Cumulatieve Inkomende Schade Getallen", - "hud.settings.speech_bubble": "Spraakbubbel", - "hud.settings.speech_bubble_dark_mode": "Donkere Modus", - "hud.settings.speech_bubble_icon": "Spraakbubbel Icoon", - "hud.settings.energybar_numbers": "Energiebalk Getallen", - "hud.settings.values": "Waarden", - "hud.settings.percentages": "Percentages", - "hud.settings.chat": "Chat", - "hud.settings.background_transparency": "Transparantie Achtergrond", - "hud.settings.chat_character_name": "Karakternamen in de Chat", - "hud.settings.loading_tips": "Laadscherm Tips", - - "hud.settings.pan_sensitivity": "Camera-gevoeligheid", - "hud.settings.zoom_sensitivity": "Zoom-gevoeligheid", - "hud.settings.invert_scroll_zoom": "Inverteer Zoom Scrollen", - "hud.settings.invert_mouse_y_axis": "Inverteer muis Y As", - "hud.settings.enable_mouse_smoothing": "Camerabeweging gelijkmaken", - "hud.settings.free_look_behavior": "Vrije camera gedrag", - "hud.settings.auto_walk_behavior": "Automatisch wandelgedrag", - "hud.settings.stop_auto_walk_on_input": "Stop automatisch -wandelen bij bewegen", - - "hud.settings.view_distance": "Kijkafstand", - "hud.settings.sprites_view_distance": "Kijkafstand sprites", - "hud.settings.figures_view_distance": "Kijkafstand entiteiten", - "hud.settings.maximum_fps": "Maximum FPS", - "hud.settings.fov": "Gezichtsveld (graden)", - "hud.settings.gamma": "Gamma", - "hud.settings.ambiance": "Omgevingshelderheid", - "hud.settings.antialiasing_mode": "AntiAliasing Modus", - "hud.settings.cloud_rendering_mode": "Wolk Rendering Modus", - "hud.settings.fluid_rendering_mode": "Vloeistoffen Rendering Mode", - "hud.settings.fluid_rendering_mode.cheap": "Goedkoop", - "hud.settings.fluid_rendering_mode.shiny": "Schitterend", - "hud.settings.cloud_rendering_mode.regular": "Gewoon", - "hud.settings.fullscreen": "Volledig scherm", - "hud.settings.fullscreen_mode": "Volledige scherm modus", - "hud.settings.fullscreen_mode.exclusive": "Exclusief", - "hud.settings.fullscreen_mode.borderless": "Randloos", - "hud.settings.particles": "Deeltjes", - "hud.settings.resolution": "Resolutie", - "hud.settings.bit_depth": "Bit diepte", - "hud.settings.refresh_rate": "Vernieuwingssnelheid", - "hud.settings.save_window_size": "Venster grootte opslaan", - "hud.settings.lighting_rendering_mode": "Licht Rendering Modus", - "hud.settings.lighting_rendering_mode.ashikhmin": "Type A", - "hud.settings.lighting_rendering_mode.blinnphong": "Type B", - "hud.settings.lighting_rendering_mode.lambertian": "Type L", - "hud.settings.shadow_rendering_mode": "Schaduw Rendering Mode", - "hud.settings.shadow_rendering_mode.none": "Geen", - "hud.settings.shadow_rendering_mode.cheap": "Goedkoop", - "hud.settings.shadow_rendering_mode.map": "Kaart", - "hud.settings.shadow_rendering_mode.map.resolution": "Resolutie", - "hud.settings.lod_detail": "LoD Detail", - "hud.settings.save_window_size": "Venster grootte opslaan", - - - "hud.settings.music_volume": "Muziek Volume", - "hud.settings.sound_effect_volume": "Geluidseffecten Volume", - "hud.settings.audio_device": "Audio Apparaat", - - "hud.settings.awaitingkey": "Druk op een toets...", - "hud.settings.unbound": "Geen", - "hud.settings.reset_keybinds": "Standaardwaarden -herstellen", - - "hud.social": "Andere spelers", - "hud.social.online": "Online:", - "hud.social.friends": "Vrienden", - "hud.social.not_yet_available": "Nog niet beschikbaar", - "hud.social.faction": "Factie", - "hud.social.play_online_fmt": "{nb_player} speler(s) online", - "hud.social.name": "Naam", - "hud.social.level": "Level", - "hud.social.zone": "Zone", - "hud.social.account": "Account", - - - "hud.crafting": "Fabriceren", - "hud.crafting.recipes": "Recepten", - "hud.crafting.ingredients": "Ingrediënten:", - "hud.crafting.craft": "Maak", - "hud.crafting.tool_cata": "Vereisten:", - - "hud.group": "Groep", - "hud.group.invite_to_join": "[{name}] heeft je voor zijn/haar groep uitgenodigd!", - "hud.group.invite": "Uitnodigen", - "hud.group.kick": "Kick", - "hud.group.assign_leader": "Maak Leider", - "hud.group.leave": "Groep Verlaten", - "hud.group.dead" : "Dood", - "hud.group.out_of_range": "Buiten Bereik", - "hud.group.add_friend": "Aan Vrienden Toevoegen", - "hud.group.link_group": "Link Groups", - "hud.group.in_menu": "In Menu", - "hud.group.members": "Groepsleden", - - "hud.spell": "Spreuken", - - "hud.free_look_indicator": "Vrij rondkijken aan. Druk {key} om uit te zetten.", - "hud.auto_walk_indicator": "Automatisch wandelen aan", - - /// End HUD section - - - /// Start GameInput section - - "gameinput.primary": "Gewone aanval", - "gameinput.secondary": "Alternatieve Aanval/Block/Mikken", - "gameinput.slot1": "Hotbar Slot 1", - "gameinput.slot2": "Hotbar Slot 2", - "gameinput.slot3": "Hotbar Slot 3", - "gameinput.slot4": "Hotbar Slot 4", - "gameinput.slot5": "Hotbar Slot 5", - "gameinput.slot6": "Hotbar Slot 6", - "gameinput.slot7": "Hotbar Slot 7", - "gameinput.slot8": "Hotbar Slot 8", - "gameinput.slot9": "Hotbar Slot 9", - "gameinput.slot10": "Hotbar Slot 10", - "gameinput.swaploadout": "Uitrusting Wisselen", - "gameinput.togglecursor": "Cursor Aan/Uit", - "gameinput.help": "Help Venster Aan/Uit", - "gameinput.toggleinterface": "Interface Aan/Uit", - "gameinput.toggledebug": "FPS en Debug Info Aan/Uit", - "gameinput.screenshot": "Screenshot maken", - "gameinput.toggleingameui": "Naamplaatjes Aan/Uit", - "gameinput.fullscreen": "Volledig Scherm Aan/Uit", - "gameinput.moveforward": "Voorwaards Bewegen", - "gameinput.moveleft": "Links Bewegen", - "gameinput.moveright": "Rechts Bewegen", - "gameinput.moveback": "Achteruit Bewegen", - "gameinput.jump": "Springen", - "gameinput.glide": "Deltavlieger", - "gameinput.roll": "Rollen", - "gameinput.climb": "Klimmen", - "gameinput.climbdown": "Naar Beneden Klimmen", - "gameinput.wallleap": "Muursprong", - "gameinput.togglelantern": "Lantaarn Aan/Uit", - "gameinput.mount": "Berijden", - "gameinput.chat": "Chat", - "gameinput.command": "Commando", - "gameinput.escape": "Sluiten", - "gameinput.map": "Kaart", - "gameinput.bag": "Rugzak", - "gameinput.social": "Sociaal", - "gameinput.sit": "Zit", - "gameinput.spellbook": "Spreuken", - "gameinput.settings": "Instellingen", - "gameinput.respawn": "Respawn", - "gameinput.charge": "Opladen", - "gameinput.togglewield": "Wapen Vastnemen/Wegsteken", - "gameinput.interact": "Gebruik", - "gameinput.freelook": "Vrije Camera", - "gameinput.autowalk": "Automatisch Wandelen", - "gameinput.dance": "Dans", - "gameinput.select": "Selecteer Entiteit", - "gameinput.acceptgroupinvite": "Accepteer Groepsuitnodiging", - "gameinput.declinegroupinvite": "Wijs Groepsuitnodiging Af", - "gameinput.crafting": "Fabriceermenu", - "gameinput.sneak": "Sluipen", - "gameinput.swimdown": "Naar Beneden Zwemmen", - "gameinput.swimup": "Naar Boven Zwemmen", - - /// End GameInput section - - - /// Start chracter selection section - "char_selection.loading_characters": "Karakters Worden Geladen...", - "char_selection.delete_permanently": "Karakter Permanent Verwijderen?", - "char_selection.deleting_character": "Karakter Wordt Verwijderen...", - "char_selection.change_server": "Server Wisselen", - "char_selection.enter_world": "Wereld Betreden", - "char_selection.logout": "Uitloggen", - "char_selection.create_new_charater": "Nieuw Karakter Maken", - "char_selection.creating_character": "Karakter Wordt Aangemaakt...", - "char_selection.character_creation": "Karaktercreatie", - - "char_selection.human_default": "Standaard Mens", - "char_selection.level_fmt": "Level {level_nb}", - "char_selection.uncanny_valley": "Wildernis", - "char_selection.plains_of_uncertainty": "Vlaktes van Onzekerheid", - "char_selection.beard": "Baard", - "char_selection.hair_style": "Haarstijl", - "char_selection.hair_color": "Haarkleur", - "char_selection.eye_color": "Oogkleur", - "char_selection.skin": "Huid", - "char_selection.eyeshape": "Oogdetails", - "char_selection.accessories": "Accessoires", - "char_selection.create_info_name": "Je karakter heeft een naam nodig!", - - /// End chracter selection section - - - /// Start character window section - "character_window.character_name": "Karakter Naam", - // Character stats - "character_window.character_stats": r#"Uithouding - -Fitheid - -Willskracht - -Bescherming -"#, - /// End character window section - - - /// Start Escape Menu Section - "esc_menu.logout": "Uitloggen", - "esc_menu.quit_game": "Spel Verlaten", - /// End Escape Menu Section - }, - - vector_map: { + + vector_map: { "loading.tips": [ "Druk op 'G' om je lantaarn te doen schijnen.", "Druk op 'F1' om alle standaardbesturingen te zien.", @@ -533,7 +66,7 @@ Bescherming "Als je het ontwikkelingsteam wil versterken of gewoon een babbeltje wil doen met ons, kom dan langs op onze Discord-Server.", "Je kan numerieke waarden in de levensbalk aan of uit zetten in de instellingen.", "Om je stats te zien kan je op 'Stats' klikken in je Inventory.", - ], + ], "npc.speech.villager_under_attack": [ "Help, Ik word aangevallen!", "Help! Ik word aangevallen!", @@ -615,6 +148,6 @@ Bescherming "Doe dat alsjeblieft niet meer.", "Wachters, gooi dit monster het meer in!", "Ik laat mijn Tarasque op je los!", - ], + ], } ) diff --git a/assets/voxygen/i18n/nl_NL/buff.ron b/assets/voxygen/i18n/nl_NL/buff.ron new file mode 100644 index 0000000000..c782b41883 --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/buff.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/nl_NL/char_selection.ron b/assets/voxygen/i18n/nl_NL/char_selection.ron new file mode 100644 index 0000000000..de347f01a9 --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/char_selection.ron @@ -0,0 +1,32 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + "char_selection.loading_characters": "Karakters Worden Geladen...", + "char_selection.delete_permanently": "Karakter Permanent Verwijderen?", + "char_selection.deleting_character": "Karakter Wordt Verwijderen...", + "char_selection.change_server": "Server Wisselen", + "char_selection.enter_world": "Wereld Betreden", + "char_selection.logout": "Uitloggen", + "char_selection.create_new_charater": "Nieuw Karakter Maken", + "char_selection.creating_character": "Karakter Wordt Aangemaakt...", + "char_selection.character_creation": "Karaktercreatie", + + "char_selection.human_default": "Standaard Mens", + "char_selection.level_fmt": "Level {level_nb}", + "char_selection.uncanny_valley": "Wildernis", + "char_selection.plains_of_uncertainty": "Vlaktes van Onzekerheid", + "char_selection.beard": "Baard", + "char_selection.hair_style": "Haarstijl", + "char_selection.hair_color": "Haarkleur", + "char_selection.eye_color": "Oogkleur", + "char_selection.skin": "Huid", + "char_selection.eyeshape": "Oogdetails", + "char_selection.accessories": "Accessoires", + "char_selection.create_info_name": "Je karakter heeft een naam nodig!", + }, + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/nl_NL/common.ron b/assets/voxygen/i18n/nl_NL/common.ron new file mode 100644 index 0000000000..26433554a5 --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/common.ron @@ -0,0 +1,71 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + // Texts used in multiple locations with the same formatting + "common.username": "Spelernaam", + "common.singleplayer": "Alleen spelen", + "common.multiplayer": "Samen spelen", + "common.servers": "Servers", + "common.quit": "Afsluiten", + "common.settings": "Instellingen", + "common.languages": "Talen", + "common.interface": "Interface", + "common.gameplay": "Gameplay", + "common.controls": "Besturing", + "common.video": "Grafische weergave", + "common.sound": "Geluid", + "common.languages": "Talen", + "common.resume": "Verder spelen", + "common.characters": "Karakters", + "common.close": "Sluiten", + "common.yes": "Ja", + "common.no": "Nee", + "common.back": "Terug", + "common.create": "Aanmaken", + "common.okay": "Oké", + "common.accept": "Aanvaarden", + "common.decline": "Afwijzen", + "common.disclaimer": "Disclaimer", + "common.cancel": "Annuleren", + "common.none": "Geen", + "common.error": "Fout", + "common.fatal_error": "Fatale fout", + "common.you": "Jij", + "common.automatic": "Auto", + "common.random": "Willekeurig", + // Settings Window title + "common.interface_settings": "Interface Instellingen", + "common.gameplay_settings": "Gameplay Instellingen", + "common.controls_settings": "Besturing Instellingen", + "common.video_settings": "Grafische instellingen", + "common.sound_settings": "Geluids instellingen", + "common.language_settings": "Taal instellingen", + + // Message when connection to the server is lost + "common.connection_lost": r#"Verbinding verloren! +Is de server opniew opgestart? +Is je client nog up to date?"#, + + + "common.species.orc": "Orc", + "common.species.human": "Mens", + "common.species.dwarf": "Dwerg", + "common.species.elf": "Elf", + "common.species.undead": "Ondood", + "common.species.danari": "Danari", + + "common.weapons.axe": "Bijl", + "common.weapons.sword": "Zwaard", + "common.weapons.staff": "Staf", + "common.weapons.bow": "Boog", + "common.weapons.hammer": "Hamer", + "common.weapons.sceptre": "Genezende scepter", + "common.rand_appearance": "Willekeurig uiterlijk en naam", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/nl_NL/esc_menu.ron b/assets/voxygen/i18n/nl_NL/esc_menu.ron new file mode 100644 index 0000000000..68690cd821 --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/esc_menu.ron @@ -0,0 +1,13 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + "esc_menu.logout": "Uitloggen", + "esc_menu.quit_game": "Spel Verlaten", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/nl_NL/gameinput.ron b/assets/voxygen/i18n/nl_NL/gameinput.ron new file mode 100644 index 0000000000..4105707186 --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/gameinput.ron @@ -0,0 +1,66 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + "gameinput.primary": "Gewone aanval", + "gameinput.secondary": "Alternatieve Aanval/Block/Mikken", + "gameinput.slot1": "Hotbar Slot 1", + "gameinput.slot2": "Hotbar Slot 2", + "gameinput.slot3": "Hotbar Slot 3", + "gameinput.slot4": "Hotbar Slot 4", + "gameinput.slot5": "Hotbar Slot 5", + "gameinput.slot6": "Hotbar Slot 6", + "gameinput.slot7": "Hotbar Slot 7", + "gameinput.slot8": "Hotbar Slot 8", + "gameinput.slot9": "Hotbar Slot 9", + "gameinput.slot10": "Hotbar Slot 10", + "gameinput.swaploadout": "Uitrusting Wisselen", + "gameinput.togglecursor": "Cursor Aan/Uit", + "gameinput.help": "Help Venster Aan/Uit", + "gameinput.toggleinterface": "Interface Aan/Uit", + "gameinput.toggledebug": "FPS en Debug Info Aan/Uit", + "gameinput.screenshot": "Screenshot maken", + "gameinput.toggleingameui": "Naamplaatjes Aan/Uit", + "gameinput.fullscreen": "Volledig Scherm Aan/Uit", + "gameinput.moveforward": "Voorwaards Bewegen", + "gameinput.moveleft": "Links Bewegen", + "gameinput.moveright": "Rechts Bewegen", + "gameinput.moveback": "Achteruit Bewegen", + "gameinput.jump": "Springen", + "gameinput.glide": "Deltavlieger", + "gameinput.roll": "Rollen", + "gameinput.climb": "Klimmen", + "gameinput.climbdown": "Naar Beneden Klimmen", + "gameinput.wallleap": "Muursprong", + "gameinput.togglelantern": "Lantaarn Aan/Uit", + "gameinput.mount": "Berijden", + "gameinput.chat": "Chat", + "gameinput.command": "Commando", + "gameinput.escape": "Sluiten", + "gameinput.map": "Kaart", + "gameinput.bag": "Rugzak", + "gameinput.social": "Sociaal", + "gameinput.sit": "Zit", + "gameinput.spellbook": "Spreuken", + "gameinput.settings": "Instellingen", + "gameinput.respawn": "Respawn", + "gameinput.charge": "Opladen", + "gameinput.togglewield": "Wapen Vastnemen/Wegsteken", + "gameinput.interact": "Gebruik", + "gameinput.freelook": "Vrije Camera", + "gameinput.autowalk": "Automatisch Wandelen", + "gameinput.dance": "Dans", + "gameinput.select": "Selecteer Entiteit", + "gameinput.acceptgroupinvite": "Accepteer Groepsuitnodiging", + "gameinput.declinegroupinvite": "Wijs Groepsuitnodiging Af", + "gameinput.crafting": "Fabriceermenu", + "gameinput.sneak": "Sluipen", + "gameinput.swimdown": "Naar Beneden Zwemmen", + "gameinput.swimup": "Naar Boven Zwemmen", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/nl_NL/hud/bag.ron b/assets/voxygen/i18n/nl_NL/hud/bag.ron new file mode 100644 index 0000000000..8b13457840 --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/hud/bag.ron @@ -0,0 +1,32 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + // Inventory + "hud.bag.inventory": "{playername}'s Rugzak", + "hud.bag.stats_title": "{playername}'s Stats", + "hud.bag.exp": "Exp", + "hud.bag.armor": "Armor", + "hud.bag.stats": "Stats", + "hud.bag.head": "Hoofd", + "hud.bag.neck": "Nek", + "hud.bag.tabard": "Tabberd", + "hud.bag.shoulders": "Schouders", + "hud.bag.chest": "Borstkas", + "hud.bag.hands": "Handen", + "hud.bag.lantern": "Lantaarn", + "hud.bag.glider": "Deltavlieger", + "hud.bag.belt": "Riem", + "hud.bag.ring": "Ring", + "hud.bag.back": "Rug", + "hud.bag.legs": "Benen", + "hud.bag.feet": "Voeten", + "hud.bag.mainhand": "Dominante hand", + "hud.bag.offhand": "Tweede hand", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/nl_NL/hud/char_window.ron b/assets/voxygen/i18n/nl_NL/hud/char_window.ron new file mode 100644 index 0000000000..82ccbaa673 --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/hud/char_window.ron @@ -0,0 +1,21 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + "character_window.character_name": "Karakter Naam", + // Character stats + "character_window.character_stats": r#"Uithouding + +Fitheid + +Willskracht + +Bescherming +"#, + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/nl_NL/hud/chat.ron b/assets/voxygen/i18n/nl_NL/hud/chat.ron new file mode 100644 index 0000000000..0db1871ffd --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/hud/chat.ron @@ -0,0 +1,32 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + "hud.chat.online_msg": "[{name}] is nu online", + "hud.chat.offline_msg": "[{name}] is offline gegaan", + + "hud.chat.default_death_msg": "[{name}] is gestorven", + "hud.chat.environmental_kill_msg": "[{name}] is gestorven in {environment}", + "hud.chat.fall_kill_msg": "[{name}] is gestorven door te vallen", + "hud.chat.suicide_msg": "[{name}] is gestorven door zelf toegebrachte verwondingen", + + "hud.chat.pvp_melee_kill_msg": "[{attacker}] versloeg [{victim}]", + "hud.chat.pvp_ranged_kill_msg": "[{attacker}] schoot [{victim}] neer", + "hud.chat.pvp_explosion_kill_msg": "[{attacker}] blies [{victim}] op", + "hud.chat.pvp_energy_kill_msg": "[{attacker}] gebruikte magie om [{victim}] te vermoorden", + + "hud.chat.npc_melee_kill_msg": "{attacker} dode [{victim}]", + "hud.chat.npc_ranged_kill_msg": "{attacker} schoot [{victim}]", + "hud.chat.npc_explosion_kill_msg": "{attacker} blies [{victim}] op", + + "hud.chat.loot_msg": "Je raapte [{item}] op", + "hud.chat.loot_fail": "Jouw inventory is vol!", + "hud.chat.goodbye": "Vaarwel!", + "hud.chat.connection_lost": "Verbinding verloren. Je wordt in {time} seconden gekicked.", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/nl_NL/hud/crafting.ron b/assets/voxygen/i18n/nl_NL/hud/crafting.ron new file mode 100644 index 0000000000..551558ea69 --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/hud/crafting.ron @@ -0,0 +1,16 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + "hud.crafting": "Fabriceren", + "hud.crafting.recipes": "Recepten", + "hud.crafting.ingredients": "Ingrediënten:", + "hud.crafting.craft": "Maak", + "hud.crafting.tool_cata": "Vereisten:", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/nl_NL/hud/group.ron b/assets/voxygen/i18n/nl_NL/hud/group.ron new file mode 100644 index 0000000000..16be7c70b1 --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/hud/group.ron @@ -0,0 +1,23 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + "hud.group": "Groep", + "hud.group.invite_to_join": "[{name}] heeft je voor zijn/haar groep uitgenodigd!", + "hud.group.invite": "Uitnodigen", + "hud.group.kick": "Kick", + "hud.group.assign_leader": "Maak Leider", + "hud.group.leave": "Groep Verlaten", + "hud.group.dead" : "Dood", + "hud.group.out_of_range": "Buiten Bereik", + "hud.group.add_friend": "Aan Vrienden Toevoegen", + "hud.group.link_group": "Link Groups", + "hud.group.in_menu": "In Menu", + "hud.group.members": "Groepsleden", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/nl_NL/hud/hud_settings.ron b/assets/voxygen/i18n/nl_NL/hud/hud_settings.ron new file mode 100644 index 0000000000..84318ff1cc --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/hud/hud_settings.ron @@ -0,0 +1,96 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + // Settings + "hud.settings.general": "Algemeen", + "hud.settings.none": "Geen", + "hud.settings.press_behavior.toggle": "Omschakelbaar", + "hud.settings.press_behavior.hold": "Inhouden", + "hud.settings.help_window": "Help Venster", + "hud.settings.debug_info": "Debug Informatie", + "hud.settings.tips_on_startup": "Tips-Bij-Opstarten", + "hud.settings.ui_scale": "UI-Schaal", + "hud.settings.relative_scaling": "Relatief Schalen", + "hud.settings.custom_scaling": "Aangepast Schalen", + "hud.settings.crosshair": "Richtkruis", + "hud.settings.transparency": "Doorschijnbaarheid", + "hud.settings.hotbar": "Hotbar", + "hud.settings.toggle_shortcuts": "Toon Sneltoetsen", + "hud.settings.toggle_bar_experience": "Toon Experience Balk", + "hud.settings.scrolling_combat_text": "Pop-up Gevechtstext", + "hud.settings.single_damage_number": "Aparte Schade Getallen", + "hud.settings.cumulated_damage": "Cumulatieve Schade Getallen", + "hud.settings.incoming_damage": "Inkomende Schade Getallen", + "hud.settings.cumulated_incoming_damage": "Cumulatieve Inkomende Schade Getallen", + "hud.settings.speech_bubble": "Spraakbubbel", + "hud.settings.speech_bubble_dark_mode": "Donkere Modus", + "hud.settings.speech_bubble_icon": "Spraakbubbel Icoon", + "hud.settings.energybar_numbers": "Energiebalk Getallen", + "hud.settings.values": "Waarden", + "hud.settings.percentages": "Percentages", + "hud.settings.chat": "Chat", + "hud.settings.background_transparency": "Transparantie Achtergrond", + "hud.settings.chat_character_name": "Karakternamen in de Chat", + "hud.settings.loading_tips": "Laadscherm Tips", + + "hud.settings.pan_sensitivity": "Camera-gevoeligheid", + "hud.settings.zoom_sensitivity": "Zoom-gevoeligheid", + "hud.settings.invert_scroll_zoom": "Inverteer Zoom Scrollen", + "hud.settings.invert_mouse_y_axis": "Inverteer muis Y As", + "hud.settings.enable_mouse_smoothing": "Camerabeweging gelijkmaken", + "hud.settings.free_look_behavior": "Vrije camera gedrag", + "hud.settings.auto_walk_behavior": "Automatisch wandelgedrag", + "hud.settings.stop_auto_walk_on_input": "Stop automatisch +wandelen bij bewegen", + + "hud.settings.view_distance": "Kijkafstand", + "hud.settings.sprites_view_distance": "Kijkafstand sprites", + "hud.settings.figures_view_distance": "Kijkafstand entiteiten", + "hud.settings.maximum_fps": "Maximum FPS", + "hud.settings.fov": "Gezichtsveld (graden)", + "hud.settings.gamma": "Gamma", + "hud.settings.ambiance": "Omgevingshelderheid", + "hud.settings.antialiasing_mode": "AntiAliasing Modus", + "hud.settings.cloud_rendering_mode": "Wolk Rendering Modus", + "hud.settings.fluid_rendering_mode": "Vloeistoffen Rendering Mode", + "hud.settings.fluid_rendering_mode.cheap": "Goedkoop", + "hud.settings.fluid_rendering_mode.shiny": "Schitterend", + "hud.settings.cloud_rendering_mode.regular": "Gewoon", + "hud.settings.fullscreen": "Volledig scherm", + "hud.settings.fullscreen_mode": "Volledige scherm modus", + "hud.settings.fullscreen_mode.exclusive": "Exclusief", + "hud.settings.fullscreen_mode.borderless": "Randloos", + "hud.settings.particles": "Deeltjes", + "hud.settings.resolution": "Resolutie", + "hud.settings.bit_depth": "Bit diepte", + "hud.settings.refresh_rate": "Vernieuwingssnelheid", + "hud.settings.save_window_size": "Venster grootte opslaan", + "hud.settings.lighting_rendering_mode": "Licht Rendering Modus", + "hud.settings.lighting_rendering_mode.ashikhmin": "Type A", + "hud.settings.lighting_rendering_mode.blinnphong": "Type B", + "hud.settings.lighting_rendering_mode.lambertian": "Type L", + "hud.settings.shadow_rendering_mode": "Schaduw Rendering Mode", + "hud.settings.shadow_rendering_mode.none": "Geen", + "hud.settings.shadow_rendering_mode.cheap": "Goedkoop", + "hud.settings.shadow_rendering_mode.map": "Kaart", + "hud.settings.shadow_rendering_mode.map.resolution": "Resolutie", + "hud.settings.lod_detail": "LoD Detail", + "hud.settings.save_window_size": "Venster grootte opslaan", + + + "hud.settings.music_volume": "Muziek Volume", + "hud.settings.sound_effect_volume": "Geluidseffecten Volume", + "hud.settings.audio_device": "Audio Apparaat", + + "hud.settings.awaitingkey": "Druk op een toets...", + "hud.settings.unbound": "Geen", + "hud.settings.reset_keybinds": "Standaardwaarden +herstellen", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/nl_NL/hud/map.ron b/assets/voxygen/i18n/nl_NL/hud/map.ron new file mode 100644 index 0000000000..48afb00453 --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/hud/map.ron @@ -0,0 +1,14 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + // Map and Questlog + "hud.map.map_title": "Kaart", + "hud.map.qlog_title": "Quests", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/nl_NL/hud/misc.ron b/assets/voxygen/i18n/nl_NL/hud/misc.ron new file mode 100644 index 0000000000..e4e722d883 --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/hud/misc.ron @@ -0,0 +1,78 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + /// Start HUD Section + "hud.do_not_show_on_startup": "Niet meer bij opstarten tonen", + "hud.show_tips": "Tips tonen", + "hud.quests": "Quests", + "hud.you_died": "Je bent gedood", + "hud.waypoint_saved": "Waypoint Opgeslagen", + + "hud.press_key_to_show_keybindings_fmt": "[{key}] Besturing", + "hud.press_key_to_toggle_lantern_fmt": "[{key}] Lantaarn", + "hud.press_key_to_show_debug_info_fmt": "Druk op {key} om debug info te tonen", + "hud.press_key_to_toggle_keybindings_fmt": "Druk op {key} om te de besturing aan/uit te zetten", + "hud.press_key_to_toggle_debug_info_fmt": "Druk op {key} om debug info aan/uit te zetten", + + // Chat outputs + + // Respawn message + "hud.press_key_to_respawn": r#"Druk op {key} om te respawnen bij het laatste kampvuur dat je bezocht."#, + + // Welcome message + "hud.welcome": r#"Welcome bij de Veloren Alpha! + +Wat tips voor je start: + + +Druk op F1 om de besturing te zien. + +Type /help in chat om de chat commando's te zien. + + +Er verschijnen kisten en andere objecten willekeurig in de wereld! + +Gebruik rechtermuisknop om ze te verzamelen! + +Om effectief hetgene dat je van de kisten krijgt te gebruiken, open je je inventory met 'B'. + +Dubbelklik op de voorwerpen in je rugzak om ze aan te doen of te gebruiken. + +Gooi dingen weg door ze eenmaal aan te klikken en dan buiten je rugzak te klikken. + + +Nachten kunnen vrij donker worden in Veloren. + +Gebruik je lantaarn door 'G' te drukken + + +Wil je je cursor gebruiken om dit venster te sluiten? Druk TAB! + + +Geniet van je verblijf in de wereld van Veloren."#, + +"hud.temp_quest_headline": r#"Help ons alsjeblieft, reiziger!"#, +"hud.temp_quest_text": r#"Kerkers vol met kwaaraardige sektes +komen overal tevoorschijn rond onze vreedzame dorpen! + + +Verzamel wat gezelschap, vul je voedselrantsoenen aan +en versla hun kwaadaardige leiders en volgelingen. + + +Misschien kan je zelfs een van hun +Maybe you can even obtain one of their +met magie gevulde objecten bemachtigen?"#, + + "hud.spell": "Spreuken", + + "hud.free_look_indicator": "Vrij rondkijken aan. Druk {key} om uit te zetten.", + "hud.auto_walk_indicator": "Automatisch wandelen aan", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/nl_NL/hud/sct.ron b/assets/voxygen/i18n/nl_NL/hud/sct.ron new file mode 100644 index 0000000000..d6b4b9ef17 --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/hud/sct.ron @@ -0,0 +1,14 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + // SCT outputs + "hud.sct.experience": "{amount} Exp", + "hud.sct.block": "GEBLOCKED", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/nl_NL/hud/skills.ron b/assets/voxygen/i18n/nl_NL/hud/skills.ron new file mode 100644 index 0000000000..c782b41883 --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/hud/skills.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/nl_NL/hud/social.ron b/assets/voxygen/i18n/nl_NL/hud/social.ron new file mode 100644 index 0000000000..0328b877d4 --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/hud/social.ron @@ -0,0 +1,22 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + "hud.social": "Andere spelers", + "hud.social.online": "Online:", + "hud.social.friends": "Vrienden", + "hud.social.not_yet_available": "Nog niet beschikbaar", + "hud.social.faction": "Factie", + "hud.social.play_online_fmt": "{nb_player} speler(s) online", + "hud.social.name": "Naam", + "hud.social.level": "Level", + "hud.social.zone": "Zone", + "hud.social.account": "Account", + }, + + + vector_map: { + } +) + diff --git a/assets/voxygen/i18n/nl_NL/hud/trade.ron b/assets/voxygen/i18n/nl_NL/hud/trade.ron new file mode 100644 index 0000000000..bac886e087 --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/hud/trade.ron @@ -0,0 +1,12 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + }, + + + vector_map: { + } +) + diff --git a/assets/voxygen/i18n/nl_NL/main.ron b/assets/voxygen/i18n/nl_NL/main.ron new file mode 100644 index 0000000000..f7f24a4e2a --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/main.ron @@ -0,0 +1,59 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + "main.connecting": "Verbinden", + "main.creating_world": "Wereld aan het maken", + "main.tip": "Tip:", + + // Welcome notice that appears the first time Veloren is started + "main.notice": r#"Welkom bij de Alpha versie van Veloren! + +Voordat de fun begint zijn hier enkele dingen om rekening mee te houden: + +- Dit is een hele vroege alpha. Verwacht bugs, extreem onafgemaakte gameplay, ruwe spelmechanics en missende functies. + +- Als je constructieve feedback hebt of bugs wil melden, kan je ons contacteren via Reddit, Gitlab of onze community Discord. + +- Veloren is onder de GPL 3 open-source licentie gelicensieerd. Dat betekent dat je vrij bent om het spel te spelen, bewerken en doorgeven op welke manier +je ook wil (zo lang afgeleide werken ook onder GPL 3 gelicensieerd zijn) + +- Veloren is een non-profit community project, en iedereen dat er aan meehelpt is een vrijwilliger. +Als je interesse hebt kan je je aansluiten bij onze ontwikkeling- of ontwerpteams! + +Bedankt voor de tijd te nemen om deze melding te lezen, we hopen dat je van het spel zult genieten! +Thanks for taking the time to read this notice, we hope you enjoy the game! + +~ De Veloren ontwikkelaars"#, + + // Login process description + "main.login_process": r#"Information over het loginproces: + +Hou er rekening mee dat je tegenwoordig een account nodig hebt +om op servers met authenticatie te spelen + +Je kan een account maken op + +https://veloren.net/account/."#, + "main.login.server_not_found": "Server nie gevonden", + "main.login.authentication_error": "Authenticatie mislukt", + "main.login.server_full": "Server zit vol", + "main.login.untrusted_auth_server": "Onvertrouwde authenticatie server", + "main.login.outdated_client_or_server": "Versieprobleem: De versie tussen de client en de server komen niet overeen. Check of er updates zijn/", + "main.login.timeout": "Timeout: De server deed er te lang over om te antwoorden. (Overblast of netwerk problemen).", + "main.login.server_shut_down": "Server is afgesloten", + "main.login.network_error": "Network problemen", + "main.login.failed_sending_request": "Kon verzoek niet naar authenticatie server sturen", + "main.login.invalid_character": "Het geselecteerde karakter is ongeldig", + "main.login.client_crashed": "Client is gecrashed", + "main.login.not_on_whitelist": "Je moet op de whitelist staan om deze wereld te joinen", + "main.login.banned": "Je bent verbannen voor de volgende reden", + "main.login.kicked": "Je bent gekicked voor de volgende reden", + "main.login.select_language": "Kies een taal", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/no_NB/_manifest.ron b/assets/voxygen/i18n/no_NB/_manifest.ron new file mode 100644 index 0000000000..7ceabf56fe --- /dev/null +++ b/assets/voxygen/i18n/no_NB/_manifest.ron @@ -0,0 +1,152 @@ +/// Translation document instructions +/// +/// In order to keep localization documents readible please follow the following +/// rules: +/// - separate the string map sections using a commentary describing the purpose +/// of the next section +/// - prepend multi-line strings with a commentary +/// - append one blank lines after a multi-line strings and two after sections +/// +/// To add a new language in Veloren, just write an additional `.ron` file in +/// `assets/voxygen/i18n` and that's it! +/// +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalisering for norsk bokmål +( + metadata: ( + language_name: "Norsk bokmål", + language_identifier: "no_NB", + ), + convert_utf8_to_ascii: false, + fonts: { + "opensans": Font ( + asset_key: "voxygen.font.OpenSans-Regular", + scale_ratio: 1.0, + ), + "metamorph": Font ( + asset_key: "voxygen.font.Metamorphous-Regular", + scale_ratio: 1.0, + ), + "alkhemi": Font ( + asset_key: "voxygen.font.Alkhemikal", + scale_ratio: 1.0, + ), + "wizard": Font ( + asset_key: "voxygen.font.wizard", + scale_ratio: 1.0, + ), + "cyri": Font ( + asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", + scale_ratio: 1.0, + ), + }, + string_map: { + }, + + + vector_map: { + "loading.tips": [ + "Trykk 'G' for å tenne lykten.", + "Trykk 'F1' for å se alle standard tastebindinger.", + "Du kan skrive /say eller /s for å bare chatte med spillere rett rundt deg.", + "Du kan skrive /region eller /r for å bare chatte med spillere et par hundre blokker rundt deg.", + "Du kan skrive /group eller /g for å bare chatte med spillere i din nåværende gruppe.", + "For å sende private meldinger skriv /tell etterfulgt av et spillernavn og meldingen din.", + "NPCer med samme nivå kan ha forskjellige problemer.", + "Hold øye med mat, kister og andre godsaker spredt over hele verden!", + "Inventar fylt med mat? Prøv å lage bedre mat med det!", + "Lurer du på hva du kan gjøre? Fangehull er merket med brune flekker på kartet!", + "Ikke glem å justere grafikken for systemet ditt. Trykk på 'N' for å åpne innstillingene.", + "Å spille med andre er gøy! Trykk 'O' for å se hvem som er online.", + "En NPC med en hodeskalle under helsebaren er ganske kraftig sammenlignet med deg selv.", + "Trykk 'J' for å danse. Fest!", + "Trykk 'L-Shift' for å åpne Glider og erobre himmelen.", + "Veloren er fortsatt i Pre-Alfa. Vi gjør vårt beste for å forbedre det hver dag!", + "Hvis du vil bli med i Dev-teamet eller bare ta en prat med oss, bli med i Discord-Serveren.", + "Du kan veksle for å vise mengden helse på helselinjen i innstillingene.", + "For å se statistikken din, klikk på 'Statistikk' -knappen i beholdningen.", + ], + "npc.speech.villager_under_attack": [ + "Hjelp, jeg er under angrep!", + "Hjelp! Jeg er under angrep!", + "Au! Jeg er under angrep!", + "Au! Jeg er under angrep! Hjelp!", + "Hjelp meg! Jeg er under angrep!", + "Jeg er under angrep! Hjelp!", + "Jeg er under angrep! Hjelp meg!", + "Hjelp!", + "Hjelp! Hjelp!", + "Hjelp! Hjelp! Hjelp!", + "Jeg er under angrep!", + "AAAHHH! Jeg er under angrep!", + "AAAHHH! Jeg er under angrep! Hjelp!", + "Hjelp! Vi er under angrep!", + "Hjelp! Morder!", + "Hjelp! Det er en morder på frifot!", + "Hjelp! De prøver å drepe meg!", + "Vakter, jeg er under angrep!", + "Vakter! Jeg er under angrep!", + "Jeg er under angrep! Vakter!", + "Hjelp! Vakter! Jeg er under angrep!", + "Vakter! Kom raskt!", + "Vakter! Vakter!", + "Vakter! Det er en skurk som angriper meg!", + "Vakter, drep denne onde skurken!", + "Vakter! Det er en morder!", + "Vakter! Hjelp meg!", + "Du kommer ikke unna med dette! Vakter!", + "Du fiende!", + "Hjelp meg!", + "Hjelp! Vœr så snill!", + "Ouch! Vakter! Hjelp!", + "De etterfølger etter meg!", + "Hjelp! Hjelp! Jeg blir undertrykt!", + "Ah, nå ser vi volden som er bygd inn i systemet.", + "Det er bare en ripe!", + "Slutt med det!", + "Hva har jeg noensinne gjort mot deg?!", + "Vær så snill slutt å angripe meg!", + "Hei! Se for deg hvor du peker den tingen!", + "Avskyelige krek, bort med deg!", + "Stop det! Gå vekk!", + "Nå gjør du meg sint!", + "Oi! Hvem tror du at du er?!", + "Jeg tar hodet ditt for det!", + "Stop, vær så snill! Jeg har ingenting av verdi på meg!", + "Jeg får broren min til å ta deg, han er større enn meg!", + "Neiii, jeg sier det til mamma!", + "Forbann deg!", + "Vœr så snill ikke gjør det.", + "Det var ikke veldig snilt!", + "Våpnet ditt funker, du kan ta det vekk nå!", + "Bespar meg!", + "Vær så snill, jeg har familie!", + "Jeg er for ung til å dø!", + "Kan vi snakke om dette?", + "Vold er aldri svaret!", + "I dag ser ut til å være en dårlig dag...", + "Hei, det kjente jeg!", + "Eek!", + "Hvor uhøflig!", + "Stop, jeg ber deg!", + "Smitte beslage deg!", + "Dette er ikke gøy.", + "Hvordan våger du?!", + "Du kommer til å betale for dette!", + "Fortsett med dette og du kommer til å be unnskyld!", + "Ikke få meg til å banke deg!", + "Dette må være en misforståelse!", + "Du trenger ikke å gjøre dette!", + "Gå vekk, skurk!", + "Det gjorde vondt!", + "Hvorfor gjorde du det?", + "Etter åndene, forsvinn!", + "Du må ha forvekslet meg med noen andre!", + "Jeg fortjener ikke dette!", + "Vær så snill ikke gjør dette igjen!", + "Vakter, kast dette mennesket i havet!", + "Jeg får min tarasque til å etterfølge deg!", + ], + } +) diff --git a/assets/voxygen/i18n/no_NB/buff.ron b/assets/voxygen/i18n/no_NB/buff.ron new file mode 100644 index 0000000000..526893d919 --- /dev/null +++ b/assets/voxygen/i18n/no_NB/buff.ron @@ -0,0 +1,25 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for norsk bokmål +( + string_map: { + /// Buffs and Debuffs + "buff.remove": "Klikk for å fjerne", + "buff.title.missing": "Mangler tittel", + "buff.desc.missing": "Mangler beskrivelse", + // Buffs + "buff.title.heal": "Helbred", + "buff.desc.heal": "Helbred over tid.", + "buff.title.potion": "Trylledrikk", + "buff.desc.potion": "Drikker...", + "buff.title.saturation": "Metning", + "buff.desc.saturation": "Helbred over tid fra forbruksvarer.", + // Debuffs + "buff.title.bleed": "Blør", + "buff.desc.bleed": "Påfører regelmessig skade.", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/no_NB/char_selection.ron b/assets/voxygen/i18n/no_NB/char_selection.ron new file mode 100644 index 0000000000..bb049b1e7b --- /dev/null +++ b/assets/voxygen/i18n/no_NB/char_selection.ron @@ -0,0 +1,32 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for norsk bokmål +( + string_map: { + "char_selection.loading_characters": "Laster inn karakterer...", + "char_selection.delete_permanently": "Slett denne karakteren permanent?", + "char_selection.deleting_character": "Sletter karakter...", + "char_selection.change_server": "Bytt server", + "char_selection.enter_world": "Gå inn i verden", + "char_selection.logout": "Logg ut", + "char_selection.create_new_character": "Lag ny karakter", + "char_selection.creating_character": "Skaper karakter...", + "char_selection.character_creation": "Karakterskaping", + + "char_selection.human_default": "Menneskestandarder", + "char_selection.level_fmt": "Nivå {level_nb}", + "char_selection.uncanny_valley": "Villmark", + "char_selection.plains_of_uncertainty": "Usikkerhetssletter", + "char_selection.beard": "Skjegg", + "char_selection.hair_style": "Hårstil", + "char_selection.hair_color": "Hårfarge", + "char_selection.eye_color": "Øyenfarge", + "char_selection.skin": "Hud", + "char_selection.eyeshape": "Øyedetaljer", + "char_selection.accessories": "Tilbehør", + "char_selection.create_info_name": "Karakteren din trenger et navn!", + }, + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/no_NB/common.ron b/assets/voxygen/i18n/no_NB/common.ron new file mode 100644 index 0000000000..aec357f32a --- /dev/null +++ b/assets/voxygen/i18n/no_NB/common.ron @@ -0,0 +1,71 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for norsk bokmål +( + string_map: { + // Texts used in multiple locations with the same formatting + "common.username": "Brukernavn", + "common.singleplayer": "Enspiller", + "common.multiplayer": "Flerspiller", + "common.servers": "Servere", + "common.quit": "Avslutt", + "common.settings": "Innstillinger", + "common.languages": "Språk", + "common.interface": "Grensesnitt", + "common.gameplay": "Spillbarhet", + "common.controls": "Kontroller", + "common.video": "Grafikk", + "common.sound": "Lyd", + "common.resume": "Fortsett", + "common.characters": "Karakterer", + "common.close": "Lukk", + "common.yes": "Ja", + "common.no": "Nei", + "common.back": "Tilbake", + "common.create": "Lag", + "common.okay": "Ok", + "common.add": "Legg til", + "common.accept": "Aksepter", + "common.decline": "Avslå", + "common.disclaimer": "Bemerk", + "common.cancel": "Avbryt", + "common.none": "Ingen", + "common.error": "Feil", + "common.fatal_error": "Kritisk Feil", + "common.you": "Du", + "common.automatic": "Automatisk", + "common.random": "Tilfeldig", + // Settings Window title + "common.interface_settings": "Grensesnitt Instillinger", + "common.gameplay_settings": "Spillbarhet Innstillinger", + "common.controls_settings": "Kontroller Innstillinger", + "common.video_settings": "Grafikk Innstillinger", + "common.sound_settings": "Lyd Innstillinger", + "common.language_settings": "Språk Innstillinger", + + // Message when connection to the server is lost + "common.connection_lost": r#"Mistet forbindelsen! +Har serveren startet på nytt? +Har det kommet nye oppdateringer?"#, + + + "common.species.orc": "Ork", + "common.species.human": "Menneske", + "common.species.dwarf": "Dverg", + "common.species.elf": "Alv", + "common.species.undead": "Udødelig", + "common.species.danari": "Danari", + + "common.weapons.axe": "Øks", + "common.weapons.sword": "Sverd", + "common.weapons.staff": "Stav", + "common.weapons.bow": "Bue", + "common.weapons.hammer": "Hammer", + "common.weapons.sceptre": "Helbredings Septer", + "common.rand_appearance": "Tilfeldig utseende og navn", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/no_NB/esc_menu.ron b/assets/voxygen/i18n/no_NB/esc_menu.ron new file mode 100644 index 0000000000..35f020c7e9 --- /dev/null +++ b/assets/voxygen/i18n/no_NB/esc_menu.ron @@ -0,0 +1,13 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for norsk bokmål +( + string_map: { + "esc_menu.logout": "Logg ut", + "esc_menu.quit_game": "Avslutt spillet", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/no_NB/gameinput.ron b/assets/voxygen/i18n/no_NB/gameinput.ron new file mode 100644 index 0000000000..52be8f36fb --- /dev/null +++ b/assets/voxygen/i18n/no_NB/gameinput.ron @@ -0,0 +1,67 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for norsk bokmål +( + string_map: { + "gameinput.primary": "Primær Angrep", + "gameinput.secondary": "Sekundær Angrep/Blokk/Sikt", + "gameinput.slot1": "Hurtigbar Luke 1", + "gameinput.slot2": "Hurtigbar Luke 2", + "gameinput.slot3": "Hurtigbar Luke 3", + "gameinput.slot4": "Hurtigbar Luke 4", + "gameinput.slot5": "Hurtigbar Luke 5", + "gameinput.slot6": "Hurtigbar Luke 6", + "gameinput.slot7": "Hurtigbar Luke 7", + "gameinput.slot8": "Hurtigbar Luke 8", + "gameinput.slot9": "Hurtigbar Luke 9", + "gameinput.slot10": "Hurtigbar Luke 10", + "gameinput.swaploadout": "Bytt utlastning", + "gameinput.togglecursor": "Veksle Musepeker", + "gameinput.help": "Veksle hjelpevindu", + "gameinput.toggleinterface": "Veksle Grensesnitt", + "gameinput.toggledebug": "Veksle FPS og feilsøkingsinfo", + "gameinput.screenshot": "Ta skjermbilde", + "gameinput.toggleingameui": "Veksle Navneskilt", + "gameinput.fullscreen": "Veksle fullskjerm", + "gameinput.moveforward": "Beveg frem", + "gameinput.moveleft": "Beveg venstre", + "gameinput.moveright": "Beveg høyre", + "gameinput.moveback": "Beveg bakover", + "gameinput.jump": "Hopp", + "gameinput.glide": "Glider", + "gameinput.roll": "Rull", + "gameinput.climb": "Klatre", + "gameinput.climbdown": "Klatre ned", + "gameinput.wallleap": "Veggsprang", + "gameinput.togglelantern": "Veksle lykt", + "gameinput.mount": "Monter", + "gameinput.chat": "Chat", + "gameinput.command": "Kommando", + "gameinput.escape": "Røm", + "gameinput.map": "Kart", + "gameinput.bag": "Bag", + "gameinput.social": "Sosial", + "gameinput.sit": "Sitt", + "gameinput.spellbook": "Trylleformler", + "gameinput.settings": "Innstillinger", + "gameinput.respawn": "Gjennopstå", + "gameinput.charge": "Lad opp", + "gameinput.togglewield": "Veksle Våpen", + "gameinput.interact": "Interaksjon", + "gameinput.freelook": "Frimodus", + "gameinput.autowalk": "Autogåing", + "gameinput.dance": "Dans", + "gameinput.select": "Velg enhet", + "gameinput.acceptgroupinvite": "Godta gruppeinvitasjon", + "gameinput.declinegroupinvite": "Avvis gruppeinvitasjon", + "gameinput.crafting": "Håndverk", + "gameinput.fly": "Fly", + "gameinput.sneak": "Snik", + "gameinput.swimdown": "Svøm nedover", + "gameinput.swimup": "Svøm oppover", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/no_NB/hud/bag.ron b/assets/voxygen/i18n/no_NB/hud/bag.ron new file mode 100644 index 0000000000..dc50db6beb --- /dev/null +++ b/assets/voxygen/i18n/no_NB/hud/bag.ron @@ -0,0 +1,32 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for norsk bokmål +( + string_map: { + // Inventory + "hud.bag.inventory": "{playername}'s Inventar", + "hud.bag.stats_title": "{playername}'s Statistikk", + "hud.bag.exp": "Exp", + "hud.bag.armor": "Utrustning", + "hud.bag.stats": "Statistikk", + "hud.bag.head": "Hode", + "hud.bag.neck": "Nakke", + "hud.bag.tabard": "Tabard", + "hud.bag.shoulders": "Skulder", + "hud.bag.chest": "Bryst", + "hud.bag.hands": "Hender", + "hud.bag.lantern": "Lykt", + "hud.bag.glider": "Glidefly", + "hud.bag.belt": "Belte", + "hud.bag.ring": "Ring", + "hud.bag.back": "Rygg", + "hud.bag.legs": "Ben", + "hud.bag.feet": "Føtter", + "hud.bag.mainhand": "Hovedhånd", + "hud.bag.offhand": "Tillegshånd", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/no_NB/hud/char_window.ron b/assets/voxygen/i18n/no_NB/hud/char_window.ron new file mode 100644 index 0000000000..0d3e194674 --- /dev/null +++ b/assets/voxygen/i18n/no_NB/hud/char_window.ron @@ -0,0 +1,22 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for norsk bokmål +( + string_map: { + /// Start character window section + "character_window.character_name": "Karakternavn", + // Character stats + "character_window.character_stats": r#"Utholdenhet + +Fitness + +Viljestyrke + +Beskyttelse +"#, + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/no_NB/hud/chat.ron b/assets/voxygen/i18n/no_NB/hud/chat.ron new file mode 100644 index 0000000000..605cbf9fe7 --- /dev/null +++ b/assets/voxygen/i18n/no_NB/hud/chat.ron @@ -0,0 +1,37 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for "global" English +( + string_map: { + // Chat outputs + "hud.chat.online_msg": "[{name}] logget på", + "hud.chat.offline_msg": "[{name}] logget av", + + "hud.chat.default_death_msg": "[{name}] døde", + "hud.chat.environmental_kill_msg": "[{name}] døde i {environment}", + "hud.chat.fall_kill_msg": "[{name}] døde av fallskade", + "hud.chat.suicide_msg": "[{name}] døde av selvskader", + + "hud.chat.pvp_melee_kill_msg": "[{attacker}] drepte [{victim}]", + "hud.chat.pvp_ranged_kill_msg": "[{attacker}] skjøt [{victim}]", + "hud.chat.pvp_explosion_kill_msg": "[{attacker}] sprengte [{victim}]", + "hud.chat.pvp_energy_kill_msg": "[{attacker}] drepte [{victim}] med magi", + "hud.chat.pvp_buff_kill_msg": "[{attacker}] drepte [{victim}]", + + + "hud.chat.npc_melee_kill_msg": "{attacker} drepte [{victim}]", + "hud.chat.npc_ranged_kill_msg": "{attacker} skjøt [{victim}]", + "hud.chat.npc_explosion_kill_msg": "{attacker} sprengte [{victim}]", + "hud.chat.npc_energy_kill_msg": "{attacker} drepte [{victim}] med magi", + "hud.chat.npc_other_kill_msg": "{attacker} drepte [{victim}]", + + "hud.chat.loot_msg": "Du plukket opp [{item}]", + "hud.chat.loot_fail": "Ditt inventar er fullt!", + "hud.chat.goodbye": "Adjø!", + "hud.chat.connection_lost": "Forbindelse mistet. Utkastet om {time} sekunder.", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/no_NB/hud/crafting.ron b/assets/voxygen/i18n/no_NB/hud/crafting.ron new file mode 100644 index 0000000000..279f6042ee --- /dev/null +++ b/assets/voxygen/i18n/no_NB/hud/crafting.ron @@ -0,0 +1,16 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for norsk bokmål +( + string_map: { + "hud.crafting": "Håndverk", + "hud.crafting.recipes": "Oppskrifter", + "hud.crafting.ingredients": "Ingredienser:", + "hud.crafting.craft": "Lag", + "hud.crafting.tool_cata": "Krever:", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/no_NB/hud/group.ron b/assets/voxygen/i18n/no_NB/hud/group.ron new file mode 100644 index 0000000000..99159f78c6 --- /dev/null +++ b/assets/voxygen/i18n/no_NB/hud/group.ron @@ -0,0 +1,23 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for norsk bokmål +( + string_map: { + "hud.group": "Gruppe", + "hud.group.invite_to_join": "[{name}] inviterte deg til gruppen deres!", + "hud.group.invite": "Inviter", + "hud.group.kick": "Spark", + "hud.group.assign_leader": "Tilordne leder", + "hud.group.leave": "Forlat Gruppe", + "hud.group.dead" : "Død", + "hud.group.out_of_range": "Ute av rekkevidde", + "hud.group.add_friend": "Legg til i vennelisten", + "hud.group.link_group": "Koble til grupper", + "hud.group.in_menu": "I Meny", + "hud.group.members": "Gruppemedlemmer", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/no_NB/hud/hud_settings.ron b/assets/voxygen/i18n/no_NB/hud/hud_settings.ron new file mode 100644 index 0000000000..7c67540070 --- /dev/null +++ b/assets/voxygen/i18n/no_NB/hud/hud_settings.ron @@ -0,0 +1,98 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for norsk bokmål +( + string_map: { + "hud.settings.general": "Generell", + "hud.settings.none": "Ingen", + "hud.settings.press_behavior.toggle": "Veksle", + "hud.settings.press_behavior.hold": "Hold", + "hud.settings.help_window": "Hjelpevindu", + "hud.settings.debug_info": "Feilsøkingsinformasjon", + "hud.settings.tips_on_startup": "Tips-På-Oppstart", + "hud.settings.ui_scale": "UI-Skalering", + "hud.settings.relative_scaling": "Relativ Skalering", + "hud.settings.custom_scaling": "Tilpasset Skalering", + "hud.settings.crosshair": "Retikkel", + "hud.settings.transparency": "Gjennomsiktighet", + "hud.settings.hotbar": "Hurtigknappsbar", + "hud.settings.toggle_shortcuts": "Veksle Snarveier", + "hud.settings.buffs_skillbar": "Ikoner på Ferdighetsbar", + "hud.settings.buffs_mmap": "Ikoner på Minimap", + "hud.settings.toggle_bar_experience": "Veksle erfaringsbar", + "hud.settings.scrolling_combat_text": "Rullende kamptekst", + "hud.settings.single_damage_number": "Enkelt skadetall", + "hud.settings.cumulated_damage": "Kumulert skade", + "hud.settings.incoming_damage": "Innkommende skade", + "hud.settings.cumulated_incoming_damage": "Kumulert innkommende skade", + "hud.settings.speech_bubble": "Snakkeboble", + "hud.settings.speech_bubble_dark_mode": "Mørk modus for snakkeboble", + "hud.settings.speech_bubble_icon": "Snakkeboble ikon", + "hud.settings.energybar_numbers": "Energibar tall", + "hud.settings.values": "Verdier", + "hud.settings.percentages": "Prosentandeler", + "hud.settings.chat": "Chat", + "hud.settings.background_transparency": "Bakgrunnsgjennomsiktighet", + "hud.settings.chat_character_name": "Karakternavn i chat", + "hud.settings.loading_tips": "Oppstartsskjerm Tips", + + "hud.settings.pan_sensitivity": "Panoreringssensitivitet", + "hud.settings.zoom_sensitivity": "Zoomingssensitivitet", + "hud.settings.invert_scroll_zoom": "Inverter skrollezoom", + "hud.settings.invert_mouse_y_axis": "Inverter mus Y Aksen", + "hud.settings.enable_mouse_smoothing": "Kamerautjevning", + "hud.settings.free_look_behavior": "Frimodus oppførsel", + "hud.settings.auto_walk_behavior": "Autogåing oppførsel", + "hud.settings.stop_auto_walk_on_input": "Stopp autogåing på bevegelse", + + "hud.settings.view_distance": "Utsiktsavstand", + "hud.settings.sprites_view_distance": "Sprites utsiktsavstand", + "hud.settings.figures_view_distance": "Enhets utsiktsavstand", + "hud.settings.maximum_fps": "Maksimum FPS", + "hud.settings.fov": "Synsfelt (deg)", + "hud.settings.gamma": "Gamma", + "hud.settings.ambiance": "Stemning Brightness", + "hud.settings.antialiasing_mode": "Kantutjevningsmodus", + "hud.settings.cloud_rendering_mode": "Tegn-skyer-modus", + "hud.settings.fluid_rendering_mode": "Tegn-væske-modus", + "hud.settings.fluid_rendering_mode.cheap": "Billig", + "hud.settings.fluid_rendering_mode.shiny": "Skinnende", + "hud.settings.cloud_rendering_mode.minimal": "Minimal", + "hud.settings.cloud_rendering_mode.low": "Lav", + "hud.settings.cloud_rendering_mode.medium": "Medium", + "hud.settings.cloud_rendering_mode.high": "Høy", + "hud.settings.fullscreen": "Full skjerm", + "hud.settings.fullscreen_mode": "Fullskjermsmodus", + "hud.settings.fullscreen_mode.exclusive": "Eksklusiv", + "hud.settings.fullscreen_mode.borderless": "Uten kanter", + "hud.settings.particles": "Partikler", + "hud.settings.resolution": "Resolusjon", + "hud.settings.bit_depth": "Bit Dybde", + "hud.settings.refresh_rate": "Oppdateringsfrekvens", + "hud.settings.save_window_size": "Spar vindusstørrelse", + "hud.settings.lighting_rendering_mode": "Tegn-belysning-modus", + "hud.settings.lighting_rendering_mode.ashikhmin": "Type A - Høy ", + "hud.settings.lighting_rendering_mode.blinnphong": "Type B - Medium", + "hud.settings.lighting_rendering_mode.lambertian": "Type L - Billing", + "hud.settings.shadow_rendering_mode": "Tegn-skygger-modus", + "hud.settings.shadow_rendering_mode.none": "Ingen", + "hud.settings.shadow_rendering_mode.cheap": "Billig", + "hud.settings.shadow_rendering_mode.map": "Kart", + "hud.settings.shadow_rendering_mode.map.resolution": "Resolusjon", + "hud.settings.lod_detail": "Nivå med detaljer", + "hud.settings.save_window_size": "Lagre vindusstørrelse", + + + "hud.settings.music_volume": "Musikkvolum", + "hud.settings.sound_effect_volume": "Lydeffektvolum", + "hud.settings.audio_device": "Lydenhet", + + "hud.settings.awaitingkey": "Trykk på en tast...", + "hud.settings.unbound": "Ingen", + "hud.settings.reset_keybinds": "Tilbakestill til standardinnstillinger", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/no_NB/hud/map.ron b/assets/voxygen/i18n/no_NB/hud/map.ron new file mode 100644 index 0000000000..07d5c8e761 --- /dev/null +++ b/assets/voxygen/i18n/no_NB/hud/map.ron @@ -0,0 +1,14 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for norsk bokmål +( + string_map: { + // Map and Questlog + "hud.map.map_title": "Kart", + "hud.map.qlog_title": "Oppdrag", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/no_NB/hud/misc.ron b/assets/voxygen/i18n/no_NB/hud/misc.ron new file mode 100644 index 0000000000..7f2f16147f --- /dev/null +++ b/assets/voxygen/i18n/no_NB/hud/misc.ron @@ -0,0 +1,76 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for norsk bokmål +( + string_map: { + /// Start HUD Section + "hud.do_not_show_on_startup": "Ikke vis dette på oppstart", + "hud.show_tips": "Vis tips", + "hud.quests": "Oppdrag", + "hud.you_died": "Du døde", + "hud.waypoint_saved": "Veipunkt lagret", + + "hud.press_key_to_show_keybindings_fmt": "[{key}] Hurtigtaster", + "hud.press_key_to_toggle_lantern_fmt": "[{key}] Lykt", + "hud.press_key_to_show_debug_info_fmt": "Trykk {key} for å vise feilsøkingsinfo", + "hud.press_key_to_toggle_keybindings_fmt": "Trykk {key} for å skru av/på hurtigtaster", + "hud.press_key_to_toggle_debug_info_fmt": "Trykk {key} for å skru av/på feilsøkingsinformasjon", + + // Respawn message + "hud.press_key_to_respawn": r#"Trykk {key} for å gjennopstå ved det siste bålet du besøkte."#, + + // Welcome message + "hud.welcome": r#"Velkommen til Veloren Alfa! + + +Noen tips før du begynner: + + +Trykk på F1 for å se tilgjengelige hurtigtaster. + +Skriv /hjelp inn i chatten for å se chat-kommandoer + + +Det er kister og andre gjenstander som spawner tilfeldig i verden! + +Høyreklikk for å samle dem. + +For å brukte det du plyndrer fra disse kistene, åpne inventaret ditt med 'B'. + +Dobbeltklikk på varene i inventaret ditt for å bruke det eller ta det på. + +Kast dem ved å klikke og dra dem utenfor inventaret. + + +Nettene kan bli ganske mørke i Veloren. + +Tenn din lykt ved å trykke på 'G'. + + +Vil du frigjøre markøren for å lukke dette vinduet? Trykk på TAB! + + +Kos deg i verden av Veloren."#, + +"hud.temp_quest_headline": r#"Vær så snill, Hjelp oss reisende!"#, +"hud.temp_quest_text": r#"Fangehull fylt med onde kultister +har dukket opp rundt våre fredelige byer! + + +Samle noe selskap, samle mat +og bekjemp deres dårlige ledere og akolytter. + + +Kanskje du til og med kan skaffe deg en av de +magisk infunderte gjenstandene?"#, + + "hud.spell": "Trylleformel", + + "hud.free_look_indicator": "Frimodus aktiv. Trykk {key} for å skru av.", + "hud.auto_walk_indicator": "Autogåing aktiv", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/no_NB/hud/sct.ron b/assets/voxygen/i18n/no_NB/hud/sct.ron new file mode 100644 index 0000000000..63d45168e1 --- /dev/null +++ b/assets/voxygen/i18n/no_NB/hud/sct.ron @@ -0,0 +1,14 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for norsk bokmål +( + string_map: { + // SCT outputs + "hud.sct.experience": "{amount} Exp", + "hud.sct.block": "BLOKERT", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/uk_UA/template.ron b/assets/voxygen/i18n/no_NB/hud/skills.ron similarity index 79% rename from assets/voxygen/i18n/uk_UA/template.ron rename to assets/voxygen/i18n/no_NB/hud/skills.ron index 68d7bf1cf3..b50e50eea5 100644 --- a/assets/voxygen/i18n/uk_UA/template.ron +++ b/assets/voxygen/i18n/no_NB/hud/skills.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Ukrainian +/// Localization for norsk bokmål ( string_map: { diff --git a/assets/voxygen/i18n/no_NB/hud/social.ron b/assets/voxygen/i18n/no_NB/hud/social.ron new file mode 100644 index 0000000000..6086ffd95a --- /dev/null +++ b/assets/voxygen/i18n/no_NB/hud/social.ron @@ -0,0 +1,22 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for norsk bokmål +( + string_map: { + "hud.social": "Andre spillere", + "hud.social.online": "Tilstede:", + "hud.social.friends": "Venner", + "hud.social.not_yet_available": "Ikke tilgjengelig enda", + "hud.social.faction": "Fraksjon", + "hud.social.play_online_fmt": "{nb_player} spiller(e) tilstede", + "hud.social.name": "Navn", + "hud.social.level": "Nivå", + "hud.social.zone": "Sone", + "hud.social.account": "Bruker", + }, + + + vector_map: { + } +) + diff --git a/assets/voxygen/i18n/hu_HU/template.ron b/assets/voxygen/i18n/no_NB/hud/trade.ron similarity index 79% rename from assets/voxygen/i18n/hu_HU/template.ron rename to assets/voxygen/i18n/no_NB/hud/trade.ron index 6e34acff25..f087a37a31 100644 --- a/assets/voxygen/i18n/hu_HU/template.ron +++ b/assets/voxygen/i18n/no_NB/hud/trade.ron @@ -1,12 +1,12 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Hungarian +/// Localization for norsk bokmål ( string_map: { - }, vector_map: { } ) + diff --git a/assets/voxygen/i18n/no_NB/main.ron b/assets/voxygen/i18n/no_NB/main.ron new file mode 100644 index 0000000000..55319b1605 --- /dev/null +++ b/assets/voxygen/i18n/no_NB/main.ron @@ -0,0 +1,63 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for norsk bokmål +( + string_map: { + "main.username": "Brukernavn", + "main.server": "Server", + "main.password": "Passord", + "main.connecting": "Kobler til", + "main.creating_world": "Lager verden", + "main.tip": "Tips:", + + // Welcome notice that appears the first time Veloren is started + "main.notice": r#"Velkommen til alfaversjonen av Veloren! + +Før du dykker inn i moroa, vennligst hold et par ting i tankene: + +- Dette er en veldig tidlig alfa. Forvent feil, ekstremt uferdig spilling, upolert mekanikk og manglende funksjoner. + +- Hvis du har konstruktive tilbakemeldinger eller feilrapporter, kan du kontakte oss via Reddit, GitLab eller vår Discord-server. + +- Veloren er lisensiert under GPL 3 åpen kildekode-lisensen. Det betyr at du er fri til å spille, endre og distribuere spillet på nytt, akkurat + som du ønsker (så lenge arbeidet også er under GPL 3). + +- Veloren er et ikke-profitt basert samfunnsprosjekt, og alle som jobber på prosjektet er frivillige. +Hvis du liker det du ser, er du velkommen til å bli med i utviklings- eller kunstteamene! + +Takk for at du tar deg tid til å lese denne meldingen, vi håper at du liker spillet! + +- Veloren-utviklerne"#, + + // Login process description + "main.login_process": r#"Informasjon om påloggingsprosessen: + +Vær oppmerksom på at du nå trenger en konto +for å spille på godkjennings-aktiverte servere. + +Du kan opprette en konto på + +https://veloren.net/account/."#, + "main.login.server_not_found": "Server ikke funnet", + "main.login.authentication_error": "Innloggingsfeil på serveren", + "main.login.server_full": "Serveren er full", + "main.login.untrusted_auth_server": "Godkjenningsserver kan ikke stoles på", + "main.login.outdated_client_or_server": "Sannsynligvis er versjoner inkompatible, se etter oppdateringer.", + "main.login.timeout": "Serveren svarte ikke i tide. (Overbelastet eller nettverksproblemer).", + "main.login.server_shut_down": "Serveren stoppet", + "main.login.network_error": "Nettverksfeil", + "main.login.failed_sending_request": "Forespørsel til godkjenningsserver mislyktes", + "main.login.invalid_character": "Den valgte karakteren er ugyldig", + "main.login.client_crashed": "Klienten krasjet", + "main.login.not_on_whitelist": "Du trenger en hvitelisteoppføring av en administrator for å bli med", + "main.login.banned": "Du har blitt utestengt av følgende grunn", + "main.login.kicked": "Du har blitt sparket ut av følgende grunn", + "main.login.select_language": "Velg språk", + + "main.servers.select_server": "Velg en server", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/no_nb/_manifest.ron b/assets/voxygen/i18n/no_nb/_manifest.ron deleted file mode 100644 index d414498d62..0000000000 --- a/assets/voxygen/i18n/no_nb/_manifest.ron +++ /dev/null @@ -1,644 +0,0 @@ -/// Translation document instructions -/// -/// In order to keep localization documents readible please follow the following -/// rules: -/// - separate the string map sections using a commentary describing the purpose -/// of the next section -/// - prepend multi-line strings with a commentary -/// - append one blank lines after a multi-line strings and two after sections -/// -/// To add a new language in Veloren, just write an additional `.ron` file in -/// `assets/voxygen/i18n` and that's it! -/// -/// WARNING: Localization files shall be saved in UTF-8 format without BOM - -/// Lokalisering for norsk bokmål -( - metadata: ( - language_name: "Norsk bokmål", - language_identifier: "no_nb", - ), - convert_utf8_to_ascii: false, - fonts: { - "opensans": Font ( - asset_key: "voxygen.font.OpenSans-Regular", - scale_ratio: 1.0, - ), - "metamorph": Font ( - asset_key: "voxygen.font.Metamorphous-Regular", - scale_ratio: 1.0, - ), - "alkhemi": Font ( - asset_key: "voxygen.font.Alkhemikal", - scale_ratio: 1.0, - ), - "wizard": Font ( - asset_key: "voxygen.font.wizard", - scale_ratio: 1.0, - ), - "cyri": Font ( - asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", - scale_ratio: 1.0, - ), - }, - string_map: { - /// Start Common section - // Texts used in multiple locations with the same formatting - "common.username": "Brukernavn", - "common.singleplayer": "Enspiller", - "common.multiplayer": "Flerspiller", - "common.servers": "Servere", - "common.quit": "Avslutt", - "common.settings": "Innstillinger", - "common.languages": "Språk", - "common.interface": "Grensesnitt", - "common.gameplay": "Spillbarhet", - "common.controls": "Kontroller", - "common.video": "Grafikk", - "common.sound": "Lyd", - "common.resume": "Fortsett", - "common.characters": "Karakterer", - "common.close": "Lukk", - "common.yes": "Ja", - "common.no": "Nei", - "common.back": "Tilbake", - "common.create": "Lag", - "common.okay": "Ok", - "common.add": "Legg til", - "common.accept": "Aksepter", - "common.decline": "Avslå", - "common.disclaimer": "Bemerk", - "common.cancel": "Avbryt", - "common.none": "Ingen", - "common.error": "Feil", - "common.fatal_error": "Kritisk Feil", - "common.you": "Du", - "common.automatic": "Automatisk", - "common.random": "Tilfeldig", - // Settings Window title - "common.interface_settings": "Grensesnitt Instillinger", - "common.gameplay_settings": "Spillbarhet Innstillinger", - "common.controls_settings": "Kontroller Innstillinger", - "common.video_settings": "Grafikk Innstillinger", - "common.sound_settings": "Lyd Innstillinger", - "common.language_settings": "Språk Innstillinger", - - // Message when connection to the server is lost - "common.connection_lost": r#"Mistet forbindelsen! -Har serveren startet på nytt? -Har det kommet nye oppdateringer?"#, - - - "common.species.orc": "Ork", - "common.species.human": "Menneske", - "common.species.dwarf": "Dverg", - "common.species.elf": "Alv", - "common.species.undead": "Udødelig", - "common.species.danari": "Danari", - - "common.weapons.axe": "Øks", - "common.weapons.sword": "Sverd", - "common.weapons.staff": "Stav", - "common.weapons.bow": "Bue", - "common.weapons.hammer": "Hammer", - "common.weapons.sceptre": "Helbredings Septer", - "common.rand_appearance": "Tilfeldig utseende og navn", - /// End Common section - - - /// Start Main screen section - "main.username": "Brukernavn", - "main.server": "Server", - "main.password": "Passord", - "main.connecting": "Kobler til", - "main.creating_world": "Lager verden", - "main.tip": "Tips:", - - // Welcome notice that appears the first time Veloren is started - "main.notice": r#"Velkommen til alfaversjonen av Veloren! - -Før du dykker inn i moroa, vennligst hold et par ting i tankene: - -- Dette er en veldig tidlig alfa. Forvent feil, ekstremt uferdig spilling, upolert mekanikk og manglende funksjoner. - -- Hvis du har konstruktive tilbakemeldinger eller feilrapporter, kan du kontakte oss via Reddit, GitLab eller vår Discord-server. - -- Veloren er lisensiert under GPL 3 åpen kildekode-lisensen. Det betyr at du er fri til å spille, endre og distribuere spillet på nytt, akkurat - som du ønsker (så lenge arbeidet også er under GPL 3). - -- Veloren er et ikke-profitt basert samfunnsprosjekt, og alle som jobber på prosjektet er frivillige. -Hvis du liker det du ser, er du velkommen til å bli med i utviklings- eller kunstteamene! - -Takk for at du tar deg tid til å lese denne meldingen, vi håper at du liker spillet! - -- Veloren-utviklerne"#, - - // Login process description - "main.login_process": r#"Informasjon om påloggingsprosessen: - -Vær oppmerksom på at du nå trenger en konto -for å spille på godkjennings-aktiverte servere. - -Du kan opprette en konto på - -https://veloren.net/account/."#, - "main.login.server_not_found": "Server ikke funnet", - "main.login.authentication_error": "Innloggingsfeil på serveren", - "main.login.server_full": "Serveren er full", - "main.login.untrusted_auth_server": "Godkjenningsserver kan ikke stoles på", - "main.login.outdated_client_or_server": "Sannsynligvis er versjoner inkompatible, se etter oppdateringer.", - "main.login.timeout": "Serveren svarte ikke i tide. (Overbelastet eller nettverksproblemer).", - "main.login.server_shut_down": "Serveren stoppet", - "main.login.network_error": "Nettverksfeil", - "main.login.failed_sending_request": "Forespørsel til godkjenningsserver mislyktes", - "main.login.invalid_character": "Den valgte karakteren er ugyldig", - "main.login.client_crashed": "Klienten krasjet", - "main.login.not_on_whitelist": "Du trenger en hvitelisteoppføring av en administrator for å bli med", - "main.login.banned": "Du har blitt utestengt av følgende grunn", - "main.login.kicked": "Du har blitt sparket ut av følgende grunn", - "main.login.select_language": "Velg språk", - - "main.servers.select_server": "Velg en server", - - /// End Main screen section - - - /// Start HUD Section - "hud.do_not_show_on_startup": "Ikke vis dette på oppstart", - "hud.show_tips": "Vis tips", - "hud.quests": "Oppdrag", - "hud.you_died": "Du døde", - "hud.waypoint_saved": "Veipunkt lagret", - - "hud.press_key_to_show_keybindings_fmt": "[{key}] Hurtigtaster", - "hud.press_key_to_toggle_lantern_fmt": "[{key}] Lykt", - "hud.press_key_to_show_debug_info_fmt": "Trykk {key} for å vise feilsøkingsinfo", - "hud.press_key_to_toggle_keybindings_fmt": "Trykk {key} for å skru av/på hurtigtaster", - "hud.press_key_to_toggle_debug_info_fmt": "Trykk {key} for å skru av/på feilsøkingsinformasjon", - - // Chat outputs - "hud.chat.online_msg": "[{name}] logget på", - "hud.chat.offline_msg": "[{name}] logget av", - - "hud.chat.default_death_msg": "[{name}] døde", - "hud.chat.environmental_kill_msg": "[{name}] døde i {environment}", - "hud.chat.fall_kill_msg": "[{name}] døde av fallskade", - "hud.chat.suicide_msg": "[{name}] døde av selvskader", - - "hud.chat.pvp_melee_kill_msg": "[{attacker}] drepte [{victim}]", - "hud.chat.pvp_ranged_kill_msg": "[{attacker}] skjøt [{victim}]", - "hud.chat.pvp_explosion_kill_msg": "[{attacker}] sprengte [{victim}]", - "hud.chat.pvp_energy_kill_msg": "[{attacker}] drepte [{victim}] med magi", - "hud.chat.pvp_buff_kill_msg": "[{attacker}] drepte [{victim}]", - - - "hud.chat.npc_melee_kill_msg": "{attacker} drepte [{victim}]", - "hud.chat.npc_ranged_kill_msg": "{attacker} skjøt [{victim}]", - "hud.chat.npc_explosion_kill_msg": "{attacker} sprengte [{victim}]", - "hud.chat.npc_energy_kill_msg": "{attacker} drepte [{victim}] med magi", - "hud.chat.npc_other_kill_msg": "{attacker} drepte [{victim}]", - - "hud.chat.loot_msg": "Du plukket opp [{item}]", - "hud.chat.loot_fail": "Ditt inventar er fullt!", - "hud.chat.goodbye": "Adjø!", - "hud.chat.connection_lost": "Forbindelse mistet. Utkastet om {time} sekunder.", - - // SCT outputs - "hud.sct.experience": "{amount} Exp", - "hud.sct.block": "BLOKERT", - - // Respawn message - "hud.press_key_to_respawn": r#"Trykk {key} for å gjennopstå ved det siste bålet du besøkte."#, - - // Welcome message - "hud.welcome": r#"Velkommen til Veloren Alfa! - - -Noen tips før du begynner: - - -Trykk på F1 for å se tilgjengelige hurtigtaster. - -Skriv /hjelp inn i chatten for å se chat-kommandoer - - -Det er kister og andre gjenstander som spawner tilfeldig i verden! - -Høyreklikk for å samle dem. - -For å brukte det du plyndrer fra disse kistene, åpne inventaret ditt med 'B'. - -Dobbeltklikk på varene i inventaret ditt for å bruke det eller ta det på. - -Kast dem ved å klikke og dra dem utenfor inventaret. - - -Nettene kan bli ganske mørke i Veloren. - -Tenn din lykt ved å trykke på 'G'. - - -Vil du frigjøre markøren for å lukke dette vinduet? Trykk på TAB! - - -Kos deg i verden av Veloren."#, - -"hud.temp_quest_headline": r#"Vær så snill, Hjelp oss reisende!"#, -"hud.temp_quest_text": r#"Fangehull fylt med onde kultister -har dukket opp rundt våre fredelige byer! - - -Samle noe selskap, samle mat -og bekjemp deres dårlige ledere og akolytter. - - -Kanskje du til og med kan skaffe deg en av de -magisk infunderte gjenstandene?"#, - - - - // Inventory - "hud.bag.inventory": "{playername}'s Inventar", - "hud.bag.stats_title": "{playername}'s Statistikk", - "hud.bag.exp": "Exp", - "hud.bag.armor": "Utrustning", - "hud.bag.stats": "Statistikk", - "hud.bag.head": "Hode", - "hud.bag.neck": "Nakke", - "hud.bag.tabard": "Tabard", - "hud.bag.shoulders": "Skulder", - "hud.bag.chest": "Bryst", - "hud.bag.hands": "Hender", - "hud.bag.lantern": "Lykt", - "hud.bag.glider": "Glidefly", - "hud.bag.belt": "Belte", - "hud.bag.ring": "Ring", - "hud.bag.back": "Rygg", - "hud.bag.legs": "Ben", - "hud.bag.feet": "Føtter", - "hud.bag.mainhand": "Hovedhånd", - "hud.bag.offhand": "Tillegshånd", - - - // Map and Questlog - "hud.map.map_title": "Kart", - "hud.map.qlog_title": "Oppdrag", - - // Settings - "hud.settings.general": "Generell", - "hud.settings.none": "Ingen", - "hud.settings.press_behavior.toggle": "Veksle", - "hud.settings.press_behavior.hold": "Hold", - "hud.settings.help_window": "Hjelpevindu", - "hud.settings.debug_info": "Feilsøkingsinformasjon", - "hud.settings.tips_on_startup": "Tips-På-Oppstart", - "hud.settings.ui_scale": "UI-Skalering", - "hud.settings.relative_scaling": "Relativ Skalering", - "hud.settings.custom_scaling": "Tilpasset Skalering", - "hud.settings.crosshair": "Retikkel", - "hud.settings.transparency": "Gjennomsiktighet", - "hud.settings.hotbar": "Hurtigknappsbar", - "hud.settings.toggle_shortcuts": "Veksle Snarveier", - "hud.settings.buffs_skillbar": "Ikoner på Ferdighetsbar", - "hud.settings.buffs_mmap": "Ikoner på Minimap", - "hud.settings.toggle_bar_experience": "Veksle erfaringsbar", - "hud.settings.scrolling_combat_text": "Rullende kamptekst", - "hud.settings.single_damage_number": "Enkelt skadetall", - "hud.settings.cumulated_damage": "Kumulert skade", - "hud.settings.incoming_damage": "Innkommende skade", - "hud.settings.cumulated_incoming_damage": "Kumulert innkommende skade", - "hud.settings.speech_bubble": "Snakkeboble", - "hud.settings.speech_bubble_dark_mode": "Mørk modus for snakkeboble", - "hud.settings.speech_bubble_icon": "Snakkeboble ikon", - "hud.settings.energybar_numbers": "Energibar tall", - "hud.settings.values": "Verdier", - "hud.settings.percentages": "Prosentandeler", - "hud.settings.chat": "Chat", - "hud.settings.background_transparency": "Bakgrunnsgjennomsiktighet", - "hud.settings.chat_character_name": "Karakternavn i chat", - "hud.settings.loading_tips": "Oppstartsskjerm Tips", - - "hud.settings.pan_sensitivity": "Panoreringssensitivitet", - "hud.settings.zoom_sensitivity": "Zoomingssensitivitet", - "hud.settings.invert_scroll_zoom": "Inverter skrollezoom", - "hud.settings.invert_mouse_y_axis": "Inverter mus Y Aksen", - "hud.settings.enable_mouse_smoothing": "Kamerautjevning", - "hud.settings.free_look_behavior": "Frimodus oppførsel", - "hud.settings.auto_walk_behavior": "Autogåing oppførsel", - "hud.settings.stop_auto_walk_on_input": "Stopp autogåing på bevegelse", - - "hud.settings.view_distance": "Utsiktsavstand", - "hud.settings.sprites_view_distance": "Sprites utsiktsavstand", - "hud.settings.figures_view_distance": "Enhets utsiktsavstand", - "hud.settings.maximum_fps": "Maksimum FPS", - "hud.settings.fov": "Synsfelt (deg)", - "hud.settings.gamma": "Gamma", - "hud.settings.ambiance": "Stemning Brightness", - "hud.settings.antialiasing_mode": "Kantutjevningsmodus", - "hud.settings.cloud_rendering_mode": "Tegn-skyer-modus", - "hud.settings.fluid_rendering_mode": "Tegn-væske-modus", - "hud.settings.fluid_rendering_mode.cheap": "Billig", - "hud.settings.fluid_rendering_mode.shiny": "Skinnende", - "hud.settings.cloud_rendering_mode.minimal": "Minimal", - "hud.settings.cloud_rendering_mode.low": "Lav", - "hud.settings.cloud_rendering_mode.medium": "Medium", - "hud.settings.cloud_rendering_mode.high": "Høy", - "hud.settings.fullscreen": "Full skjerm", - "hud.settings.fullscreen_mode": "Fullskjermsmodus", - "hud.settings.fullscreen_mode.exclusive": "Eksklusiv", - "hud.settings.fullscreen_mode.borderless": "Uten kanter", - "hud.settings.particles": "Partikler", - "hud.settings.resolution": "Resolusjon", - "hud.settings.bit_depth": "Bit Dybde", - "hud.settings.refresh_rate": "Oppdateringsfrekvens", - "hud.settings.save_window_size": "Spar vindusstørrelse", - "hud.settings.lighting_rendering_mode": "Tegn-belysning-modus", - "hud.settings.lighting_rendering_mode.ashikhmin": "Type A - Høy ", - "hud.settings.lighting_rendering_mode.blinnphong": "Type B - Medium", - "hud.settings.lighting_rendering_mode.lambertian": "Type L - Billing", - "hud.settings.shadow_rendering_mode": "Tegn-skygger-modus", - "hud.settings.shadow_rendering_mode.none": "Ingen", - "hud.settings.shadow_rendering_mode.cheap": "Billig", - "hud.settings.shadow_rendering_mode.map": "Kart", - "hud.settings.shadow_rendering_mode.map.resolution": "Resolusjon", - "hud.settings.lod_detail": "Nivå med detaljer", - "hud.settings.save_window_size": "Lagre vindusstørrelse", - - - "hud.settings.music_volume": "Musikkvolum", - "hud.settings.sound_effect_volume": "Lydeffektvolum", - "hud.settings.audio_device": "Lydenhet", - - "hud.settings.awaitingkey": "Trykk på en tast...", - "hud.settings.unbound": "Ingen", - "hud.settings.reset_keybinds": "Tilbakestill til standardinnstillinger", - - "hud.social": "Andre spillere", - "hud.social.online": "Tilstede:", - "hud.social.friends": "Venner", - "hud.social.not_yet_available": "Ikke tilgjengelig enda", - "hud.social.faction": "Fraksjon", - "hud.social.play_online_fmt": "{nb_player} spiller(e) tilstede", - "hud.social.name": "Navn", - "hud.social.level": "Nivå", - "hud.social.zone": "Sone", - "hud.social.account": "Bruker", - - - "hud.crafting": "Håndverk", - "hud.crafting.recipes": "Oppskrifter", - "hud.crafting.ingredients": "Ingredienser:", - "hud.crafting.craft": "Lag", - "hud.crafting.tool_cata": "Krever:", - - "hud.group": "Gruppe", - "hud.group.invite_to_join": "[{name}] inviterte deg til gruppen deres!", - "hud.group.invite": "Inviter", - "hud.group.kick": "Spark", - "hud.group.assign_leader": "Tilordne leder", - "hud.group.leave": "Forlat Gruppe", - "hud.group.dead" : "Død", - "hud.group.out_of_range": "Ute av rekkevidde", - "hud.group.add_friend": "Legg til i vennelisten", - "hud.group.link_group": "Koble til grupper", - "hud.group.in_menu": "I Meny", - "hud.group.members": "Gruppemedlemmer", - - "hud.spell": "Trylleformel", - - "hud.free_look_indicator": "Frimodus aktiv. Trykk {key} for å skru av.", - "hud.auto_walk_indicator": "Autogåing aktiv", - - /// End HUD section - - - /// Start GameInput section - - "gameinput.primary": "Primær Angrep", - "gameinput.secondary": "Sekundær Angrep/Blokk/Sikt", - "gameinput.slot1": "Hurtigbar Luke 1", - "gameinput.slot2": "Hurtigbar Luke 2", - "gameinput.slot3": "Hurtigbar Luke 3", - "gameinput.slot4": "Hurtigbar Luke 4", - "gameinput.slot5": "Hurtigbar Luke 5", - "gameinput.slot6": "Hurtigbar Luke 6", - "gameinput.slot7": "Hurtigbar Luke 7", - "gameinput.slot8": "Hurtigbar Luke 8", - "gameinput.slot9": "Hurtigbar Luke 9", - "gameinput.slot10": "Hurtigbar Luke 10", - "gameinput.swaploadout": "Bytt utlastning", - "gameinput.togglecursor": "Veksle Musepeker", - "gameinput.help": "Veksle hjelpevindu", - "gameinput.toggleinterface": "Veksle Grensesnitt", - "gameinput.toggledebug": "Veksle FPS og feilsøkingsinfo", - "gameinput.screenshot": "Ta skjermbilde", - "gameinput.toggleingameui": "Veksle Navneskilt", - "gameinput.fullscreen": "Veksle fullskjerm", - "gameinput.moveforward": "Beveg frem", - "gameinput.moveleft": "Beveg venstre", - "gameinput.moveright": "Beveg høyre", - "gameinput.moveback": "Beveg bakover", - "gameinput.jump": "Hopp", - "gameinput.glide": "Glider", - "gameinput.roll": "Rull", - "gameinput.climb": "Klatre", - "gameinput.climbdown": "Klatre ned", - "gameinput.wallleap": "Veggsprang", - "gameinput.togglelantern": "Veksle lykt", - "gameinput.mount": "Monter", - "gameinput.chat": "Chat", - "gameinput.command": "Kommando", - "gameinput.escape": "Røm", - "gameinput.map": "Kart", - "gameinput.bag": "Bag", - "gameinput.social": "Sosial", - "gameinput.sit": "Sitt", - "gameinput.spellbook": "Trylleformler", - "gameinput.settings": "Innstillinger", - "gameinput.respawn": "Gjennopstå", - "gameinput.charge": "Lad opp", - "gameinput.togglewield": "Veksle Våpen", - "gameinput.interact": "Interaksjon", - "gameinput.freelook": "Frimodus", - "gameinput.autowalk": "Autogåing", - "gameinput.dance": "Dans", - "gameinput.select": "Velg enhet", - "gameinput.acceptgroupinvite": "Godta gruppeinvitasjon", - "gameinput.declinegroupinvite": "Avvis gruppeinvitasjon", - "gameinput.crafting": "Håndverk", - "gameinput.fly": "Fly", - "gameinput.sneak": "Snik", - "gameinput.swimdown": "Svøm nedover", - "gameinput.swimup": "Svøm oppover", - - /// End GameInput section - - - /// Start chracter selection section - "char_selection.loading_characters": "Laster inn karakterer...", - "char_selection.delete_permanently": "Slett denne karakteren permanent?", - "char_selection.deleting_character": "Sletter karakter...", - "char_selection.change_server": "Bytt server", - "char_selection.enter_world": "Gå inn i verden", - "char_selection.logout": "Logg ut", - "char_selection.create_new_character": "Lag ny karakter", - "char_selection.creating_character": "Skaper karakter...", - "char_selection.character_creation": "Karakterskaping", - - "char_selection.human_default": "Menneskestandarder", - "char_selection.level_fmt": "Nivå {level_nb}", - "char_selection.uncanny_valley": "Villmark", - "char_selection.plains_of_uncertainty": "Usikkerhetssletter", - "char_selection.beard": "Skjegg", - "char_selection.hair_style": "Hårstil", - "char_selection.hair_color": "Hårfarge", - "char_selection.eye_color": "Øyenfarge", - "char_selection.skin": "Hud", - "char_selection.eyeshape": "Øyedetaljer", - "char_selection.accessories": "Tilbehør", - "char_selection.create_info_name": "Karakteren din trenger et navn!", - - /// End character selection section - - - /// Start character window section - "character_window.character_name": "Karakternavn", - // Character stats - "character_window.character_stats": r#"Utholdenhet - -Fitness - -Viljestyrke - -Beskyttelse -"#, - /// End character window section - - - /// Start Escape Menu Section - "esc_menu.logout": "Logg ut", - "esc_menu.quit_game": "Avslutt spillet", - /// End Escape Menu Section - - /// Buffs and Debuffs - "buff.remove": "Klikk for å fjerne", - "buff.title.missing": "Mangler tittel", - "buff.desc.missing": "Mangler beskrivelse", - // Buffs - "buff.title.heal": "Helbred", - "buff.desc.heal": "Helbred over tid.", - "buff.title.potion": "Trylledrikk", - "buff.desc.potion": "Drikker...", - "buff.title.saturation": "Metning", - "buff.desc.saturation": "Helbred over tid fra forbruksvarer.", - // Debuffs - "buff.title.bleed": "Blør", - "buff.desc.bleed": "Påfører regelmessig skade.", - }, - - - vector_map: { - "loading.tips": [ - "Trykk 'G' for å tenne lykten.", - "Trykk 'F1' for å se alle standard tastebindinger.", - "Du kan skrive /say eller /s for å bare chatte med spillere rett rundt deg.", - "Du kan skrive /region eller /r for å bare chatte med spillere et par hundre blokker rundt deg.", - "Du kan skrive /group eller /g for å bare chatte med spillere i din nåværende gruppe.", - "For å sende private meldinger skriv /tell etterfulgt av et spillernavn og meldingen din.", - "NPCer med samme nivå kan ha forskjellige problemer.", - "Hold øye med mat, kister og andre godsaker spredt over hele verden!", - "Inventar fylt med mat? Prøv å lage bedre mat med det!", - "Lurer du på hva du kan gjøre? Fangehull er merket med brune flekker på kartet!", - "Ikke glem å justere grafikken for systemet ditt. Trykk på 'N' for å åpne innstillingene.", - "Å spille med andre er gøy! Trykk 'O' for å se hvem som er online.", - "En NPC med en hodeskalle under helsebaren er ganske kraftig sammenlignet med deg selv.", - "Trykk 'J' for å danse. Fest!", - "Trykk 'L-Shift' for å åpne Glider og erobre himmelen.", - "Veloren er fortsatt i Pre-Alfa. Vi gjør vårt beste for å forbedre det hver dag!", - "Hvis du vil bli med i Dev-teamet eller bare ta en prat med oss, bli med i Discord-Serveren.", - "Du kan veksle for å vise mengden helse på helselinjen i innstillingene.", - "For å se statistikken din, klikk på 'Statistikk' -knappen i beholdningen.", - ], - "npc.speech.villager_under_attack": [ - "Hjelp, jeg er under angrep!", - "Hjelp! Jeg er under angrep!", - "Au! Jeg er under angrep!", - "Au! Jeg er under angrep! Hjelp!", - "Hjelp meg! Jeg er under angrep!", - "Jeg er under angrep! Hjelp!", - "Jeg er under angrep! Hjelp meg!", - "Hjelp!", - "Hjelp! Hjelp!", - "Hjelp! Hjelp! Hjelp!", - "Jeg er under angrep!", - "AAAHHH! Jeg er under angrep!", - "AAAHHH! Jeg er under angrep! Hjelp!", - "Hjelp! Vi er under angrep!", - "Hjelp! Morder!", - "Hjelp! Det er en morder på frifot!", - "Hjelp! De prøver å drepe meg!", - "Vakter, jeg er under angrep!", - "Vakter! Jeg er under angrep!", - "Jeg er under angrep! Vakter!", - "Hjelp! Vakter! Jeg er under angrep!", - "Vakter! Kom raskt!", - "Vakter! Vakter!", - "Vakter! Det er en skurk som angriper meg!", - "Vakter, drep denne onde skurken!", - "Vakter! Det er en morder!", - "Vakter! Hjelp meg!", - "Du kommer ikke unna med dette! Vakter!", - "Du fiende!", - "Hjelp meg!", - "Hjelp! Vœr så snill!", - "Ouch! Vakter! Hjelp!", - "De etterfølger etter meg!", - "Hjelp! Hjelp! Jeg blir undertrykt!", - "Ah, nå ser vi volden som er bygd inn i systemet.", - "Det er bare en ripe!", - "Slutt med det!", - "Hva har jeg noensinne gjort mot deg?!", - "Vær så snill slutt å angripe meg!", - "Hei! Se for deg hvor du peker den tingen!", - "Avskyelige krek, bort med deg!", - "Stop det! Gå vekk!", - "Nå gjør du meg sint!", - "Oi! Hvem tror du at du er?!", - "Jeg tar hodet ditt for det!", - "Stop, vær så snill! Jeg har ingenting av verdi på meg!", - "Jeg får broren min til å ta deg, han er større enn meg!", - "Neiii, jeg sier det til mamma!", - "Forbann deg!", - "Vœr så snill ikke gjør det.", - "Det var ikke veldig snilt!", - "Våpnet ditt funker, du kan ta det vekk nå!", - "Bespar meg!", - "Vær så snill, jeg har familie!", - "Jeg er for ung til å dø!", - "Kan vi snakke om dette?", - "Vold er aldri svaret!", - "I dag ser ut til å være en dårlig dag...", - "Hei, det kjente jeg!", - "Eek!", - "Hvor uhøflig!", - "Stop, jeg ber deg!", - "Smitte beslage deg!", - "Dette er ikke gøy.", - "Hvordan våger du?!", - "Du kommer til å betale for dette!", - "Fortsett med dette og du kommer til å be unnskyld!", - "Ikke få meg til å banke deg!", - "Dette må være en misforståelse!", - "Du trenger ikke å gjøre dette!", - "Gå vekk, skurk!", - "Det gjorde vondt!", - "Hvorfor gjorde du det?", - "Etter åndene, forsvinn!", - "Du må ha forvekslet meg med noen andre!", - "Jeg fortjener ikke dette!", - "Vær så snill ikke gjør dette igjen!", - "Vakter, kast dette mennesket i havet!", - "Jeg får min tarasque til å etterfølge deg!", - ], - } -) diff --git a/assets/voxygen/i18n/pt_BR/template.ron b/assets/voxygen/i18n/pt_BR/template.ron deleted file mode 100644 index 5d390a9c74..0000000000 --- a/assets/voxygen/i18n/pt_BR/template.ron +++ /dev/null @@ -1,12 +0,0 @@ -/// CUIDADO: Arquivos de tradução devem ser criados no formato UTF-8 sem Marca de Ordem de byte - BOM(https://pt.wikipedia.org/wiki/Marca_de_ordem_de_byte) - -/// Localization for Portuguese (Brazil) -( - string_map: { - - }, - - - vector_map: { - } -) diff --git a/assets/voxygen/i18n/pt_PT/_manifest.ron b/assets/voxygen/i18n/pt_PT/_manifest.ron index 6bdc0835b9..d646a65863 100644 --- a/assets/voxygen/i18n/pt_PT/_manifest.ron +++ b/assets/voxygen/i18n/pt_PT/_manifest.ron @@ -28,358 +28,6 @@ ), }, string_map: { - /// Start Common section - // Texts used in multiple locations with the same formatting - "common.username": "nome de utilizador", - "common.singleplayer": "Um jogador", - "common.multiplayer": "Multijogador", - "common.servers": "Servidores", - "common.quit": "Sair", - "common.settings": "Definições", - "common.languages": "Linguagens", - "common.interface": "Interface", - "common.gameplay": "Jogabilidade", - "common.controls": "Controlos", - "common.video": "Video", - "common.sound": "Som", - "common.resume": "Resumir", - "common.characters": "Personagens", - "common.close": "Fechar", - "common.yes": "Sim", - "common.no": "Não", - "common.back": "Voltar", - "common.create": "Criar", - "common.okay": "Okay", - "common.accept": "Aceitar", - "common.disclaimer": "Aviso", - "common.cancel": "Cancelar", - "common.none": "Nenhum", - "common.error": "Erro", - "common.fatal_error": "Erro fatal", - - // Message when connection to the server is lost - "common.connection_lost": r#"Conexâo perdida! -Será que o server reiniciou? -O cliente está atualizado?"#, - - - "common.species.orc": "Ogre", - "common.species.human": "Humano", - "common.species.dwarf": "Anão", - "common.species.elf": "Elfo", - "common.species.undead": "Morto-vivo", - "common.species.danari": "Danari", - - "common.weapons.axe": "Machado", - "common.weapons.sword": "Espada", - "common.weapons.staff": "Cajado", - "common.weapons.bow": "Arco", - "common.weapons.hammer": "Martelo", - /// End Common section - - - /// Start Main screen section - "main.connecting": "Conectando", - "main.creating_world": "Criando o mundo", - - // Welcome notice that appears the first time Veloren is started - "main.notice": r#"Bem vindo a versão alpha de Veloren! - -Antes de começar a jogar, por favor tenha em mente que: - -- Isto é uma versão muito experimental. Prepare-se para defeitos, jogabilidade muito inacabada, mecanismos por polir e funcionalidades por -adicionar. -- Se tiver comentários construtivos ou defeitos para reportar, pode contactar-nos através do Reddit, GitLab ou o nosso servidor comunitário de -Discord. -- Veloren está licenciado sob a licensa código aberto GPL 3. Isto significa que pode jogar, modificar e redistribuir como quiser - (Contanto que o trabalho derivado seja também GPL 3). -- Veloren é um projeto comunitário sem lucro, e toda a gente que trabalha nele é um voluntário. Se gostar do que ve, considere juntar-se a equipa -de desenvolvimento ou a de artes! -- 'Voxel RPG' é um género em si mesmo. First-person shooters costumavam ser chamados de clones do DOOM. - -Tal como eles, nós estamos a tentar construir um género. Este jogo não é um clone e o seu desenvolvimento vai divergir de jogos existentes no -futuro. - -Obrigado por ler este aviso, nós esperamos que goste do jogo! - -~ A equipa do Veloren"#, - - // Login process description - "main.login_process": r#"Informação sobre o processo de Login: - -Se tiver problemas a logar: - -Tenha em atenção que é necessário uma conta -para jogar em servidores com autenticação. - -Para criar uma conta navegue até - -https://veloren.net/account/."#, - "main.login.server_not_found": "Servidor não encontrado", - "main.login.authentication_error": "Erro de autenticação", - "main.login.server_full": "Servidor está cheio", - "main.login.untrusted_auth_server": "Server de autenticação não confiado", - "main.login.outdated_client_or_server": "Servidor endoideceu: Provavelmente as versões são incompativéis, verifique se há versões mais recentes.", - "main.login.timeout": "Tempo esgotado: O servidor não respondeu a tempo. (Sobrecarregado ou problemas de rede).", - "main.login.server_shut_down": "O servidor encerrou", - "main.login.network_error": "Error de rede", - "main.login.failed_sending_request": "Pedido ao servidor de autenticação falhou", - "main.login.client_crashed": "O cliente crashou", - "main.login.select_language": "Seleccione uma língua", - - /// End Main screen section - - - /// Start HUD Section - "hud.do_not_show_on_startup": "Não mostre no início", - "hud.show_tips": "Mostrar dicas", - "hud.quests": "Missões", - "hud.you_died": "Você Morreu", - - "hud.press_key_to_show_keybindings_fmt": "Clique em {key} para mostrar as teclas mapeadas", - "hud.press_key_to_show_debug_info_fmt": "Clique em {key} para mostrar a informação de depuração", - "hud.press_key_to_toggle_keybindings_fmt": "Clique em {key} para mostrar/ocultar as teclas mapeadas", - "hud.press_key_to_toggle_debug_info_fmt": "Clique em {key} para mostrar/ocultar a informação de depuração", - - // Respawn message - "hud.press_key_to_respawn": r#"Clique em {key} para renascer na última fogueira visitada."#, - - // Welcome message - "hud.welcome": r#"Bem vindo a Alpha do Veloren!, - - -Algumas dicas antes de começar: - - -MAIS IMPORTANTE: Para definir o seu local de renascimento escreva /waypoint no chat. - -Isto também pode ser realizado depois de morto! - - -Clique em F1 para ver as teclas mapeadas. - -Escreva /help no chat para ver os comandos de chat - - -A muitos baús e outros objetos a aperecer no mundo aleatoriamente! - -Pressione o botão direito do mouse pare coletá-los. - -Para usar o que coletou basta abrir o inventário pressionando a tecla 'B'. - -Faça duplo clique nos items para usá-los ou equipá-los. - -Deite-os fora cliquando uma vez neles e depois outra fora do inventário. - - -As noites podem ser bastante escuras. - -Acenda a lanterna escrevendo /lantern no chat. - - -Quer libertar o mouse para fechar esta janela? Clique em TAB! - - -Aprecie a sua estadia no mundo de Veloren."#, - -"hud.temp_quest_headline": r#"Please, help us Traveller!"#, -"hud.temp_quest_text": r#"Dungeons filled with evil cultists -have emerged all around our peaceful towns! - - -Gather some company, stack up on food -and defeat their vile leaders and acolytes. - - -Maybe you can even obtain one of their -magically infused items?"#, - - "hud.settings.general": "Geral", - "hud.settings.none": "Nenhum", - "hud.settings.press_behavior.toggle": "Alternar", - "hud.settings.press_behavior.hold": "Segurar", - "hud.settings.help_window": "Janela de ajuda", - "hud.settings.debug_info": "Informação de depuração", - "hud.settings.tips_on_startup": "Dicas no início", - "hud.settings.ui_scale": "Escala da interface", - "hud.settings.relative_scaling": "Escala relativa", - "hud.settings.custom_scaling": "Escala customizada", - "hud.settings.crosshair": "Crosshair", - "hud.settings.transparency": "Transparência", - "hud.settings.hotbar": "Hotbar", - "hud.settings.toggle_shortcuts": "Mostar/Ocultar atalhos", - "hud.settings.toggle_bar_experience": "Mostar/Ocultar barra de experiência", - "hud.settings.scrolling_combat_text": "Texto de combate deslizante", - "hud.settings.single_damage_number": "Números de dano únicos", - "hud.settings.cumulated_damage": "Dano acumulado", - "hud.settings.incoming_damage": "Dano recebido", - "hud.settings.cumulated_incoming_damage": "Dano recebido acumulado", - "hud.settings.energybar_numbers": "Números da barra de energia", - "hud.settings.values": "Valores", - "hud.settings.percentages": "Percentagens", - "hud.settings.chat": "Chat", - "hud.settings.background_transparency": "Transparência do fundo", - - "hud.settings.pan_sensitivity": "Sensibilidade de rotação", - "hud.settings.zoom_sensitivity": "Sensibilidade de zoom", - "hud.settings.invert_scroll_zoom": "Inverter scroll zoom", - "hud.settings.invert_mouse_y_axis": "Inverter o eixo Y do mouse", - "hud.settings.free_look_behavior": "Ativação de rotação livre", - - "hud.settings.view_distance": "Alcance de visão", - "hud.settings.maximum_fps": "FPS máximo", - "hud.settings.fov": "Campo de visão(graus)", - "hud.settings.gamma": "Luminosidade", - "hud.settings.antialiasing_mode": "Modo de antialiasing", - "hud.settings.cloud_rendering_mode": "Modo de representação de nuvens", - "hud.settings.fluid_rendering_mode": "Modo de representação de fluídos", - "hud.settings.fluid_rendering_mode.cheap": "Barato", - "hud.settings.fluid_rendering_mode.shiny": "Brilhante", - "hud.settings.cloud_rendering_mode.regular": "Normal", - "hud.settings.fullscreen": "Tela cheia", - "hud.settings.save_window_size": "Gravar dimensões", - - "hud.settings.music_volume": "Volume da música", - "hud.settings.sound_effect_volume": "Volume dos efeitos sonoros", - "hud.settings.audio_device": "Dispositivo de aúdio", - - // Control list - "hud.settings.control_names": r#"Libertar mouse -Mostar/Ocultar janela de ajuda -Mostar/Ocultar interface -Mostar/Ocultar FPS e informação de depuração -Gravar captura de ecrã -Mostar/Ocultar nomes -Mostar/Ocultar tela cheia - - -Mover para frente -Mover para a esquerda -Mover para a direita -Mover para trás - -Saltar - -Planador - -Desviar - -Rolar - -Trepar - -Descer - -Auto caminhar - -Embainhar/sacar armas - -Equipar/remover capacete - -Sentar - -Montar - -Interagir - - -Ataque básico -Ataque/bloquear/apontar secundário - - -Habilidade 1 -Habilidade 2 -Habilidade 3 -Habilidade 4 -Habilidade 5 -Habilidade 6 -Habilidade 7 -Habilidade 8 -Habilidade 9 -Habilidade 10 - - -Menu de pausa -Definições -Social -Mapa -Livro de feitiços -Personagem -Registo de missões -Inventário - - - -Enviar mensagem de chat -Scroll chat - - -Comandos de chat: - -/alias [nome] - Mudar o seu nome de chat -/tp [nome] - Teletransporta-te para outro player -/jump - Deslocar a posição -/goto - Teletransporta-te para a posição -/kill - Suicidar -/pig - Invocar NPC de porco -/wolf - Invocar NPC do lobo -/help - Mostrar comandos de chat"#, - - "hud.social": "Social", - "hud.social.online": "Online", - "hud.social.friends": "Amigos", - "hud.social.not_yet_available": "Indisponível de momento", - "hud.social.faction": "Facção", - "hud.social.play_online_fmt": "{nb_player} jogador(es) online", - - "hud.spell": "Feitiço", - - "hud.free_look_indicator": "Rotação livre ativada", - /// End HUD section - - - /// Start chracter selection section - "char_selection.delete_permanently": "Deletar esta personagem permanentemente?", - "char_selection.change_server": "Mudar de servidor", - "char_selection.enter_world": "Entrar no mundo", - "char_selection.logout": "Desconectar", - "char_selection.create_new_character": "Criar nova personagem", - "char_selection.character_creation": "Criação de personagem", - - "char_selection.human_default": "Humano padrão", - "char_selection.level_fmt": "Nível {level_nb}", - "char_selection.uncanny_valley": "Vale da estranheza", - "char_selection.plains_of_uncertainty": "Planícies da incerteza", - "char_selection.beard": "Barba", - "char_selection.hair_style": "Estilo do cabelo", - "char_selection.hair_color": "Cor do cabelo", - "char_selection.chest_color": "Cor do peitoral", - "char_selection.eye_color": "Cor dos olhos", - "char_selection.skin": "Cor da pele", - "char_selection.eyebrows": "Pestanas", - "char_selection.accessories": "Acessórios", - - /// End chracter selection section - - - /// Start character window section - "character_window.character_name": "Nome da personagem", - // Charater stats - "character_window.character_stats": r#"Resistência - -Aptidão fisíca - -Força de vontade -"#, - - - /// Start character window section - - - /// Start Escape Menu Section - "esc_menu.logout": "Desconectar", - "esc_menu.quit_game": "Sair do jogo", - /// End Escape Menu Section }, vector_map: { diff --git a/assets/voxygen/i18n/pt_PT/buff.ron b/assets/voxygen/i18n/pt_PT/buff.ron new file mode 100644 index 0000000000..960b221c7d --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/buff.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/pt_PT/char_selection.ron b/assets/voxygen/i18n/pt_PT/char_selection.ron new file mode 100644 index 0000000000..849ac64ecf --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/char_selection.ron @@ -0,0 +1,29 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + "char_selection.delete_permanently": "Deletar esta personagem permanentemente?", + "char_selection.change_server": "Mudar de servidor", + "char_selection.enter_world": "Entrar no mundo", + "char_selection.logout": "Desconectar", + "char_selection.create_new_character": "Criar nova personagem", + "char_selection.character_creation": "Criação de personagem", + + "char_selection.human_default": "Humano padrão", + "char_selection.level_fmt": "Nível {level_nb}", + "char_selection.uncanny_valley": "Vale da estranheza", + "char_selection.plains_of_uncertainty": "Planícies da incerteza", + "char_selection.beard": "Barba", + "char_selection.hair_style": "Estilo do cabelo", + "char_selection.hair_color": "Cor do cabelo", + "char_selection.chest_color": "Cor do peitoral", + "char_selection.eye_color": "Cor dos olhos", + "char_selection.skin": "Cor da pele", + "char_selection.eyebrows": "Pestanas", + "char_selection.accessories": "Acessórios", + }, + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/pt_PT/common.ron b/assets/voxygen/i18n/pt_PT/common.ron new file mode 100644 index 0000000000..e9848f546a --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/common.ron @@ -0,0 +1,57 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + // Texts used in multiple locations with the same formatting + "common.username": "nome de utilizador", + "common.singleplayer": "Um jogador", + "common.multiplayer": "Multijogador", + "common.servers": "Servidores", + "common.quit": "Sair", + "common.settings": "Definições", + "common.languages": "Linguagens", + "common.interface": "Interface", + "common.gameplay": "Jogabilidade", + "common.controls": "Controlos", + "common.video": "Video", + "common.sound": "Som", + "common.resume": "Resumir", + "common.characters": "Personagens", + "common.close": "Fechar", + "common.yes": "Sim", + "common.no": "Não", + "common.back": "Voltar", + "common.create": "Criar", + "common.okay": "Okay", + "common.accept": "Aceitar", + "common.disclaimer": "Aviso", + "common.cancel": "Cancelar", + "common.none": "Nenhum", + "common.error": "Erro", + "common.fatal_error": "Erro fatal", + + // Message when connection to the server is lost + "common.connection_lost": r#"Conexâo perdida! +Será que o server reiniciou? +O cliente está atualizado?"#, + + + "common.species.orc": "Ogre", + "common.species.human": "Humano", + "common.species.dwarf": "Anão", + "common.species.elf": "Elfo", + "common.species.undead": "Morto-vivo", + "common.species.danari": "Danari", + + "common.weapons.axe": "Machado", + "common.weapons.sword": "Espada", + "common.weapons.staff": "Cajado", + "common.weapons.bow": "Arco", + "common.weapons.hammer": "Martelo", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/pt_PT/esc_menu.ron b/assets/voxygen/i18n/pt_PT/esc_menu.ron new file mode 100644 index 0000000000..51a99240b7 --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/esc_menu.ron @@ -0,0 +1,13 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + "esc_menu.logout": "Desconectar", + "esc_menu.quit_game": "Sair do jogo", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/pt_PT/gameinput.ron b/assets/voxygen/i18n/pt_PT/gameinput.ron new file mode 100644 index 0000000000..960b221c7d --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/gameinput.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/pt_PT/hud/bag.ron b/assets/voxygen/i18n/pt_PT/hud/bag.ron new file mode 100644 index 0000000000..960b221c7d --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/hud/bag.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/pt_PT/hud/char_window.ron b/assets/voxygen/i18n/pt_PT/hud/char_window.ron new file mode 100644 index 0000000000..62bfce266c --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/hud/char_window.ron @@ -0,0 +1,19 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + "character_window.character_name": "Nome da personagem", + // Charater stats + "character_window.character_stats": r#"Resistência + +Aptidão fisíca + +Força de vontade +"#, + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/pt_PT/hud/chat.ron b/assets/voxygen/i18n/pt_PT/hud/chat.ron new file mode 100644 index 0000000000..960b221c7d --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/hud/chat.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/pt_PT/hud/crafting.ron b/assets/voxygen/i18n/pt_PT/hud/crafting.ron new file mode 100644 index 0000000000..960b221c7d --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/hud/crafting.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/pt_PT/hud/group.ron b/assets/voxygen/i18n/pt_PT/hud/group.ron new file mode 100644 index 0000000000..960b221c7d --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/hud/group.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/pt_PT/hud/hud_settings.ron b/assets/voxygen/i18n/pt_PT/hud/hud_settings.ron new file mode 100644 index 0000000000..bf19f4decb --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/hud/hud_settings.ron @@ -0,0 +1,141 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + "hud.settings.general": "Geral", + "hud.settings.none": "Nenhum", + "hud.settings.press_behavior.toggle": "Alternar", + "hud.settings.press_behavior.hold": "Segurar", + "hud.settings.help_window": "Janela de ajuda", + "hud.settings.debug_info": "Informação de depuração", + "hud.settings.tips_on_startup": "Dicas no início", + "hud.settings.ui_scale": "Escala da interface", + "hud.settings.relative_scaling": "Escala relativa", + "hud.settings.custom_scaling": "Escala customizada", + "hud.settings.crosshair": "Crosshair", + "hud.settings.transparency": "Transparência", + "hud.settings.hotbar": "Hotbar", + "hud.settings.toggle_shortcuts": "Mostar/Ocultar atalhos", + "hud.settings.toggle_bar_experience": "Mostar/Ocultar barra de experiência", + "hud.settings.scrolling_combat_text": "Texto de combate deslizante", + "hud.settings.single_damage_number": "Números de dano únicos", + "hud.settings.cumulated_damage": "Dano acumulado", + "hud.settings.incoming_damage": "Dano recebido", + "hud.settings.cumulated_incoming_damage": "Dano recebido acumulado", + "hud.settings.energybar_numbers": "Números da barra de energia", + "hud.settings.values": "Valores", + "hud.settings.percentages": "Percentagens", + "hud.settings.chat": "Chat", + "hud.settings.background_transparency": "Transparência do fundo", + + "hud.settings.pan_sensitivity": "Sensibilidade de rotação", + "hud.settings.zoom_sensitivity": "Sensibilidade de zoom", + "hud.settings.invert_scroll_zoom": "Inverter scroll zoom", + "hud.settings.invert_mouse_y_axis": "Inverter o eixo Y do mouse", + "hud.settings.free_look_behavior": "Ativação de rotação livre", + + "hud.settings.view_distance": "Alcance de visão", + "hud.settings.maximum_fps": "FPS máximo", + "hud.settings.fov": "Campo de visão(graus)", + "hud.settings.gamma": "Luminosidade", + "hud.settings.antialiasing_mode": "Modo de antialiasing", + "hud.settings.cloud_rendering_mode": "Modo de representação de nuvens", + "hud.settings.fluid_rendering_mode": "Modo de representação de fluídos", + "hud.settings.fluid_rendering_mode.cheap": "Barato", + "hud.settings.fluid_rendering_mode.shiny": "Brilhante", + "hud.settings.cloud_rendering_mode.regular": "Normal", + "hud.settings.fullscreen": "Tela cheia", + "hud.settings.save_window_size": "Gravar dimensões", + + "hud.settings.music_volume": "Volume da música", + "hud.settings.sound_effect_volume": "Volume dos efeitos sonoros", + "hud.settings.audio_device": "Dispositivo de aúdio", + + // Control list + "hud.settings.control_names": r#"Libertar mouse +Mostar/Ocultar janela de ajuda +Mostar/Ocultar interface +Mostar/Ocultar FPS e informação de depuração +Gravar captura de ecrã +Mostar/Ocultar nomes +Mostar/Ocultar tela cheia + + +Mover para frente +Mover para a esquerda +Mover para a direita +Mover para trás + +Saltar + +Planador + +Desviar + +Rolar + +Trepar + +Descer + +Auto caminhar + +Embainhar/sacar armas + +Equipar/remover capacete + +Sentar + +Montar + +Interagir + + +Ataque básico +Ataque/bloquear/apontar secundário + + +Habilidade 1 +Habilidade 2 +Habilidade 3 +Habilidade 4 +Habilidade 5 +Habilidade 6 +Habilidade 7 +Habilidade 8 +Habilidade 9 +Habilidade 10 + + +Menu de pausa +Definições +Social +Mapa +Livro de feitiços +Personagem +Registo de missões +Inventário + + + +Enviar mensagem de chat +Scroll chat + + +Comandos de chat: + +/alias [nome] - Mudar o seu nome de chat +/tp [nome] - Teletransporta-te para outro player +/jump - Deslocar a posição +/goto - Teletransporta-te para a posição +/kill - Suicidar +/pig - Invocar NPC de porco +/wolf - Invocar NPC do lobo +/help - Mostrar comandos de chat"#, + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/pt_PT/hud/map.ron b/assets/voxygen/i18n/pt_PT/hud/map.ron new file mode 100644 index 0000000000..960b221c7d --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/hud/map.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/pt_PT/hud/misc.ron b/assets/voxygen/i18n/pt_PT/hud/misc.ron new file mode 100644 index 0000000000..29609b4545 --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/hud/misc.ron @@ -0,0 +1,76 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + "hud.do_not_show_on_startup": "Não mostre no início", + "hud.show_tips": "Mostrar dicas", + "hud.quests": "Missões", + "hud.you_died": "Você Morreu", + + "hud.press_key_to_show_keybindings_fmt": "Clique em {key} para mostrar as teclas mapeadas", + "hud.press_key_to_show_debug_info_fmt": "Clique em {key} para mostrar a informação de depuração", + "hud.press_key_to_toggle_keybindings_fmt": "Clique em {key} para mostrar/ocultar as teclas mapeadas", + "hud.press_key_to_toggle_debug_info_fmt": "Clique em {key} para mostrar/ocultar a informação de depuração", + + // Respawn message + "hud.press_key_to_respawn": r#"Clique em {key} para renascer na última fogueira visitada."#, + + // Welcome message + "hud.welcome": r#"Bem vindo a Alpha do Veloren!, + + +Algumas dicas antes de começar: + + +MAIS IMPORTANTE: Para definir o seu local de renascimento escreva /waypoint no chat. + +Isto também pode ser realizado depois de morto! + + +Clique em F1 para ver as teclas mapeadas. + +Escreva /help no chat para ver os comandos de chat + + +A muitos baús e outros objetos a aperecer no mundo aleatoriamente! + +Pressione o botão direito do mouse pare coletá-los. + +Para usar o que coletou basta abrir o inventário pressionando a tecla 'B'. + +Faça duplo clique nos items para usá-los ou equipá-los. + +Deite-os fora cliquando uma vez neles e depois outra fora do inventário. + + +As noites podem ser bastante escuras. + +Acenda a lanterna escrevendo /lantern no chat. + + +Quer libertar o mouse para fechar esta janela? Clique em TAB! + + +Aprecie a sua estadia no mundo de Veloren."#, + +"hud.temp_quest_headline": r#"Please, help us Traveller!"#, +"hud.temp_quest_text": r#"Dungeons filled with evil cultists +have emerged all around our peaceful towns! + + +Gather some company, stack up on food +and defeat their vile leaders and acolytes. + + +Maybe you can even obtain one of their +magically infused items?"#, + "hud.spell": "Feitiço", + + "hud.free_look_indicator": "Rotação livre ativada", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/pt_PT/hud/sct.ron b/assets/voxygen/i18n/pt_PT/hud/sct.ron new file mode 100644 index 0000000000..960b221c7d --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/hud/sct.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/pt_PT/hud/skills.ron b/assets/voxygen/i18n/pt_PT/hud/skills.ron new file mode 100644 index 0000000000..960b221c7d --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/hud/skills.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/pt_PT/hud/social.ron b/assets/voxygen/i18n/pt_PT/hud/social.ron new file mode 100644 index 0000000000..19cbd644cb --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/hud/social.ron @@ -0,0 +1,18 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + "hud.social": "Social", + "hud.social.online": "Online", + "hud.social.friends": "Amigos", + "hud.social.not_yet_available": "Indisponível de momento", + "hud.social.faction": "Facção", + "hud.social.play_online_fmt": "{nb_player} jogador(es) online", + }, + + + vector_map: { + } +) + diff --git a/assets/voxygen/i18n/pt_PT/hud/trade.ron b/assets/voxygen/i18n/pt_PT/hud/trade.ron new file mode 100644 index 0000000000..3439af4b30 --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/hud/trade.ron @@ -0,0 +1,12 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + }, + + + vector_map: { + } +) + diff --git a/assets/voxygen/i18n/pt_PT/main.ron b/assets/voxygen/i18n/pt_PT/main.ron new file mode 100644 index 0000000000..2cb5ed45d4 --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/main.ron @@ -0,0 +1,58 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + "main.connecting": "Conectando", + "main.creating_world": "Criando o mundo", + + // Welcome notice that appears the first time Veloren is started + "main.notice": r#"Bem vindo a versão alpha de Veloren! + +Antes de começar a jogar, por favor tenha em mente que: + +- Isto é uma versão muito experimental. Prepare-se para defeitos, jogabilidade muito inacabada, mecanismos por polir e funcionalidades por +adicionar. +- Se tiver comentários construtivos ou defeitos para reportar, pode contactar-nos através do Reddit, GitLab ou o nosso servidor comunitário de +Discord. +- Veloren está licenciado sob a licensa código aberto GPL 3. Isto significa que pode jogar, modificar e redistribuir como quiser + (Contanto que o trabalho derivado seja também GPL 3). +- Veloren é um projeto comunitário sem lucro, e toda a gente que trabalha nele é um voluntário. Se gostar do que ve, considere juntar-se a equipa +de desenvolvimento ou a de artes! +- 'Voxel RPG' é um género em si mesmo. First-person shooters costumavam ser chamados de clones do DOOM. + +Tal como eles, nós estamos a tentar construir um género. Este jogo não é um clone e o seu desenvolvimento vai divergir de jogos existentes no +futuro. + +Obrigado por ler este aviso, nós esperamos que goste do jogo! + +~ A equipa do Veloren"#, + + // Login process description + "main.login_process": r#"Informação sobre o processo de Login: + +Se tiver problemas a logar: + +Tenha em atenção que é necessário uma conta +para jogar em servidores com autenticação. + +Para criar uma conta navegue até + +https://veloren.net/account/."#, + "main.login.server_not_found": "Servidor não encontrado", + "main.login.authentication_error": "Erro de autenticação", + "main.login.server_full": "Servidor está cheio", + "main.login.untrusted_auth_server": "Server de autenticação não confiado", + "main.login.outdated_client_or_server": "Servidor endoideceu: Provavelmente as versões são incompativéis, verifique se há versões mais recentes.", + "main.login.timeout": "Tempo esgotado: O servidor não respondeu a tempo. (Sobrecarregado ou problemas de rede).", + "main.login.server_shut_down": "O servidor encerrou", + "main.login.network_error": "Error de rede", + "main.login.failed_sending_request": "Pedido ao servidor de autenticação falhou", + "main.login.client_crashed": "O cliente crashou", + "main.login.select_language": "Seleccione uma língua", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/vi_VI/_manifest.ron b/assets/voxygen/i18n/vi_VI/_manifest.ron index b5ee1a57d1..b5ad2c8fc7 100644 --- a/assets/voxygen/i18n/vi_VI/_manifest.ron +++ b/assets/voxygen/i18n/vi_VI/_manifest.ron @@ -32,124 +32,11 @@ string_map: { /// Start Common section - // Texts used in multiple locations with the same formatting - "common.username": "Tên tài khoản", - "common.singleplayer": "Chơi đơn", - "common.multiplayer": "Chơi mạng", - "common.servers": "Máy chủ", - "common.quit": "Bỏ cuộc", - "common.settings": "Cài đặt", - "common.languages": "Ngôn ngữ", - "common.interface": "Giao diện", - "common.gameplay": "Lối chơi", - "common.controls": "Điều khiển", - "common.video": "Đồ họa", - "common.sound": "Âm thanh", - "common.resume": "Tiếp tục", - "common.characters": "Nhân vật", - "common.close": "Đóng", - "common.yes": "Đúng", - "common.no": "Không", - "common.back": "Trở lại", - "common.create": "Tạo nên", - "common.okay": "Được", - "common.add": "Thêm vào", - "common.accept": "Chấp nhận", - "common.decline": "Từ chối", - "common.disclaimer": "Khước từ", - "common.cancel": "Hủy bỏ", - "common.none": "Không còn", - "common.error": "Lỗi", - "common.fatal_error": "Lỗi nghiêm trọng", - "common.you": "Bạn", - "common.automatic": "Tự động", - "common.random": "Ngẫu nhiên", - - // Settings Window title - "common.interface_settings": "Cài đặt giao diện", - "common.gameplay_settings": "Cài đặt chế độ chơi", - "common.controls_settings": "Cài đặt điều khiển", - "common.video_settings": "Cài đặt hình ảnh", - "common.sound_settings": "Cài đặt âm thanh", - "common.language_settings": "Cài đặt ngôn ngữ", - // Message when connection to the server is lost - "common.connection_lost": r#"Mất mạng! -Máy chủ có khởi động lại không? -Trò chơi có được cập nhật không?"#, - - - "common.species.orc": "Loài orc", - "common.species.human": "Loài người", - "common.species.dwarf": "Quỷ lùn", - "common.species.elf": "Yêu tinh", - "common.species.undead": "Xác sống", - "common.species.danari": "Loài Danari", - - "common.weapons.axe": "Rìu", - "common.weapons.sword": "Kiếm", - "common.weapons.staff": "Ba toong", - "common.weapons.bow": "Cung", - "common.weapons.hammer": "Búa", - "common.weapons.general": "Chiến đấu chung", - "common.weapons.sceptre": "Quyền trượng chữa bệnh", - "common.rand_appearance": "Sự xuất hiện ngẫu nhiên và tên", /// End Common section /// Start Main screen section - "main.username": "Tên tài khoản", - "main.server": "Máy chủ", - "main.password": "Mật khẩu", - "main.connecting": "Đang kết nối", - "main.creating_world": "Đang tạo thế giới mới", - "main.tip": "Lời khuyên:", - // Welcome notice that appears the first time Veloren is started - "main.notice": r#"Chào mừng đến với phiên bản alpha của Veloren! - -Trước khi bạn nhảy trong vào Veloren, bạn phải nhớ những điều này: - -- Đây là một alpha rất sớm. Mong đợi lỗi chương trình, trò chơi cực kỳ chưa hoàn thành, cơ khí chưa hoàn thành, và tính năng bị thiếu. - -- Nếu bạn có phản hồi hoặc là báo cáo lỗi máy tính, liên hệ chúng tôi trên Reddit, GitLab, hoặc là máy chủ Discord của chúng tôi. - -- Veloren được cấp phép theo GPL 3 open-source licence. Đó có nghĩa là bạn được phép chơi miễn phí, sửa đổi, và phân phối lại trò chơi theo cách bạn muốn (miễn là công việc bắt nguồn cũng cấp phép theo GPL 3). - -- Veloren là một dự án cộng đồng phi lợi nhuận, và mọi người đang làm việc đó là một tình nguyện viên. Nếu bạn thích những gì bạn đang thấy, Chúng tôi mời bạn vô đội phát triển hoặc nghệ thuật! - -Cảm ơn bạn đã dành thời gian đọc thông báo này, chúng tôi hy vọng bạn thích trò chơi này! - -~ The Veloren Devs"#, - - // Login process description - "main.login_process": r#"Thông tin về quá trình đăng nhập: - -Xin lưu ý rằng bây giờ bạn cần một tài khoản -để chơi trên máy chủ xác thực được kích hoạt. - -Bạn có thể tạo một tài khoản ở - - -https://veloren.net/account/."#, - "main.login.server_not_found": "Không tìm thấy được may chủ", - "main.login.authentication_error": "Lỗi xác thực trên máy chủ", - "main.login.server_full": "Máy chủ đầy rồi", - "main.login.untrusted_auth_server": "máy chủ xác thực không đáng tin cậy", - "main.login.outdated_client_or_server": "Máy chủ nổi khùng: - Có thể các phiên bản không tương thích, kiểm tra xem có cập nhật không.", - "main.login.timeout": "Hết giờ: máy chủ không phản hồi kịp thời. (quá tải hoặc lỗi mạng).", - "main.login.server_shut_down": "Máy chủ ngừng hoạt động", - "main.login.already_logged_in": "Bạn đã đăng nhập vào máy chủ rồi.", - "main.login.network_error": "lỗi mạng", - "main.login.failed_sending_request": "yêu cầu máy chủ ủy quyền không thành công", - "main.login.invalid_character": "Ký tự đã chọn không hợp lệ", - "main.login.client_crashed": "Trò chơi bị rơi", - "main.login.not_on_whitelist": "Bạn cần được quản trị viên chấp thuận để tham gia", - "main.login.banned": "Bạn đã bị cấm tại vì", - "main.login.kicked": "Bạn đã bị đá bởi vì", - "main.login.select_language": "Chọn một ngôn ngữ", - - "main.servers.select_server": "Chọn một máy chủ", /// End Main screen section }, diff --git a/assets/voxygen/i18n/vi_VI/buff.ron b/assets/voxygen/i18n/vi_VI/buff.ron new file mode 100644 index 0000000000..81584383c1 --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/buff.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/vi_VI/char_selection.ron b/assets/voxygen/i18n/vi_VI/char_selection.ron new file mode 100644 index 0000000000..ebc3ba6d98 --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/char_selection.ron @@ -0,0 +1,10 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + }, + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/vi_VI/common.ron b/assets/voxygen/i18n/vi_VI/common.ron new file mode 100644 index 0000000000..0081d6f554 --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/common.ron @@ -0,0 +1,73 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + // Texts used in multiple locations with the same formatting + "common.username": "Tên tài khoản", + "common.singleplayer": "Chơi đơn", + "common.multiplayer": "Chơi mạng", + "common.servers": "Máy chủ", + "common.quit": "Bỏ cuộc", + "common.settings": "Cài đặt", + "common.languages": "Ngôn ngữ", + "common.interface": "Giao diện", + "common.gameplay": "Lối chơi", + "common.controls": "Điều khiển", + "common.video": "Đồ họa", + "common.sound": "Âm thanh", + "common.resume": "Tiếp tục", + "common.characters": "Nhân vật", + "common.close": "Đóng", + "common.yes": "Đúng", + "common.no": "Không", + "common.back": "Trở lại", + "common.create": "Tạo nên", + "common.okay": "Được", + "common.add": "Thêm vào", + "common.accept": "Chấp nhận", + "common.decline": "Từ chối", + "common.disclaimer": "Khước từ", + "common.cancel": "Hủy bỏ", + "common.none": "Không còn", + "common.error": "Lỗi", + "common.fatal_error": "Lỗi nghiêm trọng", + "common.you": "Bạn", + "common.automatic": "Tự động", + "common.random": "Ngẫu nhiên", + + // Settings Window title + "common.interface_settings": "Cài đặt giao diện", + "common.gameplay_settings": "Cài đặt chế độ chơi", + "common.controls_settings": "Cài đặt điều khiển", + "common.video_settings": "Cài đặt hình ảnh", + "common.sound_settings": "Cài đặt âm thanh", + "common.language_settings": "Cài đặt ngôn ngữ", + + // Message when connection to the server is lost + "common.connection_lost": r#"Mất mạng! +Máy chủ có khởi động lại không? +Trò chơi có được cập nhật không?"#, + + + "common.species.orc": "Loài orc", + "common.species.human": "Loài người", + "common.species.dwarf": "Quỷ lùn", + "common.species.elf": "Yêu tinh", + "common.species.undead": "Xác sống", + "common.species.danari": "Loài Danari", + + "common.weapons.axe": "Rìu", + "common.weapons.sword": "Kiếm", + "common.weapons.staff": "Ba toong", + "common.weapons.bow": "Cung", + "common.weapons.hammer": "Búa", + "common.weapons.general": "Chiến đấu chung", + "common.weapons.sceptre": "Quyền trượng chữa bệnh", + "common.rand_appearance": "Sự xuất hiện ngẫu nhiên và tên", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/vi_VI/esc_menu.ron b/assets/voxygen/i18n/vi_VI/esc_menu.ron new file mode 100644 index 0000000000..81584383c1 --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/esc_menu.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/vi_VI/gameinput.ron b/assets/voxygen/i18n/vi_VI/gameinput.ron new file mode 100644 index 0000000000..81584383c1 --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/gameinput.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/vi_VI/hud/bag.ron b/assets/voxygen/i18n/vi_VI/hud/bag.ron new file mode 100644 index 0000000000..81584383c1 --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/hud/bag.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/vi_VI/hud/char_window.ron b/assets/voxygen/i18n/vi_VI/hud/char_window.ron new file mode 100644 index 0000000000..81584383c1 --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/hud/char_window.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/vi_VI/hud/chat.ron b/assets/voxygen/i18n/vi_VI/hud/chat.ron new file mode 100644 index 0000000000..81584383c1 --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/hud/chat.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/vi_VI/hud/crafting.ron b/assets/voxygen/i18n/vi_VI/hud/crafting.ron new file mode 100644 index 0000000000..81584383c1 --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/hud/crafting.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/vi_VI/hud/group.ron b/assets/voxygen/i18n/vi_VI/hud/group.ron new file mode 100644 index 0000000000..81584383c1 --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/hud/group.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/vi_VI/hud/hud_settings.ron b/assets/voxygen/i18n/vi_VI/hud/hud_settings.ron new file mode 100644 index 0000000000..92d3139b83 --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/hud/hud_settings.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for "global" English +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/vi_VI/hud/map.ron b/assets/voxygen/i18n/vi_VI/hud/map.ron new file mode 100644 index 0000000000..81584383c1 --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/hud/map.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/vi_VI/hud/misc.ron b/assets/voxygen/i18n/vi_VI/hud/misc.ron new file mode 100644 index 0000000000..81584383c1 --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/hud/misc.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/vi_VI/hud/sct.ron b/assets/voxygen/i18n/vi_VI/hud/sct.ron new file mode 100644 index 0000000000..81584383c1 --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/hud/sct.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/vi_VI/hud/skills.ron b/assets/voxygen/i18n/vi_VI/hud/skills.ron new file mode 100644 index 0000000000..81584383c1 --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/hud/skills.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/vi_VI/hud/social.ron b/assets/voxygen/i18n/vi_VI/hud/social.ron new file mode 100644 index 0000000000..71161e0b3a --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/hud/social.ron @@ -0,0 +1,12 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + }, + + + vector_map: { + } +) + diff --git a/assets/voxygen/i18n/vi_VI/hud/trade.ron b/assets/voxygen/i18n/vi_VI/hud/trade.ron new file mode 100644 index 0000000000..71161e0b3a --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/hud/trade.ron @@ -0,0 +1,12 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + }, + + + vector_map: { + } +) + diff --git a/assets/voxygen/i18n/vi_VI/main.ron b/assets/voxygen/i18n/vi_VI/main.ron new file mode 100644 index 0000000000..b7251f00ba --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/main.ron @@ -0,0 +1,64 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + "main.username": "Tên tài khoản", + "main.server": "Máy chủ", + "main.password": "Mật khẩu", + "main.connecting": "Đang kết nối", + "main.creating_world": "Đang tạo thế giới mới", + "main.tip": "Lời khuyên:", + + // Welcome notice that appears the first time Veloren is started + "main.notice": r#"Chào mừng đến với phiên bản alpha của Veloren! + +Trước khi bạn nhảy trong vào Veloren, bạn phải nhớ những điều này: + +- Đây là một alpha rất sớm. Mong đợi lỗi chương trình, trò chơi cực kỳ chưa hoàn thành, cơ khí chưa hoàn thành, và tính năng bị thiếu. + +- Nếu bạn có phản hồi hoặc là báo cáo lỗi máy tính, liên hệ chúng tôi trên Reddit, GitLab, hoặc là máy chủ Discord của chúng tôi. + +- Veloren được cấp phép theo GPL 3 open-source licence. Đó có nghĩa là bạn được phép chơi miễn phí, sửa đổi, và phân phối lại trò chơi theo cách bạn muốn (miễn là công việc bắt nguồn cũng cấp phép theo GPL 3). + +- Veloren là một dự án cộng đồng phi lợi nhuận, và mọi người đang làm việc đó là một tình nguyện viên. Nếu bạn thích những gì bạn đang thấy, Chúng tôi mời bạn vô đội phát triển hoặc nghệ thuật! + +Cảm ơn bạn đã dành thời gian đọc thông báo này, chúng tôi hy vọng bạn thích trò chơi này! + +~ The Veloren Devs"#, + + // Login process description + "main.login_process": r#"Thông tin về quá trình đăng nhập: + +Xin lưu ý rằng bây giờ bạn cần một tài khoản +để chơi trên máy chủ xác thực được kích hoạt. + +Bạn có thể tạo một tài khoản ở + + +https://veloren.net/account/."#, + "main.login.server_not_found": "Không tìm thấy được may chủ", + "main.login.authentication_error": "Lỗi xác thực trên máy chủ", + "main.login.server_full": "Máy chủ đầy rồi", + "main.login.untrusted_auth_server": "máy chủ xác thực không đáng tin cậy", + "main.login.outdated_client_or_server": "Máy chủ nổi khùng: + Có thể các phiên bản không tương thích, kiểm tra xem có cập nhật không.", + "main.login.timeout": "Hết giờ: máy chủ không phản hồi kịp thời. (quá tải hoặc lỗi mạng).", + "main.login.server_shut_down": "Máy chủ ngừng hoạt động", + "main.login.already_logged_in": "Bạn đã đăng nhập vào máy chủ rồi.", + "main.login.network_error": "lỗi mạng", + "main.login.failed_sending_request": "yêu cầu máy chủ ủy quyền không thành công", + "main.login.invalid_character": "Ký tự đã chọn không hợp lệ", + "main.login.client_crashed": "Trò chơi bị rơi", + "main.login.not_on_whitelist": "Bạn cần được quản trị viên chấp thuận để tham gia", + "main.login.banned": "Bạn đã bị cấm tại vì", + "main.login.kicked": "Bạn đã bị đá bởi vì", + "main.login.select_language": "Chọn một ngôn ngữ", + + "main.servers.select_server": "Chọn một máy chủ", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/zh_CN/template.ron b/assets/voxygen/i18n/zh_CN/template.ron deleted file mode 100644 index b6fd6b234d..0000000000 --- a/assets/voxygen/i18n/zh_CN/template.ron +++ /dev/null @@ -1,12 +0,0 @@ -/// WARNING: Localization files shall be saved in UTF-8 format without BOM - -/// 本地化 "Simplified Chinese" 简体中文 -( - string_map: { - - }, - - - vector_map: { - } -) diff --git a/assets/voxygen/i18n/zh_TW/_manifest.ron b/assets/voxygen/i18n/zh_TW/_manifest.ron index fa00cc01f4..1685caff4e 100644 --- a/assets/voxygen/i18n/zh_TW/_manifest.ron +++ b/assets/voxygen/i18n/zh_TW/_manifest.ron @@ -29,354 +29,16 @@ }, string_map: { /// Start Common section - // Texts used in multiple locations with the same formatting - "common.username": "帳號名稱", - "common.singleplayer": "單人模式", - "common.multiplayer": "多人模式", - "common.servers": "伺服器", - "common.quit": "退出", - "common.settings": "設定", - "common.languages": "語言", - "common.interface": "界面", - "common.gameplay": "遊戲", - "common.controls": "控制", - "common.video": "畫面", - "common.sound": "聲音", - "common.resume": "繼續", - "common.characters": "角色", - "common.close": "關閉", - "common.yes": "是", - "common.no": "否", - "common.back": "返回", - "common.create": "建立", - "common.okay": "好", - "common.accept": "接受", - "common.disclaimer": "免責聲明", - "common.cancel": "取消", - "common.none": "無", - "common.error": "錯誤", - "common.fatal_error": "致命錯誤", - // Message when connection to the server is lost - "common.connection_lost": r#"連線中斷! -檢查看看伺服器重啟了嗎? -客戶端有更新了嗎?"#, - - - "common.races.orc": "獸人", - "common.races.human": "人類", - "common.races.dwarf": "矮人", - "common.races.elf": "精靈", - "common.races.undead": "不死族", - "common.races.danari": "丹那利", - - "common.weapons.axe": "斧", - "common.weapons.sword": "劍", - "common.weapons.staff": "杖", - "common.weapons.bow": "弓", - "common.weapons.hammer": "鎚", /// End Common section /// Start Main screen section - "main.connecting": "連線中", - "main.creating_world": "生成世界中", - - // Welcome notice that appears the first time Veloren is started - "main.notice": r#"歡迎加入 Veloren alpha 版! - -在您開始享受遊戲之前,請注意一些事情: - -- 這是非常前期的 alpha 版本,您會遇到不少錯誤、未完成遊戲模式、未完善的遊戲機制以及缺失的功能。 -- 如鬼有建設性的意見回饋或是錯誤回報,可以上 Reddit、GitLab 或者我們的 Discord 伺服器。 -- Veloren 的授權條款是 GPL 3 open-source licence,也就是任何人都可以任意的遊玩、更改並重新發布遊戲(其衍生的專案也都是 GPL 3)。 -- Veloren 是個非營利的社群專案,任何人都是自願參預開發的。如果喜歡的話,歡迎加入開發與美術設計團隊。 -- 「Voxel RPG」是個專屬的類別,就像任何的第一人稱射擊遊戲以前都稱作 Doom 的複製品。 - -就像他們一樣,我們想要打造完美的作品,這不是款複製品遊戲,而此遊戲的開發將會讓未來的遊戲更加多元化。 - -感謝您的閱讀,我們祝您能享受遊戲! - -~ Veloren 開發人員"#, - - // Login process description - "main.login_process": r#"Information on the Login Process: - -If you are having issues signing in: - -Please note that you now need an account -to play on auth-enabled servers. - -You can create an account over at - -https://veloren.net/account/."#, - "main.login.server_not_found": "找不到伺服器", - "main.login.authentication_error": "伺服器認證錯誤", - "main.login.server_full": "伺服器已滿", - "main.login.untrusted_auth_server": "認證伺服器不可信", - "main.login.outdated_client_or_server": "伺服器錯誤:版本可能不相容,請檢查更新。", - "main.login.timeout": "逾時:伺服器無法即時回應(也許試過載或者網路問題)。", - "main.login.server_shut_down": "伺服器已關閉", - "main.login.network_error": "網路錯誤", - "main.login.failed_sending_request": "認證伺服器請求失敗", - "main.login.client_crashed": "客戶端崩潰", - "main.login.select_language": "选择一种语言 ", - /// End Main screen section /// Start HUD Section - "hud.do_not_show_on_startup": "開啟時不顯示這個", - "hud.show_tips": "顯示提示", - "hud.quests": "任務", - "hud.you_died": "死亡", - - "hud.press_key_to_show_keybindings_fmt": "按 {key} 以顯示按鍵設置", - "hud.press_key_to_show_debug_info_fmt": "按 {key} 以顯示除錯資訊", - "hud.press_key_to_toggle_keybindings_fmt": "按 {key} 以切換按鍵設置", - "hud.press_key_to_toggle_debug_info_fmt": "按 {key} 以切換除錯資訊", - // Respawn message - "hud.press_key_to_respawn": r#"按 {key} 以重生在上一個營火堆。"#, - - // Welcome message - "hud.welcome": r#"歡迎來到 Veloren Alpha 版, - - -以下是些開始前的提示: - - -最重要的提示:想設置重生點請在聊天欄輸入 /waypoint 。 - -就算死了也可以作! - - -按 F1 可以查看按鍵設置。 - -在聊天欄輸入 /help 可以查看聊天指令 - - -寶箱和物品會隨機重生在世界中! - -點擊右鍵能收集它們。 - -要真的使用收集到的物品,請按「B」開啟物品欄。 - -在背包中雙擊物品來使用或裝備它們。 - -要拋棄它們的話,可以按它們一次然後再點背包外面一次 - - -Veloren 半夜會特別暗。 - -在聊天欄輸入 /lantern 可以點亮提燈 - - -想要用滑鼠關閉這個視窗?請按 TAB! - - -祝您的 Veloren 旅途愉快。"#, - // Inventory - "hud.bag.inventory": "的物品欄", - "hud.bag.stats_title": "的狀態", - "hud.bag.exp": "經驗", - "hud.bag.armor": "護甲", - "hud.bag.stats": "狀態", - - // Map and Questlog - "hud.map.map_title": "地圖", - "hud.map.qlog_title": "任務", - - // Settings - "hud.settings.general": "一般", - "hud.settings.none": "無", - "hud.settings.press_behavior.toggle": "切換", - "hud.settings.press_behavior.hold": "按住", - "hud.settings.help_window": "協助視窗", - "hud.settings.debug_info": "除錯資訊", - "hud.settings.tips_on_startup": "開啟時顯示提示", - "hud.settings.ui_scale": "界面大小", - "hud.settings.relative_scaling": "相對大小", - "hud.settings.custom_scaling": "自訂大小", - "hud.settings.crosshair": "準星", - "hud.settings.transparency": "透明度", - "hud.settings.hotbar": "角色資訊", - "hud.settings.toggle_shortcuts": "顯示快捷鍵", - "hud.settings.toggle_bar_experience": "顯示經驗條", - "hud.settings.scrolling_combat_text": "戰鬥訊息", - "hud.settings.single_damage_number": "單一傷害", - "hud.settings.cumulated_damage": "累積傷害", - "hud.settings.incoming_damage": "所受傷害", - "hud.settings.cumulated_incoming_damage": "累積所受傷害", - "hud.settings.energybar_numbers": "能量條", - "hud.settings.values": "數字", - "hud.settings.percentages": "百分比", - "hud.settings.chat": "聊天欄", - "hud.settings.background_transparency": "背景透明度", - "hud.settings.none": "無", - - "hud.settings.pan_sensitivity": "滑鼠靈敏度", - "hud.settings.zoom_sensitivity": "縮放靈敏度", - "hud.settings.invert_scroll_zoom": "反轉滾輪縮放", - "hud.settings.invert_mouse_y_axis": "反轉 Y 軸", - "hud.settings.free_look_behavior": "自由視角", - - "hud.settings.view_distance": "視野距離", - "hud.settings.maximum_fps": "最高 FPS", - "hud.settings.fov": "視野", - "hud.settings.gamma": "Gamma", - "hud.settings.antialiasing_mode": "反鋸齒模式", - "hud.settings.cloud_rendering_mode": "雲朵渲染模式", - "hud.settings.fluid_rendering_mode": "流體渲染模式", - "hud.settings.fluid_rendering_mode.cheap": "簡單", - "hud.settings.fluid_rendering_mode.shiny": "閃爍", - "hud.settings.cloud_rendering_mode.regular": "一般", - "hud.settings.fullscreen": "全螢幕", - "hud.settings.save_window_size": "儲存螢幕大小", - - "hud.settings.music_volume": "音樂音量", - "hud.settings.sound_effect_volume": "音效音量", - "hud.settings.audio_device": "音訊設備", - - // Control list - "hud.settings.control_names": r#"顯示滑鼠 -切換協助視窗 -切換界面 -切換 FPS 與除錯資訊 -拍照 -切換名稱標籤 -切換全螢幕 - - -往前移動 -往左移動 -往右移動 -往後移動 - -跳躍 - -滑翔翼 - -閃避 - -翻滾 - -攀爬 - -往下攀爬 - -自動行走 - -收刀/拔出武器 - -戴上/卸下頭盔 - -坐下 - -騎乘 - -互動 - - -基本攻擊 -附屬攻擊/格檔/瞄準 - - -技能條欄位 1 -技能條欄位 2 -技能條欄位 3 -技能條欄位 4 -技能條欄位 5 -技能條欄位 6 -技能條欄位 7 -技能條欄位 8 -技能條欄位 9 -技能條欄位 10 - - -暫停選單 -設定 -社交 -地圖 -法術書 -角色 -任務日誌 -背包 - - - -傳送聊天訊息 -滾動聊天欄 - - -自由視角 - -聊天指令: - -/alias [Name] - 變更的聊天名稱 -/tp [Name] - 傳送到其他玩家 -/jump - 偏移自己的位置 -/goto - 傳送到指定位置 -/kill - 自殺 -/pig - 生成一隻豬 NPC -/wolf - 生成一隻狼 NPC -/help - 顯示聊天指令"#, - - "hud.social": "社交", - "hud.social.online": "線上", - "hud.social.friends": "朋友", - "hud.social.not_yet_available": "尚未開放", - "hud.social.faction": "陣營", - "hud.social.play_online_fmt": "{nb_player} 位朋友在線", - - "hud.spell": "法術", - - "hud.free_look_indicator": "進入自由視角中", - /// End HUD section - - - /// Start chracter selection section - "char_selection.delete_permanently": "永久刪除這個角色嗎?", - "char_selection.change_server": "變更伺服器", - "char_selection.enter_world": "進入世界", - "char_selection.logout": "登出", - "char_selection.create_new_charater": "建立心角色", - "char_selection.character_creation": "角色建立", - - "char_selection.human_default": "預設人類", - "char_selection.level_fmt": "等級 {level_nb}", - "char_selection.uncanny_valley": "怪異峽谷", - "char_selection.plains_of_uncertainty": "疑惑平原", - "char_selection.beard": "鬍鬚", - "char_selection.hair_style": "頭髮造型", - "char_selection.hair_color": "頭髮顏色", - "char_selection.chest_color": "上半身顏色", - "char_selection.eye_color": "眼睛顏色", - "char_selection.skin": "膚色", - "char_selection.eyebrows": "眉毛", - "char_selection.accessories": "飾品", - - /// End chracter selection section - - - /// Start character window section - "character_window.character_name": "角色名稱", - // Charater stats - "character_window.character_stats": r#"耐力 - -敏捷 - -法力 -"#, - - - /// Start character window section - - - /// Start Escape Menu Section - "esc_menu.logout": "登出", - "esc_menu.quit_game": "退出遊戲", - /// End Escape Menu Section }, vector_map: { diff --git a/assets/voxygen/i18n/zh_TW/buff.ron b/assets/voxygen/i18n/zh_TW/buff.ron new file mode 100644 index 0000000000..9942ee4a90 --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/buff.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/zh_TW/char_selection.ron b/assets/voxygen/i18n/zh_TW/char_selection.ron new file mode 100644 index 0000000000..10b01b0338 --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/char_selection.ron @@ -0,0 +1,29 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + "char_selection.delete_permanently": "永久刪除這個角色嗎?", + "char_selection.change_server": "變更伺服器", + "char_selection.enter_world": "進入世界", + "char_selection.logout": "登出", + "char_selection.create_new_charater": "建立心角色", + "char_selection.character_creation": "角色建立", + + "char_selection.human_default": "預設人類", + "char_selection.level_fmt": "等級 {level_nb}", + "char_selection.uncanny_valley": "怪異峽谷", + "char_selection.plains_of_uncertainty": "疑惑平原", + "char_selection.beard": "鬍鬚", + "char_selection.hair_style": "頭髮造型", + "char_selection.hair_color": "頭髮顏色", + "char_selection.chest_color": "上半身顏色", + "char_selection.eye_color": "眼睛顏色", + "char_selection.skin": "膚色", + "char_selection.eyebrows": "眉毛", + "char_selection.accessories": "飾品", + }, + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/zh_TW/common.ron b/assets/voxygen/i18n/zh_TW/common.ron new file mode 100644 index 0000000000..f1c412f57d --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/common.ron @@ -0,0 +1,57 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + // Texts used in multiple locations with the same formatting + "common.username": "帳號名稱", + "common.singleplayer": "單人模式", + "common.multiplayer": "多人模式", + "common.servers": "伺服器", + "common.quit": "退出", + "common.settings": "設定", + "common.languages": "語言", + "common.interface": "界面", + "common.gameplay": "遊戲", + "common.controls": "控制", + "common.video": "畫面", + "common.sound": "聲音", + "common.resume": "繼續", + "common.characters": "角色", + "common.close": "關閉", + "common.yes": "是", + "common.no": "否", + "common.back": "返回", + "common.create": "建立", + "common.okay": "好", + "common.accept": "接受", + "common.disclaimer": "免責聲明", + "common.cancel": "取消", + "common.none": "無", + "common.error": "錯誤", + "common.fatal_error": "致命錯誤", + + // Message when connection to the server is lost + "common.connection_lost": r#"連線中斷! +檢查看看伺服器重啟了嗎? +客戶端有更新了嗎?"#, + + + "common.races.orc": "獸人", + "common.races.human": "人類", + "common.races.dwarf": "矮人", + "common.races.elf": "精靈", + "common.races.undead": "不死族", + "common.races.danari": "丹那利", + + "common.weapons.axe": "斧", + "common.weapons.sword": "劍", + "common.weapons.staff": "杖", + "common.weapons.bow": "弓", + "common.weapons.hammer": "鎚", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/zh_TW/esc_menu.ron b/assets/voxygen/i18n/zh_TW/esc_menu.ron new file mode 100644 index 0000000000..306b0e99f4 --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/esc_menu.ron @@ -0,0 +1,13 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + "esc_menu.logout": "登出", + "esc_menu.quit_game": "退出遊戲", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/zh_TW/gameinput.ron b/assets/voxygen/i18n/zh_TW/gameinput.ron new file mode 100644 index 0000000000..9942ee4a90 --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/gameinput.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/zh_TW/hud/bag.ron b/assets/voxygen/i18n/zh_TW/hud/bag.ron new file mode 100644 index 0000000000..b7deda04c5 --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/hud/bag.ron @@ -0,0 +1,17 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + // Inventory + "hud.bag.inventory": "的物品欄", + "hud.bag.stats_title": "的狀態", + "hud.bag.exp": "經驗", + "hud.bag.armor": "護甲", + "hud.bag.stats": "狀態", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/zh_TW/hud/char_window.ron b/assets/voxygen/i18n/zh_TW/hud/char_window.ron new file mode 100644 index 0000000000..2b2c284546 --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/hud/char_window.ron @@ -0,0 +1,20 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + /// Start character window section + "character_window.character_name": "角色名稱", + // Charater stats + "character_window.character_stats": r#"耐力 + +敏捷 + +法力 +"#, + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/zh_TW/hud/chat.ron b/assets/voxygen/i18n/zh_TW/hud/chat.ron new file mode 100644 index 0000000000..9942ee4a90 --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/hud/chat.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/zh_TW/hud/crafting.ron b/assets/voxygen/i18n/zh_TW/hud/crafting.ron new file mode 100644 index 0000000000..9942ee4a90 --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/hud/crafting.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/zh_TW/hud/group.ron b/assets/voxygen/i18n/zh_TW/hud/group.ron new file mode 100644 index 0000000000..9942ee4a90 --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/hud/group.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/zh_TW/hud/hud_settings.ron b/assets/voxygen/i18n/zh_TW/hud/hud_settings.ron new file mode 100644 index 0000000000..49684bed11 --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/hud/hud_settings.ron @@ -0,0 +1,145 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + // Settings + "hud.settings.general": "一般", + "hud.settings.none": "無", + "hud.settings.press_behavior.toggle": "切換", + "hud.settings.press_behavior.hold": "按住", + "hud.settings.help_window": "協助視窗", + "hud.settings.debug_info": "除錯資訊", + "hud.settings.tips_on_startup": "開啟時顯示提示", + "hud.settings.ui_scale": "界面大小", + "hud.settings.relative_scaling": "相對大小", + "hud.settings.custom_scaling": "自訂大小", + "hud.settings.crosshair": "準星", + "hud.settings.transparency": "透明度", + "hud.settings.hotbar": "角色資訊", + "hud.settings.toggle_shortcuts": "顯示快捷鍵", + "hud.settings.toggle_bar_experience": "顯示經驗條", + "hud.settings.scrolling_combat_text": "戰鬥訊息", + "hud.settings.single_damage_number": "單一傷害", + "hud.settings.cumulated_damage": "累積傷害", + "hud.settings.incoming_damage": "所受傷害", + "hud.settings.cumulated_incoming_damage": "累積所受傷害", + "hud.settings.energybar_numbers": "能量條", + "hud.settings.values": "數字", + "hud.settings.percentages": "百分比", + "hud.settings.chat": "聊天欄", + "hud.settings.background_transparency": "背景透明度", + "hud.settings.none": "無", + + "hud.settings.pan_sensitivity": "滑鼠靈敏度", + "hud.settings.zoom_sensitivity": "縮放靈敏度", + "hud.settings.invert_scroll_zoom": "反轉滾輪縮放", + "hud.settings.invert_mouse_y_axis": "反轉 Y 軸", + "hud.settings.free_look_behavior": "自由視角", + + "hud.settings.view_distance": "視野距離", + "hud.settings.maximum_fps": "最高 FPS", + "hud.settings.fov": "視野", + "hud.settings.gamma": "Gamma", + "hud.settings.antialiasing_mode": "反鋸齒模式", + "hud.settings.cloud_rendering_mode": "雲朵渲染模式", + "hud.settings.fluid_rendering_mode": "流體渲染模式", + "hud.settings.fluid_rendering_mode.cheap": "簡單", + "hud.settings.fluid_rendering_mode.shiny": "閃爍", + "hud.settings.cloud_rendering_mode.regular": "一般", + "hud.settings.fullscreen": "全螢幕", + "hud.settings.save_window_size": "儲存螢幕大小", + + "hud.settings.music_volume": "音樂音量", + "hud.settings.sound_effect_volume": "音效音量", + "hud.settings.audio_device": "音訊設備", + + // Control list + "hud.settings.control_names": r#"顯示滑鼠 +切換協助視窗 +切換界面 +切換 FPS 與除錯資訊 +拍照 +切換名稱標籤 +切換全螢幕 + + +往前移動 +往左移動 +往右移動 +往後移動 + +跳躍 + +滑翔翼 + +閃避 + +翻滾 + +攀爬 + +往下攀爬 + +自動行走 + +收刀/拔出武器 + +戴上/卸下頭盔 + +坐下 + +騎乘 + +互動 + + +基本攻擊 +附屬攻擊/格檔/瞄準 + + +技能條欄位 1 +技能條欄位 2 +技能條欄位 3 +技能條欄位 4 +技能條欄位 5 +技能條欄位 6 +技能條欄位 7 +技能條欄位 8 +技能條欄位 9 +技能條欄位 10 + + +暫停選單 +設定 +社交 +地圖 +法術書 +角色 +任務日誌 +背包 + + + +傳送聊天訊息 +滾動聊天欄 + + +自由視角 + +聊天指令: + +/alias [Name] - 變更的聊天名稱 +/tp [Name] - 傳送到其他玩家 +/jump - 偏移自己的位置 +/goto - 傳送到指定位置 +/kill - 自殺 +/pig - 生成一隻豬 NPC +/wolf - 生成一隻狼 NPC +/help - 顯示聊天指令"#, + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/zh_TW/hud/map.ron b/assets/voxygen/i18n/zh_TW/hud/map.ron new file mode 100644 index 0000000000..21ac3c7015 --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/hud/map.ron @@ -0,0 +1,14 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + // Map and Questlog + "hud.map.map_title": "地圖", + "hud.map.qlog_title": "任務", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/zh_TW/hud/misc.ron b/assets/voxygen/i18n/zh_TW/hud/misc.ron new file mode 100644 index 0000000000..2bd08e3fb7 --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/hud/misc.ron @@ -0,0 +1,65 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + "hud.do_not_show_on_startup": "開啟時不顯示這個", + "hud.show_tips": "顯示提示", + "hud.quests": "任務", + "hud.you_died": "死亡", + + "hud.press_key_to_show_keybindings_fmt": "按 {key} 以顯示按鍵設置", + "hud.press_key_to_show_debug_info_fmt": "按 {key} 以顯示除錯資訊", + "hud.press_key_to_toggle_keybindings_fmt": "按 {key} 以切換按鍵設置", + "hud.press_key_to_toggle_debug_info_fmt": "按 {key} 以切換除錯資訊", + + // Respawn message + "hud.press_key_to_respawn": r#"按 {key} 以重生在上一個營火堆。"#, + + // Welcome message + "hud.welcome": r#"歡迎來到 Veloren Alpha 版, + + +以下是些開始前的提示: + + +最重要的提示:想設置重生點請在聊天欄輸入 /waypoint 。 + +就算死了也可以作! + + +按 F1 可以查看按鍵設置。 + +在聊天欄輸入 /help 可以查看聊天指令 + + +寶箱和物品會隨機重生在世界中! + +點擊右鍵能收集它們。 + +要真的使用收集到的物品,請按「B」開啟物品欄。 + +在背包中雙擊物品來使用或裝備它們。 + +要拋棄它們的話,可以按它們一次然後再點背包外面一次 + + +Veloren 半夜會特別暗。 + +在聊天欄輸入 /lantern 可以點亮提燈 + + +想要用滑鼠關閉這個視窗?請按 TAB! + + +祝您的 Veloren 旅途愉快。"#, + + + "hud.spell": "法術", + "hud.free_look_indicator": "進入自由視角中", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/zh_TW/hud/sct.ron b/assets/voxygen/i18n/zh_TW/hud/sct.ron new file mode 100644 index 0000000000..9942ee4a90 --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/hud/sct.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/zh_TW/hud/skills.ron b/assets/voxygen/i18n/zh_TW/hud/skills.ron new file mode 100644 index 0000000000..9942ee4a90 --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/hud/skills.ron @@ -0,0 +1,11 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/zh_TW/hud/social.ron b/assets/voxygen/i18n/zh_TW/hud/social.ron new file mode 100644 index 0000000000..109a665f9e --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/hud/social.ron @@ -0,0 +1,18 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + "hud.social": "社交", + "hud.social.online": "線上", + "hud.social.friends": "朋友", + "hud.social.not_yet_available": "尚未開放", + "hud.social.faction": "陣營", + "hud.social.play_online_fmt": "{nb_player} 位朋友在線", + }, + + + vector_map: { + } +) + diff --git a/assets/voxygen/i18n/zh_TW/hud/trade.ron b/assets/voxygen/i18n/zh_TW/hud/trade.ron new file mode 100644 index 0000000000..4feee7e25a --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/hud/trade.ron @@ -0,0 +1,12 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + }, + + + vector_map: { + } +) + diff --git a/assets/voxygen/i18n/zh_TW/main.ron b/assets/voxygen/i18n/zh_TW/main.ron new file mode 100644 index 0000000000..103ee284df --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/main.ron @@ -0,0 +1,53 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Traditional Chinese +( + string_map: { + "main.connecting": "連線中", + "main.creating_world": "生成世界中", + + // Welcome notice that appears the first time Veloren is started + "main.notice": r#"歡迎加入 Veloren alpha 版! + +在您開始享受遊戲之前,請注意一些事情: + +- 這是非常前期的 alpha 版本,您會遇到不少錯誤、未完成遊戲模式、未完善的遊戲機制以及缺失的功能。 +- 如鬼有建設性的意見回饋或是錯誤回報,可以上 Reddit、GitLab 或者我們的 Discord 伺服器。 +- Veloren 的授權條款是 GPL 3 open-source licence,也就是任何人都可以任意的遊玩、更改並重新發布遊戲(其衍生的專案也都是 GPL 3)。 +- Veloren 是個非營利的社群專案,任何人都是自願參預開發的。如果喜歡的話,歡迎加入開發與美術設計團隊。 +- 「Voxel RPG」是個專屬的類別,就像任何的第一人稱射擊遊戲以前都稱作 Doom 的複製品。 + +就像他們一樣,我們想要打造完美的作品,這不是款複製品遊戲,而此遊戲的開發將會讓未來的遊戲更加多元化。 + +感謝您的閱讀,我們祝您能享受遊戲! + +~ Veloren 開發人員"#, + + // Login process description + "main.login_process": r#"Information on the Login Process: + +If you are having issues signing in: + +Please note that you now need an account +to play on auth-enabled servers. + +You can create an account over at + +https://veloren.net/account/."#, + "main.login.server_not_found": "找不到伺服器", + "main.login.authentication_error": "伺服器認證錯誤", + "main.login.server_full": "伺服器已滿", + "main.login.untrusted_auth_server": "認證伺服器不可信", + "main.login.outdated_client_or_server": "伺服器錯誤:版本可能不相容,請檢查更新。", + "main.login.timeout": "逾時:伺服器無法即時回應(也許試過載或者網路問題)。", + "main.login.server_shut_down": "伺服器已關閉", + "main.login.network_error": "網路錯誤", + "main.login.failed_sending_request": "認證伺服器請求失敗", + "main.login.client_crashed": "客戶端崩潰", + "main.login.select_language": "选择一种语言 ", + }, + + + vector_map: { + } +) From bb026ca21bce9ed96f329a9d3d5e570b79f58135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Sun, 1 Aug 2021 12:47:35 +0200 Subject: [PATCH 036/155] move vector map out of manifest and switch to new manifest format --- assets/voxygen/i18n/cz_CZ/_manifest.ron | 172 +------------- assets/voxygen/i18n/cz_CZ/buff.ron | 2 +- assets/voxygen/i18n/cz_CZ/char_selection.ron | 2 +- assets/voxygen/i18n/cz_CZ/common.ron | 2 +- assets/voxygen/i18n/cz_CZ/esc_menu.ron | 2 +- assets/voxygen/i18n/cz_CZ/gameinput.ron | 2 +- assets/voxygen/i18n/cz_CZ/hud/bag.ron | 2 +- assets/voxygen/i18n/cz_CZ/hud/char_window.ron | 2 +- assets/voxygen/i18n/cz_CZ/hud/chat.ron | 2 +- assets/voxygen/i18n/cz_CZ/hud/crafting.ron | 2 +- assets/voxygen/i18n/cz_CZ/hud/group.ron | 2 +- .../voxygen/i18n/cz_CZ/hud/hud_settings.ron | 2 +- assets/voxygen/i18n/cz_CZ/hud/map.ron | 2 +- assets/voxygen/i18n/cz_CZ/hud/misc.ron | 2 +- assets/voxygen/i18n/cz_CZ/hud/sct.ron | 2 +- assets/voxygen/i18n/cz_CZ/hud/skills.ron | 2 +- assets/voxygen/i18n/cz_CZ/hud/social.ron | 2 +- assets/voxygen/i18n/cz_CZ/hud/trade.ron | 2 +- assets/voxygen/i18n/cz_CZ/main.ron | 23 +- assets/voxygen/i18n/cz_CZ/npc.ron | 152 +++++++++++++ assets/voxygen/i18n/de_DE/_manifest.ron | 200 ----------------- assets/voxygen/i18n/de_DE/main.ron | 21 ++ assets/voxygen/i18n/de_DE/npc.ron | 183 +++++++++++++++ assets/voxygen/i18n/en/_manifest.ron | 209 ------------------ assets/voxygen/i18n/en/main.ron | 22 ++ assets/voxygen/i18n/en/npc.ron | 190 ++++++++++++++++ assets/voxygen/i18n/es_ES/_manifest.ron | 199 ----------------- assets/voxygen/i18n/es_ES/main.ron | 23 ++ assets/voxygen/i18n/es_ES/npc.ron | 180 +++++++++++++++ assets/voxygen/i18n/es_LA/_manifest.ron | 108 --------- assets/voxygen/i18n/es_LA/main.ron | 20 ++ assets/voxygen/i18n/es_LA/npc.ron | 93 ++++++++ assets/voxygen/i18n/fr_FR/_manifest.ron | 193 ---------------- assets/voxygen/i18n/fr_FR/main.ron | 21 ++ assets/voxygen/i18n/fr_FR/npc.ron | 175 +++++++++++++++ assets/voxygen/i18n/hu_HU/_manifest.ron | 201 ----------------- assets/voxygen/i18n/hu_HU/main.ron | 22 ++ assets/voxygen/i18n/hu_HU/npc.ron | 183 +++++++++++++++ assets/voxygen/i18n/it_IT/_manifest.ron | 200 ----------------- assets/voxygen/i18n/it_IT/main.ron | 21 ++ assets/voxygen/i18n/it_IT/npc.ron | 183 +++++++++++++++ assets/voxygen/i18n/ja_JP/_manifest.ron | 195 ---------------- assets/voxygen/i18n/ja_JP/main.ron | 21 ++ assets/voxygen/i18n/ja_JP/npc.ron | 178 +++++++++++++++ assets/voxygen/i18n/nl_NL/_manifest.ron | 109 --------- assets/voxygen/i18n/nl_NL/main.ron | 21 ++ assets/voxygen/i18n/nl_NL/npc.ron | 93 ++++++++ assets/voxygen/i18n/no_NB/_manifest.ron | 108 --------- assets/voxygen/i18n/no_NB/main.ron | 21 ++ assets/voxygen/i18n/no_NB/npc.ron | 92 ++++++++ assets/voxygen/i18n/pl_PL/_manifest.ron | 196 +--------------- assets/voxygen/i18n/pl_PL/main.ron | 21 ++ assets/voxygen/i18n/pl_PL/npc.ron | 175 +++++++++++++++ assets/voxygen/i18n/pt_BR/_manifest.ron | 201 ----------------- assets/voxygen/i18n/pt_BR/main.ron | 21 ++ assets/voxygen/i18n/pt_BR/npc.ron | 184 +++++++++++++++ assets/voxygen/i18n/pt_PT/_manifest.ron | 5 - assets/voxygen/i18n/pt_PT/npc.ron | 12 + assets/voxygen/i18n/ru_RU/_manifest.ron | 201 ----------------- assets/voxygen/i18n/ru_RU/main.ron | 21 ++ assets/voxygen/i18n/ru_RU/npc.ron | 184 +++++++++++++++ assets/voxygen/i18n/sv_SE/_manifest.ron | 201 ----------------- assets/voxygen/i18n/sv_SE/main.ron | 22 ++ assets/voxygen/i18n/sv_SE/npc.ron | 183 +++++++++++++++ assets/voxygen/i18n/tr_TR/_manifest.ron | 108 --------- assets/voxygen/i18n/tr_TR/main.ron | 20 ++ assets/voxygen/i18n/tr_TR/npc.ron | 92 ++++++++ assets/voxygen/i18n/uk_UA/_manifest.ron | 175 --------------- assets/voxygen/i18n/uk_UA/main.ron | 21 ++ assets/voxygen/i18n/uk_UA/npc.ron | 158 +++++++++++++ assets/voxygen/i18n/vi_VI/_manifest.ron | 118 ---------- assets/voxygen/i18n/vi_VI/main.ron | 24 ++ assets/voxygen/i18n/vi_VI/npc.ron | 92 ++++++++ assets/voxygen/i18n/zh_CN/_manifest.ron | 200 ----------------- assets/voxygen/i18n/zh_CN/main.ron | 21 ++ assets/voxygen/i18n/zh_CN/npc.ron | 183 +++++++++++++++ assets/voxygen/i18n/zh_TW/_manifest.ron | 19 +- assets/voxygen/i18n/zh_TW/npc.ron | 10 + voxygen/i18n/src/lib.rs | 8 +- 79 files changed, 3405 insertions(+), 3337 deletions(-) create mode 100644 assets/voxygen/i18n/cz_CZ/npc.ron create mode 100644 assets/voxygen/i18n/de_DE/npc.ron create mode 100644 assets/voxygen/i18n/en/npc.ron create mode 100644 assets/voxygen/i18n/es_ES/npc.ron create mode 100644 assets/voxygen/i18n/es_LA/npc.ron create mode 100644 assets/voxygen/i18n/fr_FR/npc.ron create mode 100644 assets/voxygen/i18n/hu_HU/npc.ron create mode 100644 assets/voxygen/i18n/it_IT/npc.ron create mode 100644 assets/voxygen/i18n/ja_JP/npc.ron create mode 100644 assets/voxygen/i18n/nl_NL/npc.ron create mode 100644 assets/voxygen/i18n/no_NB/npc.ron create mode 100644 assets/voxygen/i18n/pl_PL/npc.ron create mode 100644 assets/voxygen/i18n/pt_BR/npc.ron create mode 100644 assets/voxygen/i18n/pt_PT/npc.ron create mode 100644 assets/voxygen/i18n/ru_RU/npc.ron create mode 100644 assets/voxygen/i18n/sv_SE/npc.ron create mode 100644 assets/voxygen/i18n/tr_TR/npc.ron create mode 100644 assets/voxygen/i18n/uk_UA/npc.ron create mode 100644 assets/voxygen/i18n/vi_VI/npc.ron create mode 100644 assets/voxygen/i18n/zh_CN/npc.ron create mode 100644 assets/voxygen/i18n/zh_TW/npc.ron diff --git a/assets/voxygen/i18n/cz_CZ/_manifest.ron b/assets/voxygen/i18n/cz_CZ/_manifest.ron index 7af0195d63..38530e96b1 100644 --- a/assets/voxygen/i18n/cz_CZ/_manifest.ron +++ b/assets/voxygen/i18n/cz_CZ/_manifest.ron @@ -1,4 +1,4 @@ -/// Localization for Polish / Tłumaczenia dla języka polskiego +/// Localization for Čeština ( metadata: ( language_name: "Czech", @@ -26,173 +26,5 @@ asset_key: "voxygen.font.OpenSans-Regular", scale_ratio: 1.0, ), - }, - string_map: { - }, - - vector_map: { -"loading.tips": [ - "Stisknutím G rozsvítíš svou lucernu.", - "Stisknutím klávesy 'F1' zobrazíš všechny výchozí klávesy.", - "Můžetš použít /say nebo /s pro chat pouze s hráči přímo kolem vás.", - "Můžeš napsat /region nebo /r pro chat s hráči pát stovek bloků od vás.", - "Admini mohou napsat /build příkaz pro spuštění Stavívího Módu.", - "Můžeš napsat /group nebo /g pro chat s vaší Skupinou.", - "Pro posílání privátních zpráv napiš /tell poté jméno hráce a zprávu.", - "Dávej si pozor na jídlo, truhly a jiný kořisti rozmístěné po celém světě!", - "Inventář plný jídla? Zkus vytvořit z toho lepší jídlo!", - "Přemýšlíš co dělat? Zkus nějakou Kobku označenou na mapě!", - "Nezapomeň si nastavit Grafiku pro svůj systém. Klávesou 'N' otevřeš Nastavení.", - "Hraní s hráči je zábava! Klávesou 'O' se podívej kdo je Online.", - "Klávesou 'J' začneš Tancovat. Párty!", - "Klávesou 'L-Shift' otevřeš Kluzák a můžeš dobýt nebesa.", - "Veloren je stále v Pre-Alpha. Snažíme se hru zlepšit co to jde!", - "Jestli se chceš napojit k dev teamu nebo jen si napsat, připoj se na náš Discord server.", - "Můžeš povolit zobrazení tvého životu v healthbaru v Nastavení.", - "Sedni si k Táboráku (Klávesa 'K') pro pomalé léčení.", - "Potřebuješ více tašek, či lepší zbroj pro vaše dobrodrušství? Klávesou 'C' otevřeš nabídku Tvorby!", - ], - "npc.speech.villager": [ - "Není dnes tak překrásný den?", - "Jak se dneska máš?", - "Dobré ráno!", - "Zajímalo by mě, co si Catoblepové myslí, když jí trávu.", - "Co si myslíš o tomto počasí?", - "Přemýšlení o těchto kobkách mě děsí. Doufám, že je někdo vyčistí.", - "Rád bych šel prozkoumávat jeskyni, až budu silnější.", - "Neviděl si moji kočku?", - "Už si někdy slyšel o divokých Pozemních Žralocích? Slyšel jsem, že žijí v pouštích.", - "Říká se, že v jeskyních se nacházejí lesklé drahokamy všeho druhu.", - "Jsem jen o sýrovích šušenkách!", - "Nepůjdeš dovnitř? Právě jsem si chtěl dát sýr!", - "Říká se, že houby jsou dobré pro vaše zdraví. Nikdy jsem je neměl.", - "Nezapomeňte na sušenky!", - "Prostě zbožňuji trpasličí sýr. Přál bych si, abych ho uměl dělat.", - "Zajímalo by mě, co je na druhé straně hor.", - "Doufám, že si někdy vyrobím vlastní kluzák.", - "Chceš vidět moji zahradu? Dobře, možná někdy jindy.", - "Krásný den na procházku do lesa!", - "Být či nebýt? Myslím, že budu farmář.", - "Nemyslíš si, že naše vesnice je nejlepší?", - "Co podle vás září v Glowing Remains?", - "Myslím, že je čas na druhou snídani!", - "Už si někdy chytil světlušku?", - "Prostě nechápu, odkud ti Saurokové stále přicházejí.", - "Přál bych si, aby někdo držel vlky daleko od vesnice.", - "Minulou noc jsem měl nádherný sen o sýru. Co to znamená?", - "Nechal jsem trochu sýra s bratrem osamotě. Teď nevím, jestli existuje nebo ne. Říkám tomu Schrödingerův sýr.", - "Nechal jsem trochu sýra se setrou osamotě. Teď nevím, jestli existuje nebo ne. Říkám tomu Schrödingerův sýr.", - "Někdo by měl s těmi kultisty něco udělat. Nejlepší kdyý já ne.", - "Doufám, že brzy bude pršet. Bylo by to dobré pro plodiny.", - "Miluji med! A nesnáším včely.", - "Chci jednoho dne vidět svět. Musí tu být více života než v této vesnici.", - ], - "npc.speech.villager_cultist_alarm": [ - "Bacha! Je tu kultista!", - "Do zbroje! Kultisti útočí!", - "Jak se Kultisti opovážli útočit na naší vesnici!", - "Smrt kultistům!", - "Kultisti tu nejsou tolerováni!", - "Vražední Kultisti!", - "Ochutnej mojí čepel Kultisto", - "Nic nedokáže vyčistit krev na tvých rukách Kultisto!", - "Billions of blistering blue barnacles! A cultist among us!", - "Zlo tohoto Kultisty je ukonce!", - "Tento Kultista je můj!", - "Připrav se potkat svého Stvořitele blbý Kultisto!", - "Vidím Kultistu! Na něj!", - "Vidím Kultistu! Útok!", - "Vidím Kultistu! Nenech je utéct!", - "Uvažoval někdy úctiví Kultitsta o SMRŤI?!", - "Nikdy neodpustit! Nikdy nezapomenout! Kultista bude pikat!", - "Umři Kultisto!", - "Tvů začátek chaosu bude u konce!", - "Tady je vše za to, co si udělal!", - "Nejsme moc přátelští k lidem tvého druhu.", - "Měl si zůstat v podzemí!", - ], - "npc.speech.villager_under_attack": [ - "Pomoc, jsem pod útokem!", - "Pomoc! Jsem pod útokem!", - "Au! Jsem pod útokem!", - "Auh! Jsem pod útokem! Pomoc!", - "Pomoc! Jsem pod útokem!", - "Jsem pod útokem, Pomoc!", - "Jsem pod útokem! Pomoc!", - "Pomoc!", - "Pomoc! Pomoc!", - "Pomoc! Pomoc! Pomoc!", - "Jsem pod útokem!", - "AAAHHH! Jsem pod útokem!", - "AAAHHH! Jsem pod útokem! Pomoc!", - "Pomoc! Jseme pod útokem!", - "Pomoc! Vrah!", - "Pomoc! Je tu vrah!", - "Pomoc! Snaží se mě zabít!", - "Stráže, Jsem pod útokem!", - "Stráže! Jsem pod útokem!", - "Jsem pod útokem! Stráže!", - "Pomoc! Stráže! Jsem pod útokem!", - "Stráže! Rychle!", - "Stráže! Stráže!", - "Stráže! Padouch na mě útočí!", - "Stráže, zabte tohoto padoucha!", - "Stráže! Je tu vrah!", - "Stráže! Pomoc!", - "S tím neutečeš jen tak! Stráže!", - "Příteli!", - "Pomoc !", - "Pomoc! Prosím!", - "Ouch! Stráže! Pomoc!", - "Jdou po mě!", - "Pomoc! Pomoc! Snaží se mě utlačit!", - "Ah, teď vidíme násilí v systému", - "Tohle je jen škrábnutí!", - "Nech toho!", - "Co jsem ti provedl?!", - "Prosím přestaň na mě útočit!", - "Hey! Dávej bacha co s tím děláš!", - "Hajze, zmiz!", - "Dost! Jdi do háje!", - "Teď mě štveš!", - "Oi! Co si myslíš že jsi?!", - "Tak teď chci tvojí hlavu!", - "Přestaň, Prosím! Nemám nic u sebe ceného!", - "Pošlu na tebe bratra, je větší než já!", - "Neeee, já půjdu žalovat matce!", - "Proklínám tě!", - "Prosím nedělej to.", - "Toto nebylo pěkné!", - "Tvá zbraň funguje, teď vypadni", - "Ušetři mě!", - "Prosím, mám rodinu!", - "Jsem moc mladý, abych umřel!", - "Můžeme si o tom promluvit?", - "Násilí není nikdy odpověď!", - "Dnešek bude pěkně na nic...", - "Hey, to bolí!", - "Eek!", - "Jak hnusný!", - "Stop, prosím tě!", - "A pox upon you!", - "Tohle není sranda.", - "Jak se opovažuješ?!", - "Za to zaplatíš!", - "Ještě chvilku porkačuj a budeš toho litovat!", - "Nechtěj, abych tě zranil!", - "To musí být omyl!", - "Nepotřebuješ toto dělat!", - "Vypdni kamaráda!", - "To opravdu bolelo!", - "Proč bys to dělal?", - "ve jménu ducha svatého, vypadni!", - "Musel si se splést!", - "To si nezasloužím!", - "Prosím, nedělej to znova.", - "Stráže, hoďte toto monstrum do jezera!", - "vypustím na tebe Tarasque!", - "Proč jáááá?", - ], - - }, + } ) diff --git a/assets/voxygen/i18n/cz_CZ/buff.ron b/assets/voxygen/i18n/cz_CZ/buff.ron index 4f8a6f8f01..a9e2d9cc8f 100644 --- a/assets/voxygen/i18n/cz_CZ/buff.ron +++ b/assets/voxygen/i18n/cz_CZ/buff.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { // Buffs diff --git a/assets/voxygen/i18n/cz_CZ/char_selection.ron b/assets/voxygen/i18n/cz_CZ/char_selection.ron index 92608387fa..7d9dd2ab01 100644 --- a/assets/voxygen/i18n/cz_CZ/char_selection.ron +++ b/assets/voxygen/i18n/cz_CZ/char_selection.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { "char_selection.loading_characters": "Načítání postavy...", diff --git a/assets/voxygen/i18n/cz_CZ/common.ron b/assets/voxygen/i18n/cz_CZ/common.ron index a89b149269..d1f690bcd0 100644 --- a/assets/voxygen/i18n/cz_CZ/common.ron +++ b/assets/voxygen/i18n/cz_CZ/common.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { // Texts used in multiple locations with the same formatting diff --git a/assets/voxygen/i18n/cz_CZ/esc_menu.ron b/assets/voxygen/i18n/cz_CZ/esc_menu.ron index e3b27c71a7..f219600d73 100644 --- a/assets/voxygen/i18n/cz_CZ/esc_menu.ron +++ b/assets/voxygen/i18n/cz_CZ/esc_menu.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { "esc_menu.logout": "Odhlásit", diff --git a/assets/voxygen/i18n/cz_CZ/gameinput.ron b/assets/voxygen/i18n/cz_CZ/gameinput.ron index 0a46dd928a..2d2e337ef3 100644 --- a/assets/voxygen/i18n/cz_CZ/gameinput.ron +++ b/assets/voxygen/i18n/cz_CZ/gameinput.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { "gameinput.primary": "Základní Útok", diff --git a/assets/voxygen/i18n/cz_CZ/hud/bag.ron b/assets/voxygen/i18n/cz_CZ/hud/bag.ron index 0f124dcbb3..aa61261425 100644 --- a/assets/voxygen/i18n/cz_CZ/hud/bag.ron +++ b/assets/voxygen/i18n/cz_CZ/hud/bag.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { // Inventory diff --git a/assets/voxygen/i18n/cz_CZ/hud/char_window.ron b/assets/voxygen/i18n/cz_CZ/hud/char_window.ron index 0bb5977f09..f0506e82b6 100644 --- a/assets/voxygen/i18n/cz_CZ/hud/char_window.ron +++ b/assets/voxygen/i18n/cz_CZ/hud/char_window.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { /// Start character window section diff --git a/assets/voxygen/i18n/cz_CZ/hud/chat.ron b/assets/voxygen/i18n/cz_CZ/hud/chat.ron index d630f34e6c..83bb7da283 100644 --- a/assets/voxygen/i18n/cz_CZ/hud/chat.ron +++ b/assets/voxygen/i18n/cz_CZ/hud/chat.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { "hud.chat.online_msg": "[{name}] je online", diff --git a/assets/voxygen/i18n/cz_CZ/hud/crafting.ron b/assets/voxygen/i18n/cz_CZ/hud/crafting.ron index 42bd9cc4e0..a1662ebe10 100644 --- a/assets/voxygen/i18n/cz_CZ/hud/crafting.ron +++ b/assets/voxygen/i18n/cz_CZ/hud/crafting.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { "hud.crafting": "Výroba", diff --git a/assets/voxygen/i18n/cz_CZ/hud/group.ron b/assets/voxygen/i18n/cz_CZ/hud/group.ron index 62e496b1a7..f9cfb73264 100644 --- a/assets/voxygen/i18n/cz_CZ/hud/group.ron +++ b/assets/voxygen/i18n/cz_CZ/hud/group.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { "hud.group": "Skupina", diff --git a/assets/voxygen/i18n/cz_CZ/hud/hud_settings.ron b/assets/voxygen/i18n/cz_CZ/hud/hud_settings.ron index 3244bafc62..a5cfb49d07 100644 --- a/assets/voxygen/i18n/cz_CZ/hud/hud_settings.ron +++ b/assets/voxygen/i18n/cz_CZ/hud/hud_settings.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { // Settings diff --git a/assets/voxygen/i18n/cz_CZ/hud/map.ron b/assets/voxygen/i18n/cz_CZ/hud/map.ron index 347327577e..96b68fae6e 100644 --- a/assets/voxygen/i18n/cz_CZ/hud/map.ron +++ b/assets/voxygen/i18n/cz_CZ/hud/map.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { // Map and Questlog diff --git a/assets/voxygen/i18n/cz_CZ/hud/misc.ron b/assets/voxygen/i18n/cz_CZ/hud/misc.ron index 32d330c9fa..54c050c0eb 100644 --- a/assets/voxygen/i18n/cz_CZ/hud/misc.ron +++ b/assets/voxygen/i18n/cz_CZ/hud/misc.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { }, diff --git a/assets/voxygen/i18n/cz_CZ/hud/sct.ron b/assets/voxygen/i18n/cz_CZ/hud/sct.ron index 32d330c9fa..54c050c0eb 100644 --- a/assets/voxygen/i18n/cz_CZ/hud/sct.ron +++ b/assets/voxygen/i18n/cz_CZ/hud/sct.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { }, diff --git a/assets/voxygen/i18n/cz_CZ/hud/skills.ron b/assets/voxygen/i18n/cz_CZ/hud/skills.ron index 542c4c501d..723f1191dd 100644 --- a/assets/voxygen/i18n/cz_CZ/hud/skills.ron +++ b/assets/voxygen/i18n/cz_CZ/hud/skills.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { // General diff --git a/assets/voxygen/i18n/cz_CZ/hud/social.ron b/assets/voxygen/i18n/cz_CZ/hud/social.ron index 721d48c464..1a5f5f09ee 100644 --- a/assets/voxygen/i18n/cz_CZ/hud/social.ron +++ b/assets/voxygen/i18n/cz_CZ/hud/social.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { /// Socialní diff --git a/assets/voxygen/i18n/cz_CZ/hud/trade.ron b/assets/voxygen/i18n/cz_CZ/hud/trade.ron index c40c8d6228..c3a9f86c0d 100644 --- a/assets/voxygen/i18n/cz_CZ/hud/trade.ron +++ b/assets/voxygen/i18n/cz_CZ/hud/trade.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { /// Obchod diff --git a/assets/voxygen/i18n/cz_CZ/main.ron b/assets/voxygen/i18n/cz_CZ/main.ron index 42cb2c172a..ce6f65bfd6 100644 --- a/assets/voxygen/i18n/cz_CZ/main.ron +++ b/assets/voxygen/i18n/cz_CZ/main.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for Polish +/// Localization for Čeština ( string_map: { /// Start Main screen section @@ -63,5 +63,26 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "Stisknutím G rozsvítíš svou lucernu.", + "Stisknutím klávesy 'F1' zobrazíš všechny výchozí klávesy.", + "Můžetš použít /say nebo /s pro chat pouze s hráči přímo kolem vás.", + "Můžeš napsat /region nebo /r pro chat s hráči pát stovek bloků od vás.", + "Admini mohou napsat /build příkaz pro spuštění Stavívího Módu.", + "Můžeš napsat /group nebo /g pro chat s vaší Skupinou.", + "Pro posílání privátních zpráv napiš /tell poté jméno hráce a zprávu.", + "Dávej si pozor na jídlo, truhly a jiný kořisti rozmístěné po celém světě!", + "Inventář plný jídla? Zkus vytvořit z toho lepší jídlo!", + "Přemýšlíš co dělat? Zkus nějakou Kobku označenou na mapě!", + "Nezapomeň si nastavit Grafiku pro svůj systém. Klávesou 'N' otevřeš Nastavení.", + "Hraní s hráči je zábava! Klávesou 'O' se podívej kdo je Online.", + "Klávesou 'J' začneš Tancovat. Párty!", + "Klávesou 'L-Shift' otevřeš Kluzák a můžeš dobýt nebesa.", + "Veloren je stále v Pre-Alpha. Snažíme se hru zlepšit co to jde!", + "Jestli se chceš napojit k dev teamu nebo jen si napsat, připoj se na náš Discord server.", + "Můžeš povolit zobrazení tvého životu v healthbaru v Nastavení.", + "Sedni si k Táboráku (Klávesa 'K') pro pomalé léčení.", + "Potřebuješ více tašek, či lepší zbroj pro vaše dobrodrušství? Klávesou 'C' otevřeš nabídku Tvorby!", + ], } ) diff --git a/assets/voxygen/i18n/cz_CZ/npc.ron b/assets/voxygen/i18n/cz_CZ/npc.ron new file mode 100644 index 0000000000..06ee417757 --- /dev/null +++ b/assets/voxygen/i18n/cz_CZ/npc.ron @@ -0,0 +1,152 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Čeština +( + string_map: { + }, + + vector_map: { + "npc.speech.villager": [ + "Není dnes tak překrásný den?", + "Jak se dneska máš?", + "Dobré ráno!", + "Zajímalo by mě, co si Catoblepové myslí, když jí trávu.", + "Co si myslíš o tomto počasí?", + "Přemýšlení o těchto kobkách mě děsí. Doufám, že je někdo vyčistí.", + "Rád bych šel prozkoumávat jeskyni, až budu silnější.", + "Neviděl si moji kočku?", + "Už si někdy slyšel o divokých Pozemních Žralocích? Slyšel jsem, že žijí v pouštích.", + "Říká se, že v jeskyních se nacházejí lesklé drahokamy všeho druhu.", + "Jsem jen o sýrovích šušenkách!", + "Nepůjdeš dovnitř? Právě jsem si chtěl dát sýr!", + "Říká se, že houby jsou dobré pro vaše zdraví. Nikdy jsem je neměl.", + "Nezapomeňte na sušenky!", + "Prostě zbožňuji trpasličí sýr. Přál bych si, abych ho uměl dělat.", + "Zajímalo by mě, co je na druhé straně hor.", + "Doufám, že si někdy vyrobím vlastní kluzák.", + "Chceš vidět moji zahradu? Dobře, možná někdy jindy.", + "Krásný den na procházku do lesa!", + "Být či nebýt? Myslím, že budu farmář.", + "Nemyslíš si, že naše vesnice je nejlepší?", + "Co podle vás září v Glowing Remains?", + "Myslím, že je čas na druhou snídani!", + "Už si někdy chytil světlušku?", + "Prostě nechápu, odkud ti Saurokové stále přicházejí.", + "Přál bych si, aby někdo držel vlky daleko od vesnice.", + "Minulou noc jsem měl nádherný sen o sýru. Co to znamená?", + "Nechal jsem trochu sýra s bratrem osamotě. Teď nevím, jestli existuje nebo ne. Říkám tomu Schrödingerův sýr.", + "Nechal jsem trochu sýra se setrou osamotě. Teď nevím, jestli existuje nebo ne. Říkám tomu Schrödingerův sýr.", + "Někdo by měl s těmi kultisty něco udělat. Nejlepší kdyý já ne.", + "Doufám, že brzy bude pršet. Bylo by to dobré pro plodiny.", + "Miluji med! A nesnáším včely.", + "Chci jednoho dne vidět svět. Musí tu být více života než v této vesnici.", + ], + "npc.speech.villager_cultist_alarm": [ + "Bacha! Je tu kultista!", + "Do zbroje! Kultisti útočí!", + "Jak se Kultisti opovážli útočit na naší vesnici!", + "Smrt kultistům!", + "Kultisti tu nejsou tolerováni!", + "Vražední Kultisti!", + "Ochutnej mojí čepel Kultisto", + "Nic nedokáže vyčistit krev na tvých rukách Kultisto!", + "Billions of blistering blue barnacles! A cultist among us!", + "Zlo tohoto Kultisty je ukonce!", + "Tento Kultista je můj!", + "Připrav se potkat svého Stvořitele blbý Kultisto!", + "Vidím Kultistu! Na něj!", + "Vidím Kultistu! Útok!", + "Vidím Kultistu! Nenech je utéct!", + "Uvažoval někdy úctiví Kultitsta o SMRŤI?!", + "Nikdy neodpustit! Nikdy nezapomenout! Kultista bude pikat!", + "Umři Kultisto!", + "Tvů začátek chaosu bude u konce!", + "Tady je vše za to, co si udělal!", + "Nejsme moc přátelští k lidem tvého druhu.", + "Měl si zůstat v podzemí!", + ], + "npc.speech.villager_under_attack": [ + "Pomoc, jsem pod útokem!", + "Pomoc! Jsem pod útokem!", + "Au! Jsem pod útokem!", + "Auh! Jsem pod útokem! Pomoc!", + "Pomoc! Jsem pod útokem!", + "Jsem pod útokem, Pomoc!", + "Jsem pod útokem! Pomoc!", + "Pomoc!", + "Pomoc! Pomoc!", + "Pomoc! Pomoc! Pomoc!", + "Jsem pod útokem!", + "AAAHHH! Jsem pod útokem!", + "AAAHHH! Jsem pod útokem! Pomoc!", + "Pomoc! Jseme pod útokem!", + "Pomoc! Vrah!", + "Pomoc! Je tu vrah!", + "Pomoc! Snaží se mě zabít!", + "Stráže, Jsem pod útokem!", + "Stráže! Jsem pod útokem!", + "Jsem pod útokem! Stráže!", + "Pomoc! Stráže! Jsem pod útokem!", + "Stráže! Rychle!", + "Stráže! Stráže!", + "Stráže! Padouch na mě útočí!", + "Stráže, zabte tohoto padoucha!", + "Stráže! Je tu vrah!", + "Stráže! Pomoc!", + "S tím neutečeš jen tak! Stráže!", + "Příteli!", + "Pomoc !", + "Pomoc! Prosím!", + "Ouch! Stráže! Pomoc!", + "Jdou po mě!", + "Pomoc! Pomoc! Snaží se mě utlačit!", + "Ah, teď vidíme násilí v systému", + "Tohle je jen škrábnutí!", + "Nech toho!", + "Co jsem ti provedl?!", + "Prosím přestaň na mě útočit!", + "Hey! Dávej bacha co s tím děláš!", + "Hajze, zmiz!", + "Dost! Jdi do háje!", + "Teď mě štveš!", + "Oi! Co si myslíš že jsi?!", + "Tak teď chci tvojí hlavu!", + "Přestaň, Prosím! Nemám nic u sebe ceného!", + "Pošlu na tebe bratra, je větší než já!", + "Neeee, já půjdu žalovat matce!", + "Proklínám tě!", + "Prosím nedělej to.", + "Toto nebylo pěkné!", + "Tvá zbraň funguje, teď vypadni", + "Ušetři mě!", + "Prosím, mám rodinu!", + "Jsem moc mladý, abych umřel!", + "Můžeme si o tom promluvit?", + "Násilí není nikdy odpověď!", + "Dnešek bude pěkně na nic...", + "Hey, to bolí!", + "Eek!", + "Jak hnusný!", + "Stop, prosím tě!", + "A pox upon you!", + "Tohle není sranda.", + "Jak se opovažuješ?!", + "Za to zaplatíš!", + "Ještě chvilku porkačuj a budeš toho litovat!", + "Nechtěj, abych tě zranil!", + "To musí být omyl!", + "Nepotřebuješ toto dělat!", + "Vypdni kamaráda!", + "To opravdu bolelo!", + "Proč bys to dělal?", + "ve jménu ducha svatého, vypadni!", + "Musel si se splést!", + "To si nezasloužím!", + "Prosím, nedělej to znova.", + "Stráže, hoďte toto monstrum do jezera!", + "vypustím na tebe Tarasque!", + "Proč jáááá?", + ], + + }, +) diff --git a/assets/voxygen/i18n/de_DE/_manifest.ron b/assets/voxygen/i18n/de_DE/_manifest.ron index 509da15753..155ae923be 100644 --- a/assets/voxygen/i18n/de_DE/_manifest.ron +++ b/assets/voxygen/i18n/de_DE/_manifest.ron @@ -28,205 +28,5 @@ asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", scale_ratio: 1.0, ), - }, - - string_map: { - - }, - - vector_map: { - "loading.tips": [ - "Mit 'G' aktivierst du deine Laterne.", - "Mit 'F1' kannst du die Standard-Tastenbelegung einsehen.", - "Mit /say oder /s kannst du mit Spielern in deiner unmittelbaren Umgebung chatten.", - "Mit /region oder /r kannst du mit Spielern chatten, die sich ein paar hundert Meter um dich herum befinden.", - "Als Admin kannst du mit /build den Baumodus nutzen.", - "Mit /group oder /g können deine Nachrichten nur von Mitgliedern deiner Gruppe gelesen werden.", - "Um private Nachrichten zu verschicken, kannst du /tell, gefolgt vom Namen des Spielers, der die Nachricht erhalten soll, nutzen.", - "Halte Ausschau nach Essen, Kisten oder anderen Schätzen überall auf der Welt!", - "Deine Taschen sind voll mit Essen? Versuche besseres Essen damit herzustellen!", - "Du weißt nicht was du tun sollst? Versuche dich doch mal an den Katakomben, die auf der Karte eingezeichnet sind!", - "Vergiss nicht die Grafikeinstellungen an deine Hardware anzupassen. Mit 'N' öffnest du die Grafikeinstellungen.", - "Mit Anderen zusammen zu spielen macht noch viel mehr Spaß! Mit 'O' kannst du sehen, wer gerade online ist.", - "Mit 'J' kannst du das Tanzbein schwingen. Party!", - "Mit 'L-Shift' kannst du den Gleiter öffnen und hohe Lüfte erobern.", - "Veloren ist immernoch in der Pre-Alpha. Wir tun unser Bestes, um es jeden Tag ein Stück besser zu machen!", - "Du möchtest aktiv an der Entwicklung mitwirken oder einfach nur chatten? Dann komm auf unseren Discord-Server.", - "Die Art, wie dir deine Lebensenergie angezeigt wird, kannst du in den Einstellungen ändern.", - "Setze dich neben ein Lagerfeuer (drücke dafür 'K') um dich langsam von deinen Verletzungen zu erholen.", - "Du brauchst einen größeren Beutel oder bessere Rüstung? Dann drücke 'C', um das Crafting-Menü zu öffnen!", - ], - "npc.speech.villager": [ - "Ist das nicht ein wunderbarer Tag?", - "Wie geht's dir heute?", - "Einen schönen guten Morgen wünsche ich dir!", - "Ich frage mich, was der Catoblepas denkt, wenn er Gras isst.", - "Was hälst du vom Wetter?", - "Wenn ich an die Katakomben denke, bekomme ich Angst. Ich hoffe jemand befreit sie vom Unheil.", - "Ich würde gerne in eine der Höhlen gehen, wenn ich größer und stärker bin.", - "Hast du meine Katze gesehen?", - "Hast du schonmal etwas von den gefährlichen Landhaien gehört? Ich habe gehört sie leben in der Wüste.", - "Man sagt, es gebe Juwelen aller Art in den Höhlen der Gegend.", - "Ich bin einfach verrückt nach Käse!", - "Möchtest du nicht rein kommen? Bei uns gibt es gleich himmlischen Käse!", - "Man sagt Pilze seien gut für die Gesundheit. Ich selber habe noch nie welche gegessen.", - "Vergiss dein Feuerwerk nicht!", - "Ich liebe Zwergenkäse einfach. Ich wünschte, ich könnte selber welchen herstellen.", - "Ich frage mich, was sich auf der anderen Seite der Berge verbirgt.", - "Ich wünschte, ich könnte mir eines Tages meinen eigenen Gleiter bauen.", - "Möchtest du dir mal meinen Garten ansehen? Okay, vielleicht beim nächsten Mal.", - "Ein perfekter Tag, um in den Wald zu gehen!", - "Sein oder nicht sein? Ich glaube ich werde Landwirt.", - "Findest du nicht auch, dass unser Dorf das schönste ist?", - "Was glaubst du, was glühende Überreste zum Glühen bringt?", - "Ich glaube es ist an der Zeit für ein zweites Frühstück!", - "Hast du jemals ein Glühwürmchen gefangen?", - "Ich verstehe einfach nicht wo die ganzen Sauroks herkommen.", - "Ich wünschte, jemand könnte die ganzen Wölfe vom Dorf fernhalten.", - "Ich hatte letzte Nacht einen wunderbaren Traum über Käse. Was könnte das bedeuten?", - "Ich habe meinem Bruder ein wenig Käse dagelassen. Nun weiß ich nicht, ob er ihn schon aß oder nicht. Ich nenne es Schrödingers Käse.", - "Ich habe meiner Schwester ein wenig Käse dagelassen. Nun weiß ich nicht, ob sie ihn schon aß oder nicht. Ich nenne es Schrödingers Käse.", - "Jemand sollte etwas gegen diese Kultisten unternehmen. Vorzugsweise nicht ich.", - "Ich hoffe es regnet bald wieder. Der Ernte würde es gut tun.", - "Ich liebe Honig! Und hasse Bienen.", - "Eines Tages möchte ich die Welt bereisen. Es muss doch mehr im Leben geben als dieses Dorf.", - ], - "npc.speech.villager_decline_trade": [ - "Tut mir leid, ich habe nichts, was ich mit dir handeln könnte.", - "Du möchtest handeln? Als ob ich etwas hätte, das dich interessieren könnte.", - "Mein Haus gehört mir, ich würde es für nichts auf der Welt hergeben.", - ], - "npc.speech.merchant_advertisement": [ - "Darf ich dir einen Handel vorschlagen?", - "Möchtest du mit mir handeln?", - "Ich habe viele Waren. Möchtest du sie dir mal ansehen?" - ], - "npc.speech.merchant_busy": [ - "Hey, warte bis du an der Reihe bist.", - "Einen Moment bitte, ich kann mich nicht zerteilen.", - "Siehst du nicht, dass jemand vor dir steht?", - "Einen Moment bitte, ich bin gleich bei dir.", - "Nicht vordrängeln bitte.", - "Ich bin gerade beschäftigt, komm doch später wieder." - ], - "npc.speech.merchant_trade_successful": [ - "Vielen Dank für das Geschäft!", - "Vielen Dank!", - ], - "npc.speech.merchant_trade_declined": [ - "Vielleicht beim nächsten Mal, einen schönen Tag noch!", - "Zu schade, vielleicht beim nächsten mal, bis dann!" - ], - "npc.speech.villager_cultist_alarm": [ - "Achtung! Ein Kultist schleicht hier herum!", - "Zu den Waffen! Die Kultisten attackieren uns!", - "Wie können die Kultisten es wagen, unser Dorf zu attackieren!", - "Tod den Kultisten!", - "Kultisten werden hier nicht toleriert!", - "Mörderischer Kultist!", - "Eine Kostprobe meines Schwertes gefällig? Du reudiger Kultist!", - "Nichts kann das Blut von deinen Händen waschen, Kultist!", - "Ja brat' mir doch einer 'nen Storch! Ein Kultist weilt unter uns!", - "Die Schreckensherrschaft der Kultisten wird bald vorrüber sein!", - "Der Kultist gehört mir!", - "Bereite dich darauf vor deinem Schöpfer gegenüberzutreten, du mieser Kultist!", - "Ich sehe einen Kultisten! Ergreift ihn!", - "Ich sehe einen Kultisten!", - "Ich sehe einen Kultisten! Lasst ihn nicht entkommen!", - "Ist der ehrenwerte Kultist an ein wenig TOD interessiert?!", - "Wir vergeben nicht! Wir vergessen nicht! Kultist, büße!", - "Stirb, Kultist!", - "Deine Schreckensherrschaft wird enden!", - "Nimm das! Für alles, was du getan hast!", - "Wir wollen Abschaum wie euch hier nicht!", - "Du hättest unter der Erde bleiben sollen! Da wo du hingehörst!", - ], - "npc.speech.villager_under_attack": [ - "Hilfe, ich werde angegriffen!", - "Hilfe, ich werde angegriffen!", - "Autsch! ich werde angegriffen!", - "Autsch! ich werde angegriffen! Hilfe!", - "Helft mir! Ich werde angegriffen!", - "Ich werde angegriffen! Hilfe!", - "Ich werde angegriffen! Helft mir!", - "Hilfe!", - "Hilfe! Hilfe!", - "Hilfe! Hilfe! Hilfe!", - "Ich werde angegriffen!", - "AAAHHH! Ich werde angegriffen!", - "AAAHHH! Ich werde angegriffen! So helft mir doch!", - "Hilfe! Wir werden angegriffen!", - "Hilfe! Mörder!", - "Hilfe! Ein Mörder läuft frei herum!", - "Hilfe! Man versucht, mich zu töten!", - "Wachen, ich werde angegriffen!", - "Wachen! Ich werde angegriffen!", - "Ich werde angegriffen! Wachen!", - "Hilfe! Wachen! Ich werde angegriffen!", - "Wachen! Kommt schnell!", - "Wachen! Wachen!", - "Wachen! Ein Schurke attackiert mich!", - "Wachen, erschlagt diesen üblen Schurken!", - "Wachen! Ein Mörder!", - "Wachen! Helft mir!", - "Damit wirst du nicht davonkommen! Wachen!", - "Du Unmensch!", - "Helft mir!", - "Helft mir! Bitte!", - "Autsch! Wachen! Hilfe!", - "Sie kommen, um mich zu holen!", - "Hilfe! Hilfe! Ich werde angefeindet!", - "Ah, jetzt sehen wir die Gewalt, die dem System innewohnt.", - "Ach nur'n Kratzer!", - "Hört auf!", - "Was habe ich euch angetan?!", - "Bitte, hört auf mich anzugreifen!", - "Hey! Pass auf wo du mit dem Ding hinziehlst!", - "Abscheulicher Schuft, hinfort mit dir!", - "Halt! Verzieh dich!", - "Du bringst mich noch zur Weißglut!", - "Oi! Was denkst du wer du bist?!", - "Dafür reiße ich dir den Kopf ab!", - "Stop, bitte! Ich habe nichts wertvolles bei mir!", - "Ich setze meinen Bruder auf dich an, er ist größer als ich!", - "Neiiiin, das erzähle ich meiner Mutter!", - "Verflucht seist du!", - "Bitte, tu's nicht.", - "Das war nicht sehr nett von dir!", - "Deine Waffe erfüllt ihren Zweck, du kannst sie jetzt wegstecken!", - "Verschone mich!", - "Bitte, ich habe Familie!", - "Ich bin zu jung zum sterben!", - "Können wir darüber reden?", - "Gewalt ist keine Lösung!", - "Der heutige Tag entwickelt sich zu einem sehr schlechten Tag...", - "Hey, das tat weh!", - "AAAAHHH!", - "Wie rüpelhaft!", - "Stop, ich flehe dich an!", - "Ein Fluch soll dich heimsuchen!", - "Das ist nicht lustig.", - "Wie könnt Ihr es wagen?!", - "Dafür wirst du bezahlen!", - "Mach weiter so und es wird dir leid tun!", - "Zwing mich nicht, dir weh zu tun!", - "Das muss ein Missverständnis sein!", - "Du musst das nicht tun!", - "Fort mit dir, Schurke!", - "Das hat echt wehgetan!", - "Warum tust du das?", - "Bei den Göttern, hört auf!", - "Du musst mich mit jemand anderem verwechseln!", - "Ich verdiene das nicht!", - "Bitte, tu das nicht nochmal.", - "Wachen, in den Kerker mit diesem Schuft!", - "Ich werde meinen Tarasque auf dich hetzen!", - "Warum iiiich?", - ], - "npc.speech.villager_enemy_killed": [ - "Ich habe den Feind vernichtet!", - "Endlich Frieden!", - "... also, wo war ich stehengeblieben?", - ] } ) diff --git a/assets/voxygen/i18n/de_DE/main.ron b/assets/voxygen/i18n/de_DE/main.ron index eadf4766a8..154bca3479 100644 --- a/assets/voxygen/i18n/de_DE/main.ron +++ b/assets/voxygen/i18n/de_DE/main.ron @@ -66,5 +66,26 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "Mit 'G' aktivierst du deine Laterne.", + "Mit 'F1' kannst du die Standard-Tastenbelegung einsehen.", + "Mit /say oder /s kannst du mit Spielern in deiner unmittelbaren Umgebung chatten.", + "Mit /region oder /r kannst du mit Spielern chatten, die sich ein paar hundert Meter um dich herum befinden.", + "Als Admin kannst du mit /build den Baumodus nutzen.", + "Mit /group oder /g können deine Nachrichten nur von Mitgliedern deiner Gruppe gelesen werden.", + "Um private Nachrichten zu verschicken, kannst du /tell, gefolgt vom Namen des Spielers, der die Nachricht erhalten soll, nutzen.", + "Halte Ausschau nach Essen, Kisten oder anderen Schätzen überall auf der Welt!", + "Deine Taschen sind voll mit Essen? Versuche besseres Essen damit herzustellen!", + "Du weißt nicht was du tun sollst? Versuche dich doch mal an den Katakomben, die auf der Karte eingezeichnet sind!", + "Vergiss nicht die Grafikeinstellungen an deine Hardware anzupassen. Mit 'N' öffnest du die Grafikeinstellungen.", + "Mit Anderen zusammen zu spielen macht noch viel mehr Spaß! Mit 'O' kannst du sehen, wer gerade online ist.", + "Mit 'J' kannst du das Tanzbein schwingen. Party!", + "Mit 'L-Shift' kannst du den Gleiter öffnen und hohe Lüfte erobern.", + "Veloren ist immernoch in der Pre-Alpha. Wir tun unser Bestes, um es jeden Tag ein Stück besser zu machen!", + "Du möchtest aktiv an der Entwicklung mitwirken oder einfach nur chatten? Dann komm auf unseren Discord-Server.", + "Die Art, wie dir deine Lebensenergie angezeigt wird, kannst du in den Einstellungen ändern.", + "Setze dich neben ein Lagerfeuer (drücke dafür 'K') um dich langsam von deinen Verletzungen zu erholen.", + "Du brauchst einen größeren Beutel oder bessere Rüstung? Dann drücke 'C', um das Crafting-Menü zu öffnen!", + ], } ) diff --git a/assets/voxygen/i18n/de_DE/npc.ron b/assets/voxygen/i18n/de_DE/npc.ron new file mode 100644 index 0000000000..64dcbda40b --- /dev/null +++ b/assets/voxygen/i18n/de_DE/npc.ron @@ -0,0 +1,183 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Germany German +( + string_map: { + + }, + + vector_map: { + "npc.speech.villager": [ + "Ist das nicht ein wunderbarer Tag?", + "Wie geht's dir heute?", + "Einen schönen guten Morgen wünsche ich dir!", + "Ich frage mich, was der Catoblepas denkt, wenn er Gras isst.", + "Was hälst du vom Wetter?", + "Wenn ich an die Katakomben denke, bekomme ich Angst. Ich hoffe jemand befreit sie vom Unheil.", + "Ich würde gerne in eine der Höhlen gehen, wenn ich größer und stärker bin.", + "Hast du meine Katze gesehen?", + "Hast du schonmal etwas von den gefährlichen Landhaien gehört? Ich habe gehört sie leben in der Wüste.", + "Man sagt, es gebe Juwelen aller Art in den Höhlen der Gegend.", + "Ich bin einfach verrückt nach Käse!", + "Möchtest du nicht rein kommen? Bei uns gibt es gleich himmlischen Käse!", + "Man sagt Pilze seien gut für die Gesundheit. Ich selber habe noch nie welche gegessen.", + "Vergiss dein Feuerwerk nicht!", + "Ich liebe Zwergenkäse einfach. Ich wünschte, ich könnte selber welchen herstellen.", + "Ich frage mich, was sich auf der anderen Seite der Berge verbirgt.", + "Ich wünschte, ich könnte mir eines Tages meinen eigenen Gleiter bauen.", + "Möchtest du dir mal meinen Garten ansehen? Okay, vielleicht beim nächsten Mal.", + "Ein perfekter Tag, um in den Wald zu gehen!", + "Sein oder nicht sein? Ich glaube ich werde Landwirt.", + "Findest du nicht auch, dass unser Dorf das schönste ist?", + "Was glaubst du, was glühende Überreste zum Glühen bringt?", + "Ich glaube es ist an der Zeit für ein zweites Frühstück!", + "Hast du jemals ein Glühwürmchen gefangen?", + "Ich verstehe einfach nicht wo die ganzen Sauroks herkommen.", + "Ich wünschte, jemand könnte die ganzen Wölfe vom Dorf fernhalten.", + "Ich hatte letzte Nacht einen wunderbaren Traum über Käse. Was könnte das bedeuten?", + "Ich habe meinem Bruder ein wenig Käse dagelassen. Nun weiß ich nicht, ob er ihn schon aß oder nicht. Ich nenne es Schrödingers Käse.", + "Ich habe meiner Schwester ein wenig Käse dagelassen. Nun weiß ich nicht, ob sie ihn schon aß oder nicht. Ich nenne es Schrödingers Käse.", + "Jemand sollte etwas gegen diese Kultisten unternehmen. Vorzugsweise nicht ich.", + "Ich hoffe es regnet bald wieder. Der Ernte würde es gut tun.", + "Ich liebe Honig! Und hasse Bienen.", + "Eines Tages möchte ich die Welt bereisen. Es muss doch mehr im Leben geben als dieses Dorf.", + ], + "npc.speech.villager_decline_trade": [ + "Tut mir leid, ich habe nichts, was ich mit dir handeln könnte.", + "Du möchtest handeln? Als ob ich etwas hätte, das dich interessieren könnte.", + "Mein Haus gehört mir, ich würde es für nichts auf der Welt hergeben.", + ], + "npc.speech.merchant_advertisement": [ + "Darf ich dir einen Handel vorschlagen?", + "Möchtest du mit mir handeln?", + "Ich habe viele Waren. Möchtest du sie dir mal ansehen?" + ], + "npc.speech.merchant_busy": [ + "Hey, warte bis du an der Reihe bist.", + "Einen Moment bitte, ich kann mich nicht zerteilen.", + "Siehst du nicht, dass jemand vor dir steht?", + "Einen Moment bitte, ich bin gleich bei dir.", + "Nicht vordrängeln bitte.", + "Ich bin gerade beschäftigt, komm doch später wieder." + ], + "npc.speech.merchant_trade_successful": [ + "Vielen Dank für das Geschäft!", + "Vielen Dank!", + ], + "npc.speech.merchant_trade_declined": [ + "Vielleicht beim nächsten Mal, einen schönen Tag noch!", + "Zu schade, vielleicht beim nächsten mal, bis dann!" + ], + "npc.speech.villager_cultist_alarm": [ + "Achtung! Ein Kultist schleicht hier herum!", + "Zu den Waffen! Die Kultisten attackieren uns!", + "Wie können die Kultisten es wagen, unser Dorf zu attackieren!", + "Tod den Kultisten!", + "Kultisten werden hier nicht toleriert!", + "Mörderischer Kultist!", + "Eine Kostprobe meines Schwertes gefällig? Du reudiger Kultist!", + "Nichts kann das Blut von deinen Händen waschen, Kultist!", + "Ja brat' mir doch einer 'nen Storch! Ein Kultist weilt unter uns!", + "Die Schreckensherrschaft der Kultisten wird bald vorrüber sein!", + "Der Kultist gehört mir!", + "Bereite dich darauf vor deinem Schöpfer gegenüberzutreten, du mieser Kultist!", + "Ich sehe einen Kultisten! Ergreift ihn!", + "Ich sehe einen Kultisten!", + "Ich sehe einen Kultisten! Lasst ihn nicht entkommen!", + "Ist der ehrenwerte Kultist an ein wenig TOD interessiert?!", + "Wir vergeben nicht! Wir vergessen nicht! Kultist, büße!", + "Stirb, Kultist!", + "Deine Schreckensherrschaft wird enden!", + "Nimm das! Für alles, was du getan hast!", + "Wir wollen Abschaum wie euch hier nicht!", + "Du hättest unter der Erde bleiben sollen! Da wo du hingehörst!", + ], + "npc.speech.villager_under_attack": [ + "Hilfe, ich werde angegriffen!", + "Hilfe, ich werde angegriffen!", + "Autsch! ich werde angegriffen!", + "Autsch! ich werde angegriffen! Hilfe!", + "Helft mir! Ich werde angegriffen!", + "Ich werde angegriffen! Hilfe!", + "Ich werde angegriffen! Helft mir!", + "Hilfe!", + "Hilfe! Hilfe!", + "Hilfe! Hilfe! Hilfe!", + "Ich werde angegriffen!", + "AAAHHH! Ich werde angegriffen!", + "AAAHHH! Ich werde angegriffen! So helft mir doch!", + "Hilfe! Wir werden angegriffen!", + "Hilfe! Mörder!", + "Hilfe! Ein Mörder läuft frei herum!", + "Hilfe! Man versucht, mich zu töten!", + "Wachen, ich werde angegriffen!", + "Wachen! Ich werde angegriffen!", + "Ich werde angegriffen! Wachen!", + "Hilfe! Wachen! Ich werde angegriffen!", + "Wachen! Kommt schnell!", + "Wachen! Wachen!", + "Wachen! Ein Schurke attackiert mich!", + "Wachen, erschlagt diesen üblen Schurken!", + "Wachen! Ein Mörder!", + "Wachen! Helft mir!", + "Damit wirst du nicht davonkommen! Wachen!", + "Du Unmensch!", + "Helft mir!", + "Helft mir! Bitte!", + "Autsch! Wachen! Hilfe!", + "Sie kommen, um mich zu holen!", + "Hilfe! Hilfe! Ich werde angefeindet!", + "Ah, jetzt sehen wir die Gewalt, die dem System innewohnt.", + "Ach nur'n Kratzer!", + "Hört auf!", + "Was habe ich euch angetan?!", + "Bitte, hört auf mich anzugreifen!", + "Hey! Pass auf wo du mit dem Ding hinziehlst!", + "Abscheulicher Schuft, hinfort mit dir!", + "Halt! Verzieh dich!", + "Du bringst mich noch zur Weißglut!", + "Oi! Was denkst du wer du bist?!", + "Dafür reiße ich dir den Kopf ab!", + "Stop, bitte! Ich habe nichts wertvolles bei mir!", + "Ich setze meinen Bruder auf dich an, er ist größer als ich!", + "Neiiiin, das erzähle ich meiner Mutter!", + "Verflucht seist du!", + "Bitte, tu's nicht.", + "Das war nicht sehr nett von dir!", + "Deine Waffe erfüllt ihren Zweck, du kannst sie jetzt wegstecken!", + "Verschone mich!", + "Bitte, ich habe Familie!", + "Ich bin zu jung zum sterben!", + "Können wir darüber reden?", + "Gewalt ist keine Lösung!", + "Der heutige Tag entwickelt sich zu einem sehr schlechten Tag...", + "Hey, das tat weh!", + "AAAAHHH!", + "Wie rüpelhaft!", + "Stop, ich flehe dich an!", + "Ein Fluch soll dich heimsuchen!", + "Das ist nicht lustig.", + "Wie könnt Ihr es wagen?!", + "Dafür wirst du bezahlen!", + "Mach weiter so und es wird dir leid tun!", + "Zwing mich nicht, dir weh zu tun!", + "Das muss ein Missverständnis sein!", + "Du musst das nicht tun!", + "Fort mit dir, Schurke!", + "Das hat echt wehgetan!", + "Warum tust du das?", + "Bei den Göttern, hört auf!", + "Du musst mich mit jemand anderem verwechseln!", + "Ich verdiene das nicht!", + "Bitte, tu das nicht nochmal.", + "Wachen, in den Kerker mit diesem Schuft!", + "Ich werde meinen Tarasque auf dich hetzen!", + "Warum iiiich?", + ], + "npc.speech.villager_enemy_killed": [ + "Ich habe den Feind vernichtet!", + "Endlich Frieden!", + "... also, wo war ich stehengeblieben?", + ] + } +) diff --git a/assets/voxygen/i18n/en/_manifest.ron b/assets/voxygen/i18n/en/_manifest.ron index 07d2ef3c07..993c8fd4dd 100644 --- a/assets/voxygen/i18n/en/_manifest.ron +++ b/assets/voxygen/i18n/en/_manifest.ron @@ -28,214 +28,5 @@ asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", scale_ratio: 1.0, ), - }, - - string_map: { - - }, - - vector_map: { - "loading.tips": [ - "Press 'G' to light your lantern.", - "Press 'F1' to see all default keybindings.", - "You can type /say or /s to only chat with players directly around you.", - "You can type /region or /r to only chat with players a couple of hundred blocks around you.", - "Admins can use the /build command to enter build mode.", - "You can type /group or /g to only chat with players in your current group.", - "To send private messages type /tell followed by a player name and your message.", - "Keep an eye out for food, chests and other loot spread all around the world!", - "Inventory filled with food? Try crafting better food from it!", - "Wondering what there is to do? Try out one of the dungeons marked on the map!", - "Don't forget to adjust the graphics for your system. Press 'N' to open the settings.", - "Playing with others is fun! Press 'O' to see who is online.", - "Press 'J' to dance. Party!", - "Press 'L-Shift' to open your Glider and conquer the skies.", - "Veloren is still in Pre-Alpha. We do our best to improve it every day!", - "If you want to join the dev team or just have a chat with us, join our Discord server.", - "You can toggle showing your amount of health on the healthbar in the settings.", - "Sit near a campfire (with the 'K' key) to slowly recover from your injuries.", - "Need more bags or better armor to continue your journey? Press 'C' to open the crafting menu!", - "Try jumping when rolling through creatures.", - ], - "npc.speech.villager": [ - "Isn't it such a lovely day?", - "How are you today?", - "Top of the morning to you!", - "I wonder what the Catoblepas thinks when it eats grass.", - "What do you think about this weather?", - "Thinking about those dungeons makes me scared. I hope someone will clear them out.", - "I'd like to go spelunking in a cave when I'm stronger.", - "Have you seen my cat?", - "Have you ever heard of the ferocious Land Sharks? I hear they live in deserts.", - "They say shiny gems of all kinds can be found in caves.", - "I'm just crackers about cheese!", - "Won't you come in? We were just about to have some cheese!", - "They say mushrooms are good for your health. Never eat them myself.", - "Don't forget the crackers!", - "I simply adore dwarven cheese. I wish I could make it.", - "I wonder what is on the other side of the mountains.", - "I hope to make my own glider someday.", - "Would you like to see my garden? Okay, maybe some other time.", - "Lovely day for a stroll in the woods!", - "To be, or not to be? I think I'll be a farmer.", - "Don't you think our village is the best?", - "What do you suppose makes Glowing Remains glow?", - "I think it's time for second breakfast!", - "Have you ever caught a firefly?", - "I just can't understand where those Sauroks keep coming from.", - "I wish someone would keep the wolves away from the village.", - "I had a wonderful dream about cheese last night. What does it mean?", - "I left some cheese with my brother. Now I don't know if it exists or not. I call it Schrödinger's cheese.", - "I left some cheese with my sister. Now I don't know if it exists or not. I call it Schrödinger's cheese.", - "Someone should do something about those cultists. Preferably not me.", - "I hope it rains soon. Would be good for the crops.", - "I love honey! And I hate bees.", - "I want to see the world one day. There's got to be more to life than this village.", - ], - "npc.speech.villager_decline_trade": [ - "Sorry, I don't have anything to trade.", - "Trade? Like I got anything that may interest you.", - "My house is mine, I won't trade it for anything.", - ], - "npc.speech.merchant_advertisement": [ - "Can I interest you in a trade?", - "Do you want to trade with me?", - "I have plenty of goods, Do you want to take a look?" - ], - "npc.speech.merchant_busy": [ - "Hey, wait your turn.", - "Please wait, I'm only one person.", - "Do you see the other person in front of you?", - "Just a moment, let me finish.", - "No cutting in line.", - "I'm busy, come back later." - ], - "npc.speech.merchant_trade_successful": [ - "Thank you for trading with me!", - "Thank you!", - ], - "npc.speech.merchant_trade_declined": [ - "Maybe another time, have a good day!", - "Too bad, maybe next time, then!" - ], - "npc.speech.villager_cultist_alarm": [ - "Lookout! There is a cultist on the loose!", - "To arms! The cultists are attacking!", - "How dare the cultists attack our village!", - "Death to the cultists!", - "Cultists will not be tolerated here!", - "Murderous cultist!", - "Taste the edge of my sword, you dirty cultist!", - "Nothing can clean the blood from your hands, cultist!", - "Billions of blistering blue barnacles! A cultist among us!", - "The evils of this cultist are about to be over!", - "This cultist is mine!", - "Prepare to meet your maker, foul cultist!", - "I see a cultist! Get them!", - "I see a cultist! Attack!", - "I see a cultist! Don't let them escape!", - "Would the most honorable cultist care for some DEATH?!", - "Never forgive! Never forget! Cultist, regret!", - "Die, cultist!", - "Your reign of terror will seize!", - "Here's for all that you've done!", - "We don't take kindly to your types around here.", - "You should have stayed underground!", - ], - "npc.speech.villager_under_attack": [ - "Help, I'm under attack!", - "Help! I'm under attack!", - "Ouch! I'm under attack!", - "Ouch! I'm under attack! Help!", - "Help me! I'm under attack!", - "I'm under attack! Help!", - "I'm under attack! Help me!", - "Help!", - "Help! Help!", - "Help! Help! Help!", - "I'm under attack!", - "AAAHHH! I'm under attack!", - "AAAHHH! I'm under attack! Help!", - "Help! We're under attack!", - "Help! Murderer!", - "Help! There's a murderer on the loose!", - "Help! They're trying to kill me!", - "Guards, I'm under attack!", - "Guards! I'm under attack!", - "I'm under attack! Guards!", - "Help! Guards! I'm under attack!", - "Guards! Come quick!", - "Guards! Guards!", - "Guards! There's a villain attacking me!", - "Guards, slay this foul villain!", - "Guards! There's a murderer!", - "Guards! Help me!", - "You won't get away with this! Guards!", - "You fiend!", - "Help me!", - "Help! Please!", - "Ouch! Guards! Help!", - "They're coming for me!", - "Help! Help! I'm being repressed!", - "Ah, now we see the violence inherent in the system.", - "'Tis but a scratch!", - "Stop that!", - "What did I ever do to you?!", - "Please stop attacking me!", - "Hey! Watch where you point that thing!", - "Heinous wretch, be gone with you!", - "Stop it! Go away!", - "Now you're making me mad!", - "Oi! Who do you think you are?!", - "I'll have your head for that!", - "Stop, please! I carry nothing of value!", - "I'll set my brother on you, he's bigger than I am!", - "Nooo, I'm telling mother!", - "Curse you!", - "Please don't do that.", - "That wasn't very nice!", - "Your weapon works, you can put it away now!", - "Spare me!", - "Please, I have a family!", - "I'm too young to die!", - "Can we talk about this?", - "Violence is never the answer!", - "Today is turning out to be a very bad day...", - "Hey, that hurt!", - "Eek!", - "How rude!", - "Stop, I beg you!", - "A pox upon you!", - "This isn't fun.", - "How dare you?!", - "You'll pay for that!", - "Keep that up and you'll be sorry!", - "Don't make me hurt you!", - "There must be some misunderstanding!", - "You don't need to do this!", - "Be gone, fiend!", - "That really hurt!", - "Why would you do that?", - "By the spirits, cease!", - "You must have me confused with someone else!", - "I don't deserve this!", - "Please don't do that again.", - "Guards, throw this monster in the lake!", - "I'll set my tarasque on you!", - "Why meeeeeee?", - ], - "npc.speech.villager_enemy_killed": [ - "I have destroyed my enemy!", - "Finally at peace!", - "... now what was I doing?", - ], - "npc.speech.menacing": [ - "I'm warning you!", - "Any closer and I'll attack!", - "You don't scare me!", - "Get away from here!", - "Turn around if you want to live!", - "You're not welcome here!", - ], } ) diff --git a/assets/voxygen/i18n/en/main.ron b/assets/voxygen/i18n/en/main.ron index 6bf3f4da12..3f48895725 100644 --- a/assets/voxygen/i18n/en/main.ron +++ b/assets/voxygen/i18n/en/main.ron @@ -66,5 +66,27 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "Press 'G' to light your lantern.", + "Press 'F1' to see all default keybindings.", + "You can type /say or /s to only chat with players directly around you.", + "You can type /region or /r to only chat with players a couple of hundred blocks around you.", + "Admins can use the /build command to enter build mode.", + "You can type /group or /g to only chat with players in your current group.", + "To send private messages type /tell followed by a player name and your message.", + "Keep an eye out for food, chests and other loot spread all around the world!", + "Inventory filled with food? Try crafting better food from it!", + "Wondering what there is to do? Try out one of the dungeons marked on the map!", + "Don't forget to adjust the graphics for your system. Press 'N' to open the settings.", + "Playing with others is fun! Press 'O' to see who is online.", + "Press 'J' to dance. Party!", + "Press 'L-Shift' to open your Glider and conquer the skies.", + "Veloren is still in Pre-Alpha. We do our best to improve it every day!", + "If you want to join the dev team or just have a chat with us, join our Discord server.", + "You can toggle showing your amount of health on the healthbar in the settings.", + "Sit near a campfire (with the 'K' key) to slowly recover from your injuries.", + "Need more bags or better armor to continue your journey? Press 'C' to open the crafting menu!", + "Try jumping when rolling through creatures.", + ], } ) diff --git a/assets/voxygen/i18n/en/npc.ron b/assets/voxygen/i18n/en/npc.ron new file mode 100644 index 0000000000..b2f5683c05 --- /dev/null +++ b/assets/voxygen/i18n/en/npc.ron @@ -0,0 +1,190 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for "global" English +( + string_map: { + }, + + vector_map: { + "npc.speech.villager": [ + "Isn't it such a lovely day?", + "How are you today?", + "Top of the morning to you!", + "I wonder what the Catoblepas thinks when it eats grass.", + "What do you think about this weather?", + "Thinking about those dungeons makes me scared. I hope someone will clear them out.", + "I'd like to go spelunking in a cave when I'm stronger.", + "Have you seen my cat?", + "Have you ever heard of the ferocious Land Sharks? I hear they live in deserts.", + "They say shiny gems of all kinds can be found in caves.", + "I'm just crackers about cheese!", + "Won't you come in? We were just about to have some cheese!", + "They say mushrooms are good for your health. Never eat them myself.", + "Don't forget the crackers!", + "I simply adore dwarven cheese. I wish I could make it.", + "I wonder what is on the other side of the mountains.", + "I hope to make my own glider someday.", + "Would you like to see my garden? Okay, maybe some other time.", + "Lovely day for a stroll in the woods!", + "To be, or not to be? I think I'll be a farmer.", + "Don't you think our village is the best?", + "What do you suppose makes Glowing Remains glow?", + "I think it's time for second breakfast!", + "Have you ever caught a firefly?", + "I just can't understand where those Sauroks keep coming from.", + "I wish someone would keep the wolves away from the village.", + "I had a wonderful dream about cheese last night. What does it mean?", + "I left some cheese with my brother. Now I don't know if it exists or not. I call it Schrödinger's cheese.", + "I left some cheese with my sister. Now I don't know if it exists or not. I call it Schrödinger's cheese.", + "Someone should do something about those cultists. Preferably not me.", + "I hope it rains soon. Would be good for the crops.", + "I love honey! And I hate bees.", + "I want to see the world one day. There's got to be more to life than this village.", + ], + "npc.speech.villager_decline_trade": [ + "Sorry, I don't have anything to trade.", + "Trade? Like I got anything that may interest you.", + "My house is mine, I won't trade it for anything.", + ], + "npc.speech.merchant_advertisement": [ + "Can I interest you in a trade?", + "Do you want to trade with me?", + "I have plenty of goods, Do you want to take a look?" + ], + "npc.speech.merchant_busy": [ + "Hey, wait your turn.", + "Please wait, I'm only one person.", + "Do you see the other person in front of you?", + "Just a moment, let me finish.", + "No cutting in line.", + "I'm busy, come back later." + ], + "npc.speech.merchant_trade_successful": [ + "Thank you for trading with me!", + "Thank you!", + ], + "npc.speech.merchant_trade_declined": [ + "Maybe another time, have a good day!", + "Too bad, maybe next time, then!" + ], + "npc.speech.villager_cultist_alarm": [ + "Lookout! There is a cultist on the loose!", + "To arms! The cultists are attacking!", + "How dare the cultists attack our village!", + "Death to the cultists!", + "Cultists will not be tolerated here!", + "Murderous cultist!", + "Taste the edge of my sword, you dirty cultist!", + "Nothing can clean the blood from your hands, cultist!", + "Billions of blistering blue barnacles! A cultist among us!", + "The evils of this cultist are about to be over!", + "This cultist is mine!", + "Prepare to meet your maker, foul cultist!", + "I see a cultist! Get them!", + "I see a cultist! Attack!", + "I see a cultist! Don't let them escape!", + "Would the most honorable cultist care for some DEATH?!", + "Never forgive! Never forget! Cultist, regret!", + "Die, cultist!", + "Your reign of terror will seize!", + "Here's for all that you've done!", + "We don't take kindly to your types around here.", + "You should have stayed underground!", + ], + "npc.speech.villager_under_attack": [ + "Help, I'm under attack!", + "Help! I'm under attack!", + "Ouch! I'm under attack!", + "Ouch! I'm under attack! Help!", + "Help me! I'm under attack!", + "I'm under attack! Help!", + "I'm under attack! Help me!", + "Help!", + "Help! Help!", + "Help! Help! Help!", + "I'm under attack!", + "AAAHHH! I'm under attack!", + "AAAHHH! I'm under attack! Help!", + "Help! We're under attack!", + "Help! Murderer!", + "Help! There's a murderer on the loose!", + "Help! They're trying to kill me!", + "Guards, I'm under attack!", + "Guards! I'm under attack!", + "I'm under attack! Guards!", + "Help! Guards! I'm under attack!", + "Guards! Come quick!", + "Guards! Guards!", + "Guards! There's a villain attacking me!", + "Guards, slay this foul villain!", + "Guards! There's a murderer!", + "Guards! Help me!", + "You won't get away with this! Guards!", + "You fiend!", + "Help me!", + "Help! Please!", + "Ouch! Guards! Help!", + "They're coming for me!", + "Help! Help! I'm being repressed!", + "Ah, now we see the violence inherent in the system.", + "'Tis but a scratch!", + "Stop that!", + "What did I ever do to you?!", + "Please stop attacking me!", + "Hey! Watch where you point that thing!", + "Heinous wretch, be gone with you!", + "Stop it! Go away!", + "Now you're making me mad!", + "Oi! Who do you think you are?!", + "I'll have your head for that!", + "Stop, please! I carry nothing of value!", + "I'll set my brother on you, he's bigger than I am!", + "Nooo, I'm telling mother!", + "Curse you!", + "Please don't do that.", + "That wasn't very nice!", + "Your weapon works, you can put it away now!", + "Spare me!", + "Please, I have a family!", + "I'm too young to die!", + "Can we talk about this?", + "Violence is never the answer!", + "Today is turning out to be a very bad day...", + "Hey, that hurt!", + "Eek!", + "How rude!", + "Stop, I beg you!", + "A pox upon you!", + "This isn't fun.", + "How dare you?!", + "You'll pay for that!", + "Keep that up and you'll be sorry!", + "Don't make me hurt you!", + "There must be some misunderstanding!", + "You don't need to do this!", + "Be gone, fiend!", + "That really hurt!", + "Why would you do that?", + "By the spirits, cease!", + "You must have me confused with someone else!", + "I don't deserve this!", + "Please don't do that again.", + "Guards, throw this monster in the lake!", + "I'll set my tarasque on you!", + "Why meeeeeee?", + ], + "npc.speech.villager_enemy_killed": [ + "I have destroyed my enemy!", + "Finally at peace!", + "... now what was I doing?", + ], + "npc.speech.menacing": [ + "I'm warning you!", + "Any closer and I'll attack!", + "You don't scare me!", + "Get away from here!", + "Turn around if you want to live!", + "You're not welcome here!", + ], + } +) diff --git a/assets/voxygen/i18n/es_ES/_manifest.ron b/assets/voxygen/i18n/es_ES/_manifest.ron index 0af09c90cb..75f7decf9f 100644 --- a/assets/voxygen/i18n/es_ES/_manifest.ron +++ b/assets/voxygen/i18n/es_ES/_manifest.ron @@ -28,204 +28,5 @@ asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", scale_ratio: 1.0, ), - }, - - string_map: { - - }, - - vector_map: { - "loading.tips": [ - "Pulsa 'G' para encender tu linterna.", - "Pulsa 'F1' para ver todos las atajos de teclado predeterminados.", - "Puedes escribir /say o /s para chatear solo con jugadores que estén a tu alrededor.", - "Puedes escribir /region o /r para chatear con jugadores que se encuentren a cien bloques a tu alrededor.", - "Puedes escribir /group o /g para chatear con jugadores en tu grupo.", - "Para enviar mensajes privados escribe /tell seguido del nombre y tu mensaje.", - "NPCs con el mismo nivel pueden tener una dificultad diferente.", - "¡Observa el terreno en búsqueda de comida, cofres y botines!", - "¿Inventario lleno de comida? ¡Intenta elaborar comida mejorada con ella!", - "En busqueda de una aventura? ¡Prueba una de las mazmorras marcadas en el mapa!", - "No te olvides de ajustar los gráficos de tu pc. Pulsa 'N' para abrir la configuración.", - "¡Jugar con otros jugadores es mas divertido! Pulsa 'O' para ver quien esta en linea.", - "Un NPC con un cráneo debajo su barra de vida indica claramente que es mas poderoso que tu.", - "Pulsa 'J' para bailar. ¡Fiesta!", - "Pulsa 'Shift-Izquierdo' para desplegar tu planeador y conquistar los cielos", - "Veloren se encuentra todavia en Pre-Alpha. ¡Hacemos todo lo posible para mejorar la experiencia de juego día a día!", - "Si quieres unirte al equipo de desarrollo o solo conversar con nosotros, únete a nuestro servidor en Discord.", - "Puedes mostrar o ocultar tu total de salud en la barra de salud en configuración.", - "Para ver tus atributos, haz clic en el botón 'Atributos' del inventario.", - "Siéntate cerca de una fogata (con la tecla 'K') para descansar - recibirás una lenta sanación periódicamente.", "Need more bags or better armor to continue your journey? Press 'C' to open the crafting menu!", - "¿Necesitas más mochilas o mejores armaduras para continuar tu viaje? Pulsa 'C' para abrir el menú de elaboración.", - ], - "npc.speech.villager": [ - "¿A que es un dia bonito?", - "¿Cómo estás hoy?", - "¡Que tengas una buena mañana!", - "Me pregunto qué piensa Catoblepas cuando come hierba", - "¿Qué piensas de este tiempo?", - "Es solo pensar en esas mazmorras y me da miedo. Espero que alguien pueda poner orden ahi dentro", - "Me gustaría hacer espeleología en una cueva cuando sea más fuerte", - "¿Has visto a mi gato?", - "¿Has oído hablar de los feroces tiburones de tierra? He oído que viven en los desiertos", - "Dicen que en las cuevas se pueden encontrar gemas brillantes de todo tipo", - "¡Sólo me interesa el queso!", - "¿No vas a entrar? Estábamos a punto de comer queso!", - "Dicen que las setas son buenas para la salud. Yo nunca las he comido", - "¡No te olvides las galletas!", - "Adoro el queso enano. Me encantaria aprender hacerlo", - "Me pregunto qué habrá al otro lado de las montañas", - "Espero hacer mi propio planeador algún día", - "¿Te gustaría ver mi jardín? Bueno, tal vez en otro momento", - "¡Hace un día precioso para pasear por el bosque!", - "¿Ser o no ser? Creo que seré granjero", - "¿No crees que nuestro pueblo es el mejor?", - "¿Qué supones que hace brillar a los Restos Luminosos?", - "¡Creo que es la hora del segundo desayuno!", - "¿Has cogido alguna vez una luciérnaga?", - "No puedo entender de dónde vienen esos Sauroks", - "Me gustaría que alguien mantuviera a los lobos alejados del pueblo", - "Anoche tuve un sueño maravilloso sobre el queso. ¿Qué significa?", - "He dejado algo de queso con mi hermano. Ahora no se si existe o no. Lo llamo el queso de Schrödinger.", - "He dejado algo de queso con mi hermana. Ahora no se si existe o no. Lo llamo el queso de Schrödinger.", - "Alguien debería de hacer algo con esos cultistas. Preferiblemente alguien que no sea yo", - "Espero que llueva pronto. Sería bueno para los cultivos.", - "¡Me encanta la miel! Y odio las abejas.", - "Quiero ver el mundo algun día. Tiene que haber algo más en esta vida que este pueblo.", - ], - "npc.speech.villager_decline_trade": [ - "Lo siento, no tengo nada para comerciar.", - "¿Comerciar? Como si tuviera algo que te pueda interesar.", - "Mi casa es mía y no la cambiaré por nada.", - ], - "npc.speech.merchant_advertisement": [ - "¿Te interesaría comerciar conmigo?", - "¿Querrías comerciar conmigo?", - "Tengo muchos bienes. ¿Quieres echar un vistazo?" - ], - "npc.speech.merchant_busy": [ - "Hey, espera tu turno", - "Ten paciencia, solo soy una persona.", - "¿Que no ves que estoy comerciando con alguien?", - "Un momento, dejame acabar.", - "Nada de colarse.", - "Estoy ocupado, vuelve más tarde." - ], - "npc.speech.merchant_trade_successful": [ - "¡Gracias por comerciar conmigo!", - "¡Muchas gracias!", - ], - "npc.speech.merchant_trade_declined": [ - "Quizás en otra ocasión, ¡ten un buen día!", - "Vaya, supongo que en otra ocasión." - ], - "npc.speech.villager_cultist_alarm": [ - "¡Cuidado! ¡Hay cultistas sueltos!", - "¡A las armas! ¡Los cultistas nos atacan!", - "¡Como se atreven los cultistas a atacar esta aldea!", - "¡Muerte a los cultistas!", - "¡Aquí no toleramos a los cultistas!", - "¡Cultista asesino!", - "¡Prueba el filo de mi espada, sucio cultista!", - "¡Nada podrá limpiar la sangre de tus manos, cultista!", - "¡Esos malvados cultistas seran aniquilados!", - "¡Este cultista es mío!", - "¡Prepárate para conocer a tu creados, sucio cultista!", - "¡Veo un cultista! ¡Atrapadlo!", - "¡Veo un cultista! ¡Atacadlo!", - "¡Veo un cultista! ¡No dejéis que escape!", - "¡Nunca perdonamos!¡Nunca olvidamos!¡Muere, cultista!", - "¡Muere, cultista!", - "¡Tu reinado de terror llegará a su fin!", - "¡Pagarás por todo lo que has hecho!", - "Por aquí no tratamos con amabilidad a los de tu especie.", - "¡Deberías de haberte quedado bajo tierra!", - ], - "npc.speech.villager_under_attack": [ - "Ayuda, ¡me atacan!", - "¡Ayuda! ¡Me atacan!", - "¡Auch! ¡Me atacan!", - "¡Auch! ¡Me atacan! ¡Ayuda!", - "¡Ayúdame! ¡Me atacan!", - "¡Me atacan! ¡Ayuda!", - "¡Me atacan! ¡Ayúdame!", - "¡Ayuda!", - "¡Ayuda! ¡Ayuda!", - "¡Ayuda! ¡Ayuda! ¡Ayuda!", - "¡Me atacan!", - "¡AAAHHH! ¡Me atacan!", - "¡AAAHHH! ¡Me atacan! ¡Ayuda!", - "¡Ayuda! ¡Nos están atacando!", - "¡Ayuda! ¡Asesino!", - "¡Ayuda! ¡Hay un asesino suelto!", - "¡Ayuda! ¡Me están intentando matar!", - "Guardias, ¡me están atacando!", - "Guardias, ¡me están atacando!", - "¡Me están atacando! ¡Guardias!", - "¡Ayuda! ¡Guardias! ¡Me están atacando!", - "¡Guardias! ¡Venid rápido!", - "¡Guardias! ¡Guardias!", - "¡Guardias! ¡Un villano me ataca!", - "Guardias, ¡acabad con este infame villano!", - "¡Guardias! ¡Hay un asesino!", - "¡Guardias! ¡Ayudadme!", - "¡No te saldrás con la tuya! ¡Guardias!", - "¡Desalmado!", - "¡Ayúdame!", - "¡Ayuda! ¡Por favor!", - "¡Auch! ¡Guardias! ¡Ayuda!", - "¡Vienen a por mí!", - "¡Ayuda! ¡Ayuda! Me están reprimiendo", - "Ah, ahora vemos la violencia inherente al sistema.", - "¡No es más que un rasguño!", - "¡Deja de hacer eso!", - "¡¿Qué te he hecho?!", - "¡Porfavor deja de atacarme!", - "¡Eh! ¡Mira a dónde apuntas esa cosa!", - "Desgraciado, vete de aqui!", - "Para ya! Vete!", - "¡Me estas haciendo enfadar!", - "¡Oye! ¡¿Quién te crees que eres?!", - "Te arrancaré la cabeza por eso!", - "¡Para, por favor! ¡No llevo nada de valor!", - "¡Mi hermano es más grande que yo y te machacara!", - "¡Nooo, se lo diré a mamá!", - "¡Maldito seas!", - "Por favor, no hagas eso", - "¡Eso no fue muy agradable!", - "Tu arma funciona, ahora aléjala!", - "¡Perdóname!", - "¡Por favor, tengo familia!", - "¡Soy demasiado joven para morir!", - "¿Podemos hablar de esto?", - "¡La violencia nunca es la respuesta!", - "Hoy se está torciendo el día...", - "¡Eh, eso duele!", - "¡Ayy!", - "¡Qué grosero!", - "¡Para, te lo ruego!", - "¡Ojala te enfermes!", - "Esto no es divertido", - "¡¿Cómo te atreves?!", - "¡Pagarás por eso!", - "¡Sigue así y te arrepentirás!", - "¡No hagas que pegue!", - "¡Debe haber algún malentendido!", - "¡No hay necesidad de hacer esto!", - "¡Vete, demonio!", - "¡Eso sí que duele!", - "¿Por qué harías eso?", - "Por los espíritus, ¡basta!", - "¡Debes haberme confundido con otra persona!", - "¡No me merezco esto!", - "Por favor, no vuelvas a hacer eso.", - "¡Guardias, arrojed a este monstruo al lago!", - "¡Enviare mi Tarasca a por ti!", - ], - "npc.speech.villager_enemy_killed": [ - "¡He acabado con el enemigo!", - "¡Por fin, paz!", - "... ¿por dónde me había quedado?", - ] } ) diff --git a/assets/voxygen/i18n/es_ES/main.ron b/assets/voxygen/i18n/es_ES/main.ron index 2799b71d91..a5ac5f0f8c 100644 --- a/assets/voxygen/i18n/es_ES/main.ron +++ b/assets/voxygen/i18n/es_ES/main.ron @@ -64,5 +64,28 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "Pulsa 'G' para encender tu linterna.", + "Pulsa 'F1' para ver todos las atajos de teclado predeterminados.", + "Puedes escribir /say o /s para chatear solo con jugadores que estén a tu alrededor.", + "Puedes escribir /region o /r para chatear con jugadores que se encuentren a cien bloques a tu alrededor.", + "Puedes escribir /group o /g para chatear con jugadores en tu grupo.", + "Para enviar mensajes privados escribe /tell seguido del nombre y tu mensaje.", + "NPCs con el mismo nivel pueden tener una dificultad diferente.", + "¡Observa el terreno en búsqueda de comida, cofres y botines!", + "¿Inventario lleno de comida? ¡Intenta elaborar comida mejorada con ella!", + "En busqueda de una aventura? ¡Prueba una de las mazmorras marcadas en el mapa!", + "No te olvides de ajustar los gráficos de tu pc. Pulsa 'N' para abrir la configuración.", + "¡Jugar con otros jugadores es mas divertido! Pulsa 'O' para ver quien esta en linea.", + "Un NPC con un cráneo debajo su barra de vida indica claramente que es mas poderoso que tu.", + "Pulsa 'J' para bailar. ¡Fiesta!", + "Pulsa 'Shift-Izquierdo' para desplegar tu planeador y conquistar los cielos", + "Veloren se encuentra todavia en Pre-Alpha. ¡Hacemos todo lo posible para mejorar la experiencia de juego día a día!", + "Si quieres unirte al equipo de desarrollo o solo conversar con nosotros, únete a nuestro servidor en Discord.", + "Puedes mostrar o ocultar tu total de salud en la barra de salud en configuración.", + "Para ver tus atributos, haz clic en el botón 'Atributos' del inventario.", + "Siéntate cerca de una fogata (con la tecla 'K') para descansar - recibirás una lenta sanación periódicamente.", "Need more bags or better armor to continue your journey? Press 'C' to open the crafting menu!", + "¿Necesitas más mochilas o mejores armaduras para continuar tu viaje? Pulsa 'C' para abrir el menú de elaboración.", + ], } ) diff --git a/assets/voxygen/i18n/es_ES/npc.ron b/assets/voxygen/i18n/es_ES/npc.ron new file mode 100644 index 0000000000..57d8413b95 --- /dev/null +++ b/assets/voxygen/i18n/es_ES/npc.ron @@ -0,0 +1,180 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Spanish (Spain) +( + string_map: { + + }, + + vector_map: { + "npc.speech.villager": [ + "¿A que es un dia bonito?", + "¿Cómo estás hoy?", + "¡Que tengas una buena mañana!", + "Me pregunto qué piensa Catoblepas cuando come hierba", + "¿Qué piensas de este tiempo?", + "Es solo pensar en esas mazmorras y me da miedo. Espero que alguien pueda poner orden ahi dentro", + "Me gustaría hacer espeleología en una cueva cuando sea más fuerte", + "¿Has visto a mi gato?", + "¿Has oído hablar de los feroces tiburones de tierra? He oído que viven en los desiertos", + "Dicen que en las cuevas se pueden encontrar gemas brillantes de todo tipo", + "¡Sólo me interesa el queso!", + "¿No vas a entrar? Estábamos a punto de comer queso!", + "Dicen que las setas son buenas para la salud. Yo nunca las he comido", + "¡No te olvides las galletas!", + "Adoro el queso enano. Me encantaria aprender hacerlo", + "Me pregunto qué habrá al otro lado de las montañas", + "Espero hacer mi propio planeador algún día", + "¿Te gustaría ver mi jardín? Bueno, tal vez en otro momento", + "¡Hace un día precioso para pasear por el bosque!", + "¿Ser o no ser? Creo que seré granjero", + "¿No crees que nuestro pueblo es el mejor?", + "¿Qué supones que hace brillar a los Restos Luminosos?", + "¡Creo que es la hora del segundo desayuno!", + "¿Has cogido alguna vez una luciérnaga?", + "No puedo entender de dónde vienen esos Sauroks", + "Me gustaría que alguien mantuviera a los lobos alejados del pueblo", + "Anoche tuve un sueño maravilloso sobre el queso. ¿Qué significa?", + "He dejado algo de queso con mi hermano. Ahora no se si existe o no. Lo llamo el queso de Schrödinger.", + "He dejado algo de queso con mi hermana. Ahora no se si existe o no. Lo llamo el queso de Schrödinger.", + "Alguien debería de hacer algo con esos cultistas. Preferiblemente alguien que no sea yo", + "Espero que llueva pronto. Sería bueno para los cultivos.", + "¡Me encanta la miel! Y odio las abejas.", + "Quiero ver el mundo algun día. Tiene que haber algo más en esta vida que este pueblo.", + ], + "npc.speech.villager_decline_trade": [ + "Lo siento, no tengo nada para comerciar.", + "¿Comerciar? Como si tuviera algo que te pueda interesar.", + "Mi casa es mía y no la cambiaré por nada.", + ], + "npc.speech.merchant_advertisement": [ + "¿Te interesaría comerciar conmigo?", + "¿Querrías comerciar conmigo?", + "Tengo muchos bienes. ¿Quieres echar un vistazo?" + ], + "npc.speech.merchant_busy": [ + "Hey, espera tu turno", + "Ten paciencia, solo soy una persona.", + "¿Que no ves que estoy comerciando con alguien?", + "Un momento, dejame acabar.", + "Nada de colarse.", + "Estoy ocupado, vuelve más tarde." + ], + "npc.speech.merchant_trade_successful": [ + "¡Gracias por comerciar conmigo!", + "¡Muchas gracias!", + ], + "npc.speech.merchant_trade_declined": [ + "Quizás en otra ocasión, ¡ten un buen día!", + "Vaya, supongo que en otra ocasión." + ], + "npc.speech.villager_cultist_alarm": [ + "¡Cuidado! ¡Hay cultistas sueltos!", + "¡A las armas! ¡Los cultistas nos atacan!", + "¡Como se atreven los cultistas a atacar esta aldea!", + "¡Muerte a los cultistas!", + "¡Aquí no toleramos a los cultistas!", + "¡Cultista asesino!", + "¡Prueba el filo de mi espada, sucio cultista!", + "¡Nada podrá limpiar la sangre de tus manos, cultista!", + "¡Esos malvados cultistas seran aniquilados!", + "¡Este cultista es mío!", + "¡Prepárate para conocer a tu creados, sucio cultista!", + "¡Veo un cultista! ¡Atrapadlo!", + "¡Veo un cultista! ¡Atacadlo!", + "¡Veo un cultista! ¡No dejéis que escape!", + "¡Nunca perdonamos!¡Nunca olvidamos!¡Muere, cultista!", + "¡Muere, cultista!", + "¡Tu reinado de terror llegará a su fin!", + "¡Pagarás por todo lo que has hecho!", + "Por aquí no tratamos con amabilidad a los de tu especie.", + "¡Deberías de haberte quedado bajo tierra!", + ], + "npc.speech.villager_under_attack": [ + "Ayuda, ¡me atacan!", + "¡Ayuda! ¡Me atacan!", + "¡Auch! ¡Me atacan!", + "¡Auch! ¡Me atacan! ¡Ayuda!", + "¡Ayúdame! ¡Me atacan!", + "¡Me atacan! ¡Ayuda!", + "¡Me atacan! ¡Ayúdame!", + "¡Ayuda!", + "¡Ayuda! ¡Ayuda!", + "¡Ayuda! ¡Ayuda! ¡Ayuda!", + "¡Me atacan!", + "¡AAAHHH! ¡Me atacan!", + "¡AAAHHH! ¡Me atacan! ¡Ayuda!", + "¡Ayuda! ¡Nos están atacando!", + "¡Ayuda! ¡Asesino!", + "¡Ayuda! ¡Hay un asesino suelto!", + "¡Ayuda! ¡Me están intentando matar!", + "Guardias, ¡me están atacando!", + "Guardias, ¡me están atacando!", + "¡Me están atacando! ¡Guardias!", + "¡Ayuda! ¡Guardias! ¡Me están atacando!", + "¡Guardias! ¡Venid rápido!", + "¡Guardias! ¡Guardias!", + "¡Guardias! ¡Un villano me ataca!", + "Guardias, ¡acabad con este infame villano!", + "¡Guardias! ¡Hay un asesino!", + "¡Guardias! ¡Ayudadme!", + "¡No te saldrás con la tuya! ¡Guardias!", + "¡Desalmado!", + "¡Ayúdame!", + "¡Ayuda! ¡Por favor!", + "¡Auch! ¡Guardias! ¡Ayuda!", + "¡Vienen a por mí!", + "¡Ayuda! ¡Ayuda! Me están reprimiendo", + "Ah, ahora vemos la violencia inherente al sistema.", + "¡No es más que un rasguño!", + "¡Deja de hacer eso!", + "¡¿Qué te he hecho?!", + "¡Porfavor deja de atacarme!", + "¡Eh! ¡Mira a dónde apuntas esa cosa!", + "Desgraciado, vete de aqui!", + "Para ya! Vete!", + "¡Me estas haciendo enfadar!", + "¡Oye! ¡¿Quién te crees que eres?!", + "Te arrancaré la cabeza por eso!", + "¡Para, por favor! ¡No llevo nada de valor!", + "¡Mi hermano es más grande que yo y te machacara!", + "¡Nooo, se lo diré a mamá!", + "¡Maldito seas!", + "Por favor, no hagas eso", + "¡Eso no fue muy agradable!", + "Tu arma funciona, ahora aléjala!", + "¡Perdóname!", + "¡Por favor, tengo familia!", + "¡Soy demasiado joven para morir!", + "¿Podemos hablar de esto?", + "¡La violencia nunca es la respuesta!", + "Hoy se está torciendo el día...", + "¡Eh, eso duele!", + "¡Ayy!", + "¡Qué grosero!", + "¡Para, te lo ruego!", + "¡Ojala te enfermes!", + "Esto no es divertido", + "¡¿Cómo te atreves?!", + "¡Pagarás por eso!", + "¡Sigue así y te arrepentirás!", + "¡No hagas que pegue!", + "¡Debe haber algún malentendido!", + "¡No hay necesidad de hacer esto!", + "¡Vete, demonio!", + "¡Eso sí que duele!", + "¿Por qué harías eso?", + "Por los espíritus, ¡basta!", + "¡Debes haberme confundido con otra persona!", + "¡No me merezco esto!", + "Por favor, no vuelvas a hacer eso.", + "¡Guardias, arrojed a este monstruo al lago!", + "¡Enviare mi Tarasca a por ti!", + ], + "npc.speech.villager_enemy_killed": [ + "¡He acabado con el enemigo!", + "¡Por fin, paz!", + "... ¿por dónde me había quedado?", + ] + } +) diff --git a/assets/voxygen/i18n/es_LA/_manifest.ron b/assets/voxygen/i18n/es_LA/_manifest.ron index 5dc84fde14..39c6bc6d5a 100644 --- a/assets/voxygen/i18n/es_LA/_manifest.ron +++ b/assets/voxygen/i18n/es_LA/_manifest.ron @@ -40,113 +40,5 @@ asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", scale_ratio: 1.0, ), - }, - string_map: { - - }, - - - vector_map: { - "loading.tips": [ - "Presiona 'G' para encender tu linterna.", - "Presiona 'F1' para ver los controles predeterminados.", - "Puedes escribir /say o /s para chatear solo con jugadores alrededor tuyo.", - "Puedes escribr /region o /r para chatear solo con jugadores que están a unos cien bloques alrededor tuyo.", - "Para enviar mensajes privados escribe /tell seguido de el nombre de un jugador y luego tu mensaje.", - "NPCs con el mismo nivel pueden tener una dificultad diferente.", - "Observa el terreno en búsqueda de comida, cofres y botines!", - "¿Inventario lleno de comida? Intenta craftear mejor comida con ella!", - "¿Te preguntas dónde debes hacerlo? Los Dungeons están marcados con puntos marrones en el mapa!", - "No te olvides de ajustar los gráficos de tu pc. Presiona 'N' para abrir la configuración.", - "Jugar con otros es divertido! Presiona 'O' para ver quien esta conectado.", - "Un NPC con un craneo debajo de su barra de vida es bastante más poderoso comparado contigo.", - "Presiona 'J' para bailar. Fiesta!", - "Presiona 'Shift-Izquierdo' para abrir tu planeador y conquistar los cielos.", - "Veloren está aún en Alfa temprana. Hacemos lo mejor para mejorar día a día!", - "Si te quieres unir al equipo de desarrolladores o solo chatear con nosotros, únete a nuestro servidor en Discord.", - "Puedes elegir mostrar tu cantidad de vida en la barra de vida en la configuración.", - "Para ver tus estadísticas, haz click en el botón 'Estadísticas' en el inventario.", - ], - "npc.speech.villager_under_attack": [ - "Ayuda, ¡Me están atacando!", - "¡Ayuda! ¡Me están atacando!", - "¡Auch! ¡Me están atacando!", - "¡Auch! ¡Me están atacando! ¡Ayuda!", - "¡Ayudenme! ¡Me están atacando!", - "¡Me están atacando! ¡Ayuda!", - "¡Me están atacando! ¡Ayudenme!", - "¡Ayuda!", - "¡Ayuda! ¡Ayuda!", - "¡Ayuda! ¡Ayuda! ¡Ayuda!", - "¡Me están atacando!", - "¡AAAHH! ¡Me están atacando!", - "¡AAAHH! ¡Me están atacando! ¡Ayuda!", - "Ayuda! Nos están atacando!", - "¡Ayuda! ¡Asesino!", - "¡Ayuda! ¡Hay un asesino suelto!", - "¡Ayuda! ¡están intentando matarme!", - "Guardias, ¡Me están atacando!", - "¡Guardias! ¡Me están atacando!", - "¡Me están atacando! ¡Guardias!", - "¡Ayuda! ¡Guardias! ¡Me están atacando!", - "¡Guardias! ¡Vengan rapido!", - "¡Guardias, Guardias!", - "¡Guardias! ¡Me esta atacando un villano!", - "¡Guardias, eliminen a este desagradable villano!", - "¡Guardias! ¡Ahi esta el asesino!", - "¡Guardias! ¡Ayúdenme!", - "No te saldrás con la tuya, ¡Guardias!", - "¡Eres despreciable!", - "¡Ayúdenme!", - "¡Ayuda! ¡Porfavor!", - "¡Auch! ¡Guardias! ¡Ayuda!", - "¡Vienen por mi!", - "¡Ayuda! ¡Ayuda! Estoy siendo atacado", - "Ah, se nota que la violencia es parte del sistema.", - "¡Esto no es más que un rasguño!", - "Deja de hacer eso!", - "¿Qué te hice para merecer esto?", - "Por favor, para de atacarme!", - "Hey! Mira hacia adonde apuntas con esa cosa", - "Desgraciado, vete de aqui!", - "Para ya! Vete!", - "Me estas haciendo enojar!", - "Hey!¿Quién te piensas que eres?", - "Te arrancaré la cabeza por eso!", - "Detente, por favor! No llevo nada de valor!", - "Te voy a mandar a mi hermano, el es más grande que yo!", - "Nooo, le contaré a mi madre!", - "Maldito seas!", - "Por favor no lo hagas.", - "Eso no fue agradable!", - "Tu arma funciona, ahora aléjala!", - "Si claro...", - "Por favor, tengo familia!", - "Soy demasiado jóven para morir!", - "¿Podemos hablar sobre esto?", - "La violencia no resuelve nada!", - "Este día se esta convirtiendo en uno muy feo...", - "Hey, eso dolió!", - "Ayy!", - "Qué violento!", - "Detente, te lo suplico!", - "Ojala te enfermes!", - "Esto no es divertido.", - "¡¿Cómo te atreves?!", - "Vas a pagar por eso!", - "Sigue con eso y lo lamentarás!", - "No hagas que te lastime!", - "Tiene que ser un malentendido!", - "No necesitas hacer esto!", - "Vete, demonio!", - "Eso realmente dolió!", - "¿Por qué harias eso?", - "Por todos los Santos, para!", - "Me habrás confudido con alguien más!", - "No me merezco esto!", - "Por favor, no lo hagas de nuevo", - "Guardias, tiren este monstruo al lago", - "Invocaré mis demonios en ti!", - ], } ) diff --git a/assets/voxygen/i18n/es_LA/main.ron b/assets/voxygen/i18n/es_LA/main.ron index 0c3dfda33c..f3c30f5008 100644 --- a/assets/voxygen/i18n/es_LA/main.ron +++ b/assets/voxygen/i18n/es_LA/main.ron @@ -59,5 +59,25 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "Presiona 'G' para encender tu linterna.", + "Presiona 'F1' para ver los controles predeterminados.", + "Puedes escribir /say o /s para chatear solo con jugadores alrededor tuyo.", + "Puedes escribr /region o /r para chatear solo con jugadores que están a unos cien bloques alrededor tuyo.", + "Para enviar mensajes privados escribe /tell seguido de el nombre de un jugador y luego tu mensaje.", + "NPCs con el mismo nivel pueden tener una dificultad diferente.", + "Observa el terreno en búsqueda de comida, cofres y botines!", + "¿Inventario lleno de comida? Intenta craftear mejor comida con ella!", + "¿Te preguntas dónde debes hacerlo? Los Dungeons están marcados con puntos marrones en el mapa!", + "No te olvides de ajustar los gráficos de tu pc. Presiona 'N' para abrir la configuración.", + "Jugar con otros es divertido! Presiona 'O' para ver quien esta conectado.", + "Un NPC con un craneo debajo de su barra de vida es bastante más poderoso comparado contigo.", + "Presiona 'J' para bailar. Fiesta!", + "Presiona 'Shift-Izquierdo' para abrir tu planeador y conquistar los cielos.", + "Veloren está aún en Alfa temprana. Hacemos lo mejor para mejorar día a día!", + "Si te quieres unir al equipo de desarrolladores o solo chatear con nosotros, únete a nuestro servidor en Discord.", + "Puedes elegir mostrar tu cantidad de vida en la barra de vida en la configuración.", + "Para ver tus estadísticas, haz click en el botón 'Estadísticas' en el inventario.", + ], } ) diff --git a/assets/voxygen/i18n/es_LA/npc.ron b/assets/voxygen/i18n/es_LA/npc.ron new file mode 100644 index 0000000000..b2ac47bf75 --- /dev/null +++ b/assets/voxygen/i18n/es_LA/npc.ron @@ -0,0 +1,93 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for "latinoamericano" Latin-American +( + string_map: { + + }, + + + vector_map: { + "npc.speech.villager_under_attack": [ + "Ayuda, ¡Me están atacando!", + "¡Ayuda! ¡Me están atacando!", + "¡Auch! ¡Me están atacando!", + "¡Auch! ¡Me están atacando! ¡Ayuda!", + "¡Ayudenme! ¡Me están atacando!", + "¡Me están atacando! ¡Ayuda!", + "¡Me están atacando! ¡Ayudenme!", + "¡Ayuda!", + "¡Ayuda! ¡Ayuda!", + "¡Ayuda! ¡Ayuda! ¡Ayuda!", + "¡Me están atacando!", + "¡AAAHH! ¡Me están atacando!", + "¡AAAHH! ¡Me están atacando! ¡Ayuda!", + "Ayuda! Nos están atacando!", + "¡Ayuda! ¡Asesino!", + "¡Ayuda! ¡Hay un asesino suelto!", + "¡Ayuda! ¡están intentando matarme!", + "Guardias, ¡Me están atacando!", + "¡Guardias! ¡Me están atacando!", + "¡Me están atacando! ¡Guardias!", + "¡Ayuda! ¡Guardias! ¡Me están atacando!", + "¡Guardias! ¡Vengan rapido!", + "¡Guardias, Guardias!", + "¡Guardias! ¡Me esta atacando un villano!", + "¡Guardias, eliminen a este desagradable villano!", + "¡Guardias! ¡Ahi esta el asesino!", + "¡Guardias! ¡Ayúdenme!", + "No te saldrás con la tuya, ¡Guardias!", + "¡Eres despreciable!", + "¡Ayúdenme!", + "¡Ayuda! ¡Porfavor!", + "¡Auch! ¡Guardias! ¡Ayuda!", + "¡Vienen por mi!", + "¡Ayuda! ¡Ayuda! Estoy siendo atacado", + "Ah, se nota que la violencia es parte del sistema.", + "¡Esto no es más que un rasguño!", + "Deja de hacer eso!", + "¿Qué te hice para merecer esto?", + "Por favor, para de atacarme!", + "Hey! Mira hacia adonde apuntas con esa cosa", + "Desgraciado, vete de aqui!", + "Para ya! Vete!", + "Me estas haciendo enojar!", + "Hey!¿Quién te piensas que eres?", + "Te arrancaré la cabeza por eso!", + "Detente, por favor! No llevo nada de valor!", + "Te voy a mandar a mi hermano, el es más grande que yo!", + "Nooo, le contaré a mi madre!", + "Maldito seas!", + "Por favor no lo hagas.", + "Eso no fue agradable!", + "Tu arma funciona, ahora aléjala!", + "Si claro...", + "Por favor, tengo familia!", + "Soy demasiado jóven para morir!", + "¿Podemos hablar sobre esto?", + "La violencia no resuelve nada!", + "Este día se esta convirtiendo en uno muy feo...", + "Hey, eso dolió!", + "Ayy!", + "Qué violento!", + "Detente, te lo suplico!", + "Ojala te enfermes!", + "Esto no es divertido.", + "¡¿Cómo te atreves?!", + "Vas a pagar por eso!", + "Sigue con eso y lo lamentarás!", + "No hagas que te lastime!", + "Tiene que ser un malentendido!", + "No necesitas hacer esto!", + "Vete, demonio!", + "Eso realmente dolió!", + "¿Por qué harias eso?", + "Por todos los Santos, para!", + "Me habrás confudido con alguien más!", + "No me merezco esto!", + "Por favor, no lo hagas de nuevo", + "Guardias, tiren este monstruo al lago", + "Invocaré mis demonios en ti!", + ], + } +) diff --git a/assets/voxygen/i18n/fr_FR/_manifest.ron b/assets/voxygen/i18n/fr_FR/_manifest.ron index f7c3372ce9..f44b21ee01 100644 --- a/assets/voxygen/i18n/fr_FR/_manifest.ron +++ b/assets/voxygen/i18n/fr_FR/_manifest.ron @@ -26,198 +26,5 @@ asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", scale_ratio: 0.9, ), - }, - string_map: { - - }, - - - vector_map: { - "loading.tips": [ - "Appuyez sur 'G' pour allumer ta lanterne.", - "Appuyez sur 'F1' pour voir les raccourcis clavier par défaut.", - "Vous pouvez taper /say ou /s pour discuter aux joueurs directement à côté toi.", - "Vous pouvez taper /region ou /r pour discuter avec les joueurs situés à quelques centaines de blocs de toi.", - "Pour envoyer un message privé, tapez /tell suivi par un nom de joueur puis votre message.", - "Des PNJs avec le même niveau peuvent varier en difficulté.", - "Regardez le sol pour trouver de la nourriture, des coffres et d'autres butins !", - "Votre inventaire est rempli de nourriture ? Essayez de créer un meilleur repas avec !", - "Vous cherchez une activité ? Essayez de visiter un des donjons marqués sur la carte !", - "N'oubliez pas d'ajuster les graphismes pour votre système. Appuyez sur 'N' pour ouvrir les paramètres.", - "Jouer à plusieurs est amusant ! Appuyez sur 'O' pour voir qui est en ligne.", - "Un PNJ avec une tête de mort sous sa barre de vie est plus puissant que vous.", - "Appuyez sur 'J' pour danser. C'est la fête !", - "Appuyez sur 'L-Shift' pour ouvrir votre deltaplane et conquérir les cieux.", - "Veloren est encore en Pré-Alpha. Nous faisons de notre mieux pour l'améliorer chaque jour !", - "Si vous voulez vous joindre à l'équipe de développement ou juste discuter avec nous, rejoignez notre serveur Discord.", - "Vous pouvez afficher ou non combien de santé vous avez dans les options.", - "Pour voir vos statistiques, cliquez sur le bouton 'Stats' dans l'inventaire", - "Asseyez-vous près d'un feu de camp (avec la touche 'K') pour vous reposer - cela régénèrera votre santé.", - ], - "npc.speech.villager": [ - "N'est-ce pas une journée magnifique ?", - "Comment allez-vous aujourd'hui ?", - "Bien le bonjour à vous !", - "Je me demande ce que pense le Catoblepas quand il mange de l'herbe.", - "Que pensez-vous de ce temps ?", - "Penser à ces donjons m'angoisse un peu. J'espère que quelqu'un ira les nettoyer.", - "J'aimerais aller faire de la spéléologie dans une grotte quand je serai plus fort.", - "Avez-vous vu mon chat ?", - "Avez-vous déjà entendu parler des féroces Requins Terrestres ? J'ai entendu dire qu'ils vivent dans les déserts.", - "On dit que des pierres précieuses de toutes sortes peuvent être trouvées dans les grottes.", - "Je suis juste un mordu du fromage !", - "Vous ne voulez pas entrer ? Nous étions sur le point de manger du fromage !", - "On dit que les champignons sont bons pour la santé. Je n'en ai jamais mangé.", - "N'oubliez pas les biscuits !", - "J'adore tout simplement le fromage des nains. J'aimerais pouvoir en faire par moi-même.", - "Je me demande ce qu'il y a de l'autre côté des montagnes", - "J'espère pouvoir fabriquer mon propre planeur un jour.", - "Vous voulez voir mon jardin ? D'accord, peut-être une autre fois.", - "Belle journée pour une promenade dans les bois !", - "Être ou ne pas être ? Je pense que je serai un fermier.", - "Ne pensez-vous pas que notre village est le meilleur ?", - "D'après vous, qu'est-ce qui fait briller les Restes Lumineux ?", - "Je crois que c'est l'heure du deuxième petit-déjeuner !", - "Avez-vous déjà attrapé une luciole ?", - "Je n'arrive pas à comprendre d'où viennent ces Sauroks.", - "J'aimerais que quelqu'un garde les loups loin du village.", - "J'ai fait un merveilleux rêve sur le fromage la nuit dernière. Qu'est-ce que cela signifie ?", - ], - "npc.speech.villager_decline_trade": [ - "Désolé, je n'ai rien à vous échanger.", - "Un échange ? Comme si que j'avais quoi que ce soit qui vous intéresserait.", - "Ma maison n'est pas à vendre.", - ], - "npc.speech.merchant_advertisement": [ - "Seriez-vous intéressé par un échange ?", - "Voulez-vous faire un échange ?", - "J'ai pu amasser beaucoup d'objets, vous voulez y jeter un oeil ?" - ], - "npc.speech.merchant_busy": [ - "Hey, attendez votre tour.", - "Attendez s'il vous plait, je ne suis pas une pieuvre.", - "Un moment, laissez-moi terminer.", - "On ne dépasse pas.", - "Je suis occupé, revenez plus tard." - ], - "npc.speech.merchant_trade_successful": [ - "Merci d'avoir échangé avec moi", - "Merci!", - "Ce fut un plaisir d'échanger avec vous!" - ], - "npc.speech.merchant_trade_declined": [ - "Peut-être pour un autre jour, bonne journée !", - "Dommage, à la revoyure !" - ], - "npc.speech.villager_cultist_alarm": [ - "Attention ! Il y a un cultiste en liberté !", - "Aux armes ! Les cultistes attaquent !", - "Comment les cultistes osent-ils attaquer notre village ?", - "Mort aux cultistes !", - "Les cultistes ne seront pas tolérés ici !", - "Cultistes meurtriers !", - "Goûte le tranchant de mon épée, espèce de sale cultiste !", - "Rien ne peut nettoyer le sang de tes mains, cultiste !", - "Milles milliards de bernacles bleus foudroyants ! Un cultiste parmi nous !", - "On va mettre un terme aux méfaits de ce cultiste !", - "Ce cultiste est à moi !", - "Prépare-toi à rencontrer ton créateur, sale cultiste !", - "J'aperçois un cultiste ! Attrapez-le !", - "J'aperçois un cultiste ! Attaquez !", - "J'aperçois un cultiste ! Ne le laissez pas s'échapper !", - "Le plus honorable des cultistes aurait-il envie de MOURIR ?!", - "Ne pardonnez jamais ! N'oubliez jamais ! Cultiste, regrette !", - "Meurs, cultiste !", - "Votre règne de terreur va cesser !", - "Voilà, pour tout ce que vous avez fait !", - "On n'aime pas trop les gens comme vous par ici.", - "Vous auriez dû rester sous terre !", - ], - "npc.speech.villager_under_attack": [ - "À l'aide, on m'attaque !", - "À l'aide ! On m'attaque !", - "Aïe ! On m'attaque !", - "Aïe ! On m'attaque ! À l'aide !", - "Aidez-moi! On m'attaque !", - "On m'attaque ! À l'aide !", - "On m'attaque ! Aidez-moi !", - "À l'aide !", - "À l'aide ! À l'aide !", - "À l'aide ! À l'aide ! À l'aide !", - "On m'attaque !", - "AAAHHH ! On m'attaque !", - "AAAHHH ! On m'attaque ! À l'aide !", - "À l'aide ! Nous sommes attaqués !", - "À l'aide ! Assassin !", - "À l'aide ! Il y a un assassin en liberté !", - "À l'aide ! On essaie de me tuer !", - "Gardes, on m'attaque !", - "Gardes ! On m'attaque !", - "On m'attaque ! Gardes !", - "À l'aide ! Gardes ! On m'attaque !", - "Gardes ! Venez vite !", - "Gardes ! Gardes !", - "Gardes ! Un scélérat m'attaque !", - "Gardes, abattez ce scélérat !", - "Gardes ! Il y a un meurtrier !", - "Gardes ! Aidez-moi!", - "Vous ne vous en tirerez pas comme ça! Gardes !", - "Monstre !", - "Aidez-moi!", - "À l'aide ! S'il vous plait !", - "Aïe ! Gardes ! À l'aide !", - "Ils viennent pour moi !", - "À l'aide ! À l'aide ! Je me fais réprimer !", - "Ah, nous voyons maintenant la violence inhérente au système.", - "C'est seulement une égratignure.", - "Arrêtez ça !", - "Qu'est ce que je vous ai fait ?!", - "S'il vous plaît arrêtez de m'attaquer !", - "Hé! Regardez où vous pointez cette chose !", - "Misérable, allez-vous-en !", - "Arrêtez ! Partez ! Arrêtez !", - "Vous m'avez ennervé !", - "Oi ! Qui croyez-vous être ?!", - "J'aurais votre tête pour ça !", - "Arrêtez, s'il vous plaît ! Je ne transporte rien de valeur !", - "Je vais appeler mon frère, il est plus grand que moi !", - "Nooon, Je vais le dire à ma mère !", - "Soyez maudit !", - "Ne faites pas ça.", - "Ce n'était pas très gentil !", - "Ton arme fonctionne, tu peux la ranger maintenant !", - "Épargnez-moi !", - "Pitié, J'ai une famille !", - "Je suis trop jeune pour mourrir !", - "On peut en parler ?", - "La violence n'est jamais la solution !", - "Aujourd'hui est une très mauvaise journée...", - "Hé, ça fait mal !", - "Aïe !", - "Quelle impolitesse !", - "Stop, je vous en prie !", - "Que la peste vous emporte !", - "Ce n'est pas amusant.", - "Comment osez-vous ?!", - "Vous allez payer !", - "Continue et tu vas le regretter !", - "Ne m'obligez pas à vous faire du mal !", - "Il doit y avoir erreur !", - "Vous n'avez pas besoin de faire ça !", - "Fuyez, monstre !", - "Ça fait vraiment mal !", - "Pourquoi faites-vous cela ?", - "Par les esprits, cessez !", - "Vous devez m'avoir confondu avec quelqu'un d'autre !", - "Je ne mérite pas cela !", - "Ne faites plus cela.", - "Gardes, jetez ce monstre dans le lac !", - "Je vais t'envoyer ma tarrasque !", - ], - "npc.speech.villager_enemy_killed": [ - "J'ai détruit mon ennemi !", - "Enfin en paix !", - "... qu'est-ce que je faisais déjà ?", - ], } ) diff --git a/assets/voxygen/i18n/fr_FR/main.ron b/assets/voxygen/i18n/fr_FR/main.ron index 690870a7e3..e5d969e2fb 100644 --- a/assets/voxygen/i18n/fr_FR/main.ron +++ b/assets/voxygen/i18n/fr_FR/main.ron @@ -60,5 +60,26 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "Appuyez sur 'G' pour allumer ta lanterne.", + "Appuyez sur 'F1' pour voir les raccourcis clavier par défaut.", + "Vous pouvez taper /say ou /s pour discuter aux joueurs directement à côté toi.", + "Vous pouvez taper /region ou /r pour discuter avec les joueurs situés à quelques centaines de blocs de toi.", + "Pour envoyer un message privé, tapez /tell suivi par un nom de joueur puis votre message.", + "Des PNJs avec le même niveau peuvent varier en difficulté.", + "Regardez le sol pour trouver de la nourriture, des coffres et d'autres butins !", + "Votre inventaire est rempli de nourriture ? Essayez de créer un meilleur repas avec !", + "Vous cherchez une activité ? Essayez de visiter un des donjons marqués sur la carte !", + "N'oubliez pas d'ajuster les graphismes pour votre système. Appuyez sur 'N' pour ouvrir les paramètres.", + "Jouer à plusieurs est amusant ! Appuyez sur 'O' pour voir qui est en ligne.", + "Un PNJ avec une tête de mort sous sa barre de vie est plus puissant que vous.", + "Appuyez sur 'J' pour danser. C'est la fête !", + "Appuyez sur 'L-Shift' pour ouvrir votre deltaplane et conquérir les cieux.", + "Veloren est encore en Pré-Alpha. Nous faisons de notre mieux pour l'améliorer chaque jour !", + "Si vous voulez vous joindre à l'équipe de développement ou juste discuter avec nous, rejoignez notre serveur Discord.", + "Vous pouvez afficher ou non combien de santé vous avez dans les options.", + "Pour voir vos statistiques, cliquez sur le bouton 'Stats' dans l'inventaire", + "Asseyez-vous près d'un feu de camp (avec la touche 'K') pour vous reposer - cela régénèrera votre santé.", + ], } ) diff --git a/assets/voxygen/i18n/fr_FR/npc.ron b/assets/voxygen/i18n/fr_FR/npc.ron new file mode 100644 index 0000000000..ec75dfa123 --- /dev/null +++ b/assets/voxygen/i18n/fr_FR/npc.ron @@ -0,0 +1,175 @@ +/// Localization for French (France locale) +( + string_map: { + + }, + + + vector_map: { + "npc.speech.villager": [ + "N'est-ce pas une journée magnifique ?", + "Comment allez-vous aujourd'hui ?", + "Bien le bonjour à vous !", + "Je me demande ce que pense le Catoblepas quand il mange de l'herbe.", + "Que pensez-vous de ce temps ?", + "Penser à ces donjons m'angoisse un peu. J'espère que quelqu'un ira les nettoyer.", + "J'aimerais aller faire de la spéléologie dans une grotte quand je serai plus fort.", + "Avez-vous vu mon chat ?", + "Avez-vous déjà entendu parler des féroces Requins Terrestres ? J'ai entendu dire qu'ils vivent dans les déserts.", + "On dit que des pierres précieuses de toutes sortes peuvent être trouvées dans les grottes.", + "Je suis juste un mordu du fromage !", + "Vous ne voulez pas entrer ? Nous étions sur le point de manger du fromage !", + "On dit que les champignons sont bons pour la santé. Je n'en ai jamais mangé.", + "N'oubliez pas les biscuits !", + "J'adore tout simplement le fromage des nains. J'aimerais pouvoir en faire par moi-même.", + "Je me demande ce qu'il y a de l'autre côté des montagnes", + "J'espère pouvoir fabriquer mon propre planeur un jour.", + "Vous voulez voir mon jardin ? D'accord, peut-être une autre fois.", + "Belle journée pour une promenade dans les bois !", + "Être ou ne pas être ? Je pense que je serai un fermier.", + "Ne pensez-vous pas que notre village est le meilleur ?", + "D'après vous, qu'est-ce qui fait briller les Restes Lumineux ?", + "Je crois que c'est l'heure du deuxième petit-déjeuner !", + "Avez-vous déjà attrapé une luciole ?", + "Je n'arrive pas à comprendre d'où viennent ces Sauroks.", + "J'aimerais que quelqu'un garde les loups loin du village.", + "J'ai fait un merveilleux rêve sur le fromage la nuit dernière. Qu'est-ce que cela signifie ?", + ], + "npc.speech.villager_decline_trade": [ + "Désolé, je n'ai rien à vous échanger.", + "Un échange ? Comme si que j'avais quoi que ce soit qui vous intéresserait.", + "Ma maison n'est pas à vendre.", + ], + "npc.speech.merchant_advertisement": [ + "Seriez-vous intéressé par un échange ?", + "Voulez-vous faire un échange ?", + "J'ai pu amasser beaucoup d'objets, vous voulez y jeter un oeil ?" + ], + "npc.speech.merchant_busy": [ + "Hey, attendez votre tour.", + "Attendez s'il vous plait, je ne suis pas une pieuvre.", + "Un moment, laissez-moi terminer.", + "On ne dépasse pas.", + "Je suis occupé, revenez plus tard." + ], + "npc.speech.merchant_trade_successful": [ + "Merci d'avoir échangé avec moi", + "Merci!", + "Ce fut un plaisir d'échanger avec vous!" + ], + "npc.speech.merchant_trade_declined": [ + "Peut-être pour un autre jour, bonne journée !", + "Dommage, à la revoyure !" + ], + "npc.speech.villager_cultist_alarm": [ + "Attention ! Il y a un cultiste en liberté !", + "Aux armes ! Les cultistes attaquent !", + "Comment les cultistes osent-ils attaquer notre village ?", + "Mort aux cultistes !", + "Les cultistes ne seront pas tolérés ici !", + "Cultistes meurtriers !", + "Goûte le tranchant de mon épée, espèce de sale cultiste !", + "Rien ne peut nettoyer le sang de tes mains, cultiste !", + "Milles milliards de bernacles bleus foudroyants ! Un cultiste parmi nous !", + "On va mettre un terme aux méfaits de ce cultiste !", + "Ce cultiste est à moi !", + "Prépare-toi à rencontrer ton créateur, sale cultiste !", + "J'aperçois un cultiste ! Attrapez-le !", + "J'aperçois un cultiste ! Attaquez !", + "J'aperçois un cultiste ! Ne le laissez pas s'échapper !", + "Le plus honorable des cultistes aurait-il envie de MOURIR ?!", + "Ne pardonnez jamais ! N'oubliez jamais ! Cultiste, regrette !", + "Meurs, cultiste !", + "Votre règne de terreur va cesser !", + "Voilà, pour tout ce que vous avez fait !", + "On n'aime pas trop les gens comme vous par ici.", + "Vous auriez dû rester sous terre !", + ], + "npc.speech.villager_under_attack": [ + "À l'aide, on m'attaque !", + "À l'aide ! On m'attaque !", + "Aïe ! On m'attaque !", + "Aïe ! On m'attaque ! À l'aide !", + "Aidez-moi! On m'attaque !", + "On m'attaque ! À l'aide !", + "On m'attaque ! Aidez-moi !", + "À l'aide !", + "À l'aide ! À l'aide !", + "À l'aide ! À l'aide ! À l'aide !", + "On m'attaque !", + "AAAHHH ! On m'attaque !", + "AAAHHH ! On m'attaque ! À l'aide !", + "À l'aide ! Nous sommes attaqués !", + "À l'aide ! Assassin !", + "À l'aide ! Il y a un assassin en liberté !", + "À l'aide ! On essaie de me tuer !", + "Gardes, on m'attaque !", + "Gardes ! On m'attaque !", + "On m'attaque ! Gardes !", + "À l'aide ! Gardes ! On m'attaque !", + "Gardes ! Venez vite !", + "Gardes ! Gardes !", + "Gardes ! Un scélérat m'attaque !", + "Gardes, abattez ce scélérat !", + "Gardes ! Il y a un meurtrier !", + "Gardes ! Aidez-moi!", + "Vous ne vous en tirerez pas comme ça! Gardes !", + "Monstre !", + "Aidez-moi!", + "À l'aide ! S'il vous plait !", + "Aïe ! Gardes ! À l'aide !", + "Ils viennent pour moi !", + "À l'aide ! À l'aide ! Je me fais réprimer !", + "Ah, nous voyons maintenant la violence inhérente au système.", + "C'est seulement une égratignure.", + "Arrêtez ça !", + "Qu'est ce que je vous ai fait ?!", + "S'il vous plaît arrêtez de m'attaquer !", + "Hé! Regardez où vous pointez cette chose !", + "Misérable, allez-vous-en !", + "Arrêtez ! Partez ! Arrêtez !", + "Vous m'avez ennervé !", + "Oi ! Qui croyez-vous être ?!", + "J'aurais votre tête pour ça !", + "Arrêtez, s'il vous plaît ! Je ne transporte rien de valeur !", + "Je vais appeler mon frère, il est plus grand que moi !", + "Nooon, Je vais le dire à ma mère !", + "Soyez maudit !", + "Ne faites pas ça.", + "Ce n'était pas très gentil !", + "Ton arme fonctionne, tu peux la ranger maintenant !", + "Épargnez-moi !", + "Pitié, J'ai une famille !", + "Je suis trop jeune pour mourrir !", + "On peut en parler ?", + "La violence n'est jamais la solution !", + "Aujourd'hui est une très mauvaise journée...", + "Hé, ça fait mal !", + "Aïe !", + "Quelle impolitesse !", + "Stop, je vous en prie !", + "Que la peste vous emporte !", + "Ce n'est pas amusant.", + "Comment osez-vous ?!", + "Vous allez payer !", + "Continue et tu vas le regretter !", + "Ne m'obligez pas à vous faire du mal !", + "Il doit y avoir erreur !", + "Vous n'avez pas besoin de faire ça !", + "Fuyez, monstre !", + "Ça fait vraiment mal !", + "Pourquoi faites-vous cela ?", + "Par les esprits, cessez !", + "Vous devez m'avoir confondu avec quelqu'un d'autre !", + "Je ne mérite pas cela !", + "Ne faites plus cela.", + "Gardes, jetez ce monstre dans le lac !", + "Je vais t'envoyer ma tarrasque !", + ], + "npc.speech.villager_enemy_killed": [ + "J'ai détruit mon ennemi !", + "Enfin en paix !", + "... qu'est-ce que je faisais déjà ?", + ], + } +) diff --git a/assets/voxygen/i18n/hu_HU/_manifest.ron b/assets/voxygen/i18n/hu_HU/_manifest.ron index 6d816329b8..7427a781ee 100644 --- a/assets/voxygen/i18n/hu_HU/_manifest.ron +++ b/assets/voxygen/i18n/hu_HU/_manifest.ron @@ -28,206 +28,5 @@ asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", scale_ratio: 1.0, ), - }, - - string_map: { - - }, - - vector_map: { - "loading.tips": [ - "Lámpásod meggyújtásához nyomd meg a 'G' gombot!", - "Az alapértelmezett billentyű-összerendelések megtekintéséhez nyomd meg az 'F1' gombot!", - "Ha beírod a csevegésbe a /say vagy a /s parancsot, lehetőséged nyílik arra, hogy csak a közvetlen közeledben lévő játékosokkal beszélgess.", - "Ha beírod a csevegésbe a /region vagy a /r parancsot, lehetőséged nyílik arra, hogy csak a tőled max pár száz blokkra lévő játékosokkal beszélgess.", - "Az adminisztrátorok használhatják a /build parancsot – ezzel léphetnek be az építő módba.", - "Ha beírod a csevegésbe a /group vagy a /g parancsot, lehetőséged nyílik arra, hogy csak a csoportodban lévő játékosokkal beszélgess.", - "Privát üzenetek küldéséhez írd be a csevegésbe a /tell parancsot, majd a játékos nevét, végül pedig az üzenetet.", - "Érdemes nyitott szemmel járni, hiszen rengeteg étel, láda és egyéb zsákmány található szerte a világban!", - "Túl sok az étel a holmijaid között? Próbálj meg jobb ételt kotyvasztani belőlük!", - "Azon tűnődsz, hogy mit kellene csinálnod? Tedd magad próbára a térképen megjelölt kazamaták valamelyikében!", - "Ne felejtsd el a rendszeredhez igazítani a grafikát! A beállítások megtekintéséhez nyomd meg az 'N' gombot!", - "Másokkal játszani bizony jó muri! Hogy lásd, épp ki van fönn a hálózaton nyomd meg az 'O' gombot!", - "A táncoláshoz nyomd meg a 'J' gombot. Bulira föl!", - "Nyomd meg a 'Bal Ctrl'-t és hódítsd meg sárkányrepülőddel az eget!", - "A Veloren még mindig előzetes alfában van. Igyekszünk mindent megtenni annak érdekében, hogy napról-napra jobb és jobb legyen!", - "Szeretnél a feljesztői csapat tagja lenni, vagy netán csak csevegnél velünk? Csatlakozz a Discord szerverünkhöz!", - "A beállításokban azt is eldöntheted, hogy megjelenjen-e az életerőd mennyisége az életerő sávban, vagy sem.", - "Ha lehuppansz (a 'K' gombbal) egy tábortűz mellé szép lassan be fognak gyógyulni a sebeid.", - "Több holmitartóra vagy jobb páncélzatra van szükséged? Nyomd meg a 'C' gombot, és nézz szét a tárgykészítési menüben!", - "Próbálj meg ugrani egyet, miközben keresztülbukfencezel másokon!", - ], - "npc.speech.villager": [ - "Csodás napunk van, nemde?", - "Hogy vagy?", - "Áldott jó reggelt kívánok!", - "Vajon mire gondol a Catoblepas, miközben legelészik?", - "Mit szólsz ehhez az időjáráshoz?", - "Akárhányszor azokra a kazamatákre gondolok elfog a félelem. Remélem valaki majd megtisztítja őket...", - "Majd szeretnék elmenni barlangászni, amikor már erősebb leszek.", - "Nem láttad a macskámat?", - "Hallottál már a veszedelmes földi cápákról? Úgy tudom a sivatagokban élnek.", - "Azt mondják a barlangok tele vannak mindenféle fényes drágakővel.", - "Megőrülök a sajtért!", - "Nem nézel be hozzánk? Épp most terveztünk nekiállni sajtozni!", - "Azt mondják a gomba jót tesz az egészségednek. Én magam nem szoktam enni.", - "A kekszeket ne feledd!", - "Egyszerűen rajongok a törpe sajtért. Bárcsak én is el tudnám készíteni...", - "Mi lehet vajon a hegyen túl?", - "Remélem egyszer majd elkészíthetem a saját sárkányrepülőmet.", - "Szeretnéd látni a kertem? Hát jó, talán majd máskor.", - "Kitűnő nap ez a mai egy jó erdei sétához!", - "Lenni, vagy nem lenni? Én azt hiszem farmer leszek.", - "Hát nem a mi városkánk a legjobb?", - "Szerinted mitől ragyognak a ragyogó maradványok?", - "Azt hiszem eljött a második reggeli ideje!", - "Fogtál már szentjánosbogarat?", - "Egyszerűen képtelen vagyok rájönni, hogy ugyan honnan jönnek ezek a Saurokok...", - "Bárcsak távol tartaná valaki a farkasokat a városkától...", - "Csodás, sajtos álomban volt tegnap este részem. Mit jelenthet ez vajon?", - "Hagytam egy kis sajtot az öcsémnél. Nem tudom, hogy megvan-e még. Úgy hívom, hogy Schrödinger sajtja.", - "Hagytam egy kis sajtot a húgomnál. Nem tudom, hogy megvan-e még. Úgy hívom, hogy Schrödinger sajtja.", - "Valaki igazán kezdhetne már valamit ezekkel a kultistákkal! Valaki rajtam kívül...", - "Remélem jön némi eső hamarosan, jót tenne a terménynek.", - "Imádom a mézet... és utálom a méheket.", - "Egy napon majd szeretnék világot látni. Csak tartogat nekem valamit az élet ezen a városkán kívül is.", - ], - "npc.speech.villager_decline_trade": [ - "Sajnálom, én nem tudok mit áruba bocsájtani.", - "Üzletelni? Velem? Mintha lenne bármim, ami fel tudná kelteni az érdeklődésedet...", - "A ház az enyém! Nem fogom elcserélni semmiért!", - ], - "npc.speech.merchant_advertisement": [ - "Ajánlhatok személyemben egy kereskedőpartnert?", - "Szeretnél velem üzletelni?", - "Rengeteg árum van, szeretnél vetni rájuk egy pillantást?" - ], - "npc.speech.merchant_busy": [ - "Hé, várd ki a sorod!", - "Várj egy kicsit légyszíves, belőlem is csak egy van.", - "Látod ezt a másik embert előtted?", - "Egy pillanat, hadd fejezzem be!", - "Ne vágj be mások elé!", - "Most épp nem érek rá, gyere vissza később!" - ], - "npc.speech.merchant_trade_successful": [ - "Köszönöm, hogy velem üzleteltél!", - "Hálás köszönet!", - ], - "npc.speech.merchant_trade_declined": [ - "Talán majd máskor. Legyen szép napod!", - "Kár, majd talán legközelebb!" - ], - "npc.speech.villager_cultist_alarm": [ - "Vigyázat! Elszabadult egy kultista!", - "Fegyverbe! Támadnak a kultisták!", - "Hogy merik a kultisták megtámadni a mi városkánkat?!", - "Halál a kultistákra!", - "Itt nem tűrünk meg egy kultistát sem!", - "Te véres kultista!", - "Ízleld meg a kardom élét, mocskos kultista!", - "Semmi nem moshatja le a vért a kezedről, kultista!", - "Millió mérgező mályvaszín medúza! Egy kultista van köztünk!", - "A kultisták gonoszkodásainak hamarosan vége!", - "Ez a kultista az enyém!", - "Ideje, hogy találkozz a teremtőddel, aljas kultista!", - "Itt egy kultista! Kapjuk el!", - "Itt egy kultista! Támadás!", - "Itt egy kultista! Ne hagyjuk megszökni!", - "Nem óhajt kultista őméltósága egy kis HALÁLT?!", - "Nincs bocsánat! Nincs feledés! Kultisták, bűnhődjetek!", - "Pusztulj, kultista!", - "Egyszer véget ér a rémuralmatok!", - "Ezt azt eddigi tetteitekért!", - "Nem látjuk szívesen a fajtátokat errefelé!", - "Maradtatok volna a föld alatt!", - ], - "npc.speech.villager_under_attack": [ - "Segítség, Megtámadtak!", - "Segítség, Megtámadtak!", - "Aúú! Megtámadtak!!", - "Aúú! Megtámadtak! Segítség!", - "Segítsetek! Megtámadtak!", - "Megtámadtak! Segítség!", - "Megtámadtak! Segítsetek!", - "Segítség!", - "Segítség! Segítség!", - "Segítség! Segítség! Segítség!", - "Megtámadtak!", - "ÁÁÁÁÁÁ! Megtámadtak!", - "ÁÁÁÁÁÁ! Megtámadtak! Segítség!", - "Segítség! Megtámadtak minket!", - "Segítség! Gyilkos!", - "Segítség! Elszabadult egy gyilkos!", - "Segítség! Meg akarnak ölni!", - "Őrség, Megtámadtak!", - "Őrség! Megtámadtak!", - "Megtámadtak! Őrség!", - "Segítség! Őrség! Megtámadtak!", - "Őrség! Gyertek gyorsan!", - "Őrség! Őrség!", - "Őrség! Egy gazember megtámadott!", - "Őrség, aprítsátok fel ezt az alávaló gazembert!", - "Őrség! Itt egy gyilkos!", - "Őrség! Segítsetek!", - "Ezt nem úszod meg szárazon! Őrség!", - "Te senkiházi!", - "Valaki segítsen!!", - "Segítsetek! Kérlek!", - "Aúú! Őrség! Segítség!", - "Engem akarnak!", - "Segítség! Segítség! Valaki le akar gyűrni!", - "Áá, most láthatjuk a rendszerrel járó erőszakot.", - "Ez csak egy karcolás!", - "Hagyd abba!", - "Ártottam én neked valaha?!", - "Kérlek ne bántalmazz tovább!", - "Hé! Vigyázz, merre irányzod azt a dolgot!", - "Takarodj innen, te mocskos gazember!", - "Hagyd abba! Menj innen!", - "Sikerült igencsak felbőszítened!", - "Hé! Kinek képzeled magad?!", - "Ezért a fejeddel fogsz fizetni!", - "Hagyd abba, kérlek! Nincs nálam semmi értékes!", - "Rád uszítom a bátyámat, ő nagyobb, mint én!", - "Neee, megmondalak anyának!", - "Légy átkozott!", - "Kérlek ne tedd ezt!", - "Ez nem volt szép tőled!", - "Hatásos a fegyvered, most már igazán elrakhatnád!", - "Könyörülj rajtam!", - "Kérlek, családom van!", - "Még túl fiatal vagyok a halálhoz!", - "Nem tudnánk ezt megbeszélni?", - "Az erőszak nem megoldás!", - "Úgy látszik igencsak pocsék nap ez a mai...", - "Hé, ez fáj!", - "Ííí!", - "Milyen durva vagy!", - "Könyörögve kérlek, hagyd abba!", - "A fene vigyen el!", - "Ez nem vicces!", - "Hogy merészeled?!", - "Ezért megfizetsz!", - "Nagyon meg fogod bánni, ha ezt tovább folytatod!", - "Ne akard, hogy bántsalak!", - "Itt valami félreértés lesz!", - "Erre nincs semmi szükség!", - "Takarodj, te pokolfajzat!", - "Ez nagyon fáj!", - "Miért tennél ilyet?!", - "A szellemekre, hagyd abba!", - "Biztos keversz engem valakivel!", - "Én nem ezt érdemlem!", - "Ezt kérlek ne!", - "Őrség, dobjátok ezt a szörnyeteget a tóba!", - "Rád uszítom a taraszkomat!", - "Mért éééééén?", - ], - "npc.speech.villager_enemy_killed": [ - "Eltiportam az ellenségemet!", - "Végre ismét békességben!", - "...no, hol is tartottam?", - ] } ) diff --git a/assets/voxygen/i18n/hu_HU/main.ron b/assets/voxygen/i18n/hu_HU/main.ron index 9275a0a5f8..017b4c8d9a 100644 --- a/assets/voxygen/i18n/hu_HU/main.ron +++ b/assets/voxygen/i18n/hu_HU/main.ron @@ -67,5 +67,27 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "Lámpásod meggyújtásához nyomd meg a 'G' gombot!", + "Az alapértelmezett billentyű-összerendelések megtekintéséhez nyomd meg az 'F1' gombot!", + "Ha beírod a csevegésbe a /say vagy a /s parancsot, lehetőséged nyílik arra, hogy csak a közvetlen közeledben lévő játékosokkal beszélgess.", + "Ha beírod a csevegésbe a /region vagy a /r parancsot, lehetőséged nyílik arra, hogy csak a tőled max pár száz blokkra lévő játékosokkal beszélgess.", + "Az adminisztrátorok használhatják a /build parancsot – ezzel léphetnek be az építő módba.", + "Ha beírod a csevegésbe a /group vagy a /g parancsot, lehetőséged nyílik arra, hogy csak a csoportodban lévő játékosokkal beszélgess.", + "Privát üzenetek küldéséhez írd be a csevegésbe a /tell parancsot, majd a játékos nevét, végül pedig az üzenetet.", + "Érdemes nyitott szemmel járni, hiszen rengeteg étel, láda és egyéb zsákmány található szerte a világban!", + "Túl sok az étel a holmijaid között? Próbálj meg jobb ételt kotyvasztani belőlük!", + "Azon tűnődsz, hogy mit kellene csinálnod? Tedd magad próbára a térképen megjelölt kazamaták valamelyikében!", + "Ne felejtsd el a rendszeredhez igazítani a grafikát! A beállítások megtekintéséhez nyomd meg az 'N' gombot!", + "Másokkal játszani bizony jó muri! Hogy lásd, épp ki van fönn a hálózaton nyomd meg az 'O' gombot!", + "A táncoláshoz nyomd meg a 'J' gombot. Bulira föl!", + "Nyomd meg a 'Bal Ctrl'-t és hódítsd meg sárkányrepülőddel az eget!", + "A Veloren még mindig előzetes alfában van. Igyekszünk mindent megtenni annak érdekében, hogy napról-napra jobb és jobb legyen!", + "Szeretnél a feljesztői csapat tagja lenni, vagy netán csak csevegnél velünk? Csatlakozz a Discord szerverünkhöz!", + "A beállításokban azt is eldöntheted, hogy megjelenjen-e az életerőd mennyisége az életerő sávban, vagy sem.", + "Ha lehuppansz (a 'K' gombbal) egy tábortűz mellé szép lassan be fognak gyógyulni a sebeid.", + "Több holmitartóra vagy jobb páncélzatra van szükséged? Nyomd meg a 'C' gombot, és nézz szét a tárgykészítési menüben!", + "Próbálj meg ugrani egyet, miközben keresztülbukfencezel másokon!", + ], } ) diff --git a/assets/voxygen/i18n/hu_HU/npc.ron b/assets/voxygen/i18n/hu_HU/npc.ron new file mode 100644 index 0000000000..0a487b19dc --- /dev/null +++ b/assets/voxygen/i18n/hu_HU/npc.ron @@ -0,0 +1,183 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Hungarian +( + string_map: { + + }, + + vector_map: { + "npc.speech.villager": [ + "Csodás napunk van, nemde?", + "Hogy vagy?", + "Áldott jó reggelt kívánok!", + "Vajon mire gondol a Catoblepas, miközben legelészik?", + "Mit szólsz ehhez az időjáráshoz?", + "Akárhányszor azokra a kazamatákre gondolok elfog a félelem. Remélem valaki majd megtisztítja őket...", + "Majd szeretnék elmenni barlangászni, amikor már erősebb leszek.", + "Nem láttad a macskámat?", + "Hallottál már a veszedelmes földi cápákról? Úgy tudom a sivatagokban élnek.", + "Azt mondják a barlangok tele vannak mindenféle fényes drágakővel.", + "Megőrülök a sajtért!", + "Nem nézel be hozzánk? Épp most terveztünk nekiállni sajtozni!", + "Azt mondják a gomba jót tesz az egészségednek. Én magam nem szoktam enni.", + "A kekszeket ne feledd!", + "Egyszerűen rajongok a törpe sajtért. Bárcsak én is el tudnám készíteni...", + "Mi lehet vajon a hegyen túl?", + "Remélem egyszer majd elkészíthetem a saját sárkányrepülőmet.", + "Szeretnéd látni a kertem? Hát jó, talán majd máskor.", + "Kitűnő nap ez a mai egy jó erdei sétához!", + "Lenni, vagy nem lenni? Én azt hiszem farmer leszek.", + "Hát nem a mi városkánk a legjobb?", + "Szerinted mitől ragyognak a ragyogó maradványok?", + "Azt hiszem eljött a második reggeli ideje!", + "Fogtál már szentjánosbogarat?", + "Egyszerűen képtelen vagyok rájönni, hogy ugyan honnan jönnek ezek a Saurokok...", + "Bárcsak távol tartaná valaki a farkasokat a városkától...", + "Csodás, sajtos álomban volt tegnap este részem. Mit jelenthet ez vajon?", + "Hagytam egy kis sajtot az öcsémnél. Nem tudom, hogy megvan-e még. Úgy hívom, hogy Schrödinger sajtja.", + "Hagytam egy kis sajtot a húgomnál. Nem tudom, hogy megvan-e még. Úgy hívom, hogy Schrödinger sajtja.", + "Valaki igazán kezdhetne már valamit ezekkel a kultistákkal! Valaki rajtam kívül...", + "Remélem jön némi eső hamarosan, jót tenne a terménynek.", + "Imádom a mézet... és utálom a méheket.", + "Egy napon majd szeretnék világot látni. Csak tartogat nekem valamit az élet ezen a városkán kívül is.", + ], + "npc.speech.villager_decline_trade": [ + "Sajnálom, én nem tudok mit áruba bocsájtani.", + "Üzletelni? Velem? Mintha lenne bármim, ami fel tudná kelteni az érdeklődésedet...", + "A ház az enyém! Nem fogom elcserélni semmiért!", + ], + "npc.speech.merchant_advertisement": [ + "Ajánlhatok személyemben egy kereskedőpartnert?", + "Szeretnél velem üzletelni?", + "Rengeteg árum van, szeretnél vetni rájuk egy pillantást?" + ], + "npc.speech.merchant_busy": [ + "Hé, várd ki a sorod!", + "Várj egy kicsit légyszíves, belőlem is csak egy van.", + "Látod ezt a másik embert előtted?", + "Egy pillanat, hadd fejezzem be!", + "Ne vágj be mások elé!", + "Most épp nem érek rá, gyere vissza később!" + ], + "npc.speech.merchant_trade_successful": [ + "Köszönöm, hogy velem üzleteltél!", + "Hálás köszönet!", + ], + "npc.speech.merchant_trade_declined": [ + "Talán majd máskor. Legyen szép napod!", + "Kár, majd talán legközelebb!" + ], + "npc.speech.villager_cultist_alarm": [ + "Vigyázat! Elszabadult egy kultista!", + "Fegyverbe! Támadnak a kultisták!", + "Hogy merik a kultisták megtámadni a mi városkánkat?!", + "Halál a kultistákra!", + "Itt nem tűrünk meg egy kultistát sem!", + "Te véres kultista!", + "Ízleld meg a kardom élét, mocskos kultista!", + "Semmi nem moshatja le a vért a kezedről, kultista!", + "Millió mérgező mályvaszín medúza! Egy kultista van köztünk!", + "A kultisták gonoszkodásainak hamarosan vége!", + "Ez a kultista az enyém!", + "Ideje, hogy találkozz a teremtőddel, aljas kultista!", + "Itt egy kultista! Kapjuk el!", + "Itt egy kultista! Támadás!", + "Itt egy kultista! Ne hagyjuk megszökni!", + "Nem óhajt kultista őméltósága egy kis HALÁLT?!", + "Nincs bocsánat! Nincs feledés! Kultisták, bűnhődjetek!", + "Pusztulj, kultista!", + "Egyszer véget ér a rémuralmatok!", + "Ezt azt eddigi tetteitekért!", + "Nem látjuk szívesen a fajtátokat errefelé!", + "Maradtatok volna a föld alatt!", + ], + "npc.speech.villager_under_attack": [ + "Segítség, Megtámadtak!", + "Segítség, Megtámadtak!", + "Aúú! Megtámadtak!!", + "Aúú! Megtámadtak! Segítség!", + "Segítsetek! Megtámadtak!", + "Megtámadtak! Segítség!", + "Megtámadtak! Segítsetek!", + "Segítség!", + "Segítség! Segítség!", + "Segítség! Segítség! Segítség!", + "Megtámadtak!", + "ÁÁÁÁÁÁ! Megtámadtak!", + "ÁÁÁÁÁÁ! Megtámadtak! Segítség!", + "Segítség! Megtámadtak minket!", + "Segítség! Gyilkos!", + "Segítség! Elszabadult egy gyilkos!", + "Segítség! Meg akarnak ölni!", + "Őrség, Megtámadtak!", + "Őrség! Megtámadtak!", + "Megtámadtak! Őrség!", + "Segítség! Őrség! Megtámadtak!", + "Őrség! Gyertek gyorsan!", + "Őrség! Őrség!", + "Őrség! Egy gazember megtámadott!", + "Őrség, aprítsátok fel ezt az alávaló gazembert!", + "Őrség! Itt egy gyilkos!", + "Őrség! Segítsetek!", + "Ezt nem úszod meg szárazon! Őrség!", + "Te senkiházi!", + "Valaki segítsen!!", + "Segítsetek! Kérlek!", + "Aúú! Őrség! Segítség!", + "Engem akarnak!", + "Segítség! Segítség! Valaki le akar gyűrni!", + "Áá, most láthatjuk a rendszerrel járó erőszakot.", + "Ez csak egy karcolás!", + "Hagyd abba!", + "Ártottam én neked valaha?!", + "Kérlek ne bántalmazz tovább!", + "Hé! Vigyázz, merre irányzod azt a dolgot!", + "Takarodj innen, te mocskos gazember!", + "Hagyd abba! Menj innen!", + "Sikerült igencsak felbőszítened!", + "Hé! Kinek képzeled magad?!", + "Ezért a fejeddel fogsz fizetni!", + "Hagyd abba, kérlek! Nincs nálam semmi értékes!", + "Rád uszítom a bátyámat, ő nagyobb, mint én!", + "Neee, megmondalak anyának!", + "Légy átkozott!", + "Kérlek ne tedd ezt!", + "Ez nem volt szép tőled!", + "Hatásos a fegyvered, most már igazán elrakhatnád!", + "Könyörülj rajtam!", + "Kérlek, családom van!", + "Még túl fiatal vagyok a halálhoz!", + "Nem tudnánk ezt megbeszélni?", + "Az erőszak nem megoldás!", + "Úgy látszik igencsak pocsék nap ez a mai...", + "Hé, ez fáj!", + "Ííí!", + "Milyen durva vagy!", + "Könyörögve kérlek, hagyd abba!", + "A fene vigyen el!", + "Ez nem vicces!", + "Hogy merészeled?!", + "Ezért megfizetsz!", + "Nagyon meg fogod bánni, ha ezt tovább folytatod!", + "Ne akard, hogy bántsalak!", + "Itt valami félreértés lesz!", + "Erre nincs semmi szükség!", + "Takarodj, te pokolfajzat!", + "Ez nagyon fáj!", + "Miért tennél ilyet?!", + "A szellemekre, hagyd abba!", + "Biztos keversz engem valakivel!", + "Én nem ezt érdemlem!", + "Ezt kérlek ne!", + "Őrség, dobjátok ezt a szörnyeteget a tóba!", + "Rád uszítom a taraszkomat!", + "Mért éééééén?", + ], + "npc.speech.villager_enemy_killed": [ + "Eltiportam az ellenségemet!", + "Végre ismét békességben!", + "...no, hol is tartottam?", + ] + } +) diff --git a/assets/voxygen/i18n/it_IT/_manifest.ron b/assets/voxygen/i18n/it_IT/_manifest.ron index 99f5180143..67862b8fbc 100644 --- a/assets/voxygen/i18n/it_IT/_manifest.ron +++ b/assets/voxygen/i18n/it_IT/_manifest.ron @@ -28,205 +28,5 @@ asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", scale_ratio: 1.0, ), - }, - - string_map: { - - }, - - vector_map: { - "loading.tips": [ - "Premi 'G' per accendere la tua lanterna.", - "Premi 'F1' per vedere tutte le combinazioni di tasti base.", - "Puoi scrivere /say o /s per chattare solo con giocatori attorno a te.", - "Puoi scrivere /region o /r per chattare solo con giocatori entro qualche centinaio di blocchi attorno a te.", - "Gli Amministratori possono usare il comando /build per entrare in modalità costruzione.", - "Puoi scrivere /group o /g per chattare solo con giocatori attualmente nel tuo gruppo.", - "Per mandare messaggi privati scrivi /tell seguito dal nome di un giocatore e dal tuo messaggio.", - "Fai attenzione al cibo, ai forzieri e ad altro bottino sparso per tutto il mondo!", - "Inventario pieno di cibo? Prova a utilizzarlo per crearne di migiliore!", - "Ti stai chiedendo cosa ci sia da fare? Prova uno dei dungeon segnati sulla mappa!", - "Non dimenticare di sistemare la grafica secondo il tuo sistema. Premi 'N' per aprire le impostazioni.", - "Giocare con altri è divertente! Premi 'O' per vedere chi è online.", - "Premi 'J' per ballare. Festeggia!", - "Premi 'Shift Sinistro' per aprire il tuo Aliante e conquistare i cieli.", - "Veloren è ancora in Pre-Alpha. Facciamo del nostro meglio per migliorarlo ogni giorno!", - "Se vuoi unirti al team di sviluppo o se vuoi solamente chattare con noi, unisciti al nostro server Discord.", - "Puoi scegliere di mostrare la tua quantità di vita sulla barra della vita dalle impostazioni.", - "Siedi vicino a un fuoco (col tasto 'K') per riprenderti lentamente dalle lesioni.", - "Hai bisogno di più borse o di armature migliori per continuare la tua avventura? Premi 'C' per aprire il menu di creazione!", - ], - "npc.speech.villager": [ - "Non è una così bella giornata?", - "Come stai oggi?", - "Il meglio della mattina a te!", - "Mi chiedo cosa pensi il Catoblepas quando mangia l'erba.", - "Cosa ne pensi di questo tempo?", - "Pensare a quei dungeon mi spaventa. Spero che qualcuno li ripulisca.", - "Mi piacerebbe andare a fare speleologia in una grotta quando sarò più forte.", - "Hai visto il mio gatto?", - "Hai mai sentito dei feroci Squali di Terra? Ho sentito dire che vivono nei deserti.", - "Dicono che gemme luccicanti di tutti i tipi possono essere trovate nelle caverne.", - "Vado semplicemente pazzo per il formaggio!", - "Non vieni dentro? Stavamo per mangiare del formaggio!", - "Dicono che i funghi fanno bene alla salute. Non li ho mai mangiati io.", - "Non dimenticare i crackers!", - "Semplicemente adoro il formaggio nanico. Mi piacerebbe poterlo fare.", - "Mi chiedo cosa ci sia dall'altro lato delle montagne.", - "Spero di potermi fare il mio aliante un giorno.", - "Ti piacerebbe vedere il mio giardino? Okay, forse qualche altra volta.", - "Una piacevole giornata per una passeggiata nel bosco!", - "Essere, o non essere? Penso che sarò un contadino.", - "Non pensi che il nostro villaggio sia il migliore?", - "Cosa pensi che renda i Resti Splendenti splendenti?", - "Penso che sia il momento per una seconda colazione!", - "Hai mai catturato una lucciola?", - "Proprio non capisco da dove continuino ad arrivare quei Sauroks.", - "Spero che qualcuno tenga i lupi alla larga dal villaggio.", - "Ho avuto un sogno meraviglio sul formaggio la scorsa notte. Cosa vorrà dire?", - "Ho lasciato del formaggio con mio fratello. Ora non so se esista o meno. Io lo chiamo il formaggio di Schrödinger.", - "Ho lasciato del formaggio con mio sorella. Ora non so se esista o meno. Io lo chiamo il formaggio di Schrödinger.", - "Qualcuno dovrebbe fare qualcosa a proposito di quei cultisti. Preferibilmente non io.", - "Spero che piova presto. Sarebbe buono per il raccolto.", - "Amo il miele! E odio le api.", - "Voglio vedere il mondo un giorno. Ci deve essere dell'altro nella vita oltre questo villaggio.", - ], - "npc.speech.villager_decline_trade": [ - "Mi dispiace, non ho nulla da commerciare.", - "Commerciare? Come se avessi qualcosa che potrebbe interessarti.", - "La mia casa è mia, e non la scambierei per nulla.", - ], - "npc.speech.merchant_advertisement": [ - "Posso interessarti in uno scambio?", - "Vuoi commerciare con me?", - "Ho molti beni, vuoi dare un'occhiata?" - ], - "npc.speech.merchant_busy": [ - "Ehi, aspetta il tuo turno.", - "Ti prego di aspettare, sono solo una persona.", - "La vedi l'altra persona davanti a te?", - "Solo un momento, lasciami finire.", - "Non si salta la fila.", - "Sono occupato, torna più tardi." - ], - "npc.speech.merchant_trade_successful": [ - "Grazie per aver fatto affari con me!", - "Grazie a te!", - ], - "npc.speech.merchant_trade_declined": [ - "Magari un'altra volta, abbi una buona giornata!", - "Peccato, magari la prossima volta allora!" - ], - "npc.speech.villager_cultist_alarm": [ - "Fai attenzione! C'è un cultista in giro!", - "Alle armi! I cultisti stanno attaccando!", - "Come osano i cultisti attaccare il nostro villaggio!", - "Morte ai cultisti!", - "I cultisti non saranno tollerati qui!", - "Cultista assassino!", - "Assaggia la lama della mia spada, sporco cultista!", - "Nulla può pulire il sangue dalle tue mani, cultista!", - "Per miliardi di cirripedi blu ricoperti di vesciche! Un cultista è tra noi!", - "I mali di questo cultista stanno per finire!", - "Questo cultista è mio!", - "Preparati a incontrare il tuo creatore, schifoso cultista!", - "Vedo un cultista! Prendeteli!", - "Vedo un cultista! Attaccate!", - "Vedo un cultista! Non lasciateli scappare!", - "L'onorabile cultista gradirebbe della MORTE?!", - "Mai perdonare! Mai dimenticare! Cultista, pentiti!", - "Muori, cultista!", - "Il tuo regno di terrore cesserà!", - "Questo è per tutto quello che hai fatto!", - "Non ci vanno a genio quelli come te qui in giro.", - "Saresti dovuto rimanere nel sottosuolo!", - ], - "npc.speech.villager_under_attack": [ - "Aiuto, Sono sotto attacco!", - "Aiuto! Sono sotto attacco!", - "Ouch! Sono sotto attacco!", - "Ouch! Sono sotto attacco! Aiuto!", - "Aiutatemi! Sono sotto attacco!", - "Sono sotto attacco! Aiuto!", - "Sono sotto attacco! Aiutatemi!", - "Aiuto!", - "Aiuto! Aiuto!", - "Aiuto! Aiuto! Aiuto!", - "Sono sotto attacco!", - "AAAHHH! Sono sotto attacco!", - "AAAHHH! Sono sotto attacco! Aiuto!", - "Aiuto! Siamo sotto attacco!", - "Aiuto! Assassino!", - "Aiuto! C'è un assassino a piede libero!", - "Aiuto! Stanno cercando di uccidermi", - "Guardie, Sono sotto attacco!", - "Guardie! Sono sotto attacco!", - "Sono sotto attacco! Guardie!", - "Aiuto! Guardie! Sono sotto attacco!", - "Guardie! Venite veloci!", - "Guardie! Guardie!", - "Guardie! C'è un deliquente che mi sta attaccando!", - "Guardie, uccidete questa schifosa canaglia!", - "Guardie! C'è un assassino!", - "Guardie! Aiuto!", - "Non la farai franca! Guardie!", - "Mostro!", - "Aiuto!", - "Aiuto! Per favore!", - "Ouch! Guardie! Aiuto!", - "Stanno venendo per me!", - "Aiuto! Aiuto! Sto venendo represso!", - "Ah, ora vediamo la violenza innata nel sistema.", - "È solo un graffio!", - "Smettila!", - "Che ti ho mai fatto?!", - "Per favore smettila di attaccarmi!", - "Ehi! Stai attento a dove punti quella cosa!", - "Odioso miserabile, finiscila!", - "Smettila! Vai via!", - "Ora mi stai facendo arrabbiare!", - "Oi! Chi pensi di essere?!", - "Avrò la tua testa per ciò!", - "Smettila, per favore! Non porto nulla di valore!", - "Ti metterò contro mio fratello, è più grande di me!", - "Nooo, lo dico alla mamma!", - "Maledetto!", - "Per favore non farlo.", - "Non è stato molto carino!", - "La tua arma funziona, puoi metterla via ora!", - "Risparmiami!", - "Per favore, ho una famiglia!", - "Sono troppo giovane per morire!", - "Possiamo parlarne?", - "La violenza non è mai la risposta!", - "Oggi la giornata sta diventando brutta...", - "Ehi, ha fatto male!", - "Eek!", - "Quanto rude!", - "Fermati, ti prego!", - "Che ti ammali!", - "Non è divertente.", - "Come ti permetti?!", - "La pagherai!", - "Continua così e te ne pentirai!", - "Non mi costringere a farti del male!", - "Deve esserci un qualche malinteso!", - "Non hai bisogno di fare così!", - "Scompari, mostro!", - "Ha fatto molto male!", - "Perché mai dovresti farlo?", - "Per gli spiriti, finiscila!", - "Devi avermi confuso con qualcun'altro!", - "Non me lo merito!", - "Per favore non lo fare di nuovo.", - "Guardie, lanciate questo mostro nel lago!", - "Sguinzaglierò il mio tarasqua su di te!", - "Perché meeeeeee?", - ], - "npc.speech.villager_enemy_killed": [ - "Ho distrutto il mio nemico!", - "Finalmente in pace!", - "... ora, che cosa stavo facendo?", - ] } ) \ No newline at end of file diff --git a/assets/voxygen/i18n/it_IT/main.ron b/assets/voxygen/i18n/it_IT/main.ron index e2fce13eec..953dd47856 100644 --- a/assets/voxygen/i18n/it_IT/main.ron +++ b/assets/voxygen/i18n/it_IT/main.ron @@ -67,5 +67,26 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "Premi 'G' per accendere la tua lanterna.", + "Premi 'F1' per vedere tutte le combinazioni di tasti base.", + "Puoi scrivere /say o /s per chattare solo con giocatori attorno a te.", + "Puoi scrivere /region o /r per chattare solo con giocatori entro qualche centinaio di blocchi attorno a te.", + "Gli Amministratori possono usare il comando /build per entrare in modalità costruzione.", + "Puoi scrivere /group o /g per chattare solo con giocatori attualmente nel tuo gruppo.", + "Per mandare messaggi privati scrivi /tell seguito dal nome di un giocatore e dal tuo messaggio.", + "Fai attenzione al cibo, ai forzieri e ad altro bottino sparso per tutto il mondo!", + "Inventario pieno di cibo? Prova a utilizzarlo per crearne di migiliore!", + "Ti stai chiedendo cosa ci sia da fare? Prova uno dei dungeon segnati sulla mappa!", + "Non dimenticare di sistemare la grafica secondo il tuo sistema. Premi 'N' per aprire le impostazioni.", + "Giocare con altri è divertente! Premi 'O' per vedere chi è online.", + "Premi 'J' per ballare. Festeggia!", + "Premi 'Shift Sinistro' per aprire il tuo Aliante e conquistare i cieli.", + "Veloren è ancora in Pre-Alpha. Facciamo del nostro meglio per migliorarlo ogni giorno!", + "Se vuoi unirti al team di sviluppo o se vuoi solamente chattare con noi, unisciti al nostro server Discord.", + "Puoi scegliere di mostrare la tua quantità di vita sulla barra della vita dalle impostazioni.", + "Siedi vicino a un fuoco (col tasto 'K') per riprenderti lentamente dalle lesioni.", + "Hai bisogno di più borse o di armature migliori per continuare la tua avventura? Premi 'C' per aprire il menu di creazione!", + ], } ) diff --git a/assets/voxygen/i18n/it_IT/npc.ron b/assets/voxygen/i18n/it_IT/npc.ron new file mode 100644 index 0000000000..fd4a705a27 --- /dev/null +++ b/assets/voxygen/i18n/it_IT/npc.ron @@ -0,0 +1,183 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for italian +( + string_map: { + + }, + + vector_map: { + "npc.speech.villager": [ + "Non è una così bella giornata?", + "Come stai oggi?", + "Il meglio della mattina a te!", + "Mi chiedo cosa pensi il Catoblepas quando mangia l'erba.", + "Cosa ne pensi di questo tempo?", + "Pensare a quei dungeon mi spaventa. Spero che qualcuno li ripulisca.", + "Mi piacerebbe andare a fare speleologia in una grotta quando sarò più forte.", + "Hai visto il mio gatto?", + "Hai mai sentito dei feroci Squali di Terra? Ho sentito dire che vivono nei deserti.", + "Dicono che gemme luccicanti di tutti i tipi possono essere trovate nelle caverne.", + "Vado semplicemente pazzo per il formaggio!", + "Non vieni dentro? Stavamo per mangiare del formaggio!", + "Dicono che i funghi fanno bene alla salute. Non li ho mai mangiati io.", + "Non dimenticare i crackers!", + "Semplicemente adoro il formaggio nanico. Mi piacerebbe poterlo fare.", + "Mi chiedo cosa ci sia dall'altro lato delle montagne.", + "Spero di potermi fare il mio aliante un giorno.", + "Ti piacerebbe vedere il mio giardino? Okay, forse qualche altra volta.", + "Una piacevole giornata per una passeggiata nel bosco!", + "Essere, o non essere? Penso che sarò un contadino.", + "Non pensi che il nostro villaggio sia il migliore?", + "Cosa pensi che renda i Resti Splendenti splendenti?", + "Penso che sia il momento per una seconda colazione!", + "Hai mai catturato una lucciola?", + "Proprio non capisco da dove continuino ad arrivare quei Sauroks.", + "Spero che qualcuno tenga i lupi alla larga dal villaggio.", + "Ho avuto un sogno meraviglio sul formaggio la scorsa notte. Cosa vorrà dire?", + "Ho lasciato del formaggio con mio fratello. Ora non so se esista o meno. Io lo chiamo il formaggio di Schrödinger.", + "Ho lasciato del formaggio con mio sorella. Ora non so se esista o meno. Io lo chiamo il formaggio di Schrödinger.", + "Qualcuno dovrebbe fare qualcosa a proposito di quei cultisti. Preferibilmente non io.", + "Spero che piova presto. Sarebbe buono per il raccolto.", + "Amo il miele! E odio le api.", + "Voglio vedere il mondo un giorno. Ci deve essere dell'altro nella vita oltre questo villaggio.", + ], + "npc.speech.villager_decline_trade": [ + "Mi dispiace, non ho nulla da commerciare.", + "Commerciare? Come se avessi qualcosa che potrebbe interessarti.", + "La mia casa è mia, e non la scambierei per nulla.", + ], + "npc.speech.merchant_advertisement": [ + "Posso interessarti in uno scambio?", + "Vuoi commerciare con me?", + "Ho molti beni, vuoi dare un'occhiata?" + ], + "npc.speech.merchant_busy": [ + "Ehi, aspetta il tuo turno.", + "Ti prego di aspettare, sono solo una persona.", + "La vedi l'altra persona davanti a te?", + "Solo un momento, lasciami finire.", + "Non si salta la fila.", + "Sono occupato, torna più tardi." + ], + "npc.speech.merchant_trade_successful": [ + "Grazie per aver fatto affari con me!", + "Grazie a te!", + ], + "npc.speech.merchant_trade_declined": [ + "Magari un'altra volta, abbi una buona giornata!", + "Peccato, magari la prossima volta allora!" + ], + "npc.speech.villager_cultist_alarm": [ + "Fai attenzione! C'è un cultista in giro!", + "Alle armi! I cultisti stanno attaccando!", + "Come osano i cultisti attaccare il nostro villaggio!", + "Morte ai cultisti!", + "I cultisti non saranno tollerati qui!", + "Cultista assassino!", + "Assaggia la lama della mia spada, sporco cultista!", + "Nulla può pulire il sangue dalle tue mani, cultista!", + "Per miliardi di cirripedi blu ricoperti di vesciche! Un cultista è tra noi!", + "I mali di questo cultista stanno per finire!", + "Questo cultista è mio!", + "Preparati a incontrare il tuo creatore, schifoso cultista!", + "Vedo un cultista! Prendeteli!", + "Vedo un cultista! Attaccate!", + "Vedo un cultista! Non lasciateli scappare!", + "L'onorabile cultista gradirebbe della MORTE?!", + "Mai perdonare! Mai dimenticare! Cultista, pentiti!", + "Muori, cultista!", + "Il tuo regno di terrore cesserà!", + "Questo è per tutto quello che hai fatto!", + "Non ci vanno a genio quelli come te qui in giro.", + "Saresti dovuto rimanere nel sottosuolo!", + ], + "npc.speech.villager_under_attack": [ + "Aiuto, Sono sotto attacco!", + "Aiuto! Sono sotto attacco!", + "Ouch! Sono sotto attacco!", + "Ouch! Sono sotto attacco! Aiuto!", + "Aiutatemi! Sono sotto attacco!", + "Sono sotto attacco! Aiuto!", + "Sono sotto attacco! Aiutatemi!", + "Aiuto!", + "Aiuto! Aiuto!", + "Aiuto! Aiuto! Aiuto!", + "Sono sotto attacco!", + "AAAHHH! Sono sotto attacco!", + "AAAHHH! Sono sotto attacco! Aiuto!", + "Aiuto! Siamo sotto attacco!", + "Aiuto! Assassino!", + "Aiuto! C'è un assassino a piede libero!", + "Aiuto! Stanno cercando di uccidermi", + "Guardie, Sono sotto attacco!", + "Guardie! Sono sotto attacco!", + "Sono sotto attacco! Guardie!", + "Aiuto! Guardie! Sono sotto attacco!", + "Guardie! Venite veloci!", + "Guardie! Guardie!", + "Guardie! C'è un deliquente che mi sta attaccando!", + "Guardie, uccidete questa schifosa canaglia!", + "Guardie! C'è un assassino!", + "Guardie! Aiuto!", + "Non la farai franca! Guardie!", + "Mostro!", + "Aiuto!", + "Aiuto! Per favore!", + "Ouch! Guardie! Aiuto!", + "Stanno venendo per me!", + "Aiuto! Aiuto! Sto venendo represso!", + "Ah, ora vediamo la violenza innata nel sistema.", + "È solo un graffio!", + "Smettila!", + "Che ti ho mai fatto?!", + "Per favore smettila di attaccarmi!", + "Ehi! Stai attento a dove punti quella cosa!", + "Odioso miserabile, finiscila!", + "Smettila! Vai via!", + "Ora mi stai facendo arrabbiare!", + "Oi! Chi pensi di essere?!", + "Avrò la tua testa per ciò!", + "Smettila, per favore! Non porto nulla di valore!", + "Ti metterò contro mio fratello, è più grande di me!", + "Nooo, lo dico alla mamma!", + "Maledetto!", + "Per favore non farlo.", + "Non è stato molto carino!", + "La tua arma funziona, puoi metterla via ora!", + "Risparmiami!", + "Per favore, ho una famiglia!", + "Sono troppo giovane per morire!", + "Possiamo parlarne?", + "La violenza non è mai la risposta!", + "Oggi la giornata sta diventando brutta...", + "Ehi, ha fatto male!", + "Eek!", + "Quanto rude!", + "Fermati, ti prego!", + "Che ti ammali!", + "Non è divertente.", + "Come ti permetti?!", + "La pagherai!", + "Continua così e te ne pentirai!", + "Non mi costringere a farti del male!", + "Deve esserci un qualche malinteso!", + "Non hai bisogno di fare così!", + "Scompari, mostro!", + "Ha fatto molto male!", + "Perché mai dovresti farlo?", + "Per gli spiriti, finiscila!", + "Devi avermi confuso con qualcun'altro!", + "Non me lo merito!", + "Per favore non lo fare di nuovo.", + "Guardie, lanciate questo mostro nel lago!", + "Sguinzaglierò il mio tarasqua su di te!", + "Perché meeeeeee?", + ], + "npc.speech.villager_enemy_killed": [ + "Ho distrutto il mio nemico!", + "Finalmente in pace!", + "... ora, che cosa stavo facendo?", + ] + } +) \ No newline at end of file diff --git a/assets/voxygen/i18n/ja_JP/_manifest.ron b/assets/voxygen/i18n/ja_JP/_manifest.ron index 94b254a111..70a840119c 100644 --- a/assets/voxygen/i18n/ja_JP/_manifest.ron +++ b/assets/voxygen/i18n/ja_JP/_manifest.ron @@ -28,200 +28,5 @@ asset_key: "voxygen.font.bdfUMplus-outline", scale_ratio: 0.9, ), - }, - - string_map: { - - }, - - vector_map: { - "loading.tips": [ - "Gキーを押すとランタンが灯ります。", - "F1キーを押すとすべてのデフォルトキー設定の確認できます。", - "/sayまたは/sと入力すると自分の周りのプレイヤーとだけチャットできます。", - "/regionまたは/rと入力すると自分の周辺、数百ブロックのプレーヤーとだけチャットできます。", - "管理者は、/buildコマンドでビルドモードに入れます。", - "/groupまたは/gと入力すると現在所属しているグループのプレイヤーとだけチャットできます。", - "プライベートメッセージを送るには、/tellと入力したあと、プレイヤー名とメッセージを入力します。", - "世界中に散らばっている食料やチェストに注目してみましょう!", - "持ち物が食料でいっぱいですか?それを使ってもっといい食料をクラフトしてみましょう!", - "何をしたらいいかわからないですか?地図にあるダンジョンに挑戦してみましょう!", - "お使いのシステムに合わせてグラフィックの調整もお忘れなく。Nキーを押すと設定が開きます。", - "誰かと一緒に遊ぶのは楽しいですよね!Oキーを押すと誰がオンラインかわかります。", - "Jキーを押すとダンスします。パーティ!", - "左Shiftキーを押すとグライダーが開いて空を攻略できます。", - "Velorenは、まだアルファ版です。私たちは日々、改善のためにベストを尽くしています!", - "開発チームに参加したい方や私たちとチャットしたい方はDiscordサーバーに参加しましょう。", - "体力バーに表示される体力量の表示は、設定で切り替えられます。", - "Kキーを押して焚き火のそばに座ると体力がゆっくり回復します", - "冒険のためにバッグやいい鎧が欲しいですか?Cキーを押すとクラフトメニューが開きます。", - ], - "npc.speech.villager": [ - "こんな素敵な日があってもいいよね?", - "ご機嫌いかが?", - "最高の朝を迎えましょう!", - "カトブレパスは なにを考えて草を食べてるのだろう", - "この天気についてどうお考えですか?", - "あのダンジョンの事を考えると怖くなります。誰かがあそこをクリアしてくれないだろうか", - "強くなったら洞窟に探検に行きたいですね", - "私の猫チャンを見かけなかった?", - "ランドシャークという獰猛なサメをご存知ですか?なんでも砂漠に住んでるらしいですよ", - "洞窟には さまざまな種類の光り輝く宝石が見つかるらしいですよ", - "やっぱ チーズにはクラッカー!", - "寄っていきませんか?ちょうどチーズを食べようとしてたところなんです", - "マッシュルームは健康に良いと言われてます。自分は食べないですけど", - "クラッカーを忘れるな!", - "私はシンプルにドワーフチーズに憧れてます。作れたらなぁ", - "山の向こう側には何があるのだろう", - "いつの日か 自分のグライダーを作ってみたいですね", - "私の庭を見ていかない?うん また今度ね", - "森を散歩するには なんて素敵な日なんだ!", - "なるべきか ならざるべきか… 僕は農家にだけど", - "私たちの村が一番だと思わない?", - "なんで光る死体は光っているんだろう?", - "二度目の朝ゴハンの時間だよ!", - "ホタルを捕まえたことはある?", - "あのサウロクたちが どこから来ているのか想像できませんね", - "誰か狼を村から遠ざけてくれればいいのに", - "昨晩 素敵なチーズの夢を見ました。それってどういう意味なの?", - "兄にチーズを残してきました。でも 今となってはそれが存在するのかわかりません。だから 私は「シュレディンガーのチーズ」と呼んでいます", - "妹にチーズを残してきました。でも 今となってはそれが存在するのかわかりません。だから 私は「シュレディンガーのチーズ」と呼んでいます", - "誰かが あのカルト教団をなんとかしないといけない。私は やりたくないけど", - "早く雨が降ってほしい。雨は作物にいいからね", - "ハチミツ大好き! でも ハチは大嫌い!", - "私はいつか世界を見てみたい。この村よりももっと豊かな人生があるはずだから", - ], - "npc.speech.villager_decline_trade": [ - "ごめんなさい、取引するものがありません。", - "取引?あなたの興味のあるものを持ってきたら考えますよ。", - "この家は私の物です。この家に取引するものはありません。", - ], - "npc.speech.merchant_advertisement": [ - "取引に興味はありますか?", - "私と取引しませんか?", - "商品がたくさんあるけど、ちょっと見ていきませんか?" - ], - "npc.speech.merchant_busy": [ - "おい、順番を待ちな", - "ちょっと待ってください。私の体は一つしかないんですよ", - "目の前にいる人を見て言ってますか?", - "ちょっと待って。最後まで取引させて", - "割り込まないでください。", - "忙しいから、また後で来てね。" - ], - "npc.speech.merchant_trade_successful": [ - "取引をしてくれて、ありがとう!", - "ありがとう!", - ], - "npc.speech.merchant_trade_declined": [ - "また、機会があれば、よろしくお願いします", - "残念です。またの機会によろしく!" - ], - "npc.speech.villager_cultist_alarm": [ - "気をつけて!信者が逃げてるぞ!", - "武器を取れ!カルト信者が襲ってくるぞ!", - "よくもまあ、私たちの村をカルトが襲うなんて!", - "カルト信者に死を!", - "ここではカルト信者でいることは許されません!", - "人殺しカルト教団!", - "うす汚いカルト信者よ。俺の刃を味わえ!", - "カルト信者よ、その手の血を拭うことはできないぞ!", - "まばゆいばかりに光り輝く数十億の青いフジツボ!カルト信者が紛れ込んでいるぞ!", - "この邪悪な信者はもうすぐ終わる!", - "カルト信者は私のもの!", - "創造主に会う準備をしろ、このうす汚いカルト信者!", - "信者を見つけたぞ!捕まえろ!", - "信者を見つけたぞ!攻撃しろ!", - "信者を見つけたぞ!ヤツらを逃すな!", - "最も高潔なカルト信者は死を望むのか!?", - "忘れるな!忘れるな!カルト信者よ、悔改めよ!", - "死ね、カルト信者!", - "恐怖の支配が始まるぞ!", - "これまでの活動に感謝します!", - "ここではあなたのような方は歓迎されませんよ。", - "地下にずっと潜ってりゃよかったのに!", - ], - "npc.speech.villager_under_attack": [ - "助けて、襲撃されてます!", - "助けて!襲われてます!", - "ああっ!襲われてます!", - "ああっ!襲撃されてます!助けて!", - "助けてください!襲われてます!", - "襲われています!助けて!", - "襲われています!助けてください!", - "助けて!", - "助けて!助けて!", - "助けて!助けて!助けて!", - "襲われています!", - "あああああ!襲われてます!", - "あああああ!襲撃されてます!助けて!", - "助けて!私たちは襲撃されてます!", - "助けて!人殺し!", - "助けて!人殺しが逃亡しています!", - "助けて!私を殺そうとしています!", - "衛兵さん、襲われています!", - "衛兵!襲われてます!", - "襲われています!衛兵!", - "助けて!衛兵!襲われてます!", - "衛兵!早く来て!", - "衛兵!衛兵!", - "衛兵!悪党に襲ってきた!", - "衛兵、うす汚い悪党を切って!", - "衛兵!人殺しがいる!", - "衛兵!助けてください!", - "このままでは許さないぞ!衛兵!", - "この、悪魔め!", - "助けてください!", - "助けて!お願い!", - "ああっ!衛兵!助けて!", - "狙われてます!", - "助けて!助けて!私は抑圧されてる!", - "ああ、システムに内在する暴力が見えてきた。", - "ただのかすり傷だ!", - "止めてくれ!", - "お前に何をしたっていうんだよ!", - "お願いですから、攻撃を止めてください!", - "ヘイ!どこに向けてるんだ!", - "凶暴な奴らは消えてしまえ!", - "止まれ!出ていけ!", - "私は怒っている!", - "おい!!お前は何様だと思ってるんだ!", - "お前の首を取ってやるぜ!", - "止めて、お願い!金目のものは持ってないんだ!", - "兄貴を連れてくるぞ、俺よりデカいんだからな!", - "ノー!母ちゃんにいいつけてやる!", - "呪ってやる!", - "お願いだから止めてください。", - "ひでえな!", - "武器は使ったんだから、もうしまってくれよ!", - "惜しい!", - "お願い、私には家族がいます!", - "私は死ぬには若すぎます!", - "話し合いませんか?", - "暴力は解決策ではないぞ!", - "今日は最悪の日だ…", - "おい、痛いって!", - "えっ!", - "失礼な!", - "止めてくださいよ!", - "毒を食わわば皿まで!", - "それは楽しくないです。", - "よくもそんなことを!", - "この代償は大きいぞ!", - "そんな調子だと後悔するぞ!", - "痛い目に合わせないでくれよ!", - "なにか勘違いしていないか!", - "こんなことするなよ!", - "悪魔よ出ていけ!", - "めっちゃ痛い!", - "なぜこんなことをするの?", - "霊よ、静まれ!", - "誰かと勘違いしてるんじゃないか!", - "私にはもったいないです!", - "二度としないで。", - "衛兵、この化け物を湖に沈めて!", - "俺のタラスクを送り込んでやるぜ!", - "なぜ、わたしがー?", - ], } ) diff --git a/assets/voxygen/i18n/ja_JP/main.ron b/assets/voxygen/i18n/ja_JP/main.ron index 096dfcb786..0bcf76aabc 100644 --- a/assets/voxygen/i18n/ja_JP/main.ron +++ b/assets/voxygen/i18n/ja_JP/main.ron @@ -64,5 +64,26 @@ https://veloren.net/account/"#, vector_map: { + "loading.tips": [ + "Gキーを押すとランタンが灯ります。", + "F1キーを押すとすべてのデフォルトキー設定の確認できます。", + "/sayまたは/sと入力すると自分の周りのプレイヤーとだけチャットできます。", + "/regionまたは/rと入力すると自分の周辺、数百ブロックのプレーヤーとだけチャットできます。", + "管理者は、/buildコマンドでビルドモードに入れます。", + "/groupまたは/gと入力すると現在所属しているグループのプレイヤーとだけチャットできます。", + "プライベートメッセージを送るには、/tellと入力したあと、プレイヤー名とメッセージを入力します。", + "世界中に散らばっている食料やチェストに注目してみましょう!", + "持ち物が食料でいっぱいですか?それを使ってもっといい食料をクラフトしてみましょう!", + "何をしたらいいかわからないですか?地図にあるダンジョンに挑戦してみましょう!", + "お使いのシステムに合わせてグラフィックの調整もお忘れなく。Nキーを押すと設定が開きます。", + "誰かと一緒に遊ぶのは楽しいですよね!Oキーを押すと誰がオンラインかわかります。", + "Jキーを押すとダンスします。パーティ!", + "左Shiftキーを押すとグライダーが開いて空を攻略できます。", + "Velorenは、まだアルファ版です。私たちは日々、改善のためにベストを尽くしています!", + "開発チームに参加したい方や私たちとチャットしたい方はDiscordサーバーに参加しましょう。", + "体力バーに表示される体力量の表示は、設定で切り替えられます。", + "Kキーを押して焚き火のそばに座ると体力がゆっくり回復します", + "冒険のためにバッグやいい鎧が欲しいですか?Cキーを押すとクラフトメニューが開きます。", + ], } ) diff --git a/assets/voxygen/i18n/ja_JP/npc.ron b/assets/voxygen/i18n/ja_JP/npc.ron new file mode 100644 index 0000000000..d0b5e8da72 --- /dev/null +++ b/assets/voxygen/i18n/ja_JP/npc.ron @@ -0,0 +1,178 @@ +/// 警告: ローカライズファイルは、UTF-8のBOM無しで保存する必要があります + +/// Localization for 日本語 Japanese +( + string_map: { + + }, + + vector_map: { + "npc.speech.villager": [ + "こんな素敵な日があってもいいよね?", + "ご機嫌いかが?", + "最高の朝を迎えましょう!", + "カトブレパスは なにを考えて草を食べてるのだろう", + "この天気についてどうお考えですか?", + "あのダンジョンの事を考えると怖くなります。誰かがあそこをクリアしてくれないだろうか", + "強くなったら洞窟に探検に行きたいですね", + "私の猫チャンを見かけなかった?", + "ランドシャークという獰猛なサメをご存知ですか?なんでも砂漠に住んでるらしいですよ", + "洞窟には さまざまな種類の光り輝く宝石が見つかるらしいですよ", + "やっぱ チーズにはクラッカー!", + "寄っていきませんか?ちょうどチーズを食べようとしてたところなんです", + "マッシュルームは健康に良いと言われてます。自分は食べないですけど", + "クラッカーを忘れるな!", + "私はシンプルにドワーフチーズに憧れてます。作れたらなぁ", + "山の向こう側には何があるのだろう", + "いつの日か 自分のグライダーを作ってみたいですね", + "私の庭を見ていかない?うん また今度ね", + "森を散歩するには なんて素敵な日なんだ!", + "なるべきか ならざるべきか… 僕は農家にだけど", + "私たちの村が一番だと思わない?", + "なんで光る死体は光っているんだろう?", + "二度目の朝ゴハンの時間だよ!", + "ホタルを捕まえたことはある?", + "あのサウロクたちが どこから来ているのか想像できませんね", + "誰か狼を村から遠ざけてくれればいいのに", + "昨晩 素敵なチーズの夢を見ました。それってどういう意味なの?", + "兄にチーズを残してきました。でも 今となってはそれが存在するのかわかりません。だから 私は「シュレディンガーのチーズ」と呼んでいます", + "妹にチーズを残してきました。でも 今となってはそれが存在するのかわかりません。だから 私は「シュレディンガーのチーズ」と呼んでいます", + "誰かが あのカルト教団をなんとかしないといけない。私は やりたくないけど", + "早く雨が降ってほしい。雨は作物にいいからね", + "ハチミツ大好き! でも ハチは大嫌い!", + "私はいつか世界を見てみたい。この村よりももっと豊かな人生があるはずだから", + ], + "npc.speech.villager_decline_trade": [ + "ごめんなさい、取引するものがありません。", + "取引?あなたの興味のあるものを持ってきたら考えますよ。", + "この家は私の物です。この家に取引するものはありません。", + ], + "npc.speech.merchant_advertisement": [ + "取引に興味はありますか?", + "私と取引しませんか?", + "商品がたくさんあるけど、ちょっと見ていきませんか?" + ], + "npc.speech.merchant_busy": [ + "おい、順番を待ちな", + "ちょっと待ってください。私の体は一つしかないんですよ", + "目の前にいる人を見て言ってますか?", + "ちょっと待って。最後まで取引させて", + "割り込まないでください。", + "忙しいから、また後で来てね。" + ], + "npc.speech.merchant_trade_successful": [ + "取引をしてくれて、ありがとう!", + "ありがとう!", + ], + "npc.speech.merchant_trade_declined": [ + "また、機会があれば、よろしくお願いします", + "残念です。またの機会によろしく!" + ], + "npc.speech.villager_cultist_alarm": [ + "気をつけて!信者が逃げてるぞ!", + "武器を取れ!カルト信者が襲ってくるぞ!", + "よくもまあ、私たちの村をカルトが襲うなんて!", + "カルト信者に死を!", + "ここではカルト信者でいることは許されません!", + "人殺しカルト教団!", + "うす汚いカルト信者よ。俺の刃を味わえ!", + "カルト信者よ、その手の血を拭うことはできないぞ!", + "まばゆいばかりに光り輝く数十億の青いフジツボ!カルト信者が紛れ込んでいるぞ!", + "この邪悪な信者はもうすぐ終わる!", + "カルト信者は私のもの!", + "創造主に会う準備をしろ、このうす汚いカルト信者!", + "信者を見つけたぞ!捕まえろ!", + "信者を見つけたぞ!攻撃しろ!", + "信者を見つけたぞ!ヤツらを逃すな!", + "最も高潔なカルト信者は死を望むのか!?", + "忘れるな!忘れるな!カルト信者よ、悔改めよ!", + "死ね、カルト信者!", + "恐怖の支配が始まるぞ!", + "これまでの活動に感謝します!", + "ここではあなたのような方は歓迎されませんよ。", + "地下にずっと潜ってりゃよかったのに!", + ], + "npc.speech.villager_under_attack": [ + "助けて、襲撃されてます!", + "助けて!襲われてます!", + "ああっ!襲われてます!", + "ああっ!襲撃されてます!助けて!", + "助けてください!襲われてます!", + "襲われています!助けて!", + "襲われています!助けてください!", + "助けて!", + "助けて!助けて!", + "助けて!助けて!助けて!", + "襲われています!", + "あああああ!襲われてます!", + "あああああ!襲撃されてます!助けて!", + "助けて!私たちは襲撃されてます!", + "助けて!人殺し!", + "助けて!人殺しが逃亡しています!", + "助けて!私を殺そうとしています!", + "衛兵さん、襲われています!", + "衛兵!襲われてます!", + "襲われています!衛兵!", + "助けて!衛兵!襲われてます!", + "衛兵!早く来て!", + "衛兵!衛兵!", + "衛兵!悪党に襲ってきた!", + "衛兵、うす汚い悪党を切って!", + "衛兵!人殺しがいる!", + "衛兵!助けてください!", + "このままでは許さないぞ!衛兵!", + "この、悪魔め!", + "助けてください!", + "助けて!お願い!", + "ああっ!衛兵!助けて!", + "狙われてます!", + "助けて!助けて!私は抑圧されてる!", + "ああ、システムに内在する暴力が見えてきた。", + "ただのかすり傷だ!", + "止めてくれ!", + "お前に何をしたっていうんだよ!", + "お願いですから、攻撃を止めてください!", + "ヘイ!どこに向けてるんだ!", + "凶暴な奴らは消えてしまえ!", + "止まれ!出ていけ!", + "私は怒っている!", + "おい!!お前は何様だと思ってるんだ!", + "お前の首を取ってやるぜ!", + "止めて、お願い!金目のものは持ってないんだ!", + "兄貴を連れてくるぞ、俺よりデカいんだからな!", + "ノー!母ちゃんにいいつけてやる!", + "呪ってやる!", + "お願いだから止めてください。", + "ひでえな!", + "武器は使ったんだから、もうしまってくれよ!", + "惜しい!", + "お願い、私には家族がいます!", + "私は死ぬには若すぎます!", + "話し合いませんか?", + "暴力は解決策ではないぞ!", + "今日は最悪の日だ…", + "おい、痛いって!", + "えっ!", + "失礼な!", + "止めてくださいよ!", + "毒を食わわば皿まで!", + "それは楽しくないです。", + "よくもそんなことを!", + "この代償は大きいぞ!", + "そんな調子だと後悔するぞ!", + "痛い目に合わせないでくれよ!", + "なにか勘違いしていないか!", + "こんなことするなよ!", + "悪魔よ出ていけ!", + "めっちゃ痛い!", + "なぜこんなことをするの?", + "霊よ、静まれ!", + "誰かと勘違いしてるんじゃないか!", + "私にはもったいないです!", + "二度としないで。", + "衛兵、この化け物を湖に沈めて!", + "俺のタラスクを送り込んでやるぜ!", + "なぜ、わたしがー?", + ], + } +) diff --git a/assets/voxygen/i18n/nl_NL/_manifest.ron b/assets/voxygen/i18n/nl_NL/_manifest.ron index d1081e1d97..960e6999b9 100644 --- a/assets/voxygen/i18n/nl_NL/_manifest.ron +++ b/assets/voxygen/i18n/nl_NL/_manifest.ron @@ -40,114 +40,5 @@ asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", scale_ratio: 1.0, ), - }, - string_map: { - }, - - - vector_map: { - "loading.tips": [ - "Druk op 'G' om je lantaarn te doen schijnen.", - "Druk op 'F1' om alle standaardbesturingen te zien.", - "Je kan /say of /s typen om enkel met spelers rondom je te praten.", - "Je kan /region of /r typen om enkel met spelers binnen een hondertal blokken te praten.", - "Je kan /group of /g typen om enkel met je groepsleden te praten.", - "Om privéberichten te sturen gebruik je /tell gevolgd door de speler zijn naam en dan je bericht", - "NPCs met hetzelfde level zijn niet per sé altijd even sterk.", - "Hou je ogen open voor eten, kisten en andere buit verspreid over de wereld!", - "Zit je Inventory vol met eten? Probeer beter eten er van te craften!", - "Weet je niet wat te doen? Kerkers zijn met een bruine vlek op je kaart aangeduid!", - "Vergeet je grafische instellingen niet aan te passen naar je systeem. Druk 'N' om het instellingenmenu te openen.", - "Met anderen spelen is plezanter! Druk op 'O' om te zien wie er nog online is!", - "Een NPC met een doodshoofd onder zijn levensbalk is zeer sterk vergeleken met jezelf.", - "Druk op 'J' om te dansen. Feestje!", - "Druk op 'L-Shift' om je deltavlieger te openen en het luchtruim te veroveren.", - "Veloren is nog steeds in Pre-Alpha. We doen ons best om het elke dag te verbeteren!", - "Als je het ontwikkelingsteam wil versterken of gewoon een babbeltje wil doen met ons, kom dan langs op onze Discord-Server.", - "Je kan numerieke waarden in de levensbalk aan of uit zetten in de instellingen.", - "Om je stats te zien kan je op 'Stats' klikken in je Inventory.", - ], - "npc.speech.villager_under_attack": [ - "Help, Ik word aangevallen!", - "Help! Ik word aangevallen!", - "Ow! Ik word aangevallen!", - "Ow! Ik word aangevallen! Help!", - "Help me! Ik word aangevallen!", - "Ik word aangevallen! Help!", - "Ik word aangevallen! Help me!", - "Help!", - "Help! Help!", - "Help! Help! Help!", - "Ik word aangevallen!", - "AAAHHH! Ik word aangevallen!", - "AAAHHH! Ik word aangevallen! Help!", - "Help! We worden aangevallen!", - "Help! Moordenaar!", - "Help! Er loopt een moordenaar rond!", - "Help! Ze proberen mij te vermoorden!", - "Wachters, Ik word aangevallen!", - "Wachters! Ik word aangevallen!", - "Ik word aangevallen! Wachters!", - "Help! Wachters! Ik word aangevallen!", - "Wachters! Kom snel!", - "Wachters! Wachters!", - "Wachters! Er is een snodaard mij aan het aanvallen!", - "Wachters, slacht deze kwaadaardige snodaard!", - "Wachters! Er is een moordenaar!", - "Wachters! Help me!", - "Hier kom je niet mee weg! Wachters!", - "Jij boosdoener!", - "Help me!", - "Help! Alsjeblieft!", - "Ow! Wachters! Help!", - "Ze zitten achter me aan!", - "Help! Help! Ik word onderdrukt!", - "Ah, nu zien we het geweld eigen aan het systeem.", - "Het is maar een schrammetje!", - "Stop daarmee!", - "Wat heb ik jouw ooit aangedaan?!", - "Alsjeblieft stop met aanvallen!", - "Hey! Pas op waar je dat ding wijst!", - "Gruwelijke ellendeling, wegwezen!", - "Stop ermee! Wegwezen!", - "Nu maak je me boos!", - "Oi! Wie denk je wel niet dat je bent?!", - "Hiervoor ga je boeten!", - "Stop, Alsjeblieft! Ik heb niks waardevol!", - "Ik stuur mijn broer op je af, hij is groter dan ik!", - "Neeeee, ik ga het tegen je mama zeggen!", - "Vervloek u!", - "Alsjeblieft niet doen.", - "Dat was niet erg vriendelijk!", - "Je wapen werkt, je mag het nu wegsteken hoor!", - "Genade!", - "Ik smeek je, ik heb een familie!", - "Ik ben te jong om te sterven!", - "Ik ben te mooi om te sterven!", - "Kunnen we erover praten?", - "Geweld is nooit het antwoord!", - "Vandaag zit vol met tegenslagen...", - "Hey, dat doet pijn!", - "Eek!", - "Hoe onbeleefd!", - "Stop, ik smeek je!", - "Ik wens je de mazelen toe!", - "Dit is niet plezant.", - "Hoe durf je?!", - "Ik zet het je betaald!", - "Blijf zo doorgaan en je zult spijt krijgen!", - "Zorg er niet voor dat ik je moet pijn doen!", - "Er moet een soort van misverstand zijn!", - "Je moet dit niet doen!", - "Vertrek, duivel!", - "Dat deed echt pijn!", - "Waarom doe je dit?", - "Bij alles dat heilig is, stop!", - "Je verward mij met iemand anders!", - "Ik verdien dit niet!", - "Doe dat alsjeblieft niet meer.", - "Wachters, gooi dit monster het meer in!", - "Ik laat mijn Tarasque op je los!", - ], } ) diff --git a/assets/voxygen/i18n/nl_NL/main.ron b/assets/voxygen/i18n/nl_NL/main.ron index f7f24a4e2a..14ade0a30b 100644 --- a/assets/voxygen/i18n/nl_NL/main.ron +++ b/assets/voxygen/i18n/nl_NL/main.ron @@ -55,5 +55,26 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "Druk op 'G' om je lantaarn te doen schijnen.", + "Druk op 'F1' om alle standaardbesturingen te zien.", + "Je kan /say of /s typen om enkel met spelers rondom je te praten.", + "Je kan /region of /r typen om enkel met spelers binnen een hondertal blokken te praten.", + "Je kan /group of /g typen om enkel met je groepsleden te praten.", + "Om privéberichten te sturen gebruik je /tell gevolgd door de speler zijn naam en dan je bericht", + "NPCs met hetzelfde level zijn niet per sé altijd even sterk.", + "Hou je ogen open voor eten, kisten en andere buit verspreid over de wereld!", + "Zit je Inventory vol met eten? Probeer beter eten er van te craften!", + "Weet je niet wat te doen? Kerkers zijn met een bruine vlek op je kaart aangeduid!", + "Vergeet je grafische instellingen niet aan te passen naar je systeem. Druk 'N' om het instellingenmenu te openen.", + "Met anderen spelen is plezanter! Druk op 'O' om te zien wie er nog online is!", + "Een NPC met een doodshoofd onder zijn levensbalk is zeer sterk vergeleken met jezelf.", + "Druk op 'J' om te dansen. Feestje!", + "Druk op 'L-Shift' om je deltavlieger te openen en het luchtruim te veroveren.", + "Veloren is nog steeds in Pre-Alpha. We doen ons best om het elke dag te verbeteren!", + "Als je het ontwikkelingsteam wil versterken of gewoon een babbeltje wil doen met ons, kom dan langs op onze Discord-Server.", + "Je kan numerieke waarden in de levensbalk aan of uit zetten in de instellingen.", + "Om je stats te zien kan je op 'Stats' klikken in je Inventory.", + ], } ) diff --git a/assets/voxygen/i18n/nl_NL/npc.ron b/assets/voxygen/i18n/nl_NL/npc.ron new file mode 100644 index 0000000000..7928da0392 --- /dev/null +++ b/assets/voxygen/i18n/nl_NL/npc.ron @@ -0,0 +1,93 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for netherlands Dutch +( + string_map: { + }, + + + vector_map: { + "npc.speech.villager_under_attack": [ + "Help, Ik word aangevallen!", + "Help! Ik word aangevallen!", + "Ow! Ik word aangevallen!", + "Ow! Ik word aangevallen! Help!", + "Help me! Ik word aangevallen!", + "Ik word aangevallen! Help!", + "Ik word aangevallen! Help me!", + "Help!", + "Help! Help!", + "Help! Help! Help!", + "Ik word aangevallen!", + "AAAHHH! Ik word aangevallen!", + "AAAHHH! Ik word aangevallen! Help!", + "Help! We worden aangevallen!", + "Help! Moordenaar!", + "Help! Er loopt een moordenaar rond!", + "Help! Ze proberen mij te vermoorden!", + "Wachters, Ik word aangevallen!", + "Wachters! Ik word aangevallen!", + "Ik word aangevallen! Wachters!", + "Help! Wachters! Ik word aangevallen!", + "Wachters! Kom snel!", + "Wachters! Wachters!", + "Wachters! Er is een snodaard mij aan het aanvallen!", + "Wachters, slacht deze kwaadaardige snodaard!", + "Wachters! Er is een moordenaar!", + "Wachters! Help me!", + "Hier kom je niet mee weg! Wachters!", + "Jij boosdoener!", + "Help me!", + "Help! Alsjeblieft!", + "Ow! Wachters! Help!", + "Ze zitten achter me aan!", + "Help! Help! Ik word onderdrukt!", + "Ah, nu zien we het geweld eigen aan het systeem.", + "Het is maar een schrammetje!", + "Stop daarmee!", + "Wat heb ik jouw ooit aangedaan?!", + "Alsjeblieft stop met aanvallen!", + "Hey! Pas op waar je dat ding wijst!", + "Gruwelijke ellendeling, wegwezen!", + "Stop ermee! Wegwezen!", + "Nu maak je me boos!", + "Oi! Wie denk je wel niet dat je bent?!", + "Hiervoor ga je boeten!", + "Stop, Alsjeblieft! Ik heb niks waardevol!", + "Ik stuur mijn broer op je af, hij is groter dan ik!", + "Neeeee, ik ga het tegen je mama zeggen!", + "Vervloek u!", + "Alsjeblieft niet doen.", + "Dat was niet erg vriendelijk!", + "Je wapen werkt, je mag het nu wegsteken hoor!", + "Genade!", + "Ik smeek je, ik heb een familie!", + "Ik ben te jong om te sterven!", + "Ik ben te mooi om te sterven!", + "Kunnen we erover praten?", + "Geweld is nooit het antwoord!", + "Vandaag zit vol met tegenslagen...", + "Hey, dat doet pijn!", + "Eek!", + "Hoe onbeleefd!", + "Stop, ik smeek je!", + "Ik wens je de mazelen toe!", + "Dit is niet plezant.", + "Hoe durf je?!", + "Ik zet het je betaald!", + "Blijf zo doorgaan en je zult spijt krijgen!", + "Zorg er niet voor dat ik je moet pijn doen!", + "Er moet een soort van misverstand zijn!", + "Je moet dit niet doen!", + "Vertrek, duivel!", + "Dat deed echt pijn!", + "Waarom doe je dit?", + "Bij alles dat heilig is, stop!", + "Je verward mij met iemand anders!", + "Ik verdien dit niet!", + "Doe dat alsjeblieft niet meer.", + "Wachters, gooi dit monster het meer in!", + "Ik laat mijn Tarasque op je los!", + ], + } +) diff --git a/assets/voxygen/i18n/no_NB/_manifest.ron b/assets/voxygen/i18n/no_NB/_manifest.ron index 7ceabf56fe..cf63fde6c8 100644 --- a/assets/voxygen/i18n/no_NB/_manifest.ron +++ b/assets/voxygen/i18n/no_NB/_manifest.ron @@ -40,113 +40,5 @@ asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", scale_ratio: 1.0, ), - }, - string_map: { - }, - - - vector_map: { - "loading.tips": [ - "Trykk 'G' for å tenne lykten.", - "Trykk 'F1' for å se alle standard tastebindinger.", - "Du kan skrive /say eller /s for å bare chatte med spillere rett rundt deg.", - "Du kan skrive /region eller /r for å bare chatte med spillere et par hundre blokker rundt deg.", - "Du kan skrive /group eller /g for å bare chatte med spillere i din nåværende gruppe.", - "For å sende private meldinger skriv /tell etterfulgt av et spillernavn og meldingen din.", - "NPCer med samme nivå kan ha forskjellige problemer.", - "Hold øye med mat, kister og andre godsaker spredt over hele verden!", - "Inventar fylt med mat? Prøv å lage bedre mat med det!", - "Lurer du på hva du kan gjøre? Fangehull er merket med brune flekker på kartet!", - "Ikke glem å justere grafikken for systemet ditt. Trykk på 'N' for å åpne innstillingene.", - "Å spille med andre er gøy! Trykk 'O' for å se hvem som er online.", - "En NPC med en hodeskalle under helsebaren er ganske kraftig sammenlignet med deg selv.", - "Trykk 'J' for å danse. Fest!", - "Trykk 'L-Shift' for å åpne Glider og erobre himmelen.", - "Veloren er fortsatt i Pre-Alfa. Vi gjør vårt beste for å forbedre det hver dag!", - "Hvis du vil bli med i Dev-teamet eller bare ta en prat med oss, bli med i Discord-Serveren.", - "Du kan veksle for å vise mengden helse på helselinjen i innstillingene.", - "For å se statistikken din, klikk på 'Statistikk' -knappen i beholdningen.", - ], - "npc.speech.villager_under_attack": [ - "Hjelp, jeg er under angrep!", - "Hjelp! Jeg er under angrep!", - "Au! Jeg er under angrep!", - "Au! Jeg er under angrep! Hjelp!", - "Hjelp meg! Jeg er under angrep!", - "Jeg er under angrep! Hjelp!", - "Jeg er under angrep! Hjelp meg!", - "Hjelp!", - "Hjelp! Hjelp!", - "Hjelp! Hjelp! Hjelp!", - "Jeg er under angrep!", - "AAAHHH! Jeg er under angrep!", - "AAAHHH! Jeg er under angrep! Hjelp!", - "Hjelp! Vi er under angrep!", - "Hjelp! Morder!", - "Hjelp! Det er en morder på frifot!", - "Hjelp! De prøver å drepe meg!", - "Vakter, jeg er under angrep!", - "Vakter! Jeg er under angrep!", - "Jeg er under angrep! Vakter!", - "Hjelp! Vakter! Jeg er under angrep!", - "Vakter! Kom raskt!", - "Vakter! Vakter!", - "Vakter! Det er en skurk som angriper meg!", - "Vakter, drep denne onde skurken!", - "Vakter! Det er en morder!", - "Vakter! Hjelp meg!", - "Du kommer ikke unna med dette! Vakter!", - "Du fiende!", - "Hjelp meg!", - "Hjelp! Vœr så snill!", - "Ouch! Vakter! Hjelp!", - "De etterfølger etter meg!", - "Hjelp! Hjelp! Jeg blir undertrykt!", - "Ah, nå ser vi volden som er bygd inn i systemet.", - "Det er bare en ripe!", - "Slutt med det!", - "Hva har jeg noensinne gjort mot deg?!", - "Vær så snill slutt å angripe meg!", - "Hei! Se for deg hvor du peker den tingen!", - "Avskyelige krek, bort med deg!", - "Stop det! Gå vekk!", - "Nå gjør du meg sint!", - "Oi! Hvem tror du at du er?!", - "Jeg tar hodet ditt for det!", - "Stop, vær så snill! Jeg har ingenting av verdi på meg!", - "Jeg får broren min til å ta deg, han er større enn meg!", - "Neiii, jeg sier det til mamma!", - "Forbann deg!", - "Vœr så snill ikke gjør det.", - "Det var ikke veldig snilt!", - "Våpnet ditt funker, du kan ta det vekk nå!", - "Bespar meg!", - "Vær så snill, jeg har familie!", - "Jeg er for ung til å dø!", - "Kan vi snakke om dette?", - "Vold er aldri svaret!", - "I dag ser ut til å være en dårlig dag...", - "Hei, det kjente jeg!", - "Eek!", - "Hvor uhøflig!", - "Stop, jeg ber deg!", - "Smitte beslage deg!", - "Dette er ikke gøy.", - "Hvordan våger du?!", - "Du kommer til å betale for dette!", - "Fortsett med dette og du kommer til å be unnskyld!", - "Ikke få meg til å banke deg!", - "Dette må være en misforståelse!", - "Du trenger ikke å gjøre dette!", - "Gå vekk, skurk!", - "Det gjorde vondt!", - "Hvorfor gjorde du det?", - "Etter åndene, forsvinn!", - "Du må ha forvekslet meg med noen andre!", - "Jeg fortjener ikke dette!", - "Vær så snill ikke gjør dette igjen!", - "Vakter, kast dette mennesket i havet!", - "Jeg får min tarasque til å etterfølge deg!", - ], } ) diff --git a/assets/voxygen/i18n/no_NB/main.ron b/assets/voxygen/i18n/no_NB/main.ron index 55319b1605..f20c98cbdf 100644 --- a/assets/voxygen/i18n/no_NB/main.ron +++ b/assets/voxygen/i18n/no_NB/main.ron @@ -59,5 +59,26 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "Trykk 'G' for å tenne lykten.", + "Trykk 'F1' for å se alle standard tastebindinger.", + "Du kan skrive /say eller /s for å bare chatte med spillere rett rundt deg.", + "Du kan skrive /region eller /r for å bare chatte med spillere et par hundre blokker rundt deg.", + "Du kan skrive /group eller /g for å bare chatte med spillere i din nåværende gruppe.", + "For å sende private meldinger skriv /tell etterfulgt av et spillernavn og meldingen din.", + "NPCer med samme nivå kan ha forskjellige problemer.", + "Hold øye med mat, kister og andre godsaker spredt over hele verden!", + "Inventar fylt med mat? Prøv å lage bedre mat med det!", + "Lurer du på hva du kan gjøre? Fangehull er merket med brune flekker på kartet!", + "Ikke glem å justere grafikken for systemet ditt. Trykk på 'N' for å åpne innstillingene.", + "Å spille med andre er gøy! Trykk 'O' for å se hvem som er online.", + "En NPC med en hodeskalle under helsebaren er ganske kraftig sammenlignet med deg selv.", + "Trykk 'J' for å danse. Fest!", + "Trykk 'L-Shift' for å åpne Glider og erobre himmelen.", + "Veloren er fortsatt i Pre-Alfa. Vi gjør vårt beste for å forbedre det hver dag!", + "Hvis du vil bli med i Dev-teamet eller bare ta en prat med oss, bli med i Discord-Serveren.", + "Du kan veksle for å vise mengden helse på helselinjen i innstillingene.", + "For å se statistikken din, klikk på 'Statistikk' -knappen i beholdningen.", + ], } ) diff --git a/assets/voxygen/i18n/no_NB/npc.ron b/assets/voxygen/i18n/no_NB/npc.ron new file mode 100644 index 0000000000..b4f0ae0622 --- /dev/null +++ b/assets/voxygen/i18n/no_NB/npc.ron @@ -0,0 +1,92 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalisering for norsk bokmål +( + string_map: { + }, + + + vector_map: { + "npc.speech.villager_under_attack": [ + "Hjelp, jeg er under angrep!", + "Hjelp! Jeg er under angrep!", + "Au! Jeg er under angrep!", + "Au! Jeg er under angrep! Hjelp!", + "Hjelp meg! Jeg er under angrep!", + "Jeg er under angrep! Hjelp!", + "Jeg er under angrep! Hjelp meg!", + "Hjelp!", + "Hjelp! Hjelp!", + "Hjelp! Hjelp! Hjelp!", + "Jeg er under angrep!", + "AAAHHH! Jeg er under angrep!", + "AAAHHH! Jeg er under angrep! Hjelp!", + "Hjelp! Vi er under angrep!", + "Hjelp! Morder!", + "Hjelp! Det er en morder på frifot!", + "Hjelp! De prøver å drepe meg!", + "Vakter, jeg er under angrep!", + "Vakter! Jeg er under angrep!", + "Jeg er under angrep! Vakter!", + "Hjelp! Vakter! Jeg er under angrep!", + "Vakter! Kom raskt!", + "Vakter! Vakter!", + "Vakter! Det er en skurk som angriper meg!", + "Vakter, drep denne onde skurken!", + "Vakter! Det er en morder!", + "Vakter! Hjelp meg!", + "Du kommer ikke unna med dette! Vakter!", + "Du fiende!", + "Hjelp meg!", + "Hjelp! Vœr så snill!", + "Ouch! Vakter! Hjelp!", + "De etterfølger etter meg!", + "Hjelp! Hjelp! Jeg blir undertrykt!", + "Ah, nå ser vi volden som er bygd inn i systemet.", + "Det er bare en ripe!", + "Slutt med det!", + "Hva har jeg noensinne gjort mot deg?!", + "Vær så snill slutt å angripe meg!", + "Hei! Se for deg hvor du peker den tingen!", + "Avskyelige krek, bort med deg!", + "Stop det! Gå vekk!", + "Nå gjør du meg sint!", + "Oi! Hvem tror du at du er?!", + "Jeg tar hodet ditt for det!", + "Stop, vær så snill! Jeg har ingenting av verdi på meg!", + "Jeg får broren min til å ta deg, han er større enn meg!", + "Neiii, jeg sier det til mamma!", + "Forbann deg!", + "Vœr så snill ikke gjør det.", + "Det var ikke veldig snilt!", + "Våpnet ditt funker, du kan ta det vekk nå!", + "Bespar meg!", + "Vær så snill, jeg har familie!", + "Jeg er for ung til å dø!", + "Kan vi snakke om dette?", + "Vold er aldri svaret!", + "I dag ser ut til å være en dårlig dag...", + "Hei, det kjente jeg!", + "Eek!", + "Hvor uhøflig!", + "Stop, jeg ber deg!", + "Smitte beslage deg!", + "Dette er ikke gøy.", + "Hvordan våger du?!", + "Du kommer til å betale for dette!", + "Fortsett med dette og du kommer til å be unnskyld!", + "Ikke få meg til å banke deg!", + "Dette må være en misforståelse!", + "Du trenger ikke å gjøre dette!", + "Gå vekk, skurk!", + "Det gjorde vondt!", + "Hvorfor gjorde du det?", + "Etter åndene, forsvinn!", + "Du må ha forvekslet meg med noen andre!", + "Jeg fortjener ikke dette!", + "Vær så snill ikke gjør dette igjen!", + "Vakter, kast dette mennesket i havet!", + "Jeg får min tarasque til å etterfølge deg!", + ], + } +) diff --git a/assets/voxygen/i18n/pl_PL/_manifest.ron b/assets/voxygen/i18n/pl_PL/_manifest.ron index db841f3959..01c06b652f 100644 --- a/assets/voxygen/i18n/pl_PL/_manifest.ron +++ b/assets/voxygen/i18n/pl_PL/_manifest.ron @@ -26,199 +26,5 @@ asset_key: "voxygen.font.OpenSans-Regular", scale_ratio: 1.0, ), - }, - - string_map: { - }, - - vector_map: { - "loading.tips": [ - "Naciśnij 'G' by zapalić latarnię.", - "Naciśnij 'F1' by zobaczyć podstawową klawiszologię.", - "Wpisz /say lub /s by rozmawiać tylko z pobliskimi graczami.", - "Wpisz /region lub /r by ograniczyć zasięg wiadomości do kilkuset bloków od Ciebie.", - "Administratorzy mogą używać komendy /build by wejść w tryb budowania.", - "Możesz użyć /group lub /g by rozmawiać z graczami w grupie.", - "Aby wysłać wiadomość prywatną, użyj /tell po czym dodaj nazwę docelowego gracza i wiadomość.", - "Rozglądaj się za jedzeniem, skrzyniami oraz skarbami - są one rozrzucone po całym świecie!", - "Ekwipunek zapełniony jedzeniem? Ugotuj z tego lepsze jedzenie!", - "Zastanawiasz się nad kolejnym wypadem? Spróbuj któryś z wielu lochów na mapie!", - "Nie zapomnij o dostosowaniu ustawień graficznych. Wciśnij 'N' by otworzyć ustawienia.", - "Gra jest lepsza z innymi! Wciśnij 'O' by sprawdzić kto jest zalogowany.", - "Użyj 'J' by zatańczyć :)", - "Użyj 'L-Shift' by wyciągnąć lotnię! Spokojnie, nie jest lepiona woskiem.", - "Veloren dalej jest w fazie Pre-Alpha. Staramy się ulepszać go dzień w dzień!", - "Jeśli chcesz pomóc w rozwijaniu projektu, albo porozmawiać z nami - wpadnij na naszego Discorda [EN]", - "Możesz przełączać typ paska zdrowia w opcjach.", - "Usiądź obok ogniska (używając 'K') by powoli wyleczyć się z obrażeń.", - "Potrzebujesz więcej slotów w ekwipunku, albo nowego uzbrojenia? Wciśnij 'C' aby otworzyć menu tworzenia!", - ], - "npc.speech.villager": [ - "Co za piękny dzień!", - "Jak się masz?", - "Udanego poranka!", - "...", /// "I wonder what the Catoblepas thinks when it eats grass.", - "Co myślisz o pogodzie?", - "Boję się na samą myśl o lochach. Mam nadzieję, że ktoś je wyczyści.", - "Chciałbym zapuścić się do jaskinii, gdy stanę się silniejszy.", /// forma - "Widziałeś mojego kota?", /// forma - "Słyszałeś kiedyś o zażartych rekinach ziemnych? Słyszałem że żyją na pustyni!", /// forma - "Mówi się, że cenne klejnoty można znaleźć w jaskiniach.", - "Fascynuje mnie ser...", - "Chciałbyś wpaść? Właśnie szykujemy ser!", - "Mówią, że grzyby są zdrowe... Nigdy nie miałem okazji ich spróbować.", /// forma - "Nie zapomnij o krakersach!", - "Uwielbiam krasnoludzki ser. Chciałbym umieć go zrobić", /// forma - "Ciekawe co jest za górami...", - "Marzę by zrobić kiedyś swoją lotnię.", - "Chcesz zobaczyć mój ogród? Dobra, może innym razem...", - "Cudowny dzień na przechadzkę po lesie.", - "Być albo nie być, oto jest pytanie... Myślę, że będę farmerem.", /// forma - "Czy też uważasz, że nasze miasteczko jest najlepsze?", - "Wiesz może dlaczego Świecące Resztki (Glowing Remains) świecą?", - "Myślę, że czas na drugie śniadanie!", - "Złapałeś kiedyś ważkę?", // forma - "Nie mogę zrozumieć skąd przychodzą te Sauroki (Sauroks).", - "Chciałbym by ktoś przeganiał wilki.", /// forma - "Miałem cudowny sen ostatniej nocy. Ciekawe co oznaczał?", /// forma - "Zostawiłem trochę sera z moim bratem. Teraz nie wiem czy ser dalej istnieje czy nie. Nazywam to serem Schrödingera.", /// forma - "Zostawiłem trochę sera z moją siostrą. Teraz nie wiem czy ser dalej istnieje czy nie. Nazywam to serem Schrödingera.", /// forma - "Ktoś powinien coś zrobić z tymi kultystami.", - "Fajnie by było jakby zaczęło padać.", - "Kocham miód! Ale pszczoły już nie bardzo.", - "Chciałbym zwiedzić kiedyś świat!", /// forma - ], - "npc.speech.villager_decline_trade": [ - "Wybacz, nie mam niczego do wymiany.", - "Handel? Sugerujesz, że mam coś co Cię zainteresuje?", - "Mój dom nie jest na sprzedaż!", - ], - "npc.speech.merchant_advertisement": [ - "Pokazać Ci swoje towary?", - "Masz ochotę na mały handelek?", - "Mam wiele produktów, chcesz rzucić okiem?" - ], - "npc.speech.merchant_busy": [ - "Zaczekaj na swoją kolej.", - "Proszę czekać, nie rozdwoję się.", - "Nie widzisz kolejki?", - "Jeszcze chwila, już kończę...", - "Nie wpychać się do kolejki.", - "Jestem zajęty, wpadnij później." /// forma - ], - "npc.speech.merchant_trade_successful": [ - "Dziękuję. Wpadnij ponownie!", - "Interesy z Tobą to czysta przyjemność!", - ], - "npc.speech.merchant_trade_declined": [ - "Może innym razem, trzymaj się!", - "Ehh, wpadnij kiedy indziej!" - ], - "npc.speech.villager_cultist_alarm": [ - "Uwaga! Kultyści w pobliżu!", - "Do broni! Kultyści atakują!", - "Jak mogli zaatakować nas?!", - "Śmierć kultystom!", - "Kultyści nie są tutaj tolerowani!", - "Morderca!", - "Posmakuj mojego ostrza brudny kultysto!", - "Nic nie zmaże krwi z twoich rąk kultysto!", - "W dupę jeża! Kultysta!", - "Zbrodniarz!", - "Ten kultysta jest mój!", - "Przygotuj się na spotkanie ze stwórcą kultysto!", - "Kultysta! Brać go!", /// forma - /// "I see a cultist! Attack!", - /// "I see a cultist! Don't let them escape!", - /// "Would the most honorable cultist care for some DEATH?!", - /// "Never forgive! Never forget! Cultist, regret!", - "Giń kultysto!", - /// "Your reign of terror will seize!", - "Za wszystko co zrobiłeś!", /// forma - "Nie jesteś tutaj mile widziany. Won!", - "Powinieneś zostać pod ziemią!", /// forma - ], - "npc.speech.villager_under_attack": [ - "Pomocy, jestem atakowany!", /// forma - "Pomocy! Jestem atakowany!", /// forma - /// "Ouch! I'm under attack!", - /// "Ouch! I'm under attack! Help!", - /// "Help me! I'm under attack!", - /// "I'm under attack! Help!", - /// "I'm under attack! Help me!", - "Pomocy!", - "Pomocy! Pomocy!", - "Pomocy! Pomocy! Pomocy!", - "Atakują mnie!", - /// "AAAHHH! I'm under attack!", - /// "AAAHHH! I'm under attack! Help!", - /// "Help! We're under attack!", - "Pomocy! Morderca!", - "Pomocy! Morderca na wolności!", - "Pomocy! Próbują mnie zabić!", - "Straże, jestem atakowany!", - "Straże! Jestem atakowany!", - /// "I'm under attack! Guards!", - /// "Help! Guards! I'm under attack!", - "Straże! Szybko!", - "Straże! Straże!", - "Straże! Złoczyńca!", - /// "Guards, slay this foul villain!", - "Straże! Tu jest morderca!", - "Straże! Pomocy!", - "Nie ujdzie Ci to płazem! Straże!", - /// "You fiend!", - /// "Help me!", - /// "Help! Please!", - /// "Ouch! Guards! Help!", - "Idą po mnie!", - /// "Help! Help! I'm being repressed!", - /// "Ah, now we see the violence inherent in the system.", - "To tylko zadrapanie!", - "Przestań!", - "Co Ci zrobiłem?!", - "Przestań mnie atakować!", - "Hej! Patrz jak to trzymasz!", - "Przepadnij łajdaku!", - "Przestań! Odwal się!", - "Wkurzasz mnie!", - "*Ugh* Za kogo się uważasz?!", - "Zapłacisz za to głową!", - "Przestań proszę, nie mam nic wartościowego!", - "Naślę na ciebie starszego brata!", - "Poskarżę się mamie!", - "Bądź przeklęty!", - "Przestań proszę.", - "To nie było miłe!", - "Twoja broń działa, teraz mnie zostaw!", - "Oszczędź mnie!", - "Proszę, mam rodzinę!", - "Jestem zbyt młody by umierać!", - "Możemy o tym pogadać?", - "Przemoc nigdy nie jest odpowiedzią!", - "Dzisiaj jest bardzo zły dzień...", - "Hej! To bolało!", - "Agh!", - "Niegrzecznie!", - "Przestań, proszę!", - "Niech cię diabli!", - "To nie jest śmieszne!", - "Jak mogłeś?!", - "Zapłacisz za to!", - "Jeśli nie przestaniesz to pożałujesz!", - "Nie zmuszaj mnie bym cię skrzywdził!", - "To nieporozumienie!", - "Nie musisz tego robic!", - "Spadaj śmieciu!", - "To boli!", - "Czemu to robisz?", - "Na wielkie nieba, przepadnij!", - "Musiałeś mnie pomylić z kimś innym!", /// forma - "Nie zasługuję na to!", - "Nie rób tego ponownie.", - "Straże, wrzućcie tego potwora do jeziora!", - "Poszczuję tarasqa (tarasque) na ciebie!", - "Dlaczego ja?", - ], - }, + } ) diff --git a/assets/voxygen/i18n/pl_PL/main.ron b/assets/voxygen/i18n/pl_PL/main.ron index 0da2e81d0e..86e8778198 100644 --- a/assets/voxygen/i18n/pl_PL/main.ron +++ b/assets/voxygen/i18n/pl_PL/main.ron @@ -66,5 +66,26 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "Naciśnij 'G' by zapalić latarnię.", + "Naciśnij 'F1' by zobaczyć podstawową klawiszologię.", + "Wpisz /say lub /s by rozmawiać tylko z pobliskimi graczami.", + "Wpisz /region lub /r by ograniczyć zasięg wiadomości do kilkuset bloków od Ciebie.", + "Administratorzy mogą używać komendy /build by wejść w tryb budowania.", + "Możesz użyć /group lub /g by rozmawiać z graczami w grupie.", + "Aby wysłać wiadomość prywatną, użyj /tell po czym dodaj nazwę docelowego gracza i wiadomość.", + "Rozglądaj się za jedzeniem, skrzyniami oraz skarbami - są one rozrzucone po całym świecie!", + "Ekwipunek zapełniony jedzeniem? Ugotuj z tego lepsze jedzenie!", + "Zastanawiasz się nad kolejnym wypadem? Spróbuj któryś z wielu lochów na mapie!", + "Nie zapomnij o dostosowaniu ustawień graficznych. Wciśnij 'N' by otworzyć ustawienia.", + "Gra jest lepsza z innymi! Wciśnij 'O' by sprawdzić kto jest zalogowany.", + "Użyj 'J' by zatańczyć :)", + "Użyj 'L-Shift' by wyciągnąć lotnię! Spokojnie, nie jest lepiona woskiem.", + "Veloren dalej jest w fazie Pre-Alpha. Staramy się ulepszać go dzień w dzień!", + "Jeśli chcesz pomóc w rozwijaniu projektu, albo porozmawiać z nami - wpadnij na naszego Discorda [EN]", + "Możesz przełączać typ paska zdrowia w opcjach.", + "Usiądź obok ogniska (używając 'K') by powoli wyleczyć się z obrażeń.", + "Potrzebujesz więcej slotów w ekwipunku, albo nowego uzbrojenia? Wciśnij 'C' aby otworzyć menu tworzenia!", + ], } ) diff --git a/assets/voxygen/i18n/pl_PL/npc.ron b/assets/voxygen/i18n/pl_PL/npc.ron new file mode 100644 index 0000000000..d2213536c3 --- /dev/null +++ b/assets/voxygen/i18n/pl_PL/npc.ron @@ -0,0 +1,175 @@ +/// Localization for Polish / Tłumaczenia dla języka polskiego +( + string_map: { + }, + + vector_map: { + "npc.speech.villager": [ + "Co za piękny dzień!", + "Jak się masz?", + "Udanego poranka!", + "...", /// "I wonder what the Catoblepas thinks when it eats grass.", + "Co myślisz o pogodzie?", + "Boję się na samą myśl o lochach. Mam nadzieję, że ktoś je wyczyści.", + "Chciałbym zapuścić się do jaskinii, gdy stanę się silniejszy.", /// forma + "Widziałeś mojego kota?", /// forma + "Słyszałeś kiedyś o zażartych rekinach ziemnych? Słyszałem że żyją na pustyni!", /// forma + "Mówi się, że cenne klejnoty można znaleźć w jaskiniach.", + "Fascynuje mnie ser...", + "Chciałbyś wpaść? Właśnie szykujemy ser!", + "Mówią, że grzyby są zdrowe... Nigdy nie miałem okazji ich spróbować.", /// forma + "Nie zapomnij o krakersach!", + "Uwielbiam krasnoludzki ser. Chciałbym umieć go zrobić", /// forma + "Ciekawe co jest za górami...", + "Marzę by zrobić kiedyś swoją lotnię.", + "Chcesz zobaczyć mój ogród? Dobra, może innym razem...", + "Cudowny dzień na przechadzkę po lesie.", + "Być albo nie być, oto jest pytanie... Myślę, że będę farmerem.", /// forma + "Czy też uważasz, że nasze miasteczko jest najlepsze?", + "Wiesz może dlaczego Świecące Resztki (Glowing Remains) świecą?", + "Myślę, że czas na drugie śniadanie!", + "Złapałeś kiedyś ważkę?", // forma + "Nie mogę zrozumieć skąd przychodzą te Sauroki (Sauroks).", + "Chciałbym by ktoś przeganiał wilki.", /// forma + "Miałem cudowny sen ostatniej nocy. Ciekawe co oznaczał?", /// forma + "Zostawiłem trochę sera z moim bratem. Teraz nie wiem czy ser dalej istnieje czy nie. Nazywam to serem Schrödingera.", /// forma + "Zostawiłem trochę sera z moją siostrą. Teraz nie wiem czy ser dalej istnieje czy nie. Nazywam to serem Schrödingera.", /// forma + "Ktoś powinien coś zrobić z tymi kultystami.", + "Fajnie by było jakby zaczęło padać.", + "Kocham miód! Ale pszczoły już nie bardzo.", + "Chciałbym zwiedzić kiedyś świat!", /// forma + ], + "npc.speech.villager_decline_trade": [ + "Wybacz, nie mam niczego do wymiany.", + "Handel? Sugerujesz, że mam coś co Cię zainteresuje?", + "Mój dom nie jest na sprzedaż!", + ], + "npc.speech.merchant_advertisement": [ + "Pokazać Ci swoje towary?", + "Masz ochotę na mały handelek?", + "Mam wiele produktów, chcesz rzucić okiem?" + ], + "npc.speech.merchant_busy": [ + "Zaczekaj na swoją kolej.", + "Proszę czekać, nie rozdwoję się.", + "Nie widzisz kolejki?", + "Jeszcze chwila, już kończę...", + "Nie wpychać się do kolejki.", + "Jestem zajęty, wpadnij później." /// forma + ], + "npc.speech.merchant_trade_successful": [ + "Dziękuję. Wpadnij ponownie!", + "Interesy z Tobą to czysta przyjemność!", + ], + "npc.speech.merchant_trade_declined": [ + "Może innym razem, trzymaj się!", + "Ehh, wpadnij kiedy indziej!" + ], + "npc.speech.villager_cultist_alarm": [ + "Uwaga! Kultyści w pobliżu!", + "Do broni! Kultyści atakują!", + "Jak mogli zaatakować nas?!", + "Śmierć kultystom!", + "Kultyści nie są tutaj tolerowani!", + "Morderca!", + "Posmakuj mojego ostrza brudny kultysto!", + "Nic nie zmaże krwi z twoich rąk kultysto!", + "W dupę jeża! Kultysta!", + "Zbrodniarz!", + "Ten kultysta jest mój!", + "Przygotuj się na spotkanie ze stwórcą kultysto!", + "Kultysta! Brać go!", /// forma + /// "I see a cultist! Attack!", + /// "I see a cultist! Don't let them escape!", + /// "Would the most honorable cultist care for some DEATH?!", + /// "Never forgive! Never forget! Cultist, regret!", + "Giń kultysto!", + /// "Your reign of terror will seize!", + "Za wszystko co zrobiłeś!", /// forma + "Nie jesteś tutaj mile widziany. Won!", + "Powinieneś zostać pod ziemią!", /// forma + ], + "npc.speech.villager_under_attack": [ + "Pomocy, jestem atakowany!", /// forma + "Pomocy! Jestem atakowany!", /// forma + /// "Ouch! I'm under attack!", + /// "Ouch! I'm under attack! Help!", + /// "Help me! I'm under attack!", + /// "I'm under attack! Help!", + /// "I'm under attack! Help me!", + "Pomocy!", + "Pomocy! Pomocy!", + "Pomocy! Pomocy! Pomocy!", + "Atakują mnie!", + /// "AAAHHH! I'm under attack!", + /// "AAAHHH! I'm under attack! Help!", + /// "Help! We're under attack!", + "Pomocy! Morderca!", + "Pomocy! Morderca na wolności!", + "Pomocy! Próbują mnie zabić!", + "Straże, jestem atakowany!", + "Straże! Jestem atakowany!", + /// "I'm under attack! Guards!", + /// "Help! Guards! I'm under attack!", + "Straże! Szybko!", + "Straże! Straże!", + "Straże! Złoczyńca!", + /// "Guards, slay this foul villain!", + "Straże! Tu jest morderca!", + "Straże! Pomocy!", + "Nie ujdzie Ci to płazem! Straże!", + /// "You fiend!", + /// "Help me!", + /// "Help! Please!", + /// "Ouch! Guards! Help!", + "Idą po mnie!", + /// "Help! Help! I'm being repressed!", + /// "Ah, now we see the violence inherent in the system.", + "To tylko zadrapanie!", + "Przestań!", + "Co Ci zrobiłem?!", + "Przestań mnie atakować!", + "Hej! Patrz jak to trzymasz!", + "Przepadnij łajdaku!", + "Przestań! Odwal się!", + "Wkurzasz mnie!", + "*Ugh* Za kogo się uważasz?!", + "Zapłacisz za to głową!", + "Przestań proszę, nie mam nic wartościowego!", + "Naślę na ciebie starszego brata!", + "Poskarżę się mamie!", + "Bądź przeklęty!", + "Przestań proszę.", + "To nie było miłe!", + "Twoja broń działa, teraz mnie zostaw!", + "Oszczędź mnie!", + "Proszę, mam rodzinę!", + "Jestem zbyt młody by umierać!", + "Możemy o tym pogadać?", + "Przemoc nigdy nie jest odpowiedzią!", + "Dzisiaj jest bardzo zły dzień...", + "Hej! To bolało!", + "Agh!", + "Niegrzecznie!", + "Przestań, proszę!", + "Niech cię diabli!", + "To nie jest śmieszne!", + "Jak mogłeś?!", + "Zapłacisz za to!", + "Jeśli nie przestaniesz to pożałujesz!", + "Nie zmuszaj mnie bym cię skrzywdził!", + "To nieporozumienie!", + "Nie musisz tego robic!", + "Spadaj śmieciu!", + "To boli!", + "Czemu to robisz?", + "Na wielkie nieba, przepadnij!", + "Musiałeś mnie pomylić z kimś innym!", /// forma + "Nie zasługuję na to!", + "Nie rób tego ponownie.", + "Straże, wrzućcie tego potwora do jeziora!", + "Poszczuję tarasqa (tarasque) na ciebie!", + "Dlaczego ja?", + ], + }, +) diff --git a/assets/voxygen/i18n/pt_BR/_manifest.ron b/assets/voxygen/i18n/pt_BR/_manifest.ron index dcc329c99f..9338cd156d 100644 --- a/assets/voxygen/i18n/pt_BR/_manifest.ron +++ b/assets/voxygen/i18n/pt_BR/_manifest.ron @@ -28,206 +28,5 @@ asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", scale_ratio: 1.0, ), - }, - - string_map: { - - }, - - vector_map: { - "loading.tips": [ - "Pressione 'G' para acender sua lâmpada.", - "Pressione 'F1' para visualizar suas teclas de atalho.", - "Você pode digitar /say ou /s para conversar apenas com jogadores próximos a você.", - "Você pode digitar /region ou /r para conversar apenas com jogadores a poucas centenas de blocos de você.", - "Admins podem usar o comando /build para entrar no modo construção.", - "Você pode digitar /group ou /g para conversar apenas com jogadores do seu grupo.", - "Para enviar mensagens privadas digite /tell seguido do nome do jogador desejado.", - "Busque sempre comida, baús e outros espólios espalhados pelo mundo!", - "Inventário cheio de comidas? Tente criar alimentos melhores com elas!", - "Imaginando o que há pra fazer? Cavernas estão marcadas com pontos marrons no mapa!", - "Não esqueça de ajustar as configurações gráficas. Pressione 'N' para abrir as configurações.", - "Jogar com outros é divertido! Pressione 'O' para ver quem está online.", - "Pressione 'J' para dançar. Hora da festa!", - "Pressione 'Shift Esquerdo' para abrir o Planador e conquistar os céus.", - "Veloren ainda está no Pre-Alpha. Estamos nos empenhando ao máximo para melhorar a cada dia!", - "Se quiser ingressar no time de Desenvolvedores ou apenas conversar conosco, acesse o nosso servidor do Discord.", - "Você pode exibir sua saúde em sua barra de vida nas opções.", - "Sente ao redor de uma fogueira (usando a tecla 'K') para lentamente se recuperar de lesões.", - "Precisa de uma mochila maior para sua jornada? Pressione 'C' para abrir o menu de criação!", - ], - "npc.speech.villager": [ - "Não é um dia tão lindo?", - "Como você está?", - "Uma ótima manhã para você!", - "Fico imaginando o que um Catobelpas pensa enquanto come grama.", - "O que você está achando do clima?", - "Só de imaginar o que há em todas as masmorras me dá arrepios. Espero que alguém as limpe.", - "Adoraria explorar algumas cavernas assim que eu ficar mais forte.", - "Você viu meu gato?", - "Já ouviu falar dos ferozes Land Sharks? Ouvi dizer que eles vivem nos desertos.", - "Dizem que diversos tipos de gemas brilhantes podem ser encontradas nas cavernas.", - "Sou viciado em queijo!", - "Quer entrar? Venha, vamos comer um queijo!", - "Dizem que cogumelos são bons para saude. Nunca comi.", - "Não esqueça dos biscoitos!", - "Eu adoro queijo anão(dwarven cheese). Gostaria de saber fazer.", - "Fico imaginando o que há depois das montanhas.", - "Espero um dia conseguir fazer meu planador.", - "Gostaria de ver o meu jardim? Tá bom, talvez outro dia então.", - "Um dia adoravel para um passeio na floresta!", - "Ser ou não ser? Acho que serei um fazendeiro.", - "Nossa aldeia é a melhor, não acha?.", - "O que você acha que faz os Restos Brilhantes(Glowing Remains) brilharem?.", - "Acho que está na hora dum segundo café da manhã!", - "Já capturou uma libélula(firefly)?", - "Não consigo entender de onde vem tantos Sauroks.", - "Gostaria que alguém conseguisse espantar os lobos (wolves) da aldeia.", - "Tive um sonho magnífico sobre queijo ontem. O que será que significa?", - "Deixei um pouco de queijo com meu irmão. Agora não sei se existe ou não. Eu chamo de queijo de Schrödinger.", - "Deixei um pouco de queijo com minha irmã. Agora não sei se existe ou não. Eu chamo de queijo de Schrödinger.", - "Alguém deveria fazer algo sobre esses cultistas. De preferência, não eu.", - "Espero que chova logo. Seria bom para as colheitas.", - "Eu amo mel! E eu odeio abelhas. ", - "Eu quero viajar no mundo um dia. Deve haver mais vida do que nesta aldeia. ", - ], - "npc.speech.villager_decline_trade": [ - "Desculpe, não tenho nada para trocar.", - "Troca? Como se eu tivesse algo que pode interessar a você.", - "Minha casa é minha, não vou trocá-la por nada.", - ], - "npc.speech.merchant_advertisement": [ - "Está interessado em fazer uma troca comigo?", - "Você quer negociar comigo?", - "Eu tenho muitos produtos, você quer dar uma olhada?" - ], - "npc.speech.merchant_busy": [ - "Ei, espere sua vez.", - "Espere, por favor. Sou apenas uma pessoa.", - "Você vê a outra pessoa na sua frente?", - "Só um momento, deixe-me terminar.", - "Não fure a fila.", - "Estou ocupado, volte mais tarde." - ], - "npc.speech.merchant_trade_successful": [ - "Obrigado por negociar comigo!", - "Obrigado!", - ], - "npc.speech.merchant_trade_declined": [ - "Talvez outra hora, tenha um bom dia!", - "Que pena, talvez da próxima vez, então! " - ], - "npc.speech.villager_cultist_alarm": [ - "Olhe! Há um cultista à solta!", - "Às armas! Os cultistas estão atacando!", - "Como ousam os cultistas atacar nossa aldeia!", - "Morte aos cultistas!", - "Cultistas não serão tolerados aqui!", - "Cultista assassino!", - "Prove o gume da minha espada, seu cultista sujo!", - "Nada pode limpar o sangue de suas mãos, cultista!", - "Com mil milhões de macacos e raios e coriscos! Um cultista entre nós!", - "Com um milhão de tubarões! Um cultista entre nós!", - "Os males deste cultista estão prestes a acabar!", - "Este cultista é meu!", - "Prepare-se para encontrar o seu criador, oh sórdido cultista!", - "Vejo um cultista! Pegue eles!", - "Vejo um cultista! Atacar!", - "Vejo um cultista! Não o deixe escapar!", - "O mais honrado cultista se importaria com alguma MORTE?!", - "Nunca perdoe! Nunca se esqueça! Morra, cultista!", - "Morra, cultista!", - "Seu reinado de terror chegará ao fim!", - "Você pagará por tudo que fez!", - "Não aceitamos bem seus tipos por aqui.", - "Você deveria ter ficado no subsolo!", - ], - "npc.speech.villager_under_attack": [ - "Ajuda, Estou sendo atacado!", - "Ajuda! Estou sendo atacado!", - "Ouch! Estou sendo atacado!", - "Ouch! Estou sendo atacado! Ajuda!", - "Me ajude! Estou sendo atacado!", - "Estou sendo atacado! Ajuda!", - "Estou sendo atacado! Me ajude!", - "Ajuda!", - "Ajuda! Ajuda!", - "Ajuda! Ajuda! Ajuda!", - "Estou sendo atacado!", - "AAAHHH! Estou sendo atacado!", - "AAAHHH! Estou sendo atacado! Ajuda!", - "Ajuda! Estamos sendo atacado!", - "Ajuda! Assassino!", - "Ajuda! Há um assassinado em andamento!", - "Ajuda! Estão tentando me matar!", - "Guardas, Estou sendo atacado!", - "Guardas! Estou sendo atacado!", - "Estou sendo atacado! Guardas!", - "Ajuda! Guardas! Estou sendo atacado!", - "Guardas! Depressa!", - "Guardas! Guardas!", - "Guardas! Um vilão está me atacando!", - "Guardas, acabem com este maldito vilão!", - "Guardas! Um assasino a solta!", - "Guardas! Me ajude!", - "Você não vai se safar dessa! Guardas!", - "Maldito Vilão!", - "Me ajude!", - "Ajuda! Por favor!", - "Ouch! Guardas! Ajuda!", - "Estão atrás de mim!", - "Ajuda! Ajuda! Estou sendo repreendido", - "Ah, agora vemos a violência inerente ao sistema.", - "Só um arranhão!", - "Pare com isso!", - "O que eu fiz para você?!", - "Por favor, pare de me atacar!", - "Hey! Cuida pra onde você aponta essa coisa!", - "Desgraçado hediondo, vou acabar com você!", - "Pare com isso! Vá embora!", - "Você está me deixando louco!", - "Ow! Quem você pensa que é?!", - "Arrancarei sua cabeça por isso!", - "Pare, por favor! Não levo nada de valor!", - "Vou mandar meu irmão em você, ele é maior que eu!", - "Nãooo, Vou contar pra minha mãe!", - "Te amaldiçoo!", - "Por favor não faça isso.", - "Isso não foi muito legal!", - "Sua arma funciona, pode guardar ela agora!", - "Me poupe!", - "Por favor, tenho uma família!", - "Sou muito jovem para morrer!", - "Podemos conversar sobre isso?", - "Violência nunca é a resposta!", - "Hoje foi um péssimo dia...", - "Ei, isso dói!", - "Eek!", - "Que rude!", - "Pare, eu imploro!", - "Que você adoeça!", - "Isso não é engraçado.", - "Como ousa?!", - "Você pagará por isso!", - "Continue assim e irá se arrepender!", - "Não me faça te machucar!", - "Deve haver algum engano!", - "Não precisa fazer isso!", - "Morre, Diabo!", - "Isso Dói!", - "Porque você faria isso?", - "Pelos espíritos, Pare!", - "Você deve ter me confundido com alguém!", - "Eu não mereço isso!", - "Por favor, não faça isso novamente.", - "Guardas, joguem este monstro no lago!", - "Vou mandar meu tarrasque em você!", - "Porque eeeeeeeeeeeeeu?", - ], - "npc.speech.villager_enemy_killed": [ - "Destruí meu inimigo!", - "Finalmente em paz!", - "... agora, o que eu estava fazendo?", - ] } ) diff --git a/assets/voxygen/i18n/pt_BR/main.ron b/assets/voxygen/i18n/pt_BR/main.ron index d6f5f5b64b..b5cdc71325 100644 --- a/assets/voxygen/i18n/pt_BR/main.ron +++ b/assets/voxygen/i18n/pt_BR/main.ron @@ -66,5 +66,26 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "Pressione 'G' para acender sua lâmpada.", + "Pressione 'F1' para visualizar suas teclas de atalho.", + "Você pode digitar /say ou /s para conversar apenas com jogadores próximos a você.", + "Você pode digitar /region ou /r para conversar apenas com jogadores a poucas centenas de blocos de você.", + "Admins podem usar o comando /build para entrar no modo construção.", + "Você pode digitar /group ou /g para conversar apenas com jogadores do seu grupo.", + "Para enviar mensagens privadas digite /tell seguido do nome do jogador desejado.", + "Busque sempre comida, baús e outros espólios espalhados pelo mundo!", + "Inventário cheio de comidas? Tente criar alimentos melhores com elas!", + "Imaginando o que há pra fazer? Cavernas estão marcadas com pontos marrons no mapa!", + "Não esqueça de ajustar as configurações gráficas. Pressione 'N' para abrir as configurações.", + "Jogar com outros é divertido! Pressione 'O' para ver quem está online.", + "Pressione 'J' para dançar. Hora da festa!", + "Pressione 'Shift Esquerdo' para abrir o Planador e conquistar os céus.", + "Veloren ainda está no Pre-Alpha. Estamos nos empenhando ao máximo para melhorar a cada dia!", + "Se quiser ingressar no time de Desenvolvedores ou apenas conversar conosco, acesse o nosso servidor do Discord.", + "Você pode exibir sua saúde em sua barra de vida nas opções.", + "Sente ao redor de uma fogueira (usando a tecla 'K') para lentamente se recuperar de lesões.", + "Precisa de uma mochila maior para sua jornada? Pressione 'C' para abrir o menu de criação!", + ], } ) diff --git a/assets/voxygen/i18n/pt_BR/npc.ron b/assets/voxygen/i18n/pt_BR/npc.ron new file mode 100644 index 0000000000..025ba90c52 --- /dev/null +++ b/assets/voxygen/i18n/pt_BR/npc.ron @@ -0,0 +1,184 @@ +/// CUIDADO: Arquivos de tradução devem ser criados no formato UTF-8 sem Marca de Ordem de byte - BOM(https://pt.wikipedia.org/wiki/Marca_de_ordem_de_byte) + +/// Localization for Portuguese (Brazil) +( + string_map: { + + }, + + vector_map: { + "npc.speech.villager": [ + "Não é um dia tão lindo?", + "Como você está?", + "Uma ótima manhã para você!", + "Fico imaginando o que um Catobelpas pensa enquanto come grama.", + "O que você está achando do clima?", + "Só de imaginar o que há em todas as masmorras me dá arrepios. Espero que alguém as limpe.", + "Adoraria explorar algumas cavernas assim que eu ficar mais forte.", + "Você viu meu gato?", + "Já ouviu falar dos ferozes Land Sharks? Ouvi dizer que eles vivem nos desertos.", + "Dizem que diversos tipos de gemas brilhantes podem ser encontradas nas cavernas.", + "Sou viciado em queijo!", + "Quer entrar? Venha, vamos comer um queijo!", + "Dizem que cogumelos são bons para saude. Nunca comi.", + "Não esqueça dos biscoitos!", + "Eu adoro queijo anão(dwarven cheese). Gostaria de saber fazer.", + "Fico imaginando o que há depois das montanhas.", + "Espero um dia conseguir fazer meu planador.", + "Gostaria de ver o meu jardim? Tá bom, talvez outro dia então.", + "Um dia adoravel para um passeio na floresta!", + "Ser ou não ser? Acho que serei um fazendeiro.", + "Nossa aldeia é a melhor, não acha?.", + "O que você acha que faz os Restos Brilhantes(Glowing Remains) brilharem?.", + "Acho que está na hora dum segundo café da manhã!", + "Já capturou uma libélula(firefly)?", + "Não consigo entender de onde vem tantos Sauroks.", + "Gostaria que alguém conseguisse espantar os lobos (wolves) da aldeia.", + "Tive um sonho magnífico sobre queijo ontem. O que será que significa?", + "Deixei um pouco de queijo com meu irmão. Agora não sei se existe ou não. Eu chamo de queijo de Schrödinger.", + "Deixei um pouco de queijo com minha irmã. Agora não sei se existe ou não. Eu chamo de queijo de Schrödinger.", + "Alguém deveria fazer algo sobre esses cultistas. De preferência, não eu.", + "Espero que chova logo. Seria bom para as colheitas.", + "Eu amo mel! E eu odeio abelhas. ", + "Eu quero viajar no mundo um dia. Deve haver mais vida do que nesta aldeia. ", + ], + "npc.speech.villager_decline_trade": [ + "Desculpe, não tenho nada para trocar.", + "Troca? Como se eu tivesse algo que pode interessar a você.", + "Minha casa é minha, não vou trocá-la por nada.", + ], + "npc.speech.merchant_advertisement": [ + "Está interessado em fazer uma troca comigo?", + "Você quer negociar comigo?", + "Eu tenho muitos produtos, você quer dar uma olhada?" + ], + "npc.speech.merchant_busy": [ + "Ei, espere sua vez.", + "Espere, por favor. Sou apenas uma pessoa.", + "Você vê a outra pessoa na sua frente?", + "Só um momento, deixe-me terminar.", + "Não fure a fila.", + "Estou ocupado, volte mais tarde." + ], + "npc.speech.merchant_trade_successful": [ + "Obrigado por negociar comigo!", + "Obrigado!", + ], + "npc.speech.merchant_trade_declined": [ + "Talvez outra hora, tenha um bom dia!", + "Que pena, talvez da próxima vez, então! " + ], + "npc.speech.villager_cultist_alarm": [ + "Olhe! Há um cultista à solta!", + "Às armas! Os cultistas estão atacando!", + "Como ousam os cultistas atacar nossa aldeia!", + "Morte aos cultistas!", + "Cultistas não serão tolerados aqui!", + "Cultista assassino!", + "Prove o gume da minha espada, seu cultista sujo!", + "Nada pode limpar o sangue de suas mãos, cultista!", + "Com mil milhões de macacos e raios e coriscos! Um cultista entre nós!", + "Com um milhão de tubarões! Um cultista entre nós!", + "Os males deste cultista estão prestes a acabar!", + "Este cultista é meu!", + "Prepare-se para encontrar o seu criador, oh sórdido cultista!", + "Vejo um cultista! Pegue eles!", + "Vejo um cultista! Atacar!", + "Vejo um cultista! Não o deixe escapar!", + "O mais honrado cultista se importaria com alguma MORTE?!", + "Nunca perdoe! Nunca se esqueça! Morra, cultista!", + "Morra, cultista!", + "Seu reinado de terror chegará ao fim!", + "Você pagará por tudo que fez!", + "Não aceitamos bem seus tipos por aqui.", + "Você deveria ter ficado no subsolo!", + ], + "npc.speech.villager_under_attack": [ + "Ajuda, Estou sendo atacado!", + "Ajuda! Estou sendo atacado!", + "Ouch! Estou sendo atacado!", + "Ouch! Estou sendo atacado! Ajuda!", + "Me ajude! Estou sendo atacado!", + "Estou sendo atacado! Ajuda!", + "Estou sendo atacado! Me ajude!", + "Ajuda!", + "Ajuda! Ajuda!", + "Ajuda! Ajuda! Ajuda!", + "Estou sendo atacado!", + "AAAHHH! Estou sendo atacado!", + "AAAHHH! Estou sendo atacado! Ajuda!", + "Ajuda! Estamos sendo atacado!", + "Ajuda! Assassino!", + "Ajuda! Há um assassinado em andamento!", + "Ajuda! Estão tentando me matar!", + "Guardas, Estou sendo atacado!", + "Guardas! Estou sendo atacado!", + "Estou sendo atacado! Guardas!", + "Ajuda! Guardas! Estou sendo atacado!", + "Guardas! Depressa!", + "Guardas! Guardas!", + "Guardas! Um vilão está me atacando!", + "Guardas, acabem com este maldito vilão!", + "Guardas! Um assasino a solta!", + "Guardas! Me ajude!", + "Você não vai se safar dessa! Guardas!", + "Maldito Vilão!", + "Me ajude!", + "Ajuda! Por favor!", + "Ouch! Guardas! Ajuda!", + "Estão atrás de mim!", + "Ajuda! Ajuda! Estou sendo repreendido", + "Ah, agora vemos a violência inerente ao sistema.", + "Só um arranhão!", + "Pare com isso!", + "O que eu fiz para você?!", + "Por favor, pare de me atacar!", + "Hey! Cuida pra onde você aponta essa coisa!", + "Desgraçado hediondo, vou acabar com você!", + "Pare com isso! Vá embora!", + "Você está me deixando louco!", + "Ow! Quem você pensa que é?!", + "Arrancarei sua cabeça por isso!", + "Pare, por favor! Não levo nada de valor!", + "Vou mandar meu irmão em você, ele é maior que eu!", + "Nãooo, Vou contar pra minha mãe!", + "Te amaldiçoo!", + "Por favor não faça isso.", + "Isso não foi muito legal!", + "Sua arma funciona, pode guardar ela agora!", + "Me poupe!", + "Por favor, tenho uma família!", + "Sou muito jovem para morrer!", + "Podemos conversar sobre isso?", + "Violência nunca é a resposta!", + "Hoje foi um péssimo dia...", + "Ei, isso dói!", + "Eek!", + "Que rude!", + "Pare, eu imploro!", + "Que você adoeça!", + "Isso não é engraçado.", + "Como ousa?!", + "Você pagará por isso!", + "Continue assim e irá se arrepender!", + "Não me faça te machucar!", + "Deve haver algum engano!", + "Não precisa fazer isso!", + "Morre, Diabo!", + "Isso Dói!", + "Porque você faria isso?", + "Pelos espíritos, Pare!", + "Você deve ter me confundido com alguém!", + "Eu não mereço isso!", + "Por favor, não faça isso novamente.", + "Guardas, joguem este monstro no lago!", + "Vou mandar meu tarrasque em você!", + "Porque eeeeeeeeeeeeeu?", + ], + "npc.speech.villager_enemy_killed": [ + "Destruí meu inimigo!", + "Finalmente em paz!", + "... agora, o que eu estava fazendo?", + ] + } +) diff --git a/assets/voxygen/i18n/pt_PT/_manifest.ron b/assets/voxygen/i18n/pt_PT/_manifest.ron index d646a65863..7ae6d68cf1 100644 --- a/assets/voxygen/i18n/pt_PT/_manifest.ron +++ b/assets/voxygen/i18n/pt_PT/_manifest.ron @@ -26,10 +26,5 @@ asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", scale_ratio: 1.0, ), - }, - string_map: { - }, - - vector_map: { } ) diff --git a/assets/voxygen/i18n/pt_PT/npc.ron b/assets/voxygen/i18n/pt_PT/npc.ron new file mode 100644 index 0000000000..d2679ab63c --- /dev/null +++ b/assets/voxygen/i18n/pt_PT/npc.ron @@ -0,0 +1,12 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for portuguese (Portugal) +( + string_map: { + + }, + + vector_map: { + + } +) diff --git a/assets/voxygen/i18n/ru_RU/_manifest.ron b/assets/voxygen/i18n/ru_RU/_manifest.ron index dc396f3f6c..4a60371877 100644 --- a/assets/voxygen/i18n/ru_RU/_manifest.ron +++ b/assets/voxygen/i18n/ru_RU/_manifest.ron @@ -28,206 +28,5 @@ asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", scale_ratio: 1.0, ), - }, - - string_map: { - - }, - - - vector_map: { - "loading.tips": [ - "Нажмите 'G', чтобы зажечь фонарь.", - "Нажмите 'F1', чтобы просмотреть все клавиши по умолчанию.", - "Вы можете ввести /tell или /s, чтобы общаться только с игроками непосредственно вокруг вас.", - "Вы можете ввести /region или /r, чтобы общаться только с игроками в паре сотен блоков вокруг вас.", - "Администраторы могут использовать команду /build для входа в режим постройки.", - "Вы можете ввести /group или /g, чтобы общаться только с игроками в вашей текущей группе.", - "Чтобы отправить личные сообщения, введите /tell, а затем имя игрока и ваше сообщение.", - "Смотрите внимательно чтобы найти еду, сундуки и другие предметы, разбросанные по всему миру!", - "Инвентарь, заполненный едой? Попробуйте приготовить из нее еду получше!", - "Интересно, чем можно заняться? Попробуйте пройти одно из подземелий, отмеченных на карте!", - "Не забудьте настроить графику для вашей системы. Нажмите 'N', чтобы открыть настройки.", - "Играть с другими-это весело! Нажмите 'О', чтобы узнать, кто находится в сети.", - "Нажмите 'J', чтобы танцевать. Вечеринка!", - "Нажмите 'L-Shift', чтобы открыть свой дельтаплан и покорить небо.", - "Veloren все еще находится в Пре-Альфе. Мы делаем все возможное, чтобы улучшать его каждый день!", - "Если вы хотите присоединиться к команде разработчиков или просто пообщаться с нами, присоединяйтесь к нашему серверу Discord.", - "Вы можете переключить отображение количества здоровья на панели здоровья в настройках.", - "Сядьте у костра (с помощью клавиши 'К'), чтобы залечить свои раны.", - "Вам нужно больше сумок или лучшая броня, чтобы продолжить свое путешествие? Нажмите 'C', чтобы открыть меню крафта!", - ], - "npc.speech.villager": [ - "Хорошая погода?", - "Как дела?", - "Доброе утро!", - "Интересно, что думает Catoblepas когда ест траву.", /// in original Catoblepas (киса) но яб сменил на овцу в оригинале - "Хорошая погода, не правда ли?", - "Мысли об этих подземельях пугают меня. Надеюсь их кто-нибудь уничтожит", - "Когда я вырасту, я буду исследовать пещеры.", - "Вы не видели моего кота?", - "Вы когда-нибудь слышали о свирепых сухопутных акулах? Я слышал, они живут в пустынях", - "Говорят, в пещерах можно найти блестящие драгоценные камни всех видов.", - "Я просто помешан на сыре!", - "Ты не зайдешь? Мы как раз собирались съесть немного сыра", - "Говорят, мухоморы полезны для здоровья. Сам я их не ем.", - "Не забудь про печенья!", - "Я просто обожаю сыр дварфов. Я бы хотел научиться его готовить.", - "Интересно, что по ту сторону гор.", - "Я надеюсь сделать свой собственный дельтаплан когда-нибудь.", - "Хочешь, покажу тебе свой сад? Ладно, может в следующий раз.", - "Прекрасный день для прогулки по лесу!", - "Быть или не быть? Я подумываю о том чтобы стать фермером.", - "Тебе не кажется, что наша деревня самая лучшая?", - "Как ты думаешь, что заставляет Glowing Remains светься?", - "Время второго завтрака!", - "Ты когда - нибудь ловил светлячка?", - "I just can't understand where those Sauroks keep coming from.", - "Я бы хотел, чтобы кто-нибудь держал волков подальше от деревнию.", - "Прошлой ночью мне приснился чудесный сон о сыре. Что это значит?", - "Я оставила немного сыра у брата. Теперь я не знаю, съеден сыр или нет. Я называю его сыром Шредингера.", - "Я оставил немного сыра у сестры. Теперь я не знаю, съеден сыр или нет. Я называю его сыром Шредингера.", - "Кто-то должен что-то сделать с этими культистами. Желательно не я.", - "Надеюсь, скоро пойдет дождь. Это было бы хорошо для урожая.", - "Я люблю мед! И я ненавижу пчел.", - "Я хочу однажды увидеть мир. В жизни должно быть что-то большее, чем эта деревня.", - ], - "npc.speech.villager_decline_trade": [ - "Извините, мне нечем торговать.", - "Торговля? Как будто у меня есть что-то, что может вас заинтересовать.", - "Мой дом принадлежит мне, я не променяю его ни на что.", - ], - "npc.speech.merchant_advertisement": [ - "Могу ли я заинтересовать вас сделкой?", - "Ты хочешь со мной поторговать?", - "У меня много товаров, не хочешь взглянуть?" - ], - "npc.speech.merchant_busy": [ - "Эй, подожди своей очереди.", - "Пожалуйста, подождите, я здесь один на всех.", - "Видите другого человека перед собой?", - "Минутку, дай мне закончить.", - "Не лезь вне очереди!", - "Я занят, зайди попозже." - ], - "npc.speech.merchant_trade_successful": [ - "Спасибо, что торгуете со мной!", - "Спасибо вам!", - ], - "npc.speech.merchant_trade_declined": [ - "Может быть, в другой раз, хорошего дня!", - "Жаль, тогда, может быть, в следующий раз!" - ], - "npc.speech.villager_cultist_alarm": [ - "Берегись! На свободе разгуливает культист!", - "К оружию! Культисты атакуют!", - "Как посмели культисты напасть на нашу деревню!", - "Смерть культистам!", - "Культистов здесь не потерпят!", - "Кровожадный культист!", - "Попробуй на вкус острие моего меча, грязный культист!", - "Ничего не сможет смыть кровь с твоих рук, культист!", - "Миллиарды пузырящихся синих ракушек! Культист среди нас!", - "Зло этого культиста вот-вот закончится!", - "Этот культист мой!", - "Приготовься встретить своего создателя, грязный культист!", - "Я вижу культиста! Схватите его!", - "Я вижу культиста! В атаку!", - "Я вижу культиста! Не дайте им сбежать!", - "Будет ли самый почтенный культист заботиться о какой-то СМЕРТИ?!", - "Никогда не прощу! Никогда не забуду! Культист, сожалею!", - "Умри, культист!", - "Ваше царство террора захвачено!", - "Вот тебе за все, что ты сделал!", - "Мы не очень хорошо относимся к вашим людям здесь.", - "Тебе следовало оставаться под землей!", - ], - "npc.speech.villager_under_attack": [ - "Помогите, Меня атакуют!", - "Помогите, Меня атакуют!", - "Оуч, Меня атакуют!", - "Оуч, Меня атакуют!", - "Помоги мне! Меня атакуют!", - "Меня атакуют! Помогите!", - "Меня атакуют! Помогите мне!", - "Помогите!", - "Помогите! Помогите!", - "Помогите! Помогите! Помогите!", - "Меня атакуют!", - "АААААА! Меня атакуют!", - "АААААА! Меня атакуют! Помогите!", - "Помогите! Мы атакованны!", - "Помогите! Убийца!", - "Помогите! Убийца на свободе!", - "Помогите! Они пытаются меня убить!", - "Стража, Меня атакуют!", - "Стража! Меня атакуют!", - "Меня атакуют! Стража!", - "Помогите! Стража! Меня атакуют!", - "Стража! Скорее!", - "Стража! Стража!", - "Стража! Этот злодей бьёт меня!", - "Стража, Схватите этого негодяя!", - "Стража! Здесь убийца!", - "Стража! Помогите me!", - "Тебе это не сойдет с рук! Стража!", - "Ты изверг!", - "Помогите мне!", - "Помогите! Пожалуйста!", - "Ой! Стража! Помогите!", - "Они идут за мной!", - "Помогите! Помогите! Меня постигла расплата!", - "Ах, теперь мы видим насилие, присущее системе.", - "Это всего лишь царапина!", - "Остановитесь!", - "Что я тебе сделал?!", - "Пожалуйста, не бей!", - "Эй! Смотри, куда направляешь эту штуку", - "Гнусный негодяй, проваливай отсюда!", - "Прекрати! Уходи!", - "Ты уже достал!", - "Эй! Что ты возомнил о себе?!", - "Я тебе башку оторву!", - "Остановись пожалуйста. У меня ничего нет!", - "Я позову брата, он больше меня", - "Нет! Я расскажу маме!", - "Будь ты проклят!", - "Пожалуйста, не делай этого.", - "Это не приятно!", - "Ваше оружие работает, вы можете убрать его прямо сейчас!", - "Пощади!", - "Пожалуйста, у меня семья!", - "Я слишком молод чтобы умереть!", - "Может договоримся?", - "Насилие не выход!", - "Сегодня выдался плохой день...", - "Эй, это больно!", - "Ик!", - "Как грубо!", - "Остановись, прошу тебя!", - "Чтоб ты сдох!", - "Это не смешно.", - "Как ты смеешь?!", - "Ты заплатишь за это!", - "Ты об этом пожалеешь!", - "Не заставляй меня делать тебе больно!", - "Произошла какая то ошибка!", - "Не делай этого!", - "Изыди, дьявол", - "Это очень больно!", - "Зачем ты это сделал?", - "Ради всего святого, прекрати!", - "Ты меня перепутал с кем то", - "Я не заслуживаю этого!", - "Пожалуйста, больше так не делай.", - "Стража, утопите этого монстра в озере!", - "Я натравлю своего tarasque на тебя!", - "Почему я?", - ], - "npc.speech.villager_enemy_killed": [ - "Я уничтожил врага!", - "Наконец-то мир!", - "... что же я наделал?", - ] } ) diff --git a/assets/voxygen/i18n/ru_RU/main.ron b/assets/voxygen/i18n/ru_RU/main.ron index 752188d27f..f29dbf2775 100644 --- a/assets/voxygen/i18n/ru_RU/main.ron +++ b/assets/voxygen/i18n/ru_RU/main.ron @@ -65,5 +65,26 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "Нажмите 'G', чтобы зажечь фонарь.", + "Нажмите 'F1', чтобы просмотреть все клавиши по умолчанию.", + "Вы можете ввести /tell или /s, чтобы общаться только с игроками непосредственно вокруг вас.", + "Вы можете ввести /region или /r, чтобы общаться только с игроками в паре сотен блоков вокруг вас.", + "Администраторы могут использовать команду /build для входа в режим постройки.", + "Вы можете ввести /group или /g, чтобы общаться только с игроками в вашей текущей группе.", + "Чтобы отправить личные сообщения, введите /tell, а затем имя игрока и ваше сообщение.", + "Смотрите внимательно чтобы найти еду, сундуки и другие предметы, разбросанные по всему миру!", + "Инвентарь, заполненный едой? Попробуйте приготовить из нее еду получше!", + "Интересно, чем можно заняться? Попробуйте пройти одно из подземелий, отмеченных на карте!", + "Не забудьте настроить графику для вашей системы. Нажмите 'N', чтобы открыть настройки.", + "Играть с другими-это весело! Нажмите 'О', чтобы узнать, кто находится в сети.", + "Нажмите 'J', чтобы танцевать. Вечеринка!", + "Нажмите 'L-Shift', чтобы открыть свой дельтаплан и покорить небо.", + "Veloren все еще находится в Пре-Альфе. Мы делаем все возможное, чтобы улучшать его каждый день!", + "Если вы хотите присоединиться к команде разработчиков или просто пообщаться с нами, присоединяйтесь к нашему серверу Discord.", + "Вы можете переключить отображение количества здоровья на панели здоровья в настройках.", + "Сядьте у костра (с помощью клавиши 'К'), чтобы залечить свои раны.", + "Вам нужно больше сумок или лучшая броня, чтобы продолжить свое путешествие? Нажмите 'C', чтобы открыть меню крафта!", + ], } ) diff --git a/assets/voxygen/i18n/ru_RU/npc.ron b/assets/voxygen/i18n/ru_RU/npc.ron new file mode 100644 index 0000000000..5cca03026f --- /dev/null +++ b/assets/voxygen/i18n/ru_RU/npc.ron @@ -0,0 +1,184 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for RUS +( + string_map: { + + }, + + + vector_map: { + "npc.speech.villager": [ + "Хорошая погода?", + "Как дела?", + "Доброе утро!", + "Интересно, что думает Catoblepas когда ест траву.", /// in original Catoblepas (киса) но яб сменил на овцу в оригинале + "Хорошая погода, не правда ли?", + "Мысли об этих подземельях пугают меня. Надеюсь их кто-нибудь уничтожит", + "Когда я вырасту, я буду исследовать пещеры.", + "Вы не видели моего кота?", + "Вы когда-нибудь слышали о свирепых сухопутных акулах? Я слышал, они живут в пустынях", + "Говорят, в пещерах можно найти блестящие драгоценные камни всех видов.", + "Я просто помешан на сыре!", + "Ты не зайдешь? Мы как раз собирались съесть немного сыра", + "Говорят, мухоморы полезны для здоровья. Сам я их не ем.", + "Не забудь про печенья!", + "Я просто обожаю сыр дварфов. Я бы хотел научиться его готовить.", + "Интересно, что по ту сторону гор.", + "Я надеюсь сделать свой собственный дельтаплан когда-нибудь.", + "Хочешь, покажу тебе свой сад? Ладно, может в следующий раз.", + "Прекрасный день для прогулки по лесу!", + "Быть или не быть? Я подумываю о том чтобы стать фермером.", + "Тебе не кажется, что наша деревня самая лучшая?", + "Как ты думаешь, что заставляет Glowing Remains светься?", + "Время второго завтрака!", + "Ты когда - нибудь ловил светлячка?", + "I just can't understand where those Sauroks keep coming from.", + "Я бы хотел, чтобы кто-нибудь держал волков подальше от деревнию.", + "Прошлой ночью мне приснился чудесный сон о сыре. Что это значит?", + "Я оставила немного сыра у брата. Теперь я не знаю, съеден сыр или нет. Я называю его сыром Шредингера.", + "Я оставил немного сыра у сестры. Теперь я не знаю, съеден сыр или нет. Я называю его сыром Шредингера.", + "Кто-то должен что-то сделать с этими культистами. Желательно не я.", + "Надеюсь, скоро пойдет дождь. Это было бы хорошо для урожая.", + "Я люблю мед! И я ненавижу пчел.", + "Я хочу однажды увидеть мир. В жизни должно быть что-то большее, чем эта деревня.", + ], + "npc.speech.villager_decline_trade": [ + "Извините, мне нечем торговать.", + "Торговля? Как будто у меня есть что-то, что может вас заинтересовать.", + "Мой дом принадлежит мне, я не променяю его ни на что.", + ], + "npc.speech.merchant_advertisement": [ + "Могу ли я заинтересовать вас сделкой?", + "Ты хочешь со мной поторговать?", + "У меня много товаров, не хочешь взглянуть?" + ], + "npc.speech.merchant_busy": [ + "Эй, подожди своей очереди.", + "Пожалуйста, подождите, я здесь один на всех.", + "Видите другого человека перед собой?", + "Минутку, дай мне закончить.", + "Не лезь вне очереди!", + "Я занят, зайди попозже." + ], + "npc.speech.merchant_trade_successful": [ + "Спасибо, что торгуете со мной!", + "Спасибо вам!", + ], + "npc.speech.merchant_trade_declined": [ + "Может быть, в другой раз, хорошего дня!", + "Жаль, тогда, может быть, в следующий раз!" + ], + "npc.speech.villager_cultist_alarm": [ + "Берегись! На свободе разгуливает культист!", + "К оружию! Культисты атакуют!", + "Как посмели культисты напасть на нашу деревню!", + "Смерть культистам!", + "Культистов здесь не потерпят!", + "Кровожадный культист!", + "Попробуй на вкус острие моего меча, грязный культист!", + "Ничего не сможет смыть кровь с твоих рук, культист!", + "Миллиарды пузырящихся синих ракушек! Культист среди нас!", + "Зло этого культиста вот-вот закончится!", + "Этот культист мой!", + "Приготовься встретить своего создателя, грязный культист!", + "Я вижу культиста! Схватите его!", + "Я вижу культиста! В атаку!", + "Я вижу культиста! Не дайте им сбежать!", + "Будет ли самый почтенный культист заботиться о какой-то СМЕРТИ?!", + "Никогда не прощу! Никогда не забуду! Культист, сожалею!", + "Умри, культист!", + "Ваше царство террора захвачено!", + "Вот тебе за все, что ты сделал!", + "Мы не очень хорошо относимся к вашим людям здесь.", + "Тебе следовало оставаться под землей!", + ], + "npc.speech.villager_under_attack": [ + "Помогите, Меня атакуют!", + "Помогите, Меня атакуют!", + "Оуч, Меня атакуют!", + "Оуч, Меня атакуют!", + "Помоги мне! Меня атакуют!", + "Меня атакуют! Помогите!", + "Меня атакуют! Помогите мне!", + "Помогите!", + "Помогите! Помогите!", + "Помогите! Помогите! Помогите!", + "Меня атакуют!", + "АААААА! Меня атакуют!", + "АААААА! Меня атакуют! Помогите!", + "Помогите! Мы атакованны!", + "Помогите! Убийца!", + "Помогите! Убийца на свободе!", + "Помогите! Они пытаются меня убить!", + "Стража, Меня атакуют!", + "Стража! Меня атакуют!", + "Меня атакуют! Стража!", + "Помогите! Стража! Меня атакуют!", + "Стража! Скорее!", + "Стража! Стража!", + "Стража! Этот злодей бьёт меня!", + "Стража, Схватите этого негодяя!", + "Стража! Здесь убийца!", + "Стража! Помогите me!", + "Тебе это не сойдет с рук! Стража!", + "Ты изверг!", + "Помогите мне!", + "Помогите! Пожалуйста!", + "Ой! Стража! Помогите!", + "Они идут за мной!", + "Помогите! Помогите! Меня постигла расплата!", + "Ах, теперь мы видим насилие, присущее системе.", + "Это всего лишь царапина!", + "Остановитесь!", + "Что я тебе сделал?!", + "Пожалуйста, не бей!", + "Эй! Смотри, куда направляешь эту штуку", + "Гнусный негодяй, проваливай отсюда!", + "Прекрати! Уходи!", + "Ты уже достал!", + "Эй! Что ты возомнил о себе?!", + "Я тебе башку оторву!", + "Остановись пожалуйста. У меня ничего нет!", + "Я позову брата, он больше меня", + "Нет! Я расскажу маме!", + "Будь ты проклят!", + "Пожалуйста, не делай этого.", + "Это не приятно!", + "Ваше оружие работает, вы можете убрать его прямо сейчас!", + "Пощади!", + "Пожалуйста, у меня семья!", + "Я слишком молод чтобы умереть!", + "Может договоримся?", + "Насилие не выход!", + "Сегодня выдался плохой день...", + "Эй, это больно!", + "Ик!", + "Как грубо!", + "Остановись, прошу тебя!", + "Чтоб ты сдох!", + "Это не смешно.", + "Как ты смеешь?!", + "Ты заплатишь за это!", + "Ты об этом пожалеешь!", + "Не заставляй меня делать тебе больно!", + "Произошла какая то ошибка!", + "Не делай этого!", + "Изыди, дьявол", + "Это очень больно!", + "Зачем ты это сделал?", + "Ради всего святого, прекрати!", + "Ты меня перепутал с кем то", + "Я не заслуживаю этого!", + "Пожалуйста, больше так не делай.", + "Стража, утопите этого монстра в озере!", + "Я натравлю своего tarasque на тебя!", + "Почему я?", + ], + "npc.speech.villager_enemy_killed": [ + "Я уничтожил врага!", + "Наконец-то мир!", + "... что же я наделал?", + ] + } +) diff --git a/assets/voxygen/i18n/sv_SE/_manifest.ron b/assets/voxygen/i18n/sv_SE/_manifest.ron index 200216b724..7ecd68218b 100644 --- a/assets/voxygen/i18n/sv_SE/_manifest.ron +++ b/assets/voxygen/i18n/sv_SE/_manifest.ron @@ -28,206 +28,5 @@ asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", scale_ratio: 1.0, ), - }, - - string_map: { - - }, - - vector_map: { - "loading.tips": [ - "Tryck 'G' för att tända din lykta.", - "Tryck 'F1' för att se alla standardgenvägar.", - "Du kan skriva /say eller /s för att endast prata med spelare i din närhet.", - "Du kan skriva /region eller /r to för att endast prata med spelare upp till hundra block bort.", - "Administratörer kan använda kommandot /build för att växla till byggläget.", - "Du kan skriva /group eller /g för att endast prata med spelare i din nuvarande grupp.", - "Använd /tell följt av ett spelarnamn och meddelande för att kommunicera direkt med en spelare.", - "Håll ett öga öppet för mat, kistor och andra fynd som finns utspridda över hela världen!", - "Inventory filled with food? Try crafting better food from it!", /// TODO translate crafting - "Wondering what there is to do? Try out one of the dungeons marked on the map!", /// TODO translate dungeon - "Glöm inte anpassa grafiken för din dator. Tryck 'N' för att öppna inställningarna.", - "Delad glädje är dubbel glädje! Tryck 'O' för att se vilka som spelar just nu.", - "Tryck 'J' för att dansa. Party!", - "Tryck på den vänstra Shift-tangenten för att använda din glidare och bli himlarnas härskare.", - "Veloren är fortfarande i Pre-Alpha-stadiet. Vi gör vårt yttersta för att förbättra spelet varje dag!", - "Om du vill gå med i utvecklargruppen eller bara snacka med oss får du gärna logga in på vår Discord-server.", - "Du kan välja att visa din hälsostatus i inställningarna.", - "Sitt nära en lägereld (tryck 'K') för att långsamt återhämta dig från skador.", - "Behöver du fler säckar eller bättre rustning för din fortsatta färd? Tryck 'C' för att öppna the crafting menu!", /// TODO translate crafting - "Försök att hoppa när du rullar genom kreatur.", - ], - "npc.speech.villager": [ - "Är inte detta en underbar dag?", - "Hur står det till idag?", - "Tjenixen!", - "Undrar vad en Catoblepa tänker på när den betar.", // Catoblepa --> Catoblepa - "Vad tycker du om vädret idag?", - "Blotta tanken av dungeons ger mig rysningar. Jag hoppas att någon kommer städa ur dem.", /// TODO translate dungeon - "Jag skulle vilja utforska någon grotta när jag blir starkare.", - "Har du sett min katt?", - "Har du också hört ryktet om Landhajar? Jag hörde att de bor i öknar.", // Land Shark --> Landhaj - "De påstår att glimrande ädelstenar av alla dess slag kan hittas i grottor.", - "Visst blir man lycklig av ost!", - "Kom in, vettja! Vi skulle just börja på en ost.", - "Vissa påstår att svamp skulle vara bra för hälsan. Det skulle aldrig falla mig in att äta en.", - "Glöm inte kexen för allt i världen!", - "Jag bara älskar dvärgarnas ost. Om jag bara visste hur de tillverkades …", - "Undrar just vad som ligger på andra sidan bergen där borta.", - "Jag skulle vilja konstruera min egna glidare en dag.", - "Skulle du vilja se min trädgård? Okej, kanske någon annan gång då.", - "En underbar dag för en skogspromenad!", - "Att vara eller inte vara? Jag tror nog jag borde bli bonde.", - "Visst är väl vår by den bästa i världen?", - "Vad tror du får Skimrande Lämningar att lysa?", /// Glowing Remains --> Skimrande Lämningar - "Jag tycker nog det börjar bli dags för en andra frukost!", - "Har du lyckats fånga en eldfluga någon gång?", - "Jag kan bara inte begripa var alla dessa Sauroker kommer ifrån.", // Saurok --> Saurok - "Jag önskar att någon kunde hålla alla vargar på avstånd från byn.", - "Jag hade en fantastisk dröm om ost inatt. Vad tror du det kan betyda?", - "Jag lämnade en ost hos min bror. Nu vet jag inte om den existerar eller inte, så jag kallar den Schrödingers ost.", - "Jag lämnade en ost hos min syster. Nu vet jag inte om den existerar eller inte, så jag kallar den Schrödingers ost.", - "Någon borde göra något åt de där sektanhängarna. Förslgsvis inte jag.", /// cultist --> sektanhängare (collectively and allies) alt. sektmedlem (individually) - "Jag hoppas verkligen vi får lite regn snart. Det vore bra för grödorna.", - "Jag älskar honung! Om det inte vore för dessa fördömda bin.", - "En dag skulle jag vilja se världen. Livet måste väl vara större än bara den här hålan?", - ], - "npc.speech.villager_decline_trade": [ - "Tyvärr har jag inget till salu.", - "En vaddå? Tror inte jag har något av intresse för dig.", - "Mitt hus är mitt och jag tänker inte flytta för allt i världen.", - ], - "npc.speech.merchant_advertisement": [ - "Kan jag fresta med någon av dessa fina varor?", - "Skulle du vilja köpa någonting?", - "Jag har gott om varor, skulle du vilja se för dig själv?" - ], - "npc.speech.merchant_busy": [ - "Hallå där, vänta på din tur!", - "Ta det lugnt, jag är bara en människa.", - "Ser du inte att andra står före dig i kön?", - "Bara ett ögonblick, jag är snart klar.", - "Du får nöja dig med din plats i kön.", - "Jag är upptagen, kom igen lite senare." - ], - "npc.speech.merchant_trade_successful": [ - "Tack för att du ville handla av mig!", - "Tack så mycket!", - ], - "npc.speech.merchant_trade_declined": [ - "Kanske en annan gång, ha en bra dag!", - "Äsch, det får bli nästa gång istället!" - ], - "npc.speech.villager_cultist_alarm": [ - "Se upp! Här är en sektmedlem i farten!", - "Till vapen! Sektanhängarna anfaller!", - "Hur vågar sektanhängarna angripa vår by!", - "Död åt sekten!", - "Sektens anhängare kommer inte tolereras här!", - "Mordiska sektanhängare!", - "Smaka på min svärdsegg, din smutsiga sektanhängare!", - "Inget kan två blodet från era händer, sektanhängare!", - "Tusen troglodytiska terapeuter! En sektmedlem mitt ibland oss!", - "Sektens ondskefulla tid är snart förbi!", - "Den här sektanhängaren är min", - "Gör dig redo för ett möte med din skapare, vidriga sektanhängare!", - "Jag ser en sektmedlem! Efter dem!", - "Jag ser en sektmedlem! Till attack!", - "Jag ser en sektmedlem! Låt dem inte komma undan!", - "Skulle den högt vördade sektmedlemmen önska spilla lite blod?", - "Aldrig förlåta! Aldrig förglömma! Sektanhängare, ve er!", - "Dö, sektanhängare!", - "Ert skräckvälde ska gå under!", - "Här är betalningen för allt ni gjort!", - "Vi uppskattar inte sådana som du här omkring.", - "Ni borde stannat kvar i ert gryt!", - ], - "npc.speech.villager_under_attack": [ - "Hjälp, jag är under attack!", - "Hjälp! Jag är under attack!", - "Aj! Jag blir attackerad!", - "Aj! Jag blir attackerad! Hjälp!", - "Hjälp mig! Någon attackerar mig!", - "Någon attackerar mig! Hjälp!", - "Någon attackerar mig! Hjälp mig!", - "Hjälp!", - "Hjälp! Hjälp!", - "Hjälp! Hjälp! Hjälp!", - "Någon attackerar mig!", - "Aaahhh! Någon attackerar mig!", - "Aaahhh! Någon attackerar mig! Hjälp!", - "Hjälp! Vi blir attackerade!", - "Hjälp! Mördare!", - "Hjälp! En mördare är är i farten!", - "Hjälp! De försöker döda mig!", - "Vakter, någon attackerar mig!", - "Vakter! Någon attackerar mig!", - "Jag blir attackerad! Vakter", - "Hjälp! Vakter! Jag blir angripen!", - "Vakter! Kom fort!", - "Vakter! Vakter!", - "Vakter! En skurk angriper mig!", - "Vakter, slå ihjäl denna vidriga förbytare!", - "Vakter! Här är en mördare!", - "Vakter! Hjälp mig!", - "Du kommer inte komma undan med det här! Vakter!", - "Din skurk!", - "Hjälp mig!", - "Hjälp! Snälla!", - "Aj! Vakter, hjälp!", - "De kommer efter mig!", - "Hjälp! Hjälp! Jag blir förtryckt!", - "Och här ser vi tydligt hur systemet främjar våld.", - "Ingen fara, det här är bara en skråma!", - "Sluta upp med det!", - "Hur har jag gjort dig orätt?", - "Sluta attackera mig!", - "Hallå där, akta vart du pekar den där saken!", - "Din skändliga usling, försvinn med dig!", - "Sluta upp med det! Försvinn!", - "Hu har du gjort mig riktigt arg!", - "Hallå där! Vem tror du att du är?!", - "Det ska du få betala för med ditt huvud!", - "Snälla sluta, jag har inget av värde!", - "Jag kommer skicka min bror efter dig, han är ännu större än jag!", - "Nej, detta ska allt mamma få höra om!", - "Må olyckan följa i dina spår!", - "Gör inte om det, är du snäll.", - "Det var inte särskilt trevligt gjort!", - "Ditt vapen verkar fungera, du kan lägga det åt sidan nu!", - "Visa mig nåd!", - "Snälla, tänk på min familj!", - "Jag är för ung för att dö!", - "Kan vi inte sätta oss ner och prata istället?", - "Våld är aldrig lösningen!", - "Den här dagen blir bara bättre och bättre …", - "Aj, det gjorde faktiskt ont!", - "Ah!", - "Så oförskämt!", - "Sluta, bara sluta!", - "Du har dragit en svår olycka över dig!", - "Detta är inte roligt.", - "Hur vågar du?!", - "Det ska du allt få betala för!", - "Du kommer ångra dig om du forstätter så där!", - "Tvinga inte mig att göra dig illa!", - "Det måste ha skett ett missförstånd!", - "Du behöver inte göra det här!", - "Försvinn, demon!", - "Det gjorde riktigt ont!", - "Vad fick dig att göra så?", - "Sluta! Vid andarna, upphör nu!", - "Du måste ha blandat ihop mig med någon annan!", - "Vad har jag gjort för att förtjäna detta?", - "Gör inte om det.", - "Vakter, kasta tillbaka detta odjur i sjön!", - "Jag kommer sätta min tarask efter dig!", - "Varför just jag?", - ], - "npc.speech.villager_enemy_killed": [ - "Min fiende är förgjord!", - "Äntligen lite lugn och ro!", - "Vad var det nu jag höll på med?", - ] } ) diff --git a/assets/voxygen/i18n/sv_SE/main.ron b/assets/voxygen/i18n/sv_SE/main.ron index ce961f7526..0798d0ed22 100644 --- a/assets/voxygen/i18n/sv_SE/main.ron +++ b/assets/voxygen/i18n/sv_SE/main.ron @@ -66,5 +66,27 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "Tryck 'G' för att tända din lykta.", + "Tryck 'F1' för att se alla standardgenvägar.", + "Du kan skriva /say eller /s för att endast prata med spelare i din närhet.", + "Du kan skriva /region eller /r to för att endast prata med spelare upp till hundra block bort.", + "Administratörer kan använda kommandot /build för att växla till byggläget.", + "Du kan skriva /group eller /g för att endast prata med spelare i din nuvarande grupp.", + "Använd /tell följt av ett spelarnamn och meddelande för att kommunicera direkt med en spelare.", + "Håll ett öga öppet för mat, kistor och andra fynd som finns utspridda över hela världen!", + "Inventory filled with food? Try crafting better food from it!", /// TODO translate crafting + "Wondering what there is to do? Try out one of the dungeons marked on the map!", /// TODO translate dungeon + "Glöm inte anpassa grafiken för din dator. Tryck 'N' för att öppna inställningarna.", + "Delad glädje är dubbel glädje! Tryck 'O' för att se vilka som spelar just nu.", + "Tryck 'J' för att dansa. Party!", + "Tryck på den vänstra Shift-tangenten för att använda din glidare och bli himlarnas härskare.", + "Veloren är fortfarande i Pre-Alpha-stadiet. Vi gör vårt yttersta för att förbättra spelet varje dag!", + "Om du vill gå med i utvecklargruppen eller bara snacka med oss får du gärna logga in på vår Discord-server.", + "Du kan välja att visa din hälsostatus i inställningarna.", + "Sitt nära en lägereld (tryck 'K') för att långsamt återhämta dig från skador.", + "Behöver du fler säckar eller bättre rustning för din fortsatta färd? Tryck 'C' för att öppna the crafting menu!", /// TODO translate crafting + "Försök att hoppa när du rullar genom kreatur.", + ], } ) diff --git a/assets/voxygen/i18n/sv_SE/npc.ron b/assets/voxygen/i18n/sv_SE/npc.ron new file mode 100644 index 0000000000..a3fda4dc96 --- /dev/null +++ b/assets/voxygen/i18n/sv_SE/npc.ron @@ -0,0 +1,183 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for sweden Swedish +( + string_map: { + + }, + + vector_map: { + "npc.speech.villager": [ + "Är inte detta en underbar dag?", + "Hur står det till idag?", + "Tjenixen!", + "Undrar vad en Catoblepa tänker på när den betar.", // Catoblepa --> Catoblepa + "Vad tycker du om vädret idag?", + "Blotta tanken av dungeons ger mig rysningar. Jag hoppas att någon kommer städa ur dem.", /// TODO translate dungeon + "Jag skulle vilja utforska någon grotta när jag blir starkare.", + "Har du sett min katt?", + "Har du också hört ryktet om Landhajar? Jag hörde att de bor i öknar.", // Land Shark --> Landhaj + "De påstår att glimrande ädelstenar av alla dess slag kan hittas i grottor.", + "Visst blir man lycklig av ost!", + "Kom in, vettja! Vi skulle just börja på en ost.", + "Vissa påstår att svamp skulle vara bra för hälsan. Det skulle aldrig falla mig in att äta en.", + "Glöm inte kexen för allt i världen!", + "Jag bara älskar dvärgarnas ost. Om jag bara visste hur de tillverkades …", + "Undrar just vad som ligger på andra sidan bergen där borta.", + "Jag skulle vilja konstruera min egna glidare en dag.", + "Skulle du vilja se min trädgård? Okej, kanske någon annan gång då.", + "En underbar dag för en skogspromenad!", + "Att vara eller inte vara? Jag tror nog jag borde bli bonde.", + "Visst är väl vår by den bästa i världen?", + "Vad tror du får Skimrande Lämningar att lysa?", /// Glowing Remains --> Skimrande Lämningar + "Jag tycker nog det börjar bli dags för en andra frukost!", + "Har du lyckats fånga en eldfluga någon gång?", + "Jag kan bara inte begripa var alla dessa Sauroker kommer ifrån.", // Saurok --> Saurok + "Jag önskar att någon kunde hålla alla vargar på avstånd från byn.", + "Jag hade en fantastisk dröm om ost inatt. Vad tror du det kan betyda?", + "Jag lämnade en ost hos min bror. Nu vet jag inte om den existerar eller inte, så jag kallar den Schrödingers ost.", + "Jag lämnade en ost hos min syster. Nu vet jag inte om den existerar eller inte, så jag kallar den Schrödingers ost.", + "Någon borde göra något åt de där sektanhängarna. Förslgsvis inte jag.", /// cultist --> sektanhängare (collectively and allies) alt. sektmedlem (individually) + "Jag hoppas verkligen vi får lite regn snart. Det vore bra för grödorna.", + "Jag älskar honung! Om det inte vore för dessa fördömda bin.", + "En dag skulle jag vilja se världen. Livet måste väl vara större än bara den här hålan?", + ], + "npc.speech.villager_decline_trade": [ + "Tyvärr har jag inget till salu.", + "En vaddå? Tror inte jag har något av intresse för dig.", + "Mitt hus är mitt och jag tänker inte flytta för allt i världen.", + ], + "npc.speech.merchant_advertisement": [ + "Kan jag fresta med någon av dessa fina varor?", + "Skulle du vilja köpa någonting?", + "Jag har gott om varor, skulle du vilja se för dig själv?" + ], + "npc.speech.merchant_busy": [ + "Hallå där, vänta på din tur!", + "Ta det lugnt, jag är bara en människa.", + "Ser du inte att andra står före dig i kön?", + "Bara ett ögonblick, jag är snart klar.", + "Du får nöja dig med din plats i kön.", + "Jag är upptagen, kom igen lite senare." + ], + "npc.speech.merchant_trade_successful": [ + "Tack för att du ville handla av mig!", + "Tack så mycket!", + ], + "npc.speech.merchant_trade_declined": [ + "Kanske en annan gång, ha en bra dag!", + "Äsch, det får bli nästa gång istället!" + ], + "npc.speech.villager_cultist_alarm": [ + "Se upp! Här är en sektmedlem i farten!", + "Till vapen! Sektanhängarna anfaller!", + "Hur vågar sektanhängarna angripa vår by!", + "Död åt sekten!", + "Sektens anhängare kommer inte tolereras här!", + "Mordiska sektanhängare!", + "Smaka på min svärdsegg, din smutsiga sektanhängare!", + "Inget kan två blodet från era händer, sektanhängare!", + "Tusen troglodytiska terapeuter! En sektmedlem mitt ibland oss!", + "Sektens ondskefulla tid är snart förbi!", + "Den här sektanhängaren är min", + "Gör dig redo för ett möte med din skapare, vidriga sektanhängare!", + "Jag ser en sektmedlem! Efter dem!", + "Jag ser en sektmedlem! Till attack!", + "Jag ser en sektmedlem! Låt dem inte komma undan!", + "Skulle den högt vördade sektmedlemmen önska spilla lite blod?", + "Aldrig förlåta! Aldrig förglömma! Sektanhängare, ve er!", + "Dö, sektanhängare!", + "Ert skräckvälde ska gå under!", + "Här är betalningen för allt ni gjort!", + "Vi uppskattar inte sådana som du här omkring.", + "Ni borde stannat kvar i ert gryt!", + ], + "npc.speech.villager_under_attack": [ + "Hjälp, jag är under attack!", + "Hjälp! Jag är under attack!", + "Aj! Jag blir attackerad!", + "Aj! Jag blir attackerad! Hjälp!", + "Hjälp mig! Någon attackerar mig!", + "Någon attackerar mig! Hjälp!", + "Någon attackerar mig! Hjälp mig!", + "Hjälp!", + "Hjälp! Hjälp!", + "Hjälp! Hjälp! Hjälp!", + "Någon attackerar mig!", + "Aaahhh! Någon attackerar mig!", + "Aaahhh! Någon attackerar mig! Hjälp!", + "Hjälp! Vi blir attackerade!", + "Hjälp! Mördare!", + "Hjälp! En mördare är är i farten!", + "Hjälp! De försöker döda mig!", + "Vakter, någon attackerar mig!", + "Vakter! Någon attackerar mig!", + "Jag blir attackerad! Vakter", + "Hjälp! Vakter! Jag blir angripen!", + "Vakter! Kom fort!", + "Vakter! Vakter!", + "Vakter! En skurk angriper mig!", + "Vakter, slå ihjäl denna vidriga förbytare!", + "Vakter! Här är en mördare!", + "Vakter! Hjälp mig!", + "Du kommer inte komma undan med det här! Vakter!", + "Din skurk!", + "Hjälp mig!", + "Hjälp! Snälla!", + "Aj! Vakter, hjälp!", + "De kommer efter mig!", + "Hjälp! Hjälp! Jag blir förtryckt!", + "Och här ser vi tydligt hur systemet främjar våld.", + "Ingen fara, det här är bara en skråma!", + "Sluta upp med det!", + "Hur har jag gjort dig orätt?", + "Sluta attackera mig!", + "Hallå där, akta vart du pekar den där saken!", + "Din skändliga usling, försvinn med dig!", + "Sluta upp med det! Försvinn!", + "Hu har du gjort mig riktigt arg!", + "Hallå där! Vem tror du att du är?!", + "Det ska du få betala för med ditt huvud!", + "Snälla sluta, jag har inget av värde!", + "Jag kommer skicka min bror efter dig, han är ännu större än jag!", + "Nej, detta ska allt mamma få höra om!", + "Må olyckan följa i dina spår!", + "Gör inte om det, är du snäll.", + "Det var inte särskilt trevligt gjort!", + "Ditt vapen verkar fungera, du kan lägga det åt sidan nu!", + "Visa mig nåd!", + "Snälla, tänk på min familj!", + "Jag är för ung för att dö!", + "Kan vi inte sätta oss ner och prata istället?", + "Våld är aldrig lösningen!", + "Den här dagen blir bara bättre och bättre …", + "Aj, det gjorde faktiskt ont!", + "Ah!", + "Så oförskämt!", + "Sluta, bara sluta!", + "Du har dragit en svår olycka över dig!", + "Detta är inte roligt.", + "Hur vågar du?!", + "Det ska du allt få betala för!", + "Du kommer ångra dig om du forstätter så där!", + "Tvinga inte mig att göra dig illa!", + "Det måste ha skett ett missförstånd!", + "Du behöver inte göra det här!", + "Försvinn, demon!", + "Det gjorde riktigt ont!", + "Vad fick dig att göra så?", + "Sluta! Vid andarna, upphör nu!", + "Du måste ha blandat ihop mig med någon annan!", + "Vad har jag gjort för att förtjäna detta?", + "Gör inte om det.", + "Vakter, kasta tillbaka detta odjur i sjön!", + "Jag kommer sätta min tarask efter dig!", + "Varför just jag?", + ], + "npc.speech.villager_enemy_killed": [ + "Min fiende är förgjord!", + "Äntligen lite lugn och ro!", + "Vad var det nu jag höll på med?", + ] + } +) diff --git a/assets/voxygen/i18n/tr_TR/_manifest.ron b/assets/voxygen/i18n/tr_TR/_manifest.ron index 4584b27293..50c818fc21 100644 --- a/assets/voxygen/i18n/tr_TR/_manifest.ron +++ b/assets/voxygen/i18n/tr_TR/_manifest.ron @@ -40,113 +40,5 @@ asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", scale_ratio: 1.0, ), - }, - - string_map: { - - }, - - vector_map: { - "loading.tips": [ - "'G'ye basarak fenerini yak.", - "'F1'e basarak bütün kontrolleri görebilirsin.", - "'/say' veya '/s' yazarak sadece hemen yanındaki oyuncularla konuşabilirsin.", - "'/region' veya '/r' yazarak sadece bir kaç yüz blok içindeki oyuncularla konuşabilirsin.", - "Özel bir mesaj göndermek için '/tell' ve sonra bir oyuncu ismi ile mesajını yaz.", - "Aynı seviyedeki NPCler farklı zorluklara sahip olabilir.", - "Yemek, sandık ve diğer ganimetler için yere bak!", - "Envanterin yemekle mi dolu? Onları kullanarak daha iyi yemek yapmaya çalış!", - "Ne yapabileceğini merak mı ediyorsun? Zindanlar haritada kahverengi bölgeler olarak işaretlenmiştir!", - "Grafikleri sistemin için ayarlamayı unutma. 'N'e basarak ayarları aç.", - "Başkalarıyla oynamak eğlencelidir! 'O'ya basarak kimlerin çevirimiçi olduğunu gör.", - "Can barının yanında kurukafa olan bir NPC senden hayli bir güçlüdür.", - "'J'ye basarak dans et. Parti!", - "'L-Shift'e basarak Planörünü aç ve gökyüzünü fethet.", - "Veloren hala Pre-Alpha'da. Onu geliştirmek için her gün elimizden geleni yapıyoruz!", - "Geliştirme Takımına katılmak istiyorsan veya sadece sohbet etmek istiyorsan Discord sunucumuza katıl.", - "Can barında canı sayı olarak görmek istiyorsan, bunu ayarlardan aktifleştirebilirsin.", - "Niteliklerini görmek için envanterindeki 'Nitelikler' düğmesine tıklayabilirsin.", - ], - "npc.speech.villager_under_attack": [ - "Saldırı altındayım, yardım edin!", - "Saldırı altındayım! Yardım edin!", - "Ahhh! Saldırı altındayım!", - "Ahhh! Saldırı altındayım! Yardım edin!", - "Saldırı altındayım! Bana yardım edin!", - "Yardım edin! Saldırı altındayım!", - "Bana yardım edin! Saldırı altındayım!", - "Yardım edin!", - "Yardım edin! Yardım edin!", - "Yardım edin! Yardım edin! Yardım edin!", - "Saldırı altındayım!", - "AAAHHHH! Saldırı altındayım!", - "AAAHHHH! Yardım edin! Saldırı altındayım!", - "Saldırı altındayız! Yardım edin!", - "Katil! Yardım edin!", - "Bir katil serbestçe dolaşıyor! Yardım edin!", - "Beni öldürmeye çalışıyorlar! Yardım edin!", - "Gardiyanlar, saldırı altındayım!", - "Saldırı altındayım! Gardiyanlar!", - "Gardiyanlar! Saldırı altındayım!", - "Saldırı altındayım! Gardiyanlar! Yardım edin!", - "Gardiyanlar! Çabuk gelin!", - "Gardiyanlar! Gardiyanlar!", - "Bana saldıran bir kötü var! Yardım edin!", - "Gardiyanlar, bu pis kötüyü öldürün!", - "Gardiyanlar! Burada bir katil var!", - "Gardiyanlar! Bana yardım edin!", - "Bu yanına kalmayacak! Gardiyanlar!", - "Seni şeytan!", - "Bana yardım edin!", - "Lütfen! Yardım edin!", - "Ahhh! Gardiyanlar! Yardım edin!", - "Benim için geliyorlar!", - "Yardım edin! Yardım edin! Baskı altındayım!", - "Ah, artık sistemin doğasında var olan şiddeti görüyoruz.", - "Bu bana göre bir çizik bile değil!", - "Yapma şunu!", - "Ben sana ne yaptım ki?!", - "Lütfen bana saldırmayı kes!", - "Hey! Onu nereye yönelttiğine dikkat et!", - "Aşağılık herif, gözüm bile görmesin!", - "Durdur şunu! Git buradan!", - "Şimdi beni kızdırmaya başladın!", - "Hey! Sen kim olduğunu zannediyorsun ki?!", - "Bunun için kelleni alacağım!", - "Yapma, lütfen! Değerli hiçbir şeyim yok bile!", - "Kardeşimi üzerine salacağım, o benden bile büyük!", - "Olamaaaz, Seni anneme söyleyeceğim!", - "Lanet olsun sana!", - "Lütfen yapma şunu.", - "Bunu yapman pek kibarca değildi!", - "Evet silahın çalışıyor, şimdi kaldırabilir misin?", - "Bağışlayın beni!", - "Lütfen, benim bir ailem var!", - "Ölmek için çok gencim!", - "Bunu konuşarak çözebilir miyiz?", - "Şiddet hiçbir zaman çare değildir!", - "Günüm gittikçe kötüleşiyor...", - "Hey, bu acıttı!", - "Eek!", - "Ne kadar da kaba!", - "Dur, sana yalvarırım!", - "Lanet olsun sana!", - "Bu eğlenceli bile değil.", - "Ne cürret?!", - "Bunu sana ödeteceğim!", - "Yapmaya devam edersen bunun için pişman olacaksın!", - "Sana zarar vermek zorunda bırakma beni!", - "Bir yanlış anlaşılma olmalı!", - "Bunu yapmak zorunda değilsin!", - "Defol!", - "Bu gerçekten acıttı!", - "Bunu neden yaptın ki?", - "Ruhlar tarafından, dur!", - "Beni başkasıyla karıştırmış olmalısın!", - "Bunu haketmiyorum!", - "Lütfen bunu bir daha yapma.", - "Muhafızlar, şu canavarı göle atın!", - "Tarrasque'ımı üzerine salarım!", - ], } ) diff --git a/assets/voxygen/i18n/tr_TR/main.ron b/assets/voxygen/i18n/tr_TR/main.ron index 5df46b198d..2f81506879 100644 --- a/assets/voxygen/i18n/tr_TR/main.ron +++ b/assets/voxygen/i18n/tr_TR/main.ron @@ -63,5 +63,25 @@ bir hesap oluşturabilirsin."#, vector_map: { + "loading.tips": [ + "'G'ye basarak fenerini yak.", + "'F1'e basarak bütün kontrolleri görebilirsin.", + "'/say' veya '/s' yazarak sadece hemen yanındaki oyuncularla konuşabilirsin.", + "'/region' veya '/r' yazarak sadece bir kaç yüz blok içindeki oyuncularla konuşabilirsin.", + "Özel bir mesaj göndermek için '/tell' ve sonra bir oyuncu ismi ile mesajını yaz.", + "Aynı seviyedeki NPCler farklı zorluklara sahip olabilir.", + "Yemek, sandık ve diğer ganimetler için yere bak!", + "Envanterin yemekle mi dolu? Onları kullanarak daha iyi yemek yapmaya çalış!", + "Ne yapabileceğini merak mı ediyorsun? Zindanlar haritada kahverengi bölgeler olarak işaretlenmiştir!", + "Grafikleri sistemin için ayarlamayı unutma. 'N'e basarak ayarları aç.", + "Başkalarıyla oynamak eğlencelidir! 'O'ya basarak kimlerin çevirimiçi olduğunu gör.", + "Can barının yanında kurukafa olan bir NPC senden hayli bir güçlüdür.", + "'J'ye basarak dans et. Parti!", + "'L-Shift'e basarak Planörünü aç ve gökyüzünü fethet.", + "Veloren hala Pre-Alpha'da. Onu geliştirmek için her gün elimizden geleni yapıyoruz!", + "Geliştirme Takımına katılmak istiyorsan veya sadece sohbet etmek istiyorsan Discord sunucumuza katıl.", + "Can barında canı sayı olarak görmek istiyorsan, bunu ayarlardan aktifleştirebilirsin.", + "Niteliklerini görmek için envanterindeki 'Nitelikler' düğmesine tıklayabilirsin.", + ], } ) diff --git a/assets/voxygen/i18n/tr_TR/npc.ron b/assets/voxygen/i18n/tr_TR/npc.ron new file mode 100644 index 0000000000..dd433e925a --- /dev/null +++ b/assets/voxygen/i18n/tr_TR/npc.ron @@ -0,0 +1,92 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Turkish (Turkey) +( + string_map: { + + }, + + vector_map: { + "npc.speech.villager_under_attack": [ + "Saldırı altındayım, yardım edin!", + "Saldırı altındayım! Yardım edin!", + "Ahhh! Saldırı altındayım!", + "Ahhh! Saldırı altındayım! Yardım edin!", + "Saldırı altındayım! Bana yardım edin!", + "Yardım edin! Saldırı altındayım!", + "Bana yardım edin! Saldırı altındayım!", + "Yardım edin!", + "Yardım edin! Yardım edin!", + "Yardım edin! Yardım edin! Yardım edin!", + "Saldırı altındayım!", + "AAAHHHH! Saldırı altındayım!", + "AAAHHHH! Yardım edin! Saldırı altındayım!", + "Saldırı altındayız! Yardım edin!", + "Katil! Yardım edin!", + "Bir katil serbestçe dolaşıyor! Yardım edin!", + "Beni öldürmeye çalışıyorlar! Yardım edin!", + "Gardiyanlar, saldırı altındayım!", + "Saldırı altındayım! Gardiyanlar!", + "Gardiyanlar! Saldırı altındayım!", + "Saldırı altındayım! Gardiyanlar! Yardım edin!", + "Gardiyanlar! Çabuk gelin!", + "Gardiyanlar! Gardiyanlar!", + "Bana saldıran bir kötü var! Yardım edin!", + "Gardiyanlar, bu pis kötüyü öldürün!", + "Gardiyanlar! Burada bir katil var!", + "Gardiyanlar! Bana yardım edin!", + "Bu yanına kalmayacak! Gardiyanlar!", + "Seni şeytan!", + "Bana yardım edin!", + "Lütfen! Yardım edin!", + "Ahhh! Gardiyanlar! Yardım edin!", + "Benim için geliyorlar!", + "Yardım edin! Yardım edin! Baskı altındayım!", + "Ah, artık sistemin doğasında var olan şiddeti görüyoruz.", + "Bu bana göre bir çizik bile değil!", + "Yapma şunu!", + "Ben sana ne yaptım ki?!", + "Lütfen bana saldırmayı kes!", + "Hey! Onu nereye yönelttiğine dikkat et!", + "Aşağılık herif, gözüm bile görmesin!", + "Durdur şunu! Git buradan!", + "Şimdi beni kızdırmaya başladın!", + "Hey! Sen kim olduğunu zannediyorsun ki?!", + "Bunun için kelleni alacağım!", + "Yapma, lütfen! Değerli hiçbir şeyim yok bile!", + "Kardeşimi üzerine salacağım, o benden bile büyük!", + "Olamaaaz, Seni anneme söyleyeceğim!", + "Lanet olsun sana!", + "Lütfen yapma şunu.", + "Bunu yapman pek kibarca değildi!", + "Evet silahın çalışıyor, şimdi kaldırabilir misin?", + "Bağışlayın beni!", + "Lütfen, benim bir ailem var!", + "Ölmek için çok gencim!", + "Bunu konuşarak çözebilir miyiz?", + "Şiddet hiçbir zaman çare değildir!", + "Günüm gittikçe kötüleşiyor...", + "Hey, bu acıttı!", + "Eek!", + "Ne kadar da kaba!", + "Dur, sana yalvarırım!", + "Lanet olsun sana!", + "Bu eğlenceli bile değil.", + "Ne cürret?!", + "Bunu sana ödeteceğim!", + "Yapmaya devam edersen bunun için pişman olacaksın!", + "Sana zarar vermek zorunda bırakma beni!", + "Bir yanlış anlaşılma olmalı!", + "Bunu yapmak zorunda değilsin!", + "Defol!", + "Bu gerçekten acıttı!", + "Bunu neden yaptın ki?", + "Ruhlar tarafından, dur!", + "Beni başkasıyla karıştırmış olmalısın!", + "Bunu haketmiyorum!", + "Lütfen bunu bir daha yapma.", + "Muhafızlar, şu canavarı göle atın!", + "Tarrasque'ımı üzerine salarım!", + ], + } +) diff --git a/assets/voxygen/i18n/uk_UA/_manifest.ron b/assets/voxygen/i18n/uk_UA/_manifest.ron index 760c92db7b..bf0d8b8600 100644 --- a/assets/voxygen/i18n/uk_UA/_manifest.ron +++ b/assets/voxygen/i18n/uk_UA/_manifest.ron @@ -28,180 +28,5 @@ asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended", scale_ratio: 1.0, ), - }, - - string_map: { - - }, - - vector_map: { - "loading.tips": [ - "Натисніть 'G', щоб засвітити ліхтар.", - "Натисніть 'F1', щоб переглянути стандартні елементи керування.", - "Введіть /say чи /s, щоб написати лише гравцям поряд.", - "Введіть /region чи /r, щоб написати лише гравцям в радіусі кількох сотень блоків навколо.", - "Адміністратори можуть використовувати команду /build для переходу в режим будування", - "Введіть /group чи /g, щоб написати лише гравцям з Вашої групи.", - "Щоб надіслати приватне повідомлення, введіть /tell, ім'я гравця та Ваше повідомлення.", - "Тримайте око на вістрі - їжа, скрині та інші корисні предмети можуть бути де-завгодно!", - "Інвентар переповнений харчами? Спробуйте поєднати їх в кращу їжу!", - "Шукаєте чим би це зайнятись? Провідайте одне з позначених на мапі підземель!", - "Не забудьте налаштувати оптимальну для Вашої системи якість зображення. Натисніть 'N', щоб відкрити налаштування.", - "Грати з іншими весело! Натисніть 'O', щоб переглянути список користувачів в мережі.", - "Натисніть 'J', щоб потанцювати. Гей-Гоп!", - "Натисніть 'L-Shift', щоб дістати Дельтаплан, та підкорюйте небеса!", - "Veloren все ще на стадії ранньої альфи. Ми стараємося робити покращення кожного дня!", - "Якшо Ви хочете долучитись до розробки або ж просто поспілкуватись із нами, приєднуйтесь до нашого Discord-серверу.", - "Ви можете змінити відображення індикатора здоров'я в налаштуваннях.", - "Присядьте біля ватри (натиснувши 'K'), щоб відпочити та відновити здоров'я.", - "Потребуєте більше торбин чи кращу броню? Натисніть 'C' щоб відкрити ремісниче меню.", - ], - "npc.speech.villager": [ - "Ну хіба ж не прекрасний сьогодні день?", - "Як ся маєш?", - "Гарного тобі дня!", - "Цікаво, про що думає Катоблепас, коли їсть траву...", - "Як тобі така погода?", - "Мурашки по спині від одної тільки думки про ті підземелля! Сподіваюсь, хтось з ними розбереться.", - "Коли я посильнішаю, мені б хотілось піти в спелеопохід, досліджувати печери!", - "Ви не бачили мого кота?", - "Ви коли небудь чули про лютих Земних Акул? Кажуть, вони водяться в пустелях.", - "Кажуть, в печерах можна знайти коштовне каміння будь-яких типів.", - "Я просто шаленію від сиру!", - "Не зайдете в гості? Ми якраз збирались поласувати сиру!", - "Кажуть, гриби корисні для здоров'я. Я, правда, ніколи їх не їм.", - "Не забудь сухарики!", - "Обожнюю Дварфський Сир! Хотілось би вміти його робити...", - "Цікаво, що там по іншу сторону гір...", - "Я сподіваюсь виготовити власний дельтаплан одного дня.", - "Ви не хотіли б подивитись на мій сад? Гаразд, можливо іншим разом.", - "Прекрасний день для прогулянки в лісі!", - "Бути чи не бути? Думаю, я буду фермером.", - "Ви не думали про те, що наше селище - найкраще?", - "Як ти думаєш, чому Сяючі Залишки світяться?", - "По-моєму, час другого сніданку!", - "А ви коли небудь ловили світлячка?", - "Я не можу зрозуміти, звідки приходять ці Сауроки.", - "Хотілося б, щоб хтось захищав селище від вовків.", - "Сьогодні мені приснився прекрасний сон про сир. Що б це значило?", - ], - "npc.speech.villager_under_attack": [ - "Допоможіть, на мене напали!", - "Рятуйте! Б'ють!", - "Ай! Больно!", - "Лупцюють!", - "Допоможіть!", - "Рятуйте!", - "Хто-небудь, допоможіть!", - "Будь ласка, допоможіть!", - "АААААА! Рятуйте!", - "Рятуйте! Вбивця!", - "Рятуйте! Мене зараз вб'ють!", - "Охорона, на мене напали!", - "Охорона! На мене напали!", - "Мене атакують! Охорона!", - "Рятуйте! Охорона! На мене напали!", - "Охорона! Швидше!", - "Охорона! Охорона!", - "Охорона! Цей негідник напав на мене!", - "Охорона, розберіться з цим покидьком!", - "Охорона! Тут вбивця!", - "Охорона! Рятуйте!", - "Це тобі так просто не минеться! Охорона!", - "Ах ти ж падлюка!", - "АААААА!", - "Хто-небудь!", - "Ай! Охорона! Рятуйте!", - "Бляха... Вони прийшли за мною!", - "Рятуйте! Допоможіть! Мене катують!", - "Ага, ось вам і властива системі жорстокість.", - "Це лиш царапина!", - "Ану перестань!", - "Благаю, не бий мене!", - "Агов! Дивись куди сунеш цю штуку!", - "Котись під три чорти!", - "Перестань! Відчепись!", - "Я починаю сердитись!", - "Ким ти тут себе уявляєш?!", - "Ти за це поплатишся головою!", - "Благаю, перестань! У мене нічого немає!", - "Я розкажу моєму братові! Він набагато сильніший за мене!", - "Ааа, я розкажу мамі!", - "Пішло геть, опудало!", - "Благаю, перестань!", - "Це було не дуже етично з Вашого боку!", - "Все, все! Ти вмієш битись! Тепер перестань!", - "Пощади мене!", - "Благаю, у мене сім'я!", - "Почекайте, давайте спокійно обговоримо ситуацію?", - "Насилля - це ніколи не рішення!", - "Та що ж це за день такий...", - "Ауч! Це було больно!", - "Ого, яке нахабство!", - "Досить вже!", - "А щоб тобі!", - "Не весело.", - "Як ти смієш?!", - "Ти за це заплатиш!", - "Тільки спробуй! Ти про це пожалкуєш!", - "Не змушуй мене тебе покарати!", - "Це якесь непорозуміння!", - "В цьому немає необхідності!", - "Та відвали вже!", - "Це було дійсно больно!", - "Ай! Чому ти б'єшся?", - "Ви мене з кимось переплутали!", - "Я такого не заслужив!", - "Більше так не роби, будь ласка.", - "Охорона, викиньте цього монстра в озеро!", - "Я натравлю на тебе свою Тарраску!", - ], - "npc.speech.villager_decline_trade": [ - "Нажаль, в мене немає чим торгувати.", - "Торгівля? Ніби в мене є щось що вас цікавить.", - "Моя земля - моя. I я не продам її ні за що.", - ], - "npc.speech.merchant_advertisement": [ - "Чи можу я зацікавити вас торгівлею?", - "Хочете поторгувати зі мною?", - "В мене є багато товарів, не хочете глянути?" - ], - "npc.speech.merchant_busy": [ - "Гей, тут є черга.", - "Почекайте, в мене тільки одна пара рук.", - "Приглядіться, ви тут не один.", - "Секунду, я майже закінчив.", - "Не лізьте не в свою чергу.", - "Я зайнятий, заходьте пізніше." - ], - "npc.speech.merchant_trade_successful": [ - "Було приємно мати з вами справу!", - "Заходьте ще!", - "Дякую що обрали нас!", - ], - "npc.speech.merchant_trade_declined": [ - "Не підійшло? Можливо в інший раз!", - "Все одно, на все добре!", - ], - "npc.speech.villager_cultist_alarm": [ - "Увага! Культист крадеться!", - "За зброю! Культисти атакують!", - "Як культисти взагалі посміли прийти сюди!", - "Слава Нації! Смерть Культистам!", - "Я не священик, але ви культисти заслуговуєте на смерть!", - "Вбивця!", - "Коли ти в останнє куштував лезо меча на смак, культист!?", - "Тільки могильна земля змиє кров з твоїх рук, культист!", - "Цей культист вже нікому нічого не зробить!", - "Не чіпайте цього пацюка! Я задушу цього культиста своїми руками!", - "Якщо ти думаєш, що ми чекаємо тебе із караваєм ти сильно помиляєшся.", - "Краще б ви залишались під землею!", - "Чи мріють культисти про пещерних овець?", - ], - "npc.speech.villager_enemy_killed": [ - "Помста - це страва, яку кожен подає по-своєму!", - "Нарешті заслужений спокій!", - "... так, на чому я зупинився?", - ] } ) diff --git a/assets/voxygen/i18n/uk_UA/main.ron b/assets/voxygen/i18n/uk_UA/main.ron index 8d136536ae..bae23b7623 100644 --- a/assets/voxygen/i18n/uk_UA/main.ron +++ b/assets/voxygen/i18n/uk_UA/main.ron @@ -65,5 +65,26 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "Натисніть 'G', щоб засвітити ліхтар.", + "Натисніть 'F1', щоб переглянути стандартні елементи керування.", + "Введіть /say чи /s, щоб написати лише гравцям поряд.", + "Введіть /region чи /r, щоб написати лише гравцям в радіусі кількох сотень блоків навколо.", + "Адміністратори можуть використовувати команду /build для переходу в режим будування", + "Введіть /group чи /g, щоб написати лише гравцям з Вашої групи.", + "Щоб надіслати приватне повідомлення, введіть /tell, ім'я гравця та Ваше повідомлення.", + "Тримайте око на вістрі - їжа, скрині та інші корисні предмети можуть бути де-завгодно!", + "Інвентар переповнений харчами? Спробуйте поєднати їх в кращу їжу!", + "Шукаєте чим би це зайнятись? Провідайте одне з позначених на мапі підземель!", + "Не забудьте налаштувати оптимальну для Вашої системи якість зображення. Натисніть 'N', щоб відкрити налаштування.", + "Грати з іншими весело! Натисніть 'O', щоб переглянути список користувачів в мережі.", + "Натисніть 'J', щоб потанцювати. Гей-Гоп!", + "Натисніть 'L-Shift', щоб дістати Дельтаплан, та підкорюйте небеса!", + "Veloren все ще на стадії ранньої альфи. Ми стараємося робити покращення кожного дня!", + "Якшо Ви хочете долучитись до розробки або ж просто поспілкуватись із нами, приєднуйтесь до нашого Discord-серверу.", + "Ви можете змінити відображення індикатора здоров'я в налаштуваннях.", + "Присядьте біля ватри (натиснувши 'K'), щоб відпочити та відновити здоров'я.", + "Потребуєте більше торбин чи кращу броню? Натисніть 'C' щоб відкрити ремісниче меню.", + ], } ) diff --git a/assets/voxygen/i18n/uk_UA/npc.ron b/assets/voxygen/i18n/uk_UA/npc.ron new file mode 100644 index 0000000000..2704bddf28 --- /dev/null +++ b/assets/voxygen/i18n/uk_UA/npc.ron @@ -0,0 +1,158 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Ukrainian +( + string_map: { + + }, + + vector_map: { + "npc.speech.villager": [ + "Ну хіба ж не прекрасний сьогодні день?", + "Як ся маєш?", + "Гарного тобі дня!", + "Цікаво, про що думає Катоблепас, коли їсть траву...", + "Як тобі така погода?", + "Мурашки по спині від одної тільки думки про ті підземелля! Сподіваюсь, хтось з ними розбереться.", + "Коли я посильнішаю, мені б хотілось піти в спелеопохід, досліджувати печери!", + "Ви не бачили мого кота?", + "Ви коли небудь чули про лютих Земних Акул? Кажуть, вони водяться в пустелях.", + "Кажуть, в печерах можна знайти коштовне каміння будь-яких типів.", + "Я просто шаленію від сиру!", + "Не зайдете в гості? Ми якраз збирались поласувати сиру!", + "Кажуть, гриби корисні для здоров'я. Я, правда, ніколи їх не їм.", + "Не забудь сухарики!", + "Обожнюю Дварфський Сир! Хотілось би вміти його робити...", + "Цікаво, що там по іншу сторону гір...", + "Я сподіваюсь виготовити власний дельтаплан одного дня.", + "Ви не хотіли б подивитись на мій сад? Гаразд, можливо іншим разом.", + "Прекрасний день для прогулянки в лісі!", + "Бути чи не бути? Думаю, я буду фермером.", + "Ви не думали про те, що наше селище - найкраще?", + "Як ти думаєш, чому Сяючі Залишки світяться?", + "По-моєму, час другого сніданку!", + "А ви коли небудь ловили світлячка?", + "Я не можу зрозуміти, звідки приходять ці Сауроки.", + "Хотілося б, щоб хтось захищав селище від вовків.", + "Сьогодні мені приснився прекрасний сон про сир. Що б це значило?", + ], + "npc.speech.villager_under_attack": [ + "Допоможіть, на мене напали!", + "Рятуйте! Б'ють!", + "Ай! Больно!", + "Лупцюють!", + "Допоможіть!", + "Рятуйте!", + "Хто-небудь, допоможіть!", + "Будь ласка, допоможіть!", + "АААААА! Рятуйте!", + "Рятуйте! Вбивця!", + "Рятуйте! Мене зараз вб'ють!", + "Охорона, на мене напали!", + "Охорона! На мене напали!", + "Мене атакують! Охорона!", + "Рятуйте! Охорона! На мене напали!", + "Охорона! Швидше!", + "Охорона! Охорона!", + "Охорона! Цей негідник напав на мене!", + "Охорона, розберіться з цим покидьком!", + "Охорона! Тут вбивця!", + "Охорона! Рятуйте!", + "Це тобі так просто не минеться! Охорона!", + "Ах ти ж падлюка!", + "АААААА!", + "Хто-небудь!", + "Ай! Охорона! Рятуйте!", + "Бляха... Вони прийшли за мною!", + "Рятуйте! Допоможіть! Мене катують!", + "Ага, ось вам і властива системі жорстокість.", + "Це лиш царапина!", + "Ану перестань!", + "Благаю, не бий мене!", + "Агов! Дивись куди сунеш цю штуку!", + "Котись під три чорти!", + "Перестань! Відчепись!", + "Я починаю сердитись!", + "Ким ти тут себе уявляєш?!", + "Ти за це поплатишся головою!", + "Благаю, перестань! У мене нічого немає!", + "Я розкажу моєму братові! Він набагато сильніший за мене!", + "Ааа, я розкажу мамі!", + "Пішло геть, опудало!", + "Благаю, перестань!", + "Це було не дуже етично з Вашого боку!", + "Все, все! Ти вмієш битись! Тепер перестань!", + "Пощади мене!", + "Благаю, у мене сім'я!", + "Почекайте, давайте спокійно обговоримо ситуацію?", + "Насилля - це ніколи не рішення!", + "Та що ж це за день такий...", + "Ауч! Це було больно!", + "Ого, яке нахабство!", + "Досить вже!", + "А щоб тобі!", + "Не весело.", + "Як ти смієш?!", + "Ти за це заплатиш!", + "Тільки спробуй! Ти про це пожалкуєш!", + "Не змушуй мене тебе покарати!", + "Це якесь непорозуміння!", + "В цьому немає необхідності!", + "Та відвали вже!", + "Це було дійсно больно!", + "Ай! Чому ти б'єшся?", + "Ви мене з кимось переплутали!", + "Я такого не заслужив!", + "Більше так не роби, будь ласка.", + "Охорона, викиньте цього монстра в озеро!", + "Я натравлю на тебе свою Тарраску!", + ], + "npc.speech.villager_decline_trade": [ + "Нажаль, в мене немає чим торгувати.", + "Торгівля? Ніби в мене є щось що вас цікавить.", + "Моя земля - моя. I я не продам її ні за що.", + ], + "npc.speech.merchant_advertisement": [ + "Чи можу я зацікавити вас торгівлею?", + "Хочете поторгувати зі мною?", + "В мене є багато товарів, не хочете глянути?" + ], + "npc.speech.merchant_busy": [ + "Гей, тут є черга.", + "Почекайте, в мене тільки одна пара рук.", + "Приглядіться, ви тут не один.", + "Секунду, я майже закінчив.", + "Не лізьте не в свою чергу.", + "Я зайнятий, заходьте пізніше." + ], + "npc.speech.merchant_trade_successful": [ + "Було приємно мати з вами справу!", + "Заходьте ще!", + "Дякую що обрали нас!", + ], + "npc.speech.merchant_trade_declined": [ + "Не підійшло? Можливо в інший раз!", + "Все одно, на все добре!", + ], + "npc.speech.villager_cultist_alarm": [ + "Увага! Культист крадеться!", + "За зброю! Культисти атакують!", + "Як культисти взагалі посміли прийти сюди!", + "Слава Нації! Смерть Культистам!", + "Я не священик, але ви культисти заслуговуєте на смерть!", + "Вбивця!", + "Коли ти в останнє куштував лезо меча на смак, культист!?", + "Тільки могильна земля змиє кров з твоїх рук, культист!", + "Цей культист вже нікому нічого не зробить!", + "Не чіпайте цього пацюка! Я задушу цього культиста своїми руками!", + "Якщо ти думаєш, що ми чекаємо тебе із караваєм ти сильно помиляєшся.", + "Краще б ви залишались під землею!", + "Чи мріють культисти про пещерних овець?", + ], + "npc.speech.villager_enemy_killed": [ + "Помста - це страва, яку кожен подає по-своєму!", + "Нарешті заслужений спокій!", + "... так, на чому я зупинився?", + ] + } +) diff --git a/assets/voxygen/i18n/vi_VI/_manifest.ron b/assets/voxygen/i18n/vi_VI/_manifest.ron index b5ad2c8fc7..a119637120 100644 --- a/assets/voxygen/i18n/vi_VI/_manifest.ron +++ b/assets/voxygen/i18n/vi_VI/_manifest.ron @@ -28,123 +28,5 @@ asset_key: "voxygen.font.OpenSans-Regular", scale_ratio: 1.0, ), - }, - - string_map: { - /// Start Common section - - /// End Common section - - /// Start Main screen section - - /// End Main screen section - }, - - vector_map: { - "loading.tips": [ - "Nhấn 'G' bật đèn lồng của bạn.", - "Nhấn 'F1' để xem tất cả các liên kết phím mặc định.", - "Bạn có thể gõ /say hoặc là /s để nói chuyện xung quanh bạn.", - "Bạn có thể gõ /region hoặc là /r nói chuyện với người chơi vài trăm blocks xung quanh bạn.", - "Quản trị viên có thể sử dụng /build để vào chế độ xây dựng.", - "Bạn có thể gõ /group hoặc là /g để nói chuyện với những người chơi trong nhóm hiện tại của bạnto.", - "Để gửi tin nhắn riêng tư gõ /tell theo sau là tên người chơi và tin nhắn của bạn.", - "NPCs với cùng một mức độ có thể có một khó khăn khác nhau.", - "Coi chừng thức ăn, rương và các chiến lợi phẩm khác lan rộng khắp thế giới!", - "Thực phẩm đầy tồn kho? Hãy thử chế biến những món ăn ngon hơn từ nó!", - "Tự hỏi những gì ở đó để làm? Thử một trong những ngục tối được đánh dấu trên bản đồ!", - "Đừng quên điều chỉnh đồ họa cho hệ thống của bạn. Nhấn 'N' để mở cài đặt.", - "Chơi với những người khác rất vui! Nhấn 'O' để xem ai cũng đáng chơi hiện tại bây giờ.", - "Kẻ thù có đầu lâu bên dưới thanh máu của chúng mạnh mẽ hơn so với chính bạn.", - "Nhấn 'J' để nhảy múa. Buổi tiệc!", - "Nhấn 'L-Shift' để mở tàu lượn của bạn và chinh phục bầu trời.", - "Veloren vẫn đang trong giai đoạn Pre-Alpha. Chúng tôi cố gắng hết sức để cải thiện nó mỗi ngày!", - "Nếu bạn muốn tham gia nhóm nhà phát triển hoặc chỉ cần trò chuyện với chúng tôi, hãy tham gia Discord-Server.", - "Bạn có thể thay đổi hiển thị lượng máu của mình trên thanh sức khỏe trong cài đặt.", - "Để xem số liệu thống kê của bạn, hãy nhấn vào nút 'Stats' trong kho.", - "Ngồi gần lửa trại (nhấn nút 'K') để nghỉ ngơi - nhận được một sự chữa lành chậm theo thời gian.", - "Cần thêm túi hoặc áo giáp tốt hơn để tiếp tục cuộc hành trình của bạny? Nhấn 'C' để mở menu chế tạo!", - ], - "npc.speech.villager_under_attack": [ - "Giúp, mình đang bị tấn công!", - "Giúp! Mình đang bị tấn công!", - "Đau! Mình đang bị tấn công!", - "Đau! Mình đang bị tấn công! Giúp!", - "Giúp tôi! Mình đang bị tấn công!", - "Mình đang bị tấn công! Giúp!", - "Mình đang bị tấn công! Giúp tôi!", - "Giúp!", - "Giúp! Giúp!", - "Giúp! Giúp! Giúp!", - "Mình đang bị tấn công!", - "AAAHHH! Mình đang bị tấn công!", - "AAAHHH! Mình đang bị tấn công! Giúp!", - "Giúp! Chúng ta đang bị tấn công!", - "Giúp! Kẻ giết người!", - "Giúp! Có một kẻ giết người đang thả rông!", - "Giúp! Họ ráng giết tôi!", - "Người đâu, Mình đang bị tấn công!", - "Người đâu! Mình đang bị tấn công!", - "Mình đang bị tấn công! Lính canh!", - "Giúp! Lính canh! Mình đang bị tấn công!", - "Lính canh! Đến nhanh!", - "Lính canh! Lính canh!", - "Lính canh! Có một nhân vật phản diện đang tấn công tôi!", - "Lính canh, Giết kẻ xấu xa này!", - "Lính canh! Có một kẻ giết người!", - "Lính canh! Giúp tôi!", - "Mày sẽ không thoát khỏi điều này! Lính canh!", - "Mày khốn nạn!", - "Cứu tôi!", - "Giúp! Làm ơn!", - "Đau! Lính canh! Giúp!", - "Họ đang tìm kiếm tôi!", - "Giúp! Giúp! Tôi đang bị kìm nén!", - "Ah, bây giờ chúng ta thấy bạo lực vốn có trong hệ thống", - "Đây chỉ là một vết xước", - "Dừng lại!", - "Tôi đã làm gì cho bạn?!", - "Làm ơn đừng tấn công tôi nữa!", - "Chời ơi! Bạn phải để ý xem bạn đang chỉ cái đó ở đâu", - "Kẻ khốn nạn ghê tởm, biến mất chỗ khác!", - "Dừng lại! Đi chỗ khác!", - "Mày đang chọc tao điên!", - "Mày! Mày nghĩ bạn là ai?!", - "Tôi sẽ có đầu của mày cho điều đó!", - "Xin dừng lại! Tôi không mang gì co giá trị!", - "Tôi sẽ kể anh trai tôi. Anh to hơn bạn!", - "Khôngggg, tôi đi méc mẹ!", - "Ba má không biết dạy!", - "Làm ơn đừng làm vậy.", - "Điều đó không tốt lắm!", - "Vũ khí của bạn hoạt động, bạn có thể cất nó đi ngay bây giờ!", - "Tha cho tôi!", - "Làm ơn, tôi có một gia đình!", - "Tôi còn quá trẻ để chết!", - "Chúng ta có thể nói về điều này không?", - "Bạo lực không bao giờ là câu trả lời!", - "Hôm nay hóa ra là một ngày rất tồi tệ...", - "Chời ơi, đau đấy!", - "Eek!", - "Thật là thô lỗ!", - "Dừng lại, tôi cầu xin bạn!", - "Tôi ước bạn bệnh!", - "Điều này không vui.", - "Mày dám?!", - "Mày sẽ trả cho điều đó!", - "Hãy tiếp tục và bạn sẽ hối hận!", - "Đừng bắt tôi đánh bạn!", - "Phải có một số hiểu lầm!", - "Bạn không cần phải làm điều này!", - "Biến đi, tên khốn!", - "Đau quá!", - "Tại sao bạn lại làm vậy?", - "Chời ơi, dừng lại!", - "Bạn phải làm cho tôi nhầm lẫn với một người khác!", - "Tôi không xứng đáng điều này!", - "Xin đừng làm điều đó một lần nữa.", - "Các vệ binh, ném con quái vật này xuống hồ!", - "Tôi sẽ gọi con tarrasque của tôi để tấn công bạn!", - ], } ) diff --git a/assets/voxygen/i18n/vi_VI/main.ron b/assets/voxygen/i18n/vi_VI/main.ron index b7251f00ba..d79bcac846 100644 --- a/assets/voxygen/i18n/vi_VI/main.ron +++ b/assets/voxygen/i18n/vi_VI/main.ron @@ -60,5 +60,29 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "Nhấn 'G' bật đèn lồng của bạn.", + "Nhấn 'F1' để xem tất cả các liên kết phím mặc định.", + "Bạn có thể gõ /say hoặc là /s để nói chuyện xung quanh bạn.", + "Bạn có thể gõ /region hoặc là /r nói chuyện với người chơi vài trăm blocks xung quanh bạn.", + "Quản trị viên có thể sử dụng /build để vào chế độ xây dựng.", + "Bạn có thể gõ /group hoặc là /g để nói chuyện với những người chơi trong nhóm hiện tại của bạnto.", + "Để gửi tin nhắn riêng tư gõ /tell theo sau là tên người chơi và tin nhắn của bạn.", + "NPCs với cùng một mức độ có thể có một khó khăn khác nhau.", + "Coi chừng thức ăn, rương và các chiến lợi phẩm khác lan rộng khắp thế giới!", + "Thực phẩm đầy tồn kho? Hãy thử chế biến những món ăn ngon hơn từ nó!", + "Tự hỏi những gì ở đó để làm? Thử một trong những ngục tối được đánh dấu trên bản đồ!", + "Đừng quên điều chỉnh đồ họa cho hệ thống của bạn. Nhấn 'N' để mở cài đặt.", + "Chơi với những người khác rất vui! Nhấn 'O' để xem ai cũng đáng chơi hiện tại bây giờ.", + "Kẻ thù có đầu lâu bên dưới thanh máu của chúng mạnh mẽ hơn so với chính bạn.", + "Nhấn 'J' để nhảy múa. Buổi tiệc!", + "Nhấn 'L-Shift' để mở tàu lượn của bạn và chinh phục bầu trời.", + "Veloren vẫn đang trong giai đoạn Pre-Alpha. Chúng tôi cố gắng hết sức để cải thiện nó mỗi ngày!", + "Nếu bạn muốn tham gia nhóm nhà phát triển hoặc chỉ cần trò chuyện với chúng tôi, hãy tham gia Discord-Server.", + "Bạn có thể thay đổi hiển thị lượng máu của mình trên thanh sức khỏe trong cài đặt.", + "Để xem số liệu thống kê của bạn, hãy nhấn vào nút 'Stats' trong kho.", + "Ngồi gần lửa trại (nhấn nút 'K') để nghỉ ngơi - nhận được một sự chữa lành chậm theo thời gian.", + "Cần thêm túi hoặc áo giáp tốt hơn để tiếp tục cuộc hành trình của bạny? Nhấn 'C' để mở menu chế tạo!", + ], } ) diff --git a/assets/voxygen/i18n/vi_VI/npc.ron b/assets/voxygen/i18n/vi_VI/npc.ron new file mode 100644 index 0000000000..e251b2767a --- /dev/null +++ b/assets/voxygen/i18n/vi_VI/npc.ron @@ -0,0 +1,92 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for Vietnamese (Vietnam) +( + string_map: { + + }, + + vector_map: { + "npc.speech.villager_under_attack": [ + "Giúp, mình đang bị tấn công!", + "Giúp! Mình đang bị tấn công!", + "Đau! Mình đang bị tấn công!", + "Đau! Mình đang bị tấn công! Giúp!", + "Giúp tôi! Mình đang bị tấn công!", + "Mình đang bị tấn công! Giúp!", + "Mình đang bị tấn công! Giúp tôi!", + "Giúp!", + "Giúp! Giúp!", + "Giúp! Giúp! Giúp!", + "Mình đang bị tấn công!", + "AAAHHH! Mình đang bị tấn công!", + "AAAHHH! Mình đang bị tấn công! Giúp!", + "Giúp! Chúng ta đang bị tấn công!", + "Giúp! Kẻ giết người!", + "Giúp! Có một kẻ giết người đang thả rông!", + "Giúp! Họ ráng giết tôi!", + "Người đâu, Mình đang bị tấn công!", + "Người đâu! Mình đang bị tấn công!", + "Mình đang bị tấn công! Lính canh!", + "Giúp! Lính canh! Mình đang bị tấn công!", + "Lính canh! Đến nhanh!", + "Lính canh! Lính canh!", + "Lính canh! Có một nhân vật phản diện đang tấn công tôi!", + "Lính canh, Giết kẻ xấu xa này!", + "Lính canh! Có một kẻ giết người!", + "Lính canh! Giúp tôi!", + "Mày sẽ không thoát khỏi điều này! Lính canh!", + "Mày khốn nạn!", + "Cứu tôi!", + "Giúp! Làm ơn!", + "Đau! Lính canh! Giúp!", + "Họ đang tìm kiếm tôi!", + "Giúp! Giúp! Tôi đang bị kìm nén!", + "Ah, bây giờ chúng ta thấy bạo lực vốn có trong hệ thống", + "Đây chỉ là một vết xước", + "Dừng lại!", + "Tôi đã làm gì cho bạn?!", + "Làm ơn đừng tấn công tôi nữa!", + "Chời ơi! Bạn phải để ý xem bạn đang chỉ cái đó ở đâu", + "Kẻ khốn nạn ghê tởm, biến mất chỗ khác!", + "Dừng lại! Đi chỗ khác!", + "Mày đang chọc tao điên!", + "Mày! Mày nghĩ bạn là ai?!", + "Tôi sẽ có đầu của mày cho điều đó!", + "Xin dừng lại! Tôi không mang gì co giá trị!", + "Tôi sẽ kể anh trai tôi. Anh to hơn bạn!", + "Khôngggg, tôi đi méc mẹ!", + "Ba má không biết dạy!", + "Làm ơn đừng làm vậy.", + "Điều đó không tốt lắm!", + "Vũ khí của bạn hoạt động, bạn có thể cất nó đi ngay bây giờ!", + "Tha cho tôi!", + "Làm ơn, tôi có một gia đình!", + "Tôi còn quá trẻ để chết!", + "Chúng ta có thể nói về điều này không?", + "Bạo lực không bao giờ là câu trả lời!", + "Hôm nay hóa ra là một ngày rất tồi tệ...", + "Chời ơi, đau đấy!", + "Eek!", + "Thật là thô lỗ!", + "Dừng lại, tôi cầu xin bạn!", + "Tôi ước bạn bệnh!", + "Điều này không vui.", + "Mày dám?!", + "Mày sẽ trả cho điều đó!", + "Hãy tiếp tục và bạn sẽ hối hận!", + "Đừng bắt tôi đánh bạn!", + "Phải có một số hiểu lầm!", + "Bạn không cần phải làm điều này!", + "Biến đi, tên khốn!", + "Đau quá!", + "Tại sao bạn lại làm vậy?", + "Chời ơi, dừng lại!", + "Bạn phải làm cho tôi nhầm lẫn với một người khác!", + "Tôi không xứng đáng điều này!", + "Xin đừng làm điều đó một lần nữa.", + "Các vệ binh, ném con quái vật này xuống hồ!", + "Tôi sẽ gọi con tarrasque của tôi để tấn công bạn!", + ], + } +) diff --git a/assets/voxygen/i18n/zh_CN/_manifest.ron b/assets/voxygen/i18n/zh_CN/_manifest.ron index f6fa399ab6..19bdca60e0 100644 --- a/assets/voxygen/i18n/zh_CN/_manifest.ron +++ b/assets/voxygen/i18n/zh_CN/_manifest.ron @@ -28,205 +28,5 @@ asset_key: "voxygen.font.WenQuanYiZenHei", scale_ratio: 1.0, ), - }, - - string_map: { - - }, - - vector_map: { - "loading.tips": [ - "按下 'G' 来点亮提灯.", - "按下 'F1' 查看所有默认快捷键.", - "你可以输入 /say 或 /s 只与您周围的玩家聊天.", - "你可以输入 /region 或 /r 只与你区域范围内的玩家聊天.", - "管理员可以输入 /build 指令来进入建造模式.", - "你可以输入 /group 或 /g 只与你的队伍的玩家聊天.", - "你可以输入 /tell 玩家名称 发送私人消息.", - "注意地面上的食物,箱子以及其他战利品!", - "背包里全是食物? 尝试使用它们制作更好的食物!", - "不知道做什么? 地图上褐色标点区域有地牢!", - "不要忘记调整图形设置. 按下 'N' 打开设置.", - "和其他人一起游玩时! 按下 'O' 查看在线玩家.", - "按下 'J' 跳舞!", - "按下 'L-Shift' 可以打开滑翔翼并立刻起飞", - "Veloren 处于Pre-Alpha阶段. 我们每天都在努力改善它!", - "如果您想加入开发团队或与我们聊天,请加入我们的Discord服务器.", - "你可以在设置中的生命栏中切换显示你的生命状态.", - "坐在篝火旁(同时按下 'K' 键),会缓慢恢复血量.", - "需要更大的背包或更好的护甲来继续你的旅程吗? 按下 'C' 打开制作菜单!", - ], - "npc.speech.villager": [ - "这不是很愉快的一天吗?", - "你今天过得怎么样?", - "早上好!", - "我不知道Catoblepas吃草时会在想什么.", - "你觉得这天气怎样?", - "一想到那些地牢就会让我感到害怕. 我希望有人能把它们清除掉.", - "当我变得更强大时,我想去山洞里兜兜风.", - "你有看见我的猫吗?", - "你听说过凶猛的陆地鲨吗?我听说它们生活在沙漠中.", - "他们说在洞穴中可以找到各种闪亮的宝石.", - "我超喜欢奶酪的!", - "你不进来吗?我们正要吃奶酪呢!", - "他们说蘑菇对你的健康有益,切勿单独食用.", - "别忘了饼干的事!", - "我只是崇拜矮人奶酪,我希望我能做到.", - "我想知道山的另一边是什么.", - "我希望有一天能制做出自己的滑翔伞.", - "你想看看我的花园吗?好吧,也许还需要再等一等.", - "在树林里漫步的美好一天!", - "成败与否?我想我会成为一名农夫.", - "你不认为我们的村庄是最好的吗?", - "你认为使尸体发光的原因是什么?", - "我认为是时候吃第二顿早餐了!", - "你曾经捉住过萤火虫吗?", - "我只是不明白那些蜥蜴人从何而来.", - "我希望有人能让狼远离村子.", - "昨晚我梦见了美妙的奶酪.这意味着什么?", - "我和哥哥一起留了一些奶酪.现在我不知道它是否还在.我称它为薛定谔的奶酪.", - "我和妹妹一起留了一些奶酪.现在我不知道它是否还在.我称它为薛定谔的奶酪.", - "有人应该对那些邪教徒做些什么.最好不是我.", - "我希望快点下雨.对农作物有好处.", - "我爱蜂蜜!但我讨厌蜜蜂.", - "我希望有一天能看到外面的世界.美好的生活不仅在这村庄里.", - ], - "npc.speech.villager_decline_trade": [ - "抱歉,我没有什么可交易的.", - "交易?就好像我得到了你可能感兴趣的任何东西.", - "房子是我的,我不会用它换任何东西.", - ], - "npc.speech.merchant_advertisement": [ - "你有兴趣和我的交易吗?", - "你想和我交易吗?", - "我有很多货物,你想看看吗?" - ], - "npc.speech.merchant_busy": [ - "嘿,轮到你了.", - "请稍等,我只是一个人,忙不过来.", - "你看到别人在你面前吗?", - "请稍等,接下让我来就行", - "不要插队.", - "我很忙,稍后再回来." - ], - "npc.speech.merchant_trade_successful": [ - "谢谢您与我交易!", - "谢谢您!", - ], - "npc.speech.merchant_trade_declined": [ - "也许下次可以,祝你有美好的一天!", - "太遗憾了,也许下次可以!" - ], - "npc.speech.villager_cultist_alarm": [ - "当心!那里有一个邪教徒!", - "拿起武器!信徒们要进攻了!", - "邪教徒怎么敢攻击我们的村庄!", - "该死的邪教徒!", - "这里决不容忍邪教徒!", - "凶恶的邪教徒!", - "肮脏的邪教徒,尝尝我的剑刃!", - "你们邪教徒的手上沾满了鲜血,别想洗清你们的罪孽!", - "Billions of blistering blue barnacles! A cultist among us!", - "这个邪教徒的邪恶一生即将结束!", - "这个邪教徒是我的了!", - "准备跟你的造物主见面吧,肮脏的邪教徒!", - "我看到一个邪教徒!抓住他们!", - "我看到一个邪教徒!攻击!", - "我看到一个邪教徒!别让他跑了!", - "大多数的邪教徒都会在意死亡吗?!", - "决不原谅!永不忘记!忏悔吧,邪教徒!", - "去死吧,邪教徒!", - "你的恐怖统治即将终结!", - "你所做的这一切,罪有应得!", - "我们这里很不欢迎你这种家伙.", - "你应该下地狱!", - ], - "npc.speech.villager_under_attack": [ - "救命, 我们受到攻击!", - "救命! 我们受到攻击!", - "哎哟! 我受到攻击!", - "哎哟! 我受到攻击! 我需要帮助!", - "快救我! 我受到攻击!", - "我受到攻击! 救命!", - "我受到攻击! 我需要帮助!", - "救命!", - "救命! 救命!", - "救命! 救命! 救命!", - "我受到攻击!", - "啊啊啊啊! 我受到攻击!", - "啊啊啊啊! 我受到攻击! 救命!", - "救命! 我们受到攻击!", - "救命! 有杀人犯!", - "救命! 这里有一个杀人犯在逃跑!", - "救命! 他们想杀我!", - "守卫, 我受到攻击!", - "守卫! 我受到攻击!", - "我受到攻击! 守卫!", - "救命! 守卫! 我受到攻击!", - "守卫! 快来!", - "守卫! 守卫!", - "守卫! 这里有一个恶棍在攻击我!", - "守卫, 快杀死这个恶棍!", - "守卫! 这里有一个杀人犯!", - "守卫! 帮帮我!", - "你别想逃了! 守卫!", - "你是恶魔!", - "救命!", - "救救我! 拜托!", - "哎哟! 守卫! 救命!", - "他们会来找我的!", - "救命! 救命! 我被压迫了!", - "啊, 我们看到了这存在于系统里的暴力.", - "这只是擦伤而已!", - "停下来!", - "我曾经对你做过什么?!", - "不要攻击我了!", - "嘿! 注意你指向的东西!", - "可恶的家伙, 你们一起去死吧!", - "停下来! 然后滚蛋!", - "你现在让我很生气!", - "噢! 你以为你是谁?!", - "我会帮你的!", - "停, 请停一下! 我没有任何值钱的东西!", - "我把我的兄弟放在你身上, 他比我的大多了!", - "不, 我要告诉妈妈!", - "诅咒你!", - "请不要这么做.", - "那不是很好!", - "你的武器很好, 现在可以收起来了!", - "绕了我吧!", - "拜托了, 我还有家庭!", - "我还小就要死了!", - "我们可以谈谈这个吗?", - "暴力永远不是解决问题的方式!", - "今天真是非常糟糕的一天...", - "喂, 别打我!", - "诶!", - "真没礼貌!", - "停手, 求求你!", - "你有病啊!", - "这不好玩.", - "你怎么敢?!", - "你会为此复出代价的!", - "坚持下去你会后悔的!", - "不要让我伤害你!", - "这肯定有什么误会!", - "你没必要这样对我吧!", - "再见吧, 恶魔!", - "真的好疼!", - "为什么要这么做?", - "神经病啊, 停手!", - "你让我和别人感到很迷惑!", - "我不应该这样!", - "请不要再这样做.", - "守卫, 把这个怪物扔进湖里!", - "我会把怪兽放在你身上!", - "为什么是我...?", - ], - "npc.speech.villager_enemy_killed": [ - "我消灭了我的敌人!", - "终于和平了!", - "...现在我在做什么?", - ] } ) diff --git a/assets/voxygen/i18n/zh_CN/main.ron b/assets/voxygen/i18n/zh_CN/main.ron index bf76304f5d..aaefadbe8a 100644 --- a/assets/voxygen/i18n/zh_CN/main.ron +++ b/assets/voxygen/i18n/zh_CN/main.ron @@ -64,5 +64,26 @@ https://veloren.net/account/."#, vector_map: { + "loading.tips": [ + "按下 'G' 来点亮提灯.", + "按下 'F1' 查看所有默认快捷键.", + "你可以输入 /say 或 /s 只与您周围的玩家聊天.", + "你可以输入 /region 或 /r 只与你区域范围内的玩家聊天.", + "管理员可以输入 /build 指令来进入建造模式.", + "你可以输入 /group 或 /g 只与你的队伍的玩家聊天.", + "你可以输入 /tell 玩家名称 发送私人消息.", + "注意地面上的食物,箱子以及其他战利品!", + "背包里全是食物? 尝试使用它们制作更好的食物!", + "不知道做什么? 地图上褐色标点区域有地牢!", + "不要忘记调整图形设置. 按下 'N' 打开设置.", + "和其他人一起游玩时! 按下 'O' 查看在线玩家.", + "按下 'J' 跳舞!", + "按下 'L-Shift' 可以打开滑翔翼并立刻起飞", + "Veloren 处于Pre-Alpha阶段. 我们每天都在努力改善它!", + "如果您想加入开发团队或与我们聊天,请加入我们的Discord服务器.", + "你可以在设置中的生命栏中切换显示你的生命状态.", + "坐在篝火旁(同时按下 'K' 键),会缓慢恢复血量.", + "需要更大的背包或更好的护甲来继续你的旅程吗? 按下 'C' 打开制作菜单!", + ], } ) diff --git a/assets/voxygen/i18n/zh_CN/npc.ron b/assets/voxygen/i18n/zh_CN/npc.ron new file mode 100644 index 0000000000..03df6f1099 --- /dev/null +++ b/assets/voxygen/i18n/zh_CN/npc.ron @@ -0,0 +1,183 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// 本地化 "Simplified Chinese" 简体中文 +( + string_map: { + + }, + + vector_map: { + "npc.speech.villager": [ + "这不是很愉快的一天吗?", + "你今天过得怎么样?", + "早上好!", + "我不知道Catoblepas吃草时会在想什么.", + "你觉得这天气怎样?", + "一想到那些地牢就会让我感到害怕. 我希望有人能把它们清除掉.", + "当我变得更强大时,我想去山洞里兜兜风.", + "你有看见我的猫吗?", + "你听说过凶猛的陆地鲨吗?我听说它们生活在沙漠中.", + "他们说在洞穴中可以找到各种闪亮的宝石.", + "我超喜欢奶酪的!", + "你不进来吗?我们正要吃奶酪呢!", + "他们说蘑菇对你的健康有益,切勿单独食用.", + "别忘了饼干的事!", + "我只是崇拜矮人奶酪,我希望我能做到.", + "我想知道山的另一边是什么.", + "我希望有一天能制做出自己的滑翔伞.", + "你想看看我的花园吗?好吧,也许还需要再等一等.", + "在树林里漫步的美好一天!", + "成败与否?我想我会成为一名农夫.", + "你不认为我们的村庄是最好的吗?", + "你认为使尸体发光的原因是什么?", + "我认为是时候吃第二顿早餐了!", + "你曾经捉住过萤火虫吗?", + "我只是不明白那些蜥蜴人从何而来.", + "我希望有人能让狼远离村子.", + "昨晚我梦见了美妙的奶酪.这意味着什么?", + "我和哥哥一起留了一些奶酪.现在我不知道它是否还在.我称它为薛定谔的奶酪.", + "我和妹妹一起留了一些奶酪.现在我不知道它是否还在.我称它为薛定谔的奶酪.", + "有人应该对那些邪教徒做些什么.最好不是我.", + "我希望快点下雨.对农作物有好处.", + "我爱蜂蜜!但我讨厌蜜蜂.", + "我希望有一天能看到外面的世界.美好的生活不仅在这村庄里.", + ], + "npc.speech.villager_decline_trade": [ + "抱歉,我没有什么可交易的.", + "交易?就好像我得到了你可能感兴趣的任何东西.", + "房子是我的,我不会用它换任何东西.", + ], + "npc.speech.merchant_advertisement": [ + "你有兴趣和我的交易吗?", + "你想和我交易吗?", + "我有很多货物,你想看看吗?" + ], + "npc.speech.merchant_busy": [ + "嘿,轮到你了.", + "请稍等,我只是一个人,忙不过来.", + "你看到别人在你面前吗?", + "请稍等,接下让我来就行", + "不要插队.", + "我很忙,稍后再回来." + ], + "npc.speech.merchant_trade_successful": [ + "谢谢您与我交易!", + "谢谢您!", + ], + "npc.speech.merchant_trade_declined": [ + "也许下次可以,祝你有美好的一天!", + "太遗憾了,也许下次可以!" + ], + "npc.speech.villager_cultist_alarm": [ + "当心!那里有一个邪教徒!", + "拿起武器!信徒们要进攻了!", + "邪教徒怎么敢攻击我们的村庄!", + "该死的邪教徒!", + "这里决不容忍邪教徒!", + "凶恶的邪教徒!", + "肮脏的邪教徒,尝尝我的剑刃!", + "你们邪教徒的手上沾满了鲜血,别想洗清你们的罪孽!", + "Billions of blistering blue barnacles! A cultist among us!", + "这个邪教徒的邪恶一生即将结束!", + "这个邪教徒是我的了!", + "准备跟你的造物主见面吧,肮脏的邪教徒!", + "我看到一个邪教徒!抓住他们!", + "我看到一个邪教徒!攻击!", + "我看到一个邪教徒!别让他跑了!", + "大多数的邪教徒都会在意死亡吗?!", + "决不原谅!永不忘记!忏悔吧,邪教徒!", + "去死吧,邪教徒!", + "你的恐怖统治即将终结!", + "你所做的这一切,罪有应得!", + "我们这里很不欢迎你这种家伙.", + "你应该下地狱!", + ], + "npc.speech.villager_under_attack": [ + "救命, 我们受到攻击!", + "救命! 我们受到攻击!", + "哎哟! 我受到攻击!", + "哎哟! 我受到攻击! 我需要帮助!", + "快救我! 我受到攻击!", + "我受到攻击! 救命!", + "我受到攻击! 我需要帮助!", + "救命!", + "救命! 救命!", + "救命! 救命! 救命!", + "我受到攻击!", + "啊啊啊啊! 我受到攻击!", + "啊啊啊啊! 我受到攻击! 救命!", + "救命! 我们受到攻击!", + "救命! 有杀人犯!", + "救命! 这里有一个杀人犯在逃跑!", + "救命! 他们想杀我!", + "守卫, 我受到攻击!", + "守卫! 我受到攻击!", + "我受到攻击! 守卫!", + "救命! 守卫! 我受到攻击!", + "守卫! 快来!", + "守卫! 守卫!", + "守卫! 这里有一个恶棍在攻击我!", + "守卫, 快杀死这个恶棍!", + "守卫! 这里有一个杀人犯!", + "守卫! 帮帮我!", + "你别想逃了! 守卫!", + "你是恶魔!", + "救命!", + "救救我! 拜托!", + "哎哟! 守卫! 救命!", + "他们会来找我的!", + "救命! 救命! 我被压迫了!", + "啊, 我们看到了这存在于系统里的暴力.", + "这只是擦伤而已!", + "停下来!", + "我曾经对你做过什么?!", + "不要攻击我了!", + "嘿! 注意你指向的东西!", + "可恶的家伙, 你们一起去死吧!", + "停下来! 然后滚蛋!", + "你现在让我很生气!", + "噢! 你以为你是谁?!", + "我会帮你的!", + "停, 请停一下! 我没有任何值钱的东西!", + "我把我的兄弟放在你身上, 他比我的大多了!", + "不, 我要告诉妈妈!", + "诅咒你!", + "请不要这么做.", + "那不是很好!", + "你的武器很好, 现在可以收起来了!", + "绕了我吧!", + "拜托了, 我还有家庭!", + "我还小就要死了!", + "我们可以谈谈这个吗?", + "暴力永远不是解决问题的方式!", + "今天真是非常糟糕的一天...", + "喂, 别打我!", + "诶!", + "真没礼貌!", + "停手, 求求你!", + "你有病啊!", + "这不好玩.", + "你怎么敢?!", + "你会为此复出代价的!", + "坚持下去你会后悔的!", + "不要让我伤害你!", + "这肯定有什么误会!", + "你没必要这样对我吧!", + "再见吧, 恶魔!", + "真的好疼!", + "为什么要这么做?", + "神经病啊, 停手!", + "你让我和别人感到很迷惑!", + "我不应该这样!", + "请不要再这样做.", + "守卫, 把这个怪物扔进湖里!", + "我会把怪兽放在你身上!", + "为什么是我...?", + ], + "npc.speech.villager_enemy_killed": [ + "我消灭了我的敌人!", + "终于和平了!", + "...现在我在做什么?", + ] + } +) diff --git a/assets/voxygen/i18n/zh_TW/_manifest.ron b/assets/voxygen/i18n/zh_TW/_manifest.ron index 1685caff4e..61925db51f 100644 --- a/assets/voxygen/i18n/zh_TW/_manifest.ron +++ b/assets/voxygen/i18n/zh_TW/_manifest.ron @@ -26,22 +26,5 @@ asset_key: "voxygen.font.bdfUMplus-outline", scale_ratio: 0.75, ), - }, - string_map: { - /// Start Common section - - /// End Common section - - - /// Start Main screen section - /// End Main screen section - - - /// Start HUD Section - - }, - - vector_map: { - - }, + } ) diff --git a/assets/voxygen/i18n/zh_TW/npc.ron b/assets/voxygen/i18n/zh_TW/npc.ron new file mode 100644 index 0000000000..9f25779f55 --- /dev/null +++ b/assets/voxygen/i18n/zh_TW/npc.ron @@ -0,0 +1,10 @@ +/// Localization for Traditional Chinese +( + string_map: { + + }, + + vector_map: { + + }, +) diff --git a/voxygen/i18n/src/lib.rs b/voxygen/i18n/src/lib.rs index 160a5118c0..249d9e1493 100644 --- a/voxygen/i18n/src/lib.rs +++ b/voxygen/i18n/src/lib.rs @@ -118,12 +118,10 @@ impl common_assets::Compound for Language { .iter() { let id = fragment_asset.id(); - // Activate this once ._manifest is fully transformed and only contains metadata - // or regex: " Date: Sun, 1 Aug 2021 11:20:46 +0000 Subject: [PATCH 037/155] Fix gliderwield downhill run jitter --- CHANGELOG.md | 1 + client/src/lib.rs | 2 +- common/src/comp/character_state.rs | 8 ++++---- common/src/states/glide.rs | 12 +++++------- common/src/states/glide_wield.rs | 20 ++++++++++++++++++-- common/src/states/utils.rs | 2 +- flake.lock | 18 +++++++++--------- server/src/sys/agent.rs | 2 +- voxygen/egui/src/character_states.rs | 2 +- 9 files changed, 41 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91effc1637..339da87968 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Campfires now despawn when underwater - Players no longer spawn underground if their waypoint is underground - Map will now zoom around the cursor's position and drag correctly +- No more jittering while running down slopes with the glider out ## [0.10.0] - 2021-06-12 diff --git a/client/src/lib.rs b/client/src/lib.rs index ae69cbf55a..018ca47a64 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -1231,7 +1231,7 @@ impl Client { .map(|cs| { matches!( cs, - comp::CharacterState::GlideWield | comp::CharacterState::Glide(_) + comp::CharacterState::GlideWield(_) | comp::CharacterState::Glide(_) ) }); diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index a0f2be1ee5..2df87fcae6 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -59,7 +59,7 @@ pub enum CharacterState { Talk, Sneak, Glide(glide::Data), - GlideWield, + GlideWield(glide_wield::Data), /// A stunned state Stunned(stunned::Data), /// A basic blocking state @@ -189,7 +189,7 @@ impl CharacterState { | CharacterState::Equipping(_) | CharacterState::Dance | CharacterState::Glide(_) - | CharacterState::GlideWield + | CharacterState::GlideWield(_) | CharacterState::Talk | CharacterState::Roll(_), ) @@ -228,7 +228,7 @@ impl CharacterState { CharacterState::Talk => states::talk::Data.behavior(j), CharacterState::Climb(data) => data.behavior(j), CharacterState::Glide(data) => data.behavior(j), - CharacterState::GlideWield => states::glide_wield::Data.behavior(j), + CharacterState::GlideWield(data) => data.behavior(j), CharacterState::Stunned(data) => data.behavior(j), CharacterState::Sit => states::sit::Data::behavior(&states::sit::Data, j), CharacterState::Dance => states::dance::Data::behavior(&states::dance::Data, j), @@ -264,7 +264,7 @@ impl CharacterState { CharacterState::Talk => states::talk::Data.handle_event(j, action), CharacterState::Climb(data) => data.handle_event(j, action), CharacterState::Glide(data) => data.handle_event(j, action), - CharacterState::GlideWield => states::glide_wield::Data.handle_event(j, action), + CharacterState::GlideWield(data) => data.handle_event(j, action), CharacterState::Stunned(data) => data.handle_event(j, action), CharacterState::Sit => states::sit::Data::handle_event(&states::sit::Data, j, action), CharacterState::Dance => { diff --git a/common/src/states/glide.rs b/common/src/states/glide.rs index 00f9b65336..2542cfa211 100644 --- a/common/src/states/glide.rs +++ b/common/src/states/glide.rs @@ -4,7 +4,10 @@ use crate::{ fluid_dynamics::angle_of_attack, inventory::slot::EquipSlot, CharacterState, Ori, StateUpdate, Vel, }, - states::behavior::{CharacterBehavior, JoinData}, + states::{ + behavior::{CharacterBehavior, JoinData}, + glide_wield, + }, util::{Dir, Plane, Projection}, }; use serde::{Deserialize, Serialize}; @@ -77,8 +80,7 @@ impl CharacterBehavior for Data { if data.physics.on_ground.is_some() && (data.vel.0 - data.physics.ground_vel).magnitude_squared() < 2_f32.powi(2) { - update.character = CharacterState::GlideWield; - update.ori = update.ori.to_horizontal(); + update.character = CharacterState::GlideWield(glide_wield::Data::default()); } else if data.physics.in_liquid().is_some() || data .inventory @@ -86,7 +88,6 @@ impl CharacterBehavior for Data { .is_none() { update.character = CharacterState::Idle; - update.ori = update.ori.to_horizontal(); } else if !handle_climb(data, &mut update) { let air_flow = data .physics @@ -193,8 +194,6 @@ impl CharacterBehavior for Data { inputs_disabled, ..*self }); - } else { - update.ori = update.ori.to_horizontal(); } update @@ -203,7 +202,6 @@ impl CharacterBehavior for Data { fn unwield(&self, data: &JoinData) -> StateUpdate { let mut update = StateUpdate::from(data); update.character = CharacterState::Idle; - update.ori = update.ori.to_horizontal(); update } } diff --git a/common/src/states/glide_wield.rs b/common/src/states/glide_wield.rs index 269d8c50b2..de8af4ea12 100644 --- a/common/src/states/glide_wield.rs +++ b/common/src/states/glide_wield.rs @@ -6,8 +6,18 @@ use crate::{ glide, }, }; +use serde::{Deserialize, Serialize}; -pub struct Data; +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Data { + // time since left ground, for preventing state transition + // before block snapping kicks in + timer: f32, +} + +impl Default for Data { + fn default() -> Self { Self { timer: 0.0 } } +} impl CharacterBehavior for Data { fn behavior(&self, data: &JoinData) -> StateUpdate { @@ -21,7 +31,13 @@ impl CharacterBehavior for Data { // If not on the ground while wielding glider enter gliding state if data.physics.on_ground.is_none() { - update.character = CharacterState::Glide(glide::Data::new(10.0, 0.6, *data.ori)); + update.character = if self.timer > 0.3 { + CharacterState::Glide(glide::Data::new(10.0, 0.6, *data.ori)) + } else { + CharacterState::GlideWield(Self { + timer: self.timer + data.dt.0, + }) + }; } if data .physics diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 0275524f6f..3e0553982a 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -639,7 +639,7 @@ pub fn attempt_glide_wield(data: &JoinData<'_>, update: &mut StateUpdate) { .unwrap_or(false) && data.body.is_humanoid() { - update.character = CharacterState::GlideWield; + update.character = CharacterState::GlideWield(glide_wield::Data::default()); } } diff --git a/flake.lock b/flake.lock index 2a87ca1208..9c1d6b3ff6 100644 --- a/flake.lock +++ b/flake.lock @@ -24,11 +24,11 @@ "rustOverlay": "rustOverlay" }, "locked": { - "lastModified": 1625378930, - "narHash": "sha256-iBnCmrLweBmtN9VkG6AX4wSE5UUF//4VtfX6Ebhbaew=", + "lastModified": 1627752074, + "narHash": "sha256-iuOGIbJC4hn1XqwrBjiol6j0Xj+AImND6Z9fP/6Za74=", "owner": "yusdacra", "repo": "nix-cargo-integration", - "rev": "4d6efcfd0bc6c6235b180837257ab8020f108c23", + "rev": "47e6414440c66bfd44a0ea07d64ca62075470f62", "type": "github" }, "original": { @@ -39,11 +39,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1625375231, - "narHash": "sha256-dbp2RRftypbAYad/xhDBBG0N7s1WQW+T4jazimvtvRo=", + "lastModified": 1627533199, + "narHash": "sha256-NyIUcNevwtsMBINn56jnDF8wz3TV1AFxw+Vw6JMnkyE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8aff53d3cf23b5eb67c0ba9ba2392d694ade3930", + "rev": "dd98b100651cfbb8804f32d852f75ef7c97a6b74", "type": "github" }, "original": { @@ -62,11 +62,11 @@ "rustOverlay": { "flake": false, "locked": { - "lastModified": 1625364738, - "narHash": "sha256-TPlpEcywGnB8jNIPOlCqFVbioskGOpasrVhxdw0BHzA=", + "lastModified": 1627697717, + "narHash": "sha256-ij7rk2VkPpNf0NTbpP5jfbwuIWfrLXN00pZ+pizGnGM=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "f08a653d9d6bbf06b5cc5dd1e570f1c449acbcf3", + "rev": "6d957c2105a5a548211c412fbc97bae81b7b8eb6", "type": "github" }, "original": { diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index 77468133fb..a0ac28315e 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -291,7 +291,7 @@ impl<'a> System<'a> for Sys { let is_gliding = matches!( read_data.char_states.get(entity), - Some(CharacterState::GlideWield | CharacterState::Glide(_)) + Some(CharacterState::GlideWield(_) | CharacterState::Glide(_)) ) && physics_state.on_ground.is_none(); if let Some(pid) = agent.position_pid_controller.as_mut() { diff --git a/voxygen/egui/src/character_states.rs b/voxygen/egui/src/character_states.rs index 52b1c9df13..39a8660119 100644 --- a/voxygen/egui/src/character_states.rs +++ b/voxygen/egui/src/character_states.rs @@ -24,7 +24,7 @@ pub fn draw_char_state_group( CharacterState::Dance | CharacterState::Idle | CharacterState::Sit - | CharacterState::GlideWield + | CharacterState::GlideWield(_) | CharacterState::Sneak | CharacterState::Talk | CharacterState::Wielding => {}, From 5012e2ba8b0562147d295d0977e8a7dcdb04209b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Sun, 1 Aug 2021 12:56:24 +0200 Subject: [PATCH 038/155] rename hud_settings to settings --- .gitignore | 3 +++ .../voxygen/i18n/cz_CZ/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/de_DE/hud/{hud_settings.ron => settings.ron} | 0 assets/voxygen/i18n/en/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/es_ES/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/es_LA/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/fr_FR/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/hu_HU/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/it_IT/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/ja_JP/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/nl_NL/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/no_NB/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/pl_PL/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/pt_BR/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/pt_PT/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/sv_SE/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/tr_TR/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/uk_UA/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/vi_VI/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/zh_CN/hud/{hud_settings.ron => settings.ron} | 0 .../voxygen/i18n/zh_TW/hud/{hud_settings.ron => settings.ron} | 0 21 files changed, 3 insertions(+) rename assets/voxygen/i18n/cz_CZ/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/de_DE/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/en/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/es_ES/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/es_LA/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/fr_FR/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/hu_HU/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/it_IT/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/ja_JP/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/nl_NL/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/no_NB/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/pl_PL/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/pt_BR/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/pt_PT/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/sv_SE/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/tr_TR/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/uk_UA/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/vi_VI/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/zh_CN/hud/{hud_settings.ron => settings.ron} (100%) rename assets/voxygen/i18n/zh_TW/hud/{hud_settings.ron => settings.ron} (100%) diff --git a/.gitignore b/.gitignore index ad6f7022f6..5621834e78 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,9 @@ todo.txt userdata heaptrack.* +# allow asset hud settings +!assets/voxygen/i18n/*/hud/settings.ron + # Export data *.csv diff --git a/assets/voxygen/i18n/cz_CZ/hud/hud_settings.ron b/assets/voxygen/i18n/cz_CZ/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/cz_CZ/hud/hud_settings.ron rename to assets/voxygen/i18n/cz_CZ/hud/settings.ron diff --git a/assets/voxygen/i18n/de_DE/hud/hud_settings.ron b/assets/voxygen/i18n/de_DE/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/de_DE/hud/hud_settings.ron rename to assets/voxygen/i18n/de_DE/hud/settings.ron diff --git a/assets/voxygen/i18n/en/hud/hud_settings.ron b/assets/voxygen/i18n/en/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/en/hud/hud_settings.ron rename to assets/voxygen/i18n/en/hud/settings.ron diff --git a/assets/voxygen/i18n/es_ES/hud/hud_settings.ron b/assets/voxygen/i18n/es_ES/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/es_ES/hud/hud_settings.ron rename to assets/voxygen/i18n/es_ES/hud/settings.ron diff --git a/assets/voxygen/i18n/es_LA/hud/hud_settings.ron b/assets/voxygen/i18n/es_LA/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/es_LA/hud/hud_settings.ron rename to assets/voxygen/i18n/es_LA/hud/settings.ron diff --git a/assets/voxygen/i18n/fr_FR/hud/hud_settings.ron b/assets/voxygen/i18n/fr_FR/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/fr_FR/hud/hud_settings.ron rename to assets/voxygen/i18n/fr_FR/hud/settings.ron diff --git a/assets/voxygen/i18n/hu_HU/hud/hud_settings.ron b/assets/voxygen/i18n/hu_HU/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/hu_HU/hud/hud_settings.ron rename to assets/voxygen/i18n/hu_HU/hud/settings.ron diff --git a/assets/voxygen/i18n/it_IT/hud/hud_settings.ron b/assets/voxygen/i18n/it_IT/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/it_IT/hud/hud_settings.ron rename to assets/voxygen/i18n/it_IT/hud/settings.ron diff --git a/assets/voxygen/i18n/ja_JP/hud/hud_settings.ron b/assets/voxygen/i18n/ja_JP/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/ja_JP/hud/hud_settings.ron rename to assets/voxygen/i18n/ja_JP/hud/settings.ron diff --git a/assets/voxygen/i18n/nl_NL/hud/hud_settings.ron b/assets/voxygen/i18n/nl_NL/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/nl_NL/hud/hud_settings.ron rename to assets/voxygen/i18n/nl_NL/hud/settings.ron diff --git a/assets/voxygen/i18n/no_NB/hud/hud_settings.ron b/assets/voxygen/i18n/no_NB/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/no_NB/hud/hud_settings.ron rename to assets/voxygen/i18n/no_NB/hud/settings.ron diff --git a/assets/voxygen/i18n/pl_PL/hud/hud_settings.ron b/assets/voxygen/i18n/pl_PL/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/pl_PL/hud/hud_settings.ron rename to assets/voxygen/i18n/pl_PL/hud/settings.ron diff --git a/assets/voxygen/i18n/pt_BR/hud/hud_settings.ron b/assets/voxygen/i18n/pt_BR/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/pt_BR/hud/hud_settings.ron rename to assets/voxygen/i18n/pt_BR/hud/settings.ron diff --git a/assets/voxygen/i18n/pt_PT/hud/hud_settings.ron b/assets/voxygen/i18n/pt_PT/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/pt_PT/hud/hud_settings.ron rename to assets/voxygen/i18n/pt_PT/hud/settings.ron diff --git a/assets/voxygen/i18n/sv_SE/hud/hud_settings.ron b/assets/voxygen/i18n/sv_SE/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/sv_SE/hud/hud_settings.ron rename to assets/voxygen/i18n/sv_SE/hud/settings.ron diff --git a/assets/voxygen/i18n/tr_TR/hud/hud_settings.ron b/assets/voxygen/i18n/tr_TR/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/tr_TR/hud/hud_settings.ron rename to assets/voxygen/i18n/tr_TR/hud/settings.ron diff --git a/assets/voxygen/i18n/uk_UA/hud/hud_settings.ron b/assets/voxygen/i18n/uk_UA/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/uk_UA/hud/hud_settings.ron rename to assets/voxygen/i18n/uk_UA/hud/settings.ron diff --git a/assets/voxygen/i18n/vi_VI/hud/hud_settings.ron b/assets/voxygen/i18n/vi_VI/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/vi_VI/hud/hud_settings.ron rename to assets/voxygen/i18n/vi_VI/hud/settings.ron diff --git a/assets/voxygen/i18n/zh_CN/hud/hud_settings.ron b/assets/voxygen/i18n/zh_CN/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/zh_CN/hud/hud_settings.ron rename to assets/voxygen/i18n/zh_CN/hud/settings.ron diff --git a/assets/voxygen/i18n/zh_TW/hud/hud_settings.ron b/assets/voxygen/i18n/zh_TW/hud/settings.ron similarity index 100% rename from assets/voxygen/i18n/zh_TW/hud/hud_settings.ron rename to assets/voxygen/i18n/zh_TW/hud/settings.ron From 2d83ef1c0e87d83d70b345930f86aa26ef2b7109 Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 21 Jul 2021 04:58:03 -0400 Subject: [PATCH 039/155] Initial bloom impl --- .../voxygen/shaders/duel-downsample-frag.glsl | 31 +++ .../voxygen/shaders/duel-upsample-frag.glsl | 33 +++ assets/voxygen/shaders/postprocess-frag.glsl | 6 + voxygen/src/lib.rs | 2 + voxygen/src/render/pipelines/bloom.rs | 197 ++++++++++++++++++ voxygen/src/render/pipelines/mod.rs | 1 + voxygen/src/render/pipelines/postprocess.rs | 25 ++- voxygen/src/render/renderer.rs | 85 ++++++-- voxygen/src/render/renderer/drawer.rs | 55 ++++- voxygen/src/render/renderer/locals.rs | 40 +++- .../src/render/renderer/pipeline_creation.rs | 35 +++- voxygen/src/session/mod.rs | 6 + 12 files changed, 478 insertions(+), 38 deletions(-) create mode 100644 assets/voxygen/shaders/duel-downsample-frag.glsl create mode 100644 assets/voxygen/shaders/duel-upsample-frag.glsl create mode 100644 voxygen/src/render/pipelines/bloom.rs diff --git a/assets/voxygen/shaders/duel-downsample-frag.glsl b/assets/voxygen/shaders/duel-downsample-frag.glsl new file mode 100644 index 0000000000..51e9f3129f --- /dev/null +++ b/assets/voxygen/shaders/duel-downsample-frag.glsl @@ -0,0 +1,31 @@ +#version 420 core + +layout(set = 0, binding = 0) +uniform texture2D t_src_color; +layout(set = 0, binding = 1) +uniform sampler s_src_color; +layout(set = 0, binding = 2) +uniform vec2 halfpixel; + +layout(location = 0) in vec2 uv; + +layout(location = 0) out vec4 tgt_color; + +vec4 simplesample(vec2 uv) { + return textureLod(sampler2D(t_src_color, s_src_color), uv, 0); +} + +// From: https://community.arm.com/cfs-file/__key/communityserver-blogs-components-weblogfiles/00-00-00-20-66/siggraph2015_2D00_mmg_2D00_marius_2D00_notes.pdf +vec4 downsample(vec2 uv, vec2 halfpixel) { + vec4 sum = simplesample(uv) * 4.0; + sum += simplesample(uv - halfpixel.xy); + sum += simplesample(uv + halfpixel.xy); + sum += simplesample(uv + vec2(halfpixel.x, -halfpixel.y)); + sum += simplesample(uv - vec2(halfpixel.x, -halfpixel.y)); + + return sum / 8.0; +} + +void main() { + tgt_color = downsample(uv, halfpixel); +} diff --git a/assets/voxygen/shaders/duel-upsample-frag.glsl b/assets/voxygen/shaders/duel-upsample-frag.glsl new file mode 100644 index 0000000000..6224f29927 --- /dev/null +++ b/assets/voxygen/shaders/duel-upsample-frag.glsl @@ -0,0 +1,33 @@ +#version 420 core + +layout(set = 0, binding = 0) +uniform texture2D t_src_color; +layout(set = 0, binding = 1) +uniform sampler s_src_color; +layout(set = 0, binding = 2) +uniform vec2 halfpixel; + +layout(location = 0) in vec2 uv; + +layout(location = 0) out vec4 tgt_color; + +vec4 simplesample(vec2 uv) { + return textureLod(sampler2D(t_src_color, s_src_color), uv, 0); +} + +// From: https://community.arm.com/cfs-file/__key/communityserver-blogs-components-weblogfiles/00-00-00-20-66/siggraph2015_2D00_mmg_2D00_marius_2D00_notes.pdf +vec4 upsample(vec2 uv, vec2 halfpixel) { + vec4 sum = simplesample(uv + vec2(-halfpixel.x * 2.0, 0.0)); + sum += simplesample(uv + vec2(-halfpixel.x, halfpixel.y)) * 2.0; + sum += simplesample(uv + vec2(0.0, halfpixel.y * 2.0)); + sum += simplesample(uv + vec2(halfpixel.x, halfpixel.y)) * 2.0; + sum += simplesample(uv + vec2(halfpixel.x * 2.0, 0.0)); + sum += simplesample(uv + vec2(halfpixel.x, -halfpixel.y)) * 2.0; + sum += simplesample(uv + vec2(0.0, -halfpixel.y * 2.0)); + sum += simplesample(uv + vec2(-halfpixel.x, -halfpixel.y)) * 2.0; + return sum / 12.0; +} + +void main() { + tgt_color = upsample(uv, halfpixel); +} diff --git a/assets/voxygen/shaders/postprocess-frag.glsl b/assets/voxygen/shaders/postprocess-frag.glsl index aeba45f350..947019bc06 100644 --- a/assets/voxygen/shaders/postprocess-frag.glsl +++ b/assets/voxygen/shaders/postprocess-frag.glsl @@ -25,6 +25,8 @@ layout(set = 1, binding = 0) uniform texture2D t_src_color; layout(set = 1, binding = 1) +uniform texture2D t_src_bloom; +layout(set = 1, binding = 2) uniform sampler s_src_color; @@ -182,6 +184,10 @@ void main() { vec4 aa_color = aa_apply(t_src_color, s_src_color, uv * screen_res.xy, screen_res.xy); + // Bloom + vec4 bloom = textureLod(sampler2D(t_src_bloom, s_src_color), uv, 0) * 0.05; + aa_color += bloom; + // Tonemapping float exposure_offset = 1.0; // Adding an in-code offset to gamma and exposure let us have more precise control over the game's look diff --git a/voxygen/src/lib.rs b/voxygen/src/lib.rs index cf4d673534..6404738e50 100644 --- a/voxygen/src/lib.rs +++ b/voxygen/src/lib.rs @@ -4,6 +4,8 @@ #![deny(clippy::clone_on_ref_ptr)] #![feature( array_map, + array_methods, + array_zip, bool_to_option, const_generics, drain_filter, diff --git a/voxygen/src/render/pipelines/bloom.rs b/voxygen/src/render/pipelines/bloom.rs new file mode 100644 index 0000000000..56afdf1838 --- /dev/null +++ b/voxygen/src/render/pipelines/bloom.rs @@ -0,0 +1,197 @@ +use super::super::Consts; +use bytemuck::{Pod, Zeroable}; +use vek::*; + +/// Each level is a multiple of 2 smaller in both dimensions. +/// For a total of 8 passes from the largest to the smallest to the largest +/// again. +pub const NUM_SIZES: usize = 5; + +pub struct BindGroup { + pub(in super::super) bind_group: wgpu::BindGroup, +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Zeroable, Pod)] +pub struct HalfPixel([f32; 2]); + +impl HalfPixel { + pub fn new(source_texture_resolution: Vec2) -> Self { + Self(source_texture_resolution.map(|e| 0.5 / e).into_array()) + } +} + +pub struct BloomLayout { + pub layout: wgpu::BindGroupLayout, +} + +impl BloomLayout { + pub fn new(device: &wgpu::Device) -> Self { + Self { + layout: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: None, + entries: &[ + // Color source + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, + count: None, + }, + // halfpixel + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + ], + }), + } + } + + pub fn bind( + &self, + device: &wgpu::Device, + src_color: &wgpu::TextureView, + sampler: &wgpu::Sampler, + half_pixel: Consts, + ) -> BindGroup { + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(src_color), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(sampler), + }, + wgpu::BindGroupEntry { + binding: 2, + resource: half_pixel.buf().as_entire_binding(), + }, + ], + }); + + BindGroup { bind_group } + } +} + +pub struct BloomPipelines { + //pub downsample_filtered: wgpu::RenderPipeline, + pub downsample: wgpu::RenderPipeline, + pub upsample: wgpu::RenderPipeline, +} + +impl BloomPipelines { + pub fn new( + device: &wgpu::Device, + vs_module: &wgpu::ShaderModule, + //downsample_filtered_fs_module: &wgpu::ShaderModule, + downsample_fs_module: &wgpu::ShaderModule, + upsample_fs_module: &wgpu::ShaderModule, + target_format: wgpu::TextureFormat, + layout: &BloomLayout, + ) -> Self { + common_base::span!(_guard, "BloomPipelines::new"); + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Bloom pipelines layout"), + push_constant_ranges: &[], + bind_group_layouts: &[&layout.layout], + }); + + let downsample_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Bloom downsample pipeline"), + layout: Some(&render_pipeline_layout), + vertex: wgpu::VertexState { + module: vs_module, + entry_point: "main", + buffers: &[], + }, + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: None, + clamp_depth: false, + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState { + count: 1, + mask: !0, + alpha_to_coverage_enabled: false, + }, + fragment: Some(wgpu::FragmentState { + module: downsample_fs_module, + entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: target_format, + blend: None, + write_mask: wgpu::ColorWrite::ALL, + }], + }), + }); + + let upsample_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Bloom upsample pipeline"), + layout: Some(&render_pipeline_layout), + vertex: wgpu::VertexState { + module: vs_module, + entry_point: "main", + buffers: &[], + }, + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: None, + clamp_depth: false, + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState { + count: 1, + mask: !0, + alpha_to_coverage_enabled: false, + }, + fragment: Some(wgpu::FragmentState { + module: upsample_fs_module, + entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: target_format, + blend: None, + write_mask: wgpu::ColorWrite::ALL, + }], + }), + }); + + Self { + downsample: downsample_pipeline, + upsample: upsample_pipeline, + } + } +} diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index 592d1da64d..d4a0ee3c46 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -1,4 +1,5 @@ pub mod blit; +pub mod bloom; pub mod clouds; pub mod debug; pub mod figure; diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 18c982f50c..f990f81dcb 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -39,7 +39,19 @@ impl PostProcessLayout { // src color wgpu::BindGroupLayoutEntry { binding: 0, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + // TODO: make optional + // src bloom + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Float { filterable: true }, view_dimension: wgpu::TextureViewDimension::D2, @@ -49,7 +61,7 @@ impl PostProcessLayout { }, wgpu::BindGroupLayoutEntry { binding: 1, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + visibility: wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { filtering: true, comparison: false, @@ -76,6 +88,7 @@ impl PostProcessLayout { &self, device: &wgpu::Device, src_color: &wgpu::TextureView, + src_bloom: &wgpu::TextureView, sampler: &wgpu::Sampler, locals: &Consts, ) -> BindGroup { @@ -87,6 +100,14 @@ impl PostProcessLayout { binding: 0, resource: wgpu::BindingResource::TextureView(src_color), }, + // TODO: might be cheaper to premix bloom at lower resolution if we are doing + // extensive upscaling + // TODO: if there is no upscaling we can do the last bloom upsampling in post + // process to save a pass and the need for the final full size bloom render target + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(src_bloom), + }, wgpu::BindGroupEntry { binding: 1, resource: wgpu::BindingResource::Sampler(sampler), diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 4b58ca095f..27f411ac41 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -21,8 +21,8 @@ use super::{ mesh::Mesh, model::{DynamicModel, Model}, pipelines::{ - blit, clouds, debug, figure, postprocess, shadow, sprite, terrain, ui, GlobalsBindGroup, - GlobalsLayouts, ShadowTexturesBindGroup, + blit, bloom, clouds, debug, figure, postprocess, shadow, sprite, terrain, ui, + GlobalsBindGroup, GlobalsLayouts, ShadowTexturesBindGroup, }, texture::Texture, AaMode, AddressMode, FilterMode, RenderError, RenderMode, ShadowMapMode, ShadowMode, Vertex, @@ -49,13 +49,14 @@ const QUAD_INDEX_BUFFER_U32_START_VERT_LEN: u32 = 3000; struct Layouts { global: GlobalsLayouts, - clouds: clouds::CloudsLayout, debug: debug::DebugLayout, figure: figure::FigureLayout, - postprocess: postprocess::PostProcessLayout, shadow: shadow::ShadowLayout, sprite: sprite::SpriteLayout, terrain: terrain::TerrainLayout, + clouds: clouds::CloudsLayout, + bloom: bloom::BloomLayout, + postprocess: postprocess::PostProcessLayout, ui: ui::UiLayout, blit: blit::BlitLayout, } @@ -67,6 +68,8 @@ struct Views { tgt_color: wgpu::TextureView, tgt_depth: wgpu::TextureView, + + bloom_tgts: [wgpu::TextureView; bloom::NUM_SIZES], // TODO: rename tgt_color_pp: wgpu::TextureView, } @@ -305,26 +308,28 @@ impl Renderer { let layouts = { let global = GlobalsLayouts::new(&device); - let clouds = clouds::CloudsLayout::new(&device); let debug = debug::DebugLayout::new(&device); let figure = figure::FigureLayout::new(&device); - let postprocess = postprocess::PostProcessLayout::new(&device); let shadow = shadow::ShadowLayout::new(&device); let sprite = sprite::SpriteLayout::new(&device); let terrain = terrain::TerrainLayout::new(&device); + let clouds = clouds::CloudsLayout::new(&device); + let bloom = bloom::BloomLayout::new(&device); + let postprocess = postprocess::PostProcessLayout::new(&device); let ui = ui::UiLayout::new(&device); let blit = blit::BlitLayout::new(&device); Layouts { global, - clouds, debug, figure, - postprocess, shadow, sprite, terrain, + clouds, + bloom, + postprocess, ui, blit, } @@ -350,7 +355,8 @@ impl Renderer { creating, }; - let views = Self::create_rt_views(&device, (dims.width, dims.height), &mode)?; + let (views, bloom_sizes) = + Self::create_rt_views(&device, (dims.width, dims.height), &mode)?; let create_sampler = |filter| { device.create_sampler(&wgpu::SamplerDescriptor { @@ -379,6 +385,8 @@ impl Renderer { let clouds_locals = Self::create_consts_inner(&device, &queue, &[clouds::Locals::default()]); + let bloom_locals = bloom_sizes + .map(|size| Self::create_consts_inner(&device, &queue, &[bloom::HalfPixel::new(size)])); let postprocess_locals = Self::create_consts_inner(&device, &queue, &[postprocess::Locals::default()]); @@ -386,9 +394,18 @@ impl Renderer { &device, &layouts, clouds_locals, + bloom_locals, postprocess_locals, &views.tgt_color, &views.tgt_depth, + [ + &views.tgt_color, + &views.bloom_tgts[1], + &views.bloom_tgts[2], + &views.bloom_tgts[3], + &views.bloom_tgts[4], + ], + &views.bloom_tgts[0], &views.tgt_color_pp, &sampler, &depth_sampler, @@ -546,13 +563,26 @@ impl Renderer { self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc); // Resize other render targets - self.views = Self::create_rt_views(&self.device, (dims.x, dims.y), &self.mode)?; + let (views, bloom_sizes) = + Self::create_rt_views(&self.device, (dims.x, dims.y), &self.mode)?; + self.views = views; + let bloom_locals = + bloom_sizes.map(|size| self.create_consts(&[bloom::HalfPixel::new(size)])); // Rebind views to clouds/postprocess bind groups self.locals.rebind( &self.device, &self.layouts, + bloom_locals, &self.views.tgt_color, &self.views.tgt_depth, + [ + &self.views.tgt_color, + &self.views.bloom_tgts[1], + &self.views.bloom_tgts[2], + &self.views.bloom_tgts[3], + &self.views.bloom_tgts[4], + ], + &self.views.bloom_tgts[0], &self.views.tgt_color_pp, &self.sampler, &self.depth_sampler, @@ -625,7 +655,7 @@ impl Renderer { device: &wgpu::Device, size: (u32, u32), mode: &RenderMode, - ) -> Result { + ) -> Result<(Views, [Vec2; bloom::NUM_SIZES]), RenderError> { let upscaled = Vec2::::from(size) .map(|e| (e as f32 * mode.upscale_mode.factor) as u32) .into_tuple(); @@ -637,7 +667,7 @@ impl Renderer { }; let levels = 1; - let color_view = || { + let color_view = |width, height| { let tex = device.create_texture(&wgpu::TextureDescriptor { label: None, size: wgpu::Extent3d { @@ -665,8 +695,19 @@ impl Renderer { }) }; - let tgt_color_view = color_view(); - let tgt_color_pp_view = color_view(); + let tgt_color_view = color_view(width, height); + let tgt_color_pp_view = color_view(width, height); + + let mut size_shift = 0; + // TODO: skip creating bloom stuff when it is disabled + let bloom_sizes = [(); bloom::NUM_SIZES].map(|()| { + // .max(1) to ensure we don't create zero sized textures + let size = Vec2::new(width, height).map(|e| (e >> size_shift).max(1)); + size_shift += 1; + size + }); + + let bloom_tgt_views = bloom_sizes.map(|size| color_view(size.x, size.y)); let tgt_depth_tex = device.create_texture(&wgpu::TextureDescriptor { label: None, @@ -717,12 +758,16 @@ impl Renderer { array_layer_count: None, }); - Ok(Views { - tgt_color: tgt_color_view, - tgt_depth: tgt_depth_view, - tgt_color_pp: tgt_color_pp_view, - _win_depth: win_depth_view, - }) + Ok(( + Views { + tgt_color: tgt_color_view, + tgt_depth: tgt_depth_view, + bloom_tgts: bloom_tgt_views, + tgt_color_pp: tgt_color_pp_view, + _win_depth: win_depth_view, + }, + bloom_sizes.map(|s| s.map(|e| e as f32)), + )) } /// Get the resolution of the render target. diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 8034a251b5..a7816a95b6 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -4,8 +4,8 @@ use super::{ instances::Instances, model::{DynamicModel, Model, SubModel}, pipelines::{ - blit, clouds, debug, figure, fluid, lod_terrain, particle, shadow, skybox, sprite, - terrain, ui, ColLights, GlobalsBindGroup, ShadowTexturesBindGroup, + blit, bloom, clouds, debug, figure, fluid, lod_terrain, particle, shadow, skybox, + sprite, terrain, ui, ColLights, GlobalsBindGroup, ShadowTexturesBindGroup, }, }, Renderer, ShadowMap, ShadowMapRenderer, @@ -241,6 +241,57 @@ impl<'frame> Drawer<'frame> { }) } + /// To be ran between the second pass and the third pass + /// does nothing if the ingame pipelines are not yet ready + pub fn run_bloom_passes(&mut self) { + let pipelines = match self.borrow.pipelines.all() { + Some(p) => p, + None => return, + }; + + let locals = &self.borrow.locals; + let views = &self.borrow.views; + + let encoder = self.encoder.as_mut().unwrap(); + let device = self.borrow.device; + + let mut run_bloom_pass = |bind, view, label: String, pipeline| { + let mut render_pass = + encoder.scoped_render_pass(&label, device, &wgpu::RenderPassDescriptor { + label: Some(&label), + color_attachments: &[wgpu::RenderPassColorAttachment { + resolve_target: None, + view, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), + store: true, + }, + }], + depth_stencil_attachment: None, + }); + + render_pass.set_bind_group(0, bind, &[]); + render_pass.set_pipeline(pipeline); + render_pass.draw(0..3, 0..1); + }; + + // Downsample filter passes + (0..bloom::NUM_SIZES - 1).for_each(|index| { + let bind = &locals.bloom_binds[index].bind_group; + let view = &views.bloom_tgts[index + 1]; + let label = format!("bloom downsample pass {}", index + 1); + run_bloom_pass(bind, view, label, &pipelines.bloom.downsample); + }); + + // Upsample filter passes + (0..bloom::NUM_SIZES - 1).for_each(|index| { + let bind = &locals.bloom_binds[bloom::NUM_SIZES - 1 - index].bind_group; + let view = &views.bloom_tgts[bloom::NUM_SIZES - 2 - index]; + let label = format!("bloom upsample pass {}", index + 1); + run_bloom_pass(bind, view, label, &pipelines.bloom.upsample); + }); + } + pub fn third_pass(&mut self) -> ThirdPassDrawer { let encoder = self.encoder.as_mut().unwrap(); let device = self.borrow.device; diff --git a/voxygen/src/render/renderer/locals.rs b/voxygen/src/render/renderer/locals.rs index b7c94c5396..8a3c549604 100644 --- a/voxygen/src/render/renderer/locals.rs +++ b/voxygen/src/render/renderer/locals.rs @@ -1,7 +1,7 @@ use super::{ super::{ consts::Consts, - pipelines::{clouds, postprocess}, + pipelines::{bloom, clouds, postprocess}, }, Layouts, }; @@ -10,6 +10,8 @@ pub struct Locals { pub clouds: Consts, pub clouds_bind: clouds::BindGroup, + pub bloom_binds: [bloom::BindGroup; bloom::NUM_SIZES], + pub postprocess: Consts, pub postprocess_bind: postprocess::BindGroup, } @@ -19,9 +21,12 @@ impl Locals { device: &wgpu::Device, layouts: &Layouts, clouds_locals: Consts, + bloom_locals: [Consts; bloom::NUM_SIZES], postprocess_locals: Consts, tgt_color_view: &wgpu::TextureView, tgt_depth_view: &wgpu::TextureView, + bloom_src_views: [&wgpu::TextureView; bloom::NUM_SIZES], + bloom_final_tgt_view: &wgpu::TextureView, tgt_color_pp_view: &wgpu::TextureView, sampler: &wgpu::Sampler, depth_sampler: &wgpu::Sampler, @@ -34,14 +39,22 @@ impl Locals { depth_sampler, &clouds_locals, ); - let postprocess_bind = - layouts - .postprocess - .bind(device, tgt_color_pp_view, sampler, &postprocess_locals); + let bloom_binds = bloom_src_views + .zip(bloom_locals) + .map(|(view, locals)| layouts.bloom.bind(device, view, sampler, locals)); + + let postprocess_bind = layouts.postprocess.bind( + device, + tgt_color_pp_view, + bloom_final_tgt_view, + sampler, + &postprocess_locals, + ); Self { clouds: clouds_locals, clouds_bind, + bloom_binds, postprocess: postprocess_locals, postprocess_bind, } @@ -53,8 +66,11 @@ impl Locals { layouts: &Layouts, // Call when these are recreated and need to be rebound // e.g. resizing + bloom_locals: [Consts; bloom::NUM_SIZES], tgt_color_view: &wgpu::TextureView, tgt_depth_view: &wgpu::TextureView, + bloom_src_views: [&wgpu::TextureView; bloom::NUM_SIZES], + bloom_final_tgt_view: &wgpu::TextureView, tgt_color_pp_view: &wgpu::TextureView, sampler: &wgpu::Sampler, depth_sampler: &wgpu::Sampler, @@ -67,9 +83,15 @@ impl Locals { depth_sampler, &self.clouds, ); - self.postprocess_bind = - layouts - .postprocess - .bind(device, tgt_color_pp_view, sampler, &self.postprocess); + self.bloom_binds = bloom_src_views + .zip(bloom_locals) + .map(|(view, locals)| layouts.bloom.bind(device, view, sampler, locals)); + self.postprocess_bind = layouts.postprocess.bind( + device, + tgt_color_pp_view, + bloom_final_tgt_view, + sampler, + &self.postprocess, + ); } } diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index 1aca7f43f1..36f55b6a60 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -1,8 +1,8 @@ use super::{ super::{ pipelines::{ - blit, clouds, debug, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, - sprite, terrain, ui, + blit, bloom, clouds, debug, figure, fluid, lod_terrain, particle, postprocess, shadow, + skybox, sprite, terrain, ui, }, AaMode, CloudMode, FluidMode, LightingMode, RenderError, RenderMode, ShadowMode, }, @@ -20,6 +20,7 @@ pub struct Pipelines { pub lod_terrain: lod_terrain::LodTerrainPipeline, pub particle: particle::ParticlePipeline, pub clouds: clouds::CloudsPipeline, + pub bloom: bloom::BloomPipelines, pub postprocess: postprocess::PostProcessPipeline, // Consider reenabling at some time // player_shadow: figure::FigurePipeline, @@ -39,6 +40,7 @@ pub struct IngamePipelines { lod_terrain: lod_terrain::LodTerrainPipeline, particle: particle::ParticlePipeline, clouds: clouds::CloudsPipeline, + bloom: bloom::BloomPipelines, postprocess: postprocess::PostProcessPipeline, // Consider reenabling at some time // player_shadow: figure::FigurePipeline, @@ -74,6 +76,7 @@ impl Pipelines { lod_terrain: ingame.lod_terrain, particle: ingame.particle, clouds: ingame.clouds, + bloom: ingame.bloom, postprocess: ingame.postprocess, //player_shadow: ingame.player_shadow, skybox: ingame.skybox, @@ -107,6 +110,8 @@ struct ShaderModules { lod_terrain_frag: wgpu::ShaderModule, clouds_vert: wgpu::ShaderModule, clouds_frag: wgpu::ShaderModule, + duel_downsample_frag: wgpu::ShaderModule, + duel_upsample_frag: wgpu::ShaderModule, postprocess_vert: wgpu::ShaderModule, postprocess_frag: wgpu::ShaderModule, blit_vert: wgpu::ShaderModule, @@ -255,6 +260,8 @@ impl ShaderModules { lod_terrain_frag: create_shader("lod-terrain-frag", ShaderKind::Fragment)?, clouds_vert: create_shader("clouds-vert", ShaderKind::Vertex)?, clouds_frag: create_shader("clouds-frag", ShaderKind::Fragment)?, + duel_downsample_frag: create_shader("duel-downsample-frag", ShaderKind::Fragment)?, + duel_upsample_frag: create_shader("duel-upsample-frag", ShaderKind::Fragment)?, postprocess_vert: create_shader("postprocess-vert", ShaderKind::Vertex)?, postprocess_frag: create_shader("postprocess-frag", ShaderKind::Fragment)?, blit_vert: create_shader("blit-vert", ShaderKind::Vertex)?, @@ -360,7 +367,7 @@ fn create_interface_pipelines( fn create_ingame_and_shadow_pipelines( needs: PipelineNeeds, pool: &rayon::ThreadPool, - tasks: [Task; 13], + tasks: [Task; 14], ) -> IngameAndShadowPipelines { prof_span!(_guard, "create_ingame_and_shadow_pipelines"); @@ -382,6 +389,7 @@ fn create_ingame_and_shadow_pipelines( particle_task, lod_terrain_task, clouds_task, + bloom_task, postprocess_task, // TODO: if these are ever actually optionally done, counting them // as tasks to do beforehand seems kind of iffy since they will just @@ -535,6 +543,22 @@ fn create_ingame_and_shadow_pipelines( "clouds pipeline creation", ) }; + // Pipelines for rendering our bloom + let create_bloom = || { + bloom_task.run( + || { + bloom::BloomPipelines::new( + device, + &shaders.blit_vert, + &shaders.duel_downsample_frag, + &shaders.duel_upsample_frag, + wgpu::TextureFormat::Rgba16Float, + &layouts.bloom, + ) + }, + "bloom pipelines creation", + ) + }; // Pipeline for rendering our post-processing let create_postprocess = || { postprocess_task.run( @@ -622,7 +646,7 @@ fn create_ingame_and_shadow_pipelines( }; let j1 = || pool.join(create_debug, || pool.join(create_skybox, create_figure)); - let j2 = || pool.join(create_terrain, create_fluid); + let j2 = || pool.join(create_terrain, || pool.join(create_fluid, create_bloom)); let j3 = || pool.join(create_sprite, create_particle); let j4 = || pool.join(create_lod_terrain, create_clouds); let j5 = || pool.join(create_postprocess, create_point_shadow); @@ -636,7 +660,7 @@ fn create_ingame_and_shadow_pipelines( // Ignore this let ( ( - ((debug, (skybox, figure)), (terrain, fluid)), + ((debug, (skybox, figure)), (terrain, (fluid, bloom))), ((sprite, particle), (lod_terrain, clouds)), ), ((postprocess, point_shadow), (terrain_directed_shadow, figure_directed_shadow)), @@ -653,6 +677,7 @@ fn create_ingame_and_shadow_pipelines( lod_terrain, particle, clouds, + bloom, postprocess, skybox, sprite, diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 3e7bda0b77..eaf2469d95 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -1483,6 +1483,12 @@ impl PlayState for SessionState { second_pass.draw_clouds(); } } + // Bloom + // TODO: make optional + { + prof_span!("bloom"); + drawer.run_bloom_passes() + } // PostProcess and UI { prof_span!("post-process and ui"); From 74e01f10e341d1419b45e1a2923a3bfe368472cd Mon Sep 17 00:00:00 2001 From: Imbris Date: Wed, 21 Jul 2021 05:39:30 -0400 Subject: [PATCH 040/155] Fixes and extra bloom --- assets/voxygen/shaders/duel-downsample-frag.glsl | 5 ++++- assets/voxygen/shaders/duel-upsample-frag.glsl | 4 +++- assets/voxygen/shaders/postprocess-frag.glsl | 4 ++-- voxygen/src/render/pipelines/postprocess.rs | 12 ++++++------ voxygen/src/render/renderer/shaders.rs | 3 +++ 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/assets/voxygen/shaders/duel-downsample-frag.glsl b/assets/voxygen/shaders/duel-downsample-frag.glsl index 51e9f3129f..fb8cfdf9dc 100644 --- a/assets/voxygen/shaders/duel-downsample-frag.glsl +++ b/assets/voxygen/shaders/duel-downsample-frag.glsl @@ -5,7 +5,10 @@ uniform texture2D t_src_color; layout(set = 0, binding = 1) uniform sampler s_src_color; layout(set = 0, binding = 2) -uniform vec2 halfpixel; +// TODO: refactor in rust +uniform u_locals { + vec2 halfpixel; +}; layout(location = 0) in vec2 uv; diff --git a/assets/voxygen/shaders/duel-upsample-frag.glsl b/assets/voxygen/shaders/duel-upsample-frag.glsl index 6224f29927..10d1b1fdc6 100644 --- a/assets/voxygen/shaders/duel-upsample-frag.glsl +++ b/assets/voxygen/shaders/duel-upsample-frag.glsl @@ -5,7 +5,9 @@ uniform texture2D t_src_color; layout(set = 0, binding = 1) uniform sampler s_src_color; layout(set = 0, binding = 2) -uniform vec2 halfpixel; +uniform u_locals { + vec2 halfpixel; +}; layout(location = 0) in vec2 uv; diff --git a/assets/voxygen/shaders/postprocess-frag.glsl b/assets/voxygen/shaders/postprocess-frag.glsl index 947019bc06..8bcc1f6acd 100644 --- a/assets/voxygen/shaders/postprocess-frag.glsl +++ b/assets/voxygen/shaders/postprocess-frag.glsl @@ -32,7 +32,7 @@ uniform sampler s_src_color; layout(location = 0) in vec2 uv; -layout (std140, set = 1, binding = 2) +layout (std140, set = 1, binding = 3) uniform u_locals { mat4 proj_mat_inv; mat4 view_mat_inv; @@ -185,7 +185,7 @@ void main() { vec4 aa_color = aa_apply(t_src_color, s_src_color, uv * screen_res.xy, screen_res.xy); // Bloom - vec4 bloom = textureLod(sampler2D(t_src_bloom, s_src_color), uv, 0) * 0.05; + vec4 bloom = textureLod(sampler2D(t_src_bloom, s_src_color), uv, 0) * 0.75; aa_color += bloom; // Tonemapping diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index f990f81dcb..4efac906f1 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -50,7 +50,7 @@ impl PostProcessLayout { // TODO: make optional // src bloom wgpu::BindGroupLayoutEntry { - binding: 0, + binding: 1, visibility: wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Float { filterable: true }, @@ -60,7 +60,7 @@ impl PostProcessLayout { count: None, }, wgpu::BindGroupLayoutEntry { - binding: 1, + binding: 2, visibility: wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Sampler { filtering: true, @@ -70,7 +70,7 @@ impl PostProcessLayout { }, // Locals wgpu::BindGroupLayoutEntry { - binding: 2, + binding: 3, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, @@ -105,15 +105,15 @@ impl PostProcessLayout { // TODO: if there is no upscaling we can do the last bloom upsampling in post // process to save a pass and the need for the final full size bloom render target wgpu::BindGroupEntry { - binding: 0, + binding: 1, resource: wgpu::BindingResource::TextureView(src_bloom), }, wgpu::BindGroupEntry { - binding: 1, + binding: 2, resource: wgpu::BindingResource::Sampler(sampler), }, wgpu::BindGroupEntry { - binding: 2, + binding: 3, resource: locals.buf().as_entire_binding(), }, ], diff --git a/voxygen/src/render/renderer/shaders.rs b/voxygen/src/render/renderer/shaders.rs index eb3a148a89..21ac844627 100644 --- a/voxygen/src/render/renderer/shaders.rs +++ b/voxygen/src/render/renderer/shaders.rs @@ -68,6 +68,9 @@ impl assets::Compound for Shaders { "lod-terrain-frag", "clouds-vert", "clouds-frag", + "duel-downsample-frag", + "duel-upsample-frag", + "clouds-frag", "postprocess-vert", "postprocess-frag", "blit-vert", From 29bfee26c063518ec37e5339d3d9ae8010f6e927 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 24 Jul 2021 00:48:26 -0400 Subject: [PATCH 041/155] Add bloom passes in character select screen, use proper source image for bloom after clouds are applied, add blurred and less blurred stages of bloom together (experimental could remove), add filtering downsample pass that is not yet used --- .../dual-downsample-filtered-frag.glsl | 73 ++++++++++ ...le-frag.glsl => dual-downsample-frag.glsl} | 0 ...mple-frag.glsl => dual-upsample-frag.glsl} | 0 assets/voxygen/shaders/postprocess-frag.glsl | 6 +- voxygen/src/menu/char_selection/mod.rs | 5 + voxygen/src/render/pipelines/bloom.rs | 133 +++++++++--------- voxygen/src/render/renderer.rs | 4 +- voxygen/src/render/renderer/drawer.rs | 39 +++-- .../src/render/renderer/pipeline_creation.rs | 18 ++- voxygen/src/render/renderer/shaders.rs | 5 +- 10 files changed, 193 insertions(+), 90 deletions(-) create mode 100644 assets/voxygen/shaders/dual-downsample-filtered-frag.glsl rename assets/voxygen/shaders/{duel-downsample-frag.glsl => dual-downsample-frag.glsl} (100%) rename assets/voxygen/shaders/{duel-upsample-frag.glsl => dual-upsample-frag.glsl} (100%) diff --git a/assets/voxygen/shaders/dual-downsample-filtered-frag.glsl b/assets/voxygen/shaders/dual-downsample-filtered-frag.glsl new file mode 100644 index 0000000000..01235bf798 --- /dev/null +++ b/assets/voxygen/shaders/dual-downsample-filtered-frag.glsl @@ -0,0 +1,73 @@ +#version 420 core + +layout(set = 0, binding = 0) +uniform texture2D t_src_color; +layout(set = 0, binding = 1) +uniform sampler s_src_color; +layout(set = 0, binding = 2) +// TODO: refactor in rust +uniform u_locals { + vec2 halfpixel; +}; + +layout(location = 0) in vec2 uv; + +layout(location = 0) out vec4 tgt_color; + +vec4 simplesample(vec2 uv) { + return textureLod(sampler2D(t_src_color, s_src_color), uv, 0); +} + +// check whether the texel color is higher than threshold, if so output as brightness color +vec4 filterDim(vec4 color) { + // TODO: note where this constant came from if we keep it + float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); + if(brightness > 1.0) + return vec4(color.rgb, 1.0); + else + return vec4(0.0, 0.0, 0.0, 1.0); +} + +vec4 filteredFetch(ivec2 uv) { + return filterDim(simplesample(uv)); +} + +// Derived from: https://community.arm.com/cfs-file/__key/communityserver-blogs-components-weblogfiles/00-00-00-20-66/siggraph2015_2D00_mmg_2D00_marius_2D00_notes.pdf +vec4 filteredDownsample(vec2 uv, vec2 halfpixel) { + vec2 tex_res = 2.0 / halfpixel; + // coordinate of the top left texel + // _ _ _ _ + // |x|_|_|_| + // |_|_|_|_| + // |_|_|_|_| + // |_|_|_|_| + // + ivec2 tl_coord = ivec2(uv * tex_res + vec2(-1.5, 1.5)); + + // Fetch inner square + vec4 sum = filteredFetch(tl_coord + ivec2(1, 1)); + sum += filteredFetch(tl_coord + ivec2(2, 1)); + sum += filteredFetch(tl_coord + ivec2(1, 2)); + sum += filteredFetch(tl_coord + ivec2(2, 2)); + // Weight inner square + sum *= 5.0; + // Fetch border + sum += filteredFetch(tl_coord + ivec2(0, 0)); + sum += filteredFetch(tl_coord + ivec2(1, 0)); + sum += filteredFetch(tl_coord + ivec2(2, 0)); + sum += filteredFetch(tl_coord + ivec2(3, 0)); + sum += filteredFetch(tl_coord + ivec2(0, 1)); + sum += filteredFetch(tl_coord + ivec2(3, 1)); + sum += filteredFetch(tl_coord + ivec2(0, 2)); + sum += filteredFetch(tl_coord + ivec2(3, 2)); + sum += filteredFetch(tl_coord + ivec2(0, 3)); + sum += filteredFetch(tl_coord + ivec2(1, 3)); + sum += filteredFetch(tl_coord + ivec2(2, 3)); + sum += filteredFetch(tl_coord + ivec2(3, 3)); + + return sum / 32.0; +} + +void main() { + tgt_color = filteredDownsample(uv, halfpixel); +} diff --git a/assets/voxygen/shaders/duel-downsample-frag.glsl b/assets/voxygen/shaders/dual-downsample-frag.glsl similarity index 100% rename from assets/voxygen/shaders/duel-downsample-frag.glsl rename to assets/voxygen/shaders/dual-downsample-frag.glsl diff --git a/assets/voxygen/shaders/duel-upsample-frag.glsl b/assets/voxygen/shaders/dual-upsample-frag.glsl similarity index 100% rename from assets/voxygen/shaders/duel-upsample-frag.glsl rename to assets/voxygen/shaders/dual-upsample-frag.glsl diff --git a/assets/voxygen/shaders/postprocess-frag.glsl b/assets/voxygen/shaders/postprocess-frag.glsl index 8bcc1f6acd..6308d73d16 100644 --- a/assets/voxygen/shaders/postprocess-frag.glsl +++ b/assets/voxygen/shaders/postprocess-frag.glsl @@ -185,8 +185,10 @@ void main() { vec4 aa_color = aa_apply(t_src_color, s_src_color, uv * screen_res.xy, screen_res.xy); // Bloom - vec4 bloom = textureLod(sampler2D(t_src_bloom, s_src_color), uv, 0) * 0.75; - aa_color += bloom; + // divide by 4.0 to account for adding blurred layers together + vec4 bloom = textureLod(sampler2D(t_src_bloom, s_src_color), uv, 0) / 4.0; + float bloom_factor = 0.10; + aa_color = aa_color * (1.0 - bloom_factor) + bloom * bloom_factor; // Tonemapping float exposure_offset = 1.0; diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 8941cfc8bf..688d53f465 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -257,6 +257,11 @@ impl PlayState for CharSelectionState { if let Some(mut second_pass) = drawer.second_pass() { second_pass.draw_clouds(); } + // Bloom + // TODO: make optional + { + drawer.run_bloom_passes() + } // PostProcess and UI let mut third_pass = drawer.third_pass(); third_pass.draw_postprocess(); diff --git a/voxygen/src/render/pipelines/bloom.rs b/voxygen/src/render/pipelines/bloom.rs index 56afdf1838..061ef0871f 100644 --- a/voxygen/src/render/pipelines/bloom.rs +++ b/voxygen/src/render/pipelines/bloom.rs @@ -1,7 +1,12 @@ +//! Based on: https://community.arm.com/cfs-file/__key/communityserver-blogs-components-weblogfiles/00-00-00-20-66/siggraph2015_2D00_mmg_2D00_marius_2D00_notes.pdf + use super::super::Consts; use bytemuck::{Pod, Zeroable}; use vek::*; +// TODO: auto-tune the number of passes to maintain roughly constant blur per +// unit of FOV so changing resolution / FOV doesn't change the blur appearance +// significantly /// Each level is a multiple of 2 smaller in both dimensions. /// For a total of 8 passes from the largest to the smallest to the largest /// again. @@ -98,7 +103,7 @@ impl BloomLayout { } pub struct BloomPipelines { - //pub downsample_filtered: wgpu::RenderPipeline, + pub downsample_filtered: wgpu::RenderPipeline, pub downsample: wgpu::RenderPipeline, pub upsample: wgpu::RenderPipeline, } @@ -107,7 +112,7 @@ impl BloomPipelines { pub fn new( device: &wgpu::Device, vs_module: &wgpu::ShaderModule, - //downsample_filtered_fs_module: &wgpu::ShaderModule, + downsample_filtered_fs_module: &wgpu::ShaderModule, downsample_fs_module: &wgpu::ShaderModule, upsample_fs_module: &wgpu::ShaderModule, target_format: wgpu::TextureFormat, @@ -121,75 +126,69 @@ impl BloomPipelines { bind_group_layouts: &[&layout.layout], }); - let downsample_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("Bloom downsample pipeline"), - layout: Some(&render_pipeline_layout), - vertex: wgpu::VertexState { - module: vs_module, - entry_point: "main", - buffers: &[], - }, - primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleList, - strip_index_format: None, - front_face: wgpu::FrontFace::Ccw, - cull_mode: None, - clamp_depth: false, - polygon_mode: wgpu::PolygonMode::Fill, - conservative: false, - }, - depth_stencil: None, - multisample: wgpu::MultisampleState { - count: 1, - mask: !0, - alpha_to_coverage_enabled: false, - }, - fragment: Some(wgpu::FragmentState { - module: downsample_fs_module, - entry_point: "main", - targets: &[wgpu::ColorTargetState { - format: target_format, - blend: None, - write_mask: wgpu::ColorWrite::ALL, - }], - }), - }); + let create_pipeline = |label, fs_module, blend| { + device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some(label), + layout: Some(&render_pipeline_layout), + vertex: wgpu::VertexState { + module: vs_module, + entry_point: "main", + buffers: &[], + }, + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: None, + clamp_depth: false, + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState { + count: 1, + mask: !0, + alpha_to_coverage_enabled: false, + }, + fragment: Some(wgpu::FragmentState { + module: fs_module, + entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: target_format, + blend, + write_mask: wgpu::ColorWrite::ALL, + }], + }), + }) + }; - let upsample_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("Bloom upsample pipeline"), - layout: Some(&render_pipeline_layout), - vertex: wgpu::VertexState { - module: vs_module, - entry_point: "main", - buffers: &[], - }, - primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleList, - strip_index_format: None, - front_face: wgpu::FrontFace::Ccw, - cull_mode: None, - clamp_depth: false, - polygon_mode: wgpu::PolygonMode::Fill, - conservative: false, - }, - depth_stencil: None, - multisample: wgpu::MultisampleState { - count: 1, - mask: !0, - alpha_to_coverage_enabled: false, - }, - fragment: Some(wgpu::FragmentState { - module: upsample_fs_module, - entry_point: "main", - targets: &[wgpu::ColorTargetState { - format: target_format, - blend: None, - write_mask: wgpu::ColorWrite::ALL, - }], + let downsample_filtered_pipeline = create_pipeline( + "Bloom downsample filtered pipeline", + downsample_filtered_fs_module, + None, + ); + let downsample_pipeline = + create_pipeline("Bloom downsample pipeline", downsample_fs_module, None); + let upsample_pipeline = create_pipeline( + "Bloom upsample pipeline", + upsample_fs_module, + Some(wgpu::BlendState { + color: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, + // we don't really use this, but... we need something here + alpha: wgpu::BlendComponent { + src_factor: wgpu::BlendFactor::One, + dst_factor: wgpu::BlendFactor::One, + operation: wgpu::BlendOperation::Add, + }, }), - }); + ); Self { + downsample_filtered: downsample_filtered_pipeline, downsample: downsample_pipeline, upsample: upsample_pipeline, } diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 27f411ac41..9e923adf3d 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -399,7 +399,7 @@ impl Renderer { &views.tgt_color, &views.tgt_depth, [ - &views.tgt_color, + &views.tgt_color_pp, &views.bloom_tgts[1], &views.bloom_tgts[2], &views.bloom_tgts[3], @@ -576,7 +576,7 @@ impl Renderer { &self.views.tgt_color, &self.views.tgt_depth, [ - &self.views.tgt_color, + &self.views.tgt_color_pp, &self.views.bloom_tgts[1], &self.views.bloom_tgts[2], &self.views.bloom_tgts[3], diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index a7816a95b6..f0e2a301bd 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -252,20 +252,18 @@ impl<'frame> Drawer<'frame> { let locals = &self.borrow.locals; let views = &self.borrow.views; - let encoder = self.encoder.as_mut().unwrap(); let device = self.borrow.device; + let mut encoder = self.encoder.as_mut().unwrap().scope("bloom", device); - let mut run_bloom_pass = |bind, view, label: String, pipeline| { + let mut run_bloom_pass = |bind, view, label: String, pipeline, load| { + let pass_label = format!("bloom {} pass", label); let mut render_pass = encoder.scoped_render_pass(&label, device, &wgpu::RenderPassDescriptor { - label: Some(&label), + label: Some(&pass_label), color_attachments: &[wgpu::RenderPassColorAttachment { resolve_target: None, view, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), - store: true, - }, + ops: wgpu::Operations { store: true, load }, }], depth_stencil_attachment: None, }); @@ -279,16 +277,35 @@ impl<'frame> Drawer<'frame> { (0..bloom::NUM_SIZES - 1).for_each(|index| { let bind = &locals.bloom_binds[index].bind_group; let view = &views.bloom_tgts[index + 1]; - let label = format!("bloom downsample pass {}", index + 1); - run_bloom_pass(bind, view, label, &pipelines.bloom.downsample); + let label = format!("downsample {}", index + 1); + run_bloom_pass( + bind, + view, + label, + &pipelines.bloom.downsample, + wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), + ); }); // Upsample filter passes (0..bloom::NUM_SIZES - 1).for_each(|index| { let bind = &locals.bloom_binds[bloom::NUM_SIZES - 1 - index].bind_group; let view = &views.bloom_tgts[bloom::NUM_SIZES - 2 - index]; - let label = format!("bloom upsample pass {}", index + 1); - run_bloom_pass(bind, view, label, &pipelines.bloom.upsample); + let label = format!("upsample {}", index + 1); + run_bloom_pass( + bind, + view, + label, + &pipelines.bloom.upsample, + if index + 2 == bloom::NUM_SIZES { + // Clear for the final image since that is just stuff from the pervious frame. + wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT) + } else { + // Add to less blurred images to get gradient of blur instead of a smudge> + // https://catlikecoding.com/unity/tutorials/advanced-rendering/bloom/ + wgpu::LoadOp::Load + }, + ); }); } diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index 36f55b6a60..10d02ba298 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -110,8 +110,9 @@ struct ShaderModules { lod_terrain_frag: wgpu::ShaderModule, clouds_vert: wgpu::ShaderModule, clouds_frag: wgpu::ShaderModule, - duel_downsample_frag: wgpu::ShaderModule, - duel_upsample_frag: wgpu::ShaderModule, + dual_downsample_filtered_frag: wgpu::ShaderModule, + dual_downsample_frag: wgpu::ShaderModule, + dual_upsample_frag: wgpu::ShaderModule, postprocess_vert: wgpu::ShaderModule, postprocess_frag: wgpu::ShaderModule, blit_vert: wgpu::ShaderModule, @@ -260,8 +261,12 @@ impl ShaderModules { lod_terrain_frag: create_shader("lod-terrain-frag", ShaderKind::Fragment)?, clouds_vert: create_shader("clouds-vert", ShaderKind::Vertex)?, clouds_frag: create_shader("clouds-frag", ShaderKind::Fragment)?, - duel_downsample_frag: create_shader("duel-downsample-frag", ShaderKind::Fragment)?, - duel_upsample_frag: create_shader("duel-upsample-frag", ShaderKind::Fragment)?, + dual_downsample_filtered_frag: create_shader( + "dual-downsample-filtered-frag", + ShaderKind::Fragment, + )?, + dual_downsample_frag: create_shader("dual-downsample-frag", ShaderKind::Fragment)?, + dual_upsample_frag: create_shader("dual-upsample-frag", ShaderKind::Fragment)?, postprocess_vert: create_shader("postprocess-vert", ShaderKind::Vertex)?, postprocess_frag: create_shader("postprocess-frag", ShaderKind::Fragment)?, blit_vert: create_shader("blit-vert", ShaderKind::Vertex)?, @@ -550,8 +555,9 @@ fn create_ingame_and_shadow_pipelines( bloom::BloomPipelines::new( device, &shaders.blit_vert, - &shaders.duel_downsample_frag, - &shaders.duel_upsample_frag, + &shaders.dual_downsample_filtered_frag, + &shaders.dual_downsample_frag, + &shaders.dual_upsample_frag, wgpu::TextureFormat::Rgba16Float, &layouts.bloom, ) diff --git a/voxygen/src/render/renderer/shaders.rs b/voxygen/src/render/renderer/shaders.rs index 21ac844627..2d8f32556c 100644 --- a/voxygen/src/render/renderer/shaders.rs +++ b/voxygen/src/render/renderer/shaders.rs @@ -68,8 +68,9 @@ impl assets::Compound for Shaders { "lod-terrain-frag", "clouds-vert", "clouds-frag", - "duel-downsample-frag", - "duel-upsample-frag", + "dual-downsample-filtered-frag", + "dual-downsample-frag", + "dual-upsample-frag", "clouds-frag", "postprocess-vert", "postprocess-frag", From 7da064fb236ebac904ebfa89c59fa2360326b983 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 24 Jul 2021 01:10:29 -0400 Subject: [PATCH 042/155] Add ability to edit shader to enable filtering dim values for experimentation --- .../dual-downsample-filtered-frag.glsl | 31 ++++++++++++++----- voxygen/src/render/renderer/drawer.rs | 15 +++++++-- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/assets/voxygen/shaders/dual-downsample-filtered-frag.glsl b/assets/voxygen/shaders/dual-downsample-filtered-frag.glsl index 01235bf798..b4a54ec5c6 100644 --- a/assets/voxygen/shaders/dual-downsample-filtered-frag.glsl +++ b/assets/voxygen/shaders/dual-downsample-filtered-frag.glsl @@ -14,27 +14,27 @@ layout(location = 0) in vec2 uv; layout(location = 0) out vec4 tgt_color; -vec4 simplesample(vec2 uv) { - return textureLod(sampler2D(t_src_color, s_src_color), uv, 0); +vec4 simplefetch(ivec2 uv) { + return texelFetch(sampler2D(t_src_color, s_src_color), uv, 0); } // check whether the texel color is higher than threshold, if so output as brightness color vec4 filterDim(vec4 color) { // TODO: note where this constant came from if we keep it float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); - if(brightness > 1.0) + if(brightness > 1.00) return vec4(color.rgb, 1.0); else return vec4(0.0, 0.0, 0.0, 1.0); } vec4 filteredFetch(ivec2 uv) { - return filterDim(simplesample(uv)); + return filterDim(simplefetch(uv)); } // Derived from: https://community.arm.com/cfs-file/__key/communityserver-blogs-components-weblogfiles/00-00-00-20-66/siggraph2015_2D00_mmg_2D00_marius_2D00_notes.pdf vec4 filteredDownsample(vec2 uv, vec2 halfpixel) { - vec2 tex_res = 2.0 / halfpixel; + vec2 tex_res = 0.5 / halfpixel; // coordinate of the top left texel // _ _ _ _ // |x|_|_|_| @@ -68,6 +68,23 @@ vec4 filteredDownsample(vec2 uv, vec2 halfpixel) { return sum / 32.0; } -void main() { - tgt_color = filteredDownsample(uv, halfpixel); +vec4 simplesample(vec2 uv) { + return textureLod(sampler2D(t_src_color, s_src_color), uv, 0); +} + +// From: https://community.arm.com/cfs-file/__key/communityserver-blogs-components-weblogfiles/00-00-00-20-66/siggraph2015_2D00_mmg_2D00_marius_2D00_notes.pdf +vec4 downsample(vec2 uv, vec2 halfpixel) { + vec4 sum = simplesample(uv) * 4.0; + sum += simplesample(uv - halfpixel.xy); + sum += simplesample(uv + halfpixel.xy); + sum += simplesample(uv + vec2(halfpixel.x, -halfpixel.y)); + sum += simplesample(uv - vec2(halfpixel.x, -halfpixel.y)); + + return sum / 8.0; +} + +void main() { + // Uncomment to experiment with filtering out dim pixels + //tgt_color = filteredDownsample(uv, halfpixel); + tgt_color = downsample(uv, halfpixel); } diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index f0e2a301bd..4c5bc22887 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -277,12 +277,23 @@ impl<'frame> Drawer<'frame> { (0..bloom::NUM_SIZES - 1).for_each(|index| { let bind = &locals.bloom_binds[index].bind_group; let view = &views.bloom_tgts[index + 1]; - let label = format!("downsample {}", index + 1); + // Do filtering out of non-bright things during the first downsample + let (label, pipeline) = if index == 0 { + ( + format!("downsample filtered {}", index + 1), + &pipelines.bloom.downsample_filtered, + ) + } else { + ( + format!("downsample {}", index + 1), + &pipelines.bloom.downsample, + ) + }; run_bloom_pass( bind, view, label, - &pipelines.bloom.downsample, + pipeline, wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), ); }); From bfdee903dd58945eef2150a9afe390e0a2f9d759 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 24 Jul 2021 01:40:17 -0400 Subject: [PATCH 043/155] Add some of the changes from zesterer's patch including decreasing figure glow power, increasing glow of some particles, and fixing water normal normalization --- assets/voxygen/shaders/dual-downsample-filtered-frag.glsl | 4 ++-- assets/voxygen/shaders/figure-frag.glsl | 2 +- assets/voxygen/shaders/fluid-frag/shiny.glsl | 2 +- assets/voxygen/shaders/particle-vert.glsl | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/assets/voxygen/shaders/dual-downsample-filtered-frag.glsl b/assets/voxygen/shaders/dual-downsample-filtered-frag.glsl index b4a54ec5c6..1c381e166b 100644 --- a/assets/voxygen/shaders/dual-downsample-filtered-frag.glsl +++ b/assets/voxygen/shaders/dual-downsample-filtered-frag.glsl @@ -18,9 +18,9 @@ vec4 simplefetch(ivec2 uv) { return texelFetch(sampler2D(t_src_color, s_src_color), uv, 0); } -// check whether the texel color is higher than threshold, if so output as brightness color +// Check whether the texel color is higher than threshold, if so output as brightness color vec4 filterDim(vec4 color) { - // TODO: note where this constant came from if we keep it + // constants from: https://learnopengl.com/Advanced-Lighting/Bloom float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); if(brightness > 1.00) return vec4(color.rgb, 1.0); diff --git a/assets/voxygen/shaders/figure-frag.glsl b/assets/voxygen/shaders/figure-frag.glsl index 3b084366da..ebd636fea7 100644 --- a/assets/voxygen/shaders/figure-frag.glsl +++ b/assets/voxygen/shaders/figure-frag.glsl @@ -198,7 +198,7 @@ void main() { // For now, just make glowing material light be the same colour as the surface // TODO: Add a way to control this better outside the shaders if ((material & (1u << 0u)) > 0u) { - emitted_light += 1000 * surf_color; + emitted_light += 10 * surf_color; } float glow_mag = length(model_glow.xyz); diff --git a/assets/voxygen/shaders/fluid-frag/shiny.glsl b/assets/voxygen/shaders/fluid-frag/shiny.glsl index 019e2b0618..67aae23766 100644 --- a/assets/voxygen/shaders/fluid-frag/shiny.glsl +++ b/assets/voxygen/shaders/fluid-frag/shiny.glsl @@ -145,7 +145,7 @@ void main() { nmap = mix(f_norm, normalize(nmap), min(1.0 / pow(frag_dist, 0.75), 1)); //float suppress_waves = max(dot(), 0); - vec3 norm = vec3(0, 0, 1) * nmap.z + b_norm * nmap.x + c_norm * nmap.y; + vec3 norm = normalize(vec3(0, 0, 1) * nmap.z + b_norm * nmap.x + c_norm * nmap.y); // vec3 norm = f_norm; vec3 water_color = (1.0 - MU_WATER) * MU_SCATTER; diff --git a/assets/voxygen/shaders/particle-vert.glsl b/assets/voxygen/shaders/particle-vert.glsl index 8f2a494079..1e29ffb9e4 100644 --- a/assets/voxygen/shaders/particle-vert.glsl +++ b/assets/voxygen/shaders/particle-vert.glsl @@ -355,7 +355,7 @@ void main() { sin(lifetime * 2.0 + rand2) + sin(lifetime * 9.0 + rand5) * 0.3 ), vec3(raise), - vec4(vec3(5, 5, 1.1), 1), + vec4(vec3(10.3, 9, 1.5), 1), spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 5) ); break; @@ -386,7 +386,7 @@ void main() { attr = Attr( spiral_motion(vec3(0, 0, rand3 + 1), spiral_radius, lifetime, abs(rand0), rand1 * 2 * PI) + vec3(0, 0, rand2), vec3(6 * abs(rand4) * (1 - slow_start(2)) * pow(spiral_radius / length(inst_dir), 0.5)), - vec4(vec3(0, 1.7, 0.7), 1), + vec4(vec3(0, 1.7, 0.7) * 3, 1), spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3) ); break; @@ -397,7 +397,7 @@ void main() { attr = Attr( spiral_motion(inst_dir, 0.3 * (floor(2 * rand0 + 0.5) - 0.5) * min(linear_scale(10), 1), lifetime / inst_lifespan, 10.0, inst_time), vec3((1.7 - 0.7 * abs(floor(2 * rand0 - 0.5) + 0.5)) * (1.5 + 0.5 * sin(tick.x * 10 - lifetime * 4))), - vec4(vec3(purple_col, green_col, 0.75 * purple_col), 1), + vec4(vec3(purple_col, green_col, 0.75 * purple_col) * 3, 1), spin_in_axis(inst_dir, tick.z) ); break; From 6cabd74871e090801b63d9d7b4875c3d4d2bf340 Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 29 Jul 2021 02:06:56 -0400 Subject: [PATCH 044/155] Make bloom optional with a config option that is not exposed in the UI (to give artists time to refine bloom before exposing the option) --- .../dual-downsample-filtered-frag.glsl | 2 +- .../voxygen/shaders/dual-downsample-frag.glsl | 2 +- assets/voxygen/shaders/figure-frag.glsl | 2 +- assets/voxygen/shaders/include/constants.glsl | 3 + assets/voxygen/shaders/postprocess-frag.glsl | 14 +- voxygen/src/menu/char_selection/mod.rs | 7 +- voxygen/src/render/mod.rs | 42 +++ voxygen/src/render/pipelines/bloom.rs | 12 +- voxygen/src/render/pipelines/postprocess.rs | 145 +++++---- voxygen/src/render/renderer.rs | 290 +++++++++++------- voxygen/src/render/renderer/drawer.rs | 45 +-- voxygen/src/render/renderer/locals.rs | 39 ++- .../src/render/renderer/pipeline_creation.rs | 140 +++++---- voxygen/src/scene/figure/mod.rs | 2 +- voxygen/src/scene/mod.rs | 4 +- voxygen/src/scene/terrain.rs | 2 +- voxygen/src/session/mod.rs | 3 +- voxygen/src/settings/graphics.rs | 2 + voxygen/src/window.rs | 3 +- 19 files changed, 480 insertions(+), 279 deletions(-) diff --git a/assets/voxygen/shaders/dual-downsample-filtered-frag.glsl b/assets/voxygen/shaders/dual-downsample-filtered-frag.glsl index 1c381e166b..9ce06098ae 100644 --- a/assets/voxygen/shaders/dual-downsample-filtered-frag.glsl +++ b/assets/voxygen/shaders/dual-downsample-filtered-frag.glsl @@ -5,7 +5,7 @@ uniform texture2D t_src_color; layout(set = 0, binding = 1) uniform sampler s_src_color; layout(set = 0, binding = 2) -// TODO: refactor in rust + uniform u_locals { vec2 halfpixel; }; diff --git a/assets/voxygen/shaders/dual-downsample-frag.glsl b/assets/voxygen/shaders/dual-downsample-frag.glsl index fb8cfdf9dc..af9fa46c09 100644 --- a/assets/voxygen/shaders/dual-downsample-frag.glsl +++ b/assets/voxygen/shaders/dual-downsample-frag.glsl @@ -5,7 +5,7 @@ uniform texture2D t_src_color; layout(set = 0, binding = 1) uniform sampler s_src_color; layout(set = 0, binding = 2) -// TODO: refactor in rust + uniform u_locals { vec2 halfpixel; }; diff --git a/assets/voxygen/shaders/figure-frag.glsl b/assets/voxygen/shaders/figure-frag.glsl index ebd636fea7..0c1948023c 100644 --- a/assets/voxygen/shaders/figure-frag.glsl +++ b/assets/voxygen/shaders/figure-frag.glsl @@ -198,7 +198,7 @@ void main() { // For now, just make glowing material light be the same colour as the surface // TODO: Add a way to control this better outside the shaders if ((material & (1u << 0u)) > 0u) { - emitted_light += 10 * surf_color; + emitted_light += 20 * surf_color; } float glow_mag = length(model_glow.xyz); diff --git a/assets/voxygen/shaders/include/constants.glsl b/assets/voxygen/shaders/include/constants.glsl index f1bc2a8aa9..8cd90ca072 100644 --- a/assets/voxygen/shaders/include/constants.glsl +++ b/assets/voxygen/shaders/include/constants.glsl @@ -24,6 +24,9 @@ #define SHADOW_MODE_CHEAP 1 #define SHADOW_MODE_MAP 2 +#define BLOOM_DISABLED 0 +#define BLOOM_ENABLED 1 + /* Unlike the other flags (for now anyway), these are bitmask values */ #define LIGHTING_TYPE_REFLECTION 0x01 #define LIGHTING_TYPE_TRANSMISSION 0x02 diff --git a/assets/voxygen/shaders/postprocess-frag.glsl b/assets/voxygen/shaders/postprocess-frag.glsl index 6308d73d16..57df871073 100644 --- a/assets/voxygen/shaders/postprocess-frag.glsl +++ b/assets/voxygen/shaders/postprocess-frag.glsl @@ -25,19 +25,21 @@ layout(set = 1, binding = 0) uniform texture2D t_src_color; layout(set = 1, binding = 1) -uniform texture2D t_src_bloom; -layout(set = 1, binding = 2) uniform sampler s_src_color; - layout(location = 0) in vec2 uv; -layout (std140, set = 1, binding = 3) +layout (std140, set = 1, binding = 2) uniform u_locals { mat4 proj_mat_inv; mat4 view_mat_inv; }; +#if (BLOOM == BLOOM_ENABLED) +layout(set = 1, binding = 3) +uniform texture2D t_src_bloom; +#endif + layout(location = 0) out vec4 tgt_color; vec3 rgb2hsv(vec3 c) { @@ -185,10 +187,12 @@ void main() { vec4 aa_color = aa_apply(t_src_color, s_src_color, uv * screen_res.xy, screen_res.xy); // Bloom + #if (BLOOM == BLOOM_ENABLED) // divide by 4.0 to account for adding blurred layers together vec4 bloom = textureLod(sampler2D(t_src_bloom, s_src_color), uv, 0) / 4.0; float bloom_factor = 0.10; - aa_color = aa_color * (1.0 - bloom_factor) + bloom * bloom_factor; + aa_color = mix(aa_color, bloom, bloom_factor); + #endif // Tonemapping float exposure_offset = 1.0; diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 688d53f465..a5e96f3c20 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -257,11 +257,8 @@ impl PlayState for CharSelectionState { if let Some(mut second_pass) = drawer.second_pass() { second_pass.draw_clouds(); } - // Bloom - // TODO: make optional - { - drawer.run_bloom_passes() - } + // Bloom (does nothing if bloom is disabled) + drawer.run_bloom_passes(); // PostProcess and UI let mut third_pass = drawer.third_pass(); third_pass.draw_postprocess(); diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index d7598d5508..a2a8786c01 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -274,7 +274,49 @@ pub struct RenderMode { pub fluid: FluidMode, pub lighting: LightingMode, pub shadow: ShadowMode, + pub bloom: bool, + pub upscale_mode: UpscaleMode, pub present_mode: PresentMode, pub profiler_enabled: bool, } + +impl RenderMode { + fn split(self) -> (PipelineModes, OtherModes) { + ( + PipelineModes { + aa: self.aa, + cloud: self.cloud, + fluid: self.fluid, + lighting: self.lighting, + shadow: self.shadow, + bloom: self.bloom, + }, + OtherModes { + upscale_mode: self.upscale_mode, + present_mode: self.present_mode, + profiler_enabled: self.profiler_enabled, + }, + ) + } +} + +/// Render modes that require pipeline recreation (e.g. shader recompilation) +/// when changed +#[derive(PartialEq, Clone, Debug)] +pub struct PipelineModes { + aa: AaMode, + cloud: CloudMode, + fluid: FluidMode, + lighting: LightingMode, + pub shadow: ShadowMode, + bloom: bool, +} + +/// Other render modes that don't effect pipelines +#[derive(PartialEq, Clone, Debug)] +struct OtherModes { + upscale_mode: UpscaleMode, + present_mode: PresentMode, + profiler_enabled: bool, +} diff --git a/voxygen/src/render/pipelines/bloom.rs b/voxygen/src/render/pipelines/bloom.rs index 061ef0871f..64463278e2 100644 --- a/voxygen/src/render/pipelines/bloom.rs +++ b/voxygen/src/render/pipelines/bloom.rs @@ -18,11 +18,15 @@ pub struct BindGroup { #[repr(C)] #[derive(Copy, Clone, Debug, Zeroable, Pod)] -pub struct HalfPixel([f32; 2]); +pub struct Locals { + halfpixel: [f32; 2], +} -impl HalfPixel { +impl Locals { pub fn new(source_texture_resolution: Vec2) -> Self { - Self(source_texture_resolution.map(|e| 0.5 / e).into_array()) + Self { + halfpixel: source_texture_resolution.map(|e| 0.5 / e).into_array(), + } } } @@ -77,7 +81,7 @@ impl BloomLayout { device: &wgpu::Device, src_color: &wgpu::TextureView, sampler: &wgpu::Sampler, - half_pixel: Consts, + half_pixel: Consts, ) -> BindGroup { let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: None, diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index 4efac906f1..ccb83b52c1 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -1,4 +1,4 @@ -use super::super::{Consts, GlobalsLayouts}; +use super::super::{Consts, GlobalsLayouts, PipelineModes}; use bytemuck::{Pod, Zeroable}; use vek::*; @@ -31,55 +31,61 @@ pub struct PostProcessLayout { } impl PostProcessLayout { - pub fn new(device: &wgpu::Device) -> Self { + pub fn new(device: &wgpu::Device, pipeline_modes: &PipelineModes) -> Self { + let mut bind_entries = vec![ + // src color + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Sampler { + filtering: true, + comparison: false, + }, + count: None, + }, + // Locals + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + ]; + + if pipeline_modes.bloom { + bind_entries.push( + // src bloom + wgpu::BindGroupLayoutEntry { + binding: 3, + visibility: wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::D2, + multisampled: false, + }, + count: None, + }, + ); + } + Self { layout: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { label: None, - entries: &[ - // src color - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - // TODO: make optional - // src bloom - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::D2, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 2, - visibility: wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Sampler { - filtering: true, - comparison: false, - }, - count: None, - }, - // Locals - wgpu::BindGroupLayoutEntry { - binding: 3, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: false, - min_binding_size: None, - }, - count: None, - }, - ], + entries: &bind_entries, }), } } @@ -88,35 +94,42 @@ impl PostProcessLayout { &self, device: &wgpu::Device, src_color: &wgpu::TextureView, - src_bloom: &wgpu::TextureView, + src_bloom: Option<&wgpu::TextureView>, sampler: &wgpu::Sampler, locals: &Consts, ) -> BindGroup { - let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - label: None, - layout: &self.layout, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView(src_color), - }, + let mut entries = vec![ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(src_color), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(sampler), + }, + wgpu::BindGroupEntry { + binding: 2, + resource: locals.buf().as_entire_binding(), + }, + ]; + // Optional bloom source + if let Some(src_bloom) = src_bloom { + entries.push( // TODO: might be cheaper to premix bloom at lower resolution if we are doing // extensive upscaling // TODO: if there is no upscaling we can do the last bloom upsampling in post // process to save a pass and the need for the final full size bloom render target wgpu::BindGroupEntry { - binding: 1, + binding: 3, resource: wgpu::BindingResource::TextureView(src_bloom), }, - wgpu::BindGroupEntry { - binding: 2, - resource: wgpu::BindingResource::Sampler(sampler), - }, - wgpu::BindGroupEntry { - binding: 3, - resource: locals.buf().as_entire_binding(), - }, - ], + ); + } + + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: None, + layout: &self.layout, + entries: &entries, }); BindGroup { bind_group } diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 9e923adf3d..a7f2f78d48 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -25,7 +25,8 @@ use super::{ GlobalsBindGroup, GlobalsLayouts, ShadowTexturesBindGroup, }, texture::Texture, - AaMode, AddressMode, FilterMode, RenderError, RenderMode, ShadowMapMode, ShadowMode, Vertex, + AaMode, AddressMode, FilterMode, OtherModes, PipelineModes, RenderError, RenderMode, + ShadowMapMode, ShadowMode, Vertex, }; use common::assets::{self, AssetExt, AssetHandle}; use common_base::span; @@ -45,8 +46,9 @@ pub type ColLightInfo = (Vec<[u8; 4]>, Vec2); const QUAD_INDEX_BUFFER_U16_START_VERT_LEN: u16 = 3000; const QUAD_INDEX_BUFFER_U32_START_VERT_LEN: u32 = 3000; -/// A type that stores all the layouts associated with this renderer. -struct Layouts { +/// A type that stores all the layouts associated with this renderer that never +/// change when the RenderMode is modified. +struct ImmutableLayouts { global: GlobalsLayouts, debug: debug::DebugLayout, @@ -56,11 +58,23 @@ struct Layouts { terrain: terrain::TerrainLayout, clouds: clouds::CloudsLayout, bloom: bloom::BloomLayout, - postprocess: postprocess::PostProcessLayout, ui: ui::UiLayout, blit: blit::BlitLayout, } +/// A type that stores all the layouts associated with this renderer. +struct Layouts { + immutable: Arc, + + postprocess: Arc, +} + +impl core::ops::Deref for Layouts { + type Target = ImmutableLayouts; + + fn deref(&self) -> &Self::Target { &self.immutable } +} + /// Render target views struct Views { // NOTE: unused for now, maybe... we will want it for something @@ -69,7 +83,7 @@ struct Views { tgt_color: wgpu::TextureView, tgt_depth: wgpu::TextureView, - bloom_tgts: [wgpu::TextureView; bloom::NUM_SIZES], + bloom_tgts: Option<[wgpu::TextureView; bloom::NUM_SIZES]>, // TODO: rename tgt_color_pp: wgpu::TextureView, } @@ -84,6 +98,7 @@ struct Shadow { /// 1. Only interface pipelines created /// 2. All of the pipelines have been created #[allow(clippy::large_enum_variant)] // They are both pretty large +#[allow(clippy::type_complexity)] enum State { // NOTE: this is used as a transient placeholder for moving things out of State temporarily Nothing, @@ -96,7 +111,19 @@ enum State { Complete { pipelines: Pipelines, shadow: Shadow, - recreating: Option>>, + recreating: Option< + PipelineCreation< + Result< + ( + Pipelines, + ShadowPipelines, + PipelineModes, + Arc, + ), + RenderError, + >, + >, + >, }, } @@ -115,11 +142,11 @@ pub struct Renderer { depth_sampler: wgpu::Sampler, state: State, - // true if there is a pending need to recreate the pipelines (e.g. RenderMode change or shader + // Some if there is a pending need to recreate the pipelines (e.g. RenderMode change or shader // hotloading) - recreation_pending: bool, + recreation_pending: Option, - layouts: Arc, + layouts: Layouts, // Note: we keep these here since their bind groups need to be updated if we resize the // color/depth textures locals: Locals, @@ -131,7 +158,8 @@ pub struct Renderer { shaders: AssetHandle, - mode: RenderMode, + pipeline_modes: PipelineModes, + other_modes: OtherModes, resolution: Vec2, // If this is Some then a screenshot will be taken and passed to the handler here @@ -155,7 +183,8 @@ pub struct Renderer { impl Renderer { /// Create a new `Renderer` from a variety of backend-specific components /// and the window targets. - pub fn new(window: &winit::window::Window, mut mode: RenderMode) -> Result { + pub fn new(window: &winit::window::Window, mode: RenderMode) -> Result { + let (pipeline_modes, mut other_modes) = mode.split(); // Enable seamless cubemaps globally, where available--they are essentially a // strict improvement on regular cube maps. // @@ -288,7 +317,7 @@ impl Renderer { format, width: dims.width, height: dims.height, - present_mode: mode.present_mode.into(), + present_mode: other_modes.present_mode.into(), }; let swap_chain = device.create_swap_chain(&surface, &sc_desc); @@ -296,7 +325,7 @@ impl Renderer { let shadow_views = ShadowMap::create_shadow_views( &device, (dims.width, dims.height), - &ShadowMapMode::try_from(mode.shadow).unwrap_or_default(), + &ShadowMapMode::try_from(pipeline_modes.shadow).unwrap_or_default(), ) .map_err(|err| { warn!("Could not create shadow map views: {:?}", err); @@ -315,11 +344,14 @@ impl Renderer { let terrain = terrain::TerrainLayout::new(&device); let clouds = clouds::CloudsLayout::new(&device); let bloom = bloom::BloomLayout::new(&device); - let postprocess = postprocess::PostProcessLayout::new(&device); + let postprocess = Arc::new(postprocess::PostProcessLayout::new( + &device, + &pipeline_modes, + )); let ui = ui::UiLayout::new(&device); let blit = blit::BlitLayout::new(&device); - Layouts { + let immutable = Arc::new(ImmutableLayouts { global, debug, @@ -329,22 +361,27 @@ impl Renderer { terrain, clouds, bloom, - postprocess, ui, blit, + }); + + Layouts { + immutable, + postprocess, } }; - // Arcify the device and layouts + // Arcify the device let device = Arc::new(device); - let layouts = Arc::new(layouts); let (interface_pipelines, creating) = pipeline_creation::initial_create_pipelines( - // TODO: combine Arcs? Arc::clone(&device), - Arc::clone(&layouts), + Layouts { + immutable: Arc::clone(&layouts.immutable), + postprocess: Arc::clone(&layouts.postprocess), + }, shaders.read().clone(), - mode.clone(), + pipeline_modes.clone(), sc_desc.clone(), // Note: cheap clone shadow_views.is_some(), )?; @@ -355,8 +392,12 @@ impl Renderer { creating, }; - let (views, bloom_sizes) = - Self::create_rt_views(&device, (dims.width, dims.height), &mode)?; + let (views, bloom_sizes) = Self::create_rt_views( + &device, + (dims.width, dims.height), + &pipeline_modes, + &other_modes, + ); let create_sampler = |filter| { device.create_sampler(&wgpu::SamplerDescriptor { @@ -385,8 +426,6 @@ impl Renderer { let clouds_locals = Self::create_consts_inner(&device, &queue, &[clouds::Locals::default()]); - let bloom_locals = bloom_sizes - .map(|size| Self::create_consts_inner(&device, &queue, &[bloom::HalfPixel::new(size)])); let postprocess_locals = Self::create_consts_inner(&device, &queue, &[postprocess::Locals::default()]); @@ -394,18 +433,16 @@ impl Renderer { &device, &layouts, clouds_locals, - bloom_locals, postprocess_locals, &views.tgt_color, &views.tgt_depth, - [ - &views.tgt_color_pp, - &views.bloom_tgts[1], - &views.bloom_tgts[2], - &views.bloom_tgts[3], - &views.bloom_tgts[4], - ], - &views.bloom_tgts[0], + views.bloom_tgts.as_ref().map(|tgts| locals::BloomParams { + locals: bloom_sizes.map(|size| { + Self::create_consts_inner(&device, &queue, &[bloom::Locals::new(size)]) + }), + src_views: [&views.tgt_color_pp, &tgts[1], &tgts[2], &tgts[3], &tgts[4]], + final_tgt_view: &tgts[0], + }), &views.tgt_color_pp, &sampler, &depth_sampler, @@ -416,9 +453,9 @@ impl Renderer { let quad_index_buffer_u32 = create_quad_index_buffer_u32(&device, QUAD_INDEX_BUFFER_U32_START_VERT_LEN as usize); let mut profiler = wgpu_profiler::GpuProfiler::new(4, queue.get_timestamp_period()); - mode.profiler_enabled &= profiler_features_enabled; - profiler.enable_timer = mode.profiler_enabled; - profiler.enable_debug_marker = mode.profiler_enabled; + other_modes.profiler_enabled &= profiler_features_enabled; + profiler.enable_timer = other_modes.profiler_enabled; + profiler.enable_debug_marker = other_modes.profiler_enabled; #[cfg(feature = "egui-ui")] let egui_renderpass = @@ -432,7 +469,7 @@ impl Renderer { sc_desc, state, - recreation_pending: false, + recreation_pending: None, layouts, locals, @@ -447,7 +484,8 @@ impl Renderer { shaders, - mode, + pipeline_modes, + other_modes, resolution: Vec2::new(dims.width, dims.height), take_screenshot: None, @@ -492,37 +530,47 @@ impl Renderer { /// Change the render mode. pub fn set_render_mode(&mut self, mode: RenderMode) -> Result<(), RenderError> { - // TODO: are there actually any issues with the current mode not matching the - // pipelines (since we could previously have inconsistencies from - // pipelines failing to build due to shader editing)? - // TODO: FIXME: defer mode changing until pipelines are rebuilt to prevent - // incompatibilities as pipelines are now rebuilt in a deferred mannder in the - // background TODO: consider separating changes that don't require - // rebuilding pipelines - self.mode = mode; - self.sc_desc.present_mode = self.mode.present_mode.into(); + let (pipeline_modes, other_modes) = mode.split(); - // Only enable profiling if the wgpu features are enabled - self.mode.profiler_enabled &= self.profiler_features_enabled; - // Enable/disable profiler - if !self.mode.profiler_enabled { - // Clear the times if disabled - core::mem::take(&mut self.profile_times); + if self.other_modes != other_modes { + self.other_modes = other_modes; + + // Update present mode in swap chain descriptor + self.sc_desc.present_mode = self.other_modes.present_mode.into(); + + // Only enable profiling if the wgpu features are enabled + self.other_modes.profiler_enabled &= self.profiler_features_enabled; + // Enable/disable profiler + if !self.other_modes.profiler_enabled { + // Clear the times if disabled + core::mem::take(&mut self.profile_times); + } + self.profiler.enable_timer = self.other_modes.profiler_enabled; + self.profiler.enable_debug_marker = self.other_modes.profiler_enabled; + + // Recreate render target + self.on_resize(self.resolution); } - self.profiler.enable_timer = self.mode.profiler_enabled; - self.profiler.enable_debug_marker = self.mode.profiler_enabled; - // Recreate render target - self.on_resize(self.resolution)?; - - // Recreate pipelines with the new AA mode - self.recreate_pipelines(); + // We can't cancel the pending recreation even if the new settings are equal + // to the current ones becuase the recreation could be triggered by something + // else like shader hotloading + if dbg!(self.pipeline_modes != pipeline_modes) + || dbg!( + self.recreation_pending + .as_ref() + .map_or(false, |modes| modes != &pipeline_modes) + ) + { + // Recreate pipelines with new modes + self.recreate_pipelines(pipeline_modes); + } Ok(()) } - /// Get the render mode. - pub fn render_mode(&self) -> &RenderMode { &self.mode } + /// Get the pipelines mode. + pub fn pipeline_modes(&self) -> &PipelineModes { &self.pipeline_modes } /// Get the current profiling times /// Nested timings immediately follow their parent @@ -552,7 +600,7 @@ impl Renderer { } /// Resize internal render targets to match window render target dimensions. - pub fn on_resize(&mut self, dims: Vec2) -> Result<(), RenderError> { + pub fn on_resize(&mut self, dims: Vec2) { // Avoid panics when creating texture with w,h of 0,0. if dims.x != 0 && dims.y != 0 { self.is_minimized = false; @@ -563,26 +611,36 @@ impl Renderer { self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc); // Resize other render targets - let (views, bloom_sizes) = - Self::create_rt_views(&self.device, (dims.x, dims.y), &self.mode)?; + let (views, bloom_sizes) = Self::create_rt_views( + &self.device, + (dims.x, dims.y), + &self.pipeline_modes, + &self.other_modes, + ); self.views = views; - let bloom_locals = - bloom_sizes.map(|size| self.create_consts(&[bloom::HalfPixel::new(size)])); - // Rebind views to clouds/postprocess bind groups + + // appease borrow check + let device = &self.device; + let queue = &self.queue; + let views = &self.views; + let bloom_params = self + .views + .bloom_tgts + .as_ref() + .map(|tgts| locals::BloomParams { + locals: bloom_sizes.map(|size| { + Self::create_consts_inner(device, queue, &[bloom::Locals::new(size)]) + }), + src_views: [&views.tgt_color_pp, &tgts[1], &tgts[2], &tgts[3], &tgts[4]], + final_tgt_view: &tgts[0], + }); + self.locals.rebind( &self.device, &self.layouts, - bloom_locals, &self.views.tgt_color, &self.views.tgt_depth, - [ - &self.views.tgt_color_pp, - &self.views.bloom_tgts[1], - &self.views.bloom_tgts[2], - &self.views.bloom_tgts[3], - &self.views.bloom_tgts[4], - ], - &self.views.bloom_tgts[0], + bloom_params, &self.views.tgt_color_pp, &self.sampler, &self.depth_sampler, @@ -606,7 +664,7 @@ impl Renderer { }; if let (Some((point_depth, directed_depth)), ShadowMode::Map(mode)) = - (shadow_views, self.mode.shadow) + (shadow_views, self.pipeline_modes.shadow) { match ShadowMap::create_shadow_views(&self.device, (dims.x, dims.y), &mode) { Ok((new_point_depth, new_directed_depth)) => { @@ -638,8 +696,6 @@ impl Renderer { } else { self.is_minimized = true; } - - Ok(()) } pub fn maintain(&self) { @@ -654,12 +710,13 @@ impl Renderer { fn create_rt_views( device: &wgpu::Device, size: (u32, u32), - mode: &RenderMode, - ) -> Result<(Views, [Vec2; bloom::NUM_SIZES]), RenderError> { + pipeline_modes: &PipelineModes, + other_modes: &OtherModes, + ) -> (Views, [Vec2; bloom::NUM_SIZES]) { let upscaled = Vec2::::from(size) - .map(|e| (e as f32 * mode.upscale_mode.factor) as u32) + .map(|e| (e as f32 * other_modes.upscale_mode.factor) as u32) .into_tuple(); - let (width, height, sample_count) = match mode.aa { + let (width, height, sample_count) = match pipeline_modes.aa { AaMode::None | AaMode::Fxaa => (upscaled.0, upscaled.1, 1), AaMode::MsaaX4 => (upscaled.0, upscaled.1, 4), AaMode::MsaaX8 => (upscaled.0, upscaled.1, 8), @@ -707,7 +764,9 @@ impl Renderer { size }); - let bloom_tgt_views = bloom_sizes.map(|size| color_view(size.x, size.y)); + let bloom_tgt_views = pipeline_modes + .bloom + .then(|| bloom_sizes.map(|size| color_view(size.x, size.y))); let tgt_depth_tex = device.create_texture(&wgpu::TextureDescriptor { label: None, @@ -758,7 +817,7 @@ impl Renderer { array_layer_count: None, }); - Ok(( + ( Views { tgt_color: tgt_color_view, tgt_depth: tgt_depth_view, @@ -767,7 +826,7 @@ impl Renderer { _win_depth: win_depth_view, }, bloom_sizes.map(|s| s.map(|e| e as f32)), - )) + ) } /// Get the resolution of the render target. @@ -841,7 +900,7 @@ impl Renderer { } // Try to get the latest profiling results - if self.mode.profiler_enabled { + if self.other_modes.profiler_enabled { // Note: this lags a few frames behind if let Some(profile_times) = self.profiler.process_finished_frame() { self.profile_times = profile_times; @@ -851,6 +910,10 @@ impl Renderer { // Handle polling background pipeline creation/recreation // Temporarily set to nothing and then replace in the statement below let state = core::mem::replace(&mut self.state, State::Nothing); + // Indicator for if pipeline recreation finished and we need to recreate bind + // groups / render targets (handling defered so that State will be valid + // when calling Self::on_resize) + let mut trigger_on_resize = false; // If still creating initial pipelines, check if complete self.state = if let State::Interface { pipelines: interface, @@ -906,7 +969,7 @@ impl Renderer { } = state { match recreating.try_complete() { - Ok(Ok((pipelines, shadow_pipelines))) => { + Ok(Ok((pipelines, shadow_pipelines, new_pipeline_modes, postprocess_layout))) => { if let ( Some(point_pipeline), Some(terrain_directed_pipeline), @@ -922,6 +985,14 @@ impl Renderer { shadow_map.terrain_directed_pipeline = terrain_directed_pipeline; shadow_map.figure_directed_pipeline = figure_directed_pipeline; } + + self.pipeline_modes = new_pipeline_modes; + self.layouts.postprocess = postprocess_layout; + // TODO: we have the potential to skip recreating bindings / render targets on + // pipeline recreation trigged by shader reloading (would need to ensure new + // postprocess_layout is not created...) + trigger_on_resize = true; + State::Complete { pipelines, shadow, @@ -947,17 +1018,26 @@ impl Renderer { state }; + // Call on_resize to recreate render targets and their bind groups if the + // pipelines were recreated with a new postprocess layout and or changes in the + // render modes + if trigger_on_resize { + self.on_resize(self.resolution); + } + // If the shaders files were changed attempt to recreate the shaders if self.shaders.reloaded() { - self.recreate_pipelines(); + self.recreate_pipelines(self.pipeline_modes.clone()); } // Or if we have a recreation pending - if self.recreation_pending - && matches!(&self.state, State::Complete { recreating, .. } if recreating.is_none()) - { - self.recreation_pending = false; - self.recreate_pipelines(); + if matches!(&self.state, State::Complete { + recreating: None, + .. + }) { + if let Some(new_pipeline_modes) = self.recreation_pending.take() { + self.recreate_pipelines(new_pipeline_modes); + } } let tex = match self.swap_chain.get_current_frame() { @@ -965,7 +1045,8 @@ impl Renderer { // If lost recreate the swap chain Err(err @ wgpu::SwapChainError::Lost) => { warn!("{}. Recreating swap chain. A frame will be missed", err); - return self.on_resize(self.resolution).map(|()| None); + self.on_resize(self.resolution); + return Ok(None); }, Err(wgpu::SwapChainError::Timeout) => { // This will probably be resolved on the next frame @@ -990,21 +1071,24 @@ impl Renderer { } /// Recreate the pipelines - fn recreate_pipelines(&mut self) { + fn recreate_pipelines(&mut self, pipeline_modes: PipelineModes) { match &mut self.state { State::Complete { recreating, .. } if recreating.is_some() => { // Defer recreation so that we are not building multiple sets of pipelines in // the background at once - self.recreation_pending = true; + self.recreation_pending = Some(pipeline_modes); }, State::Complete { recreating, shadow, .. } => { *recreating = Some(pipeline_creation::recreate_pipelines( Arc::clone(&self.device), - Arc::clone(&self.layouts), + Arc::clone(&self.layouts.immutable), self.shaders.read().clone(), - self.mode.clone(), + self.pipeline_modes.clone(), + // NOTE: if present_mode starts to be used to configure pipelines then it needs + // to become a part of the pipeline modes (note here since the present mode is + // accessible through the swap chain descriptor) self.sc_desc.clone(), // Note: cheap clone shadow.map.is_enabled(), )); @@ -1012,7 +1096,7 @@ impl Renderer { State::Interface { .. } => { // Defer recreation so that we are not building multiple sets of pipelines in // the background at once - self.recreation_pending = true; + self.recreation_pending = Some(pipeline_modes); }, State::Nothing => {}, } @@ -1229,7 +1313,7 @@ impl Renderer { // Queue screenshot self.take_screenshot = Some(Box::new(screenshot_handler)); // Take profiler snapshot - if self.mode.profiler_enabled { + if self.other_modes.profiler_enabled { let file_name = format!( "frame-trace_{}.json", std::time::SystemTime::now() diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 4c5bc22887..16f67b76f2 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -61,7 +61,7 @@ struct RendererBorrow<'frame> { pipelines: Pipelines<'frame>, locals: &'frame super::locals::Locals, views: &'frame super::Views, - mode: &'frame super::super::RenderMode, + pipeline_modes: &'frame super::super::PipelineModes, quad_index_buffer_u16: &'frame Buffer, quad_index_buffer_u32: &'frame Buffer, #[cfg(feature = "egui-ui")] @@ -112,7 +112,7 @@ impl<'frame> Drawer<'frame> { pipelines, locals: &renderer.locals, views: &renderer.views, - mode: &renderer.mode, + pipeline_modes: &renderer.pipeline_modes, quad_index_buffer_u16: &renderer.quad_index_buffer_u16, quad_index_buffer_u32: &renderer.quad_index_buffer_u32, #[cfg(feature = "egui-ui")] @@ -131,13 +131,13 @@ impl<'frame> Drawer<'frame> { } } - /// Get the render mode. - pub fn render_mode(&self) -> &super::super::RenderMode { self.borrow.mode } + /// Get the pipeline modes. + pub fn pipeline_modes(&self) -> &super::super::PipelineModes { self.borrow.pipeline_modes } /// Returns None if the shadow renderer is not enabled at some level or the /// pipelines are not available yet pub fn shadow_pass(&mut self) -> Option { - if !self.borrow.mode.shadow.is_map() { + if !self.borrow.pipeline_modes.shadow.is_map() { return None; } @@ -243,15 +243,24 @@ impl<'frame> Drawer<'frame> { /// To be ran between the second pass and the third pass /// does nothing if the ingame pipelines are not yet ready + /// does nothing if bloom is disabled pub fn run_bloom_passes(&mut self) { - let pipelines = match self.borrow.pipelines.all() { - Some(p) => p, - None => return, - }; - let locals = &self.borrow.locals; let views = &self.borrow.views; + let bloom_pipelines = match self.borrow.pipelines.all() { + Some(super::Pipelines { bloom: Some(p), .. }) => p, + _ => return, + }; + + // TODO: consider consolidating optional bloom bind groups and optional pipeline + // into a single structure? + let (bloom_tgts, bloom_binds) = + match views.bloom_tgts.as_ref().zip(locals.bloom_binds.as_ref()) { + Some((t, b)) => (t, b), + None => return, + }; + let device = self.borrow.device; let mut encoder = self.encoder.as_mut().unwrap().scope("bloom", device); @@ -275,18 +284,18 @@ impl<'frame> Drawer<'frame> { // Downsample filter passes (0..bloom::NUM_SIZES - 1).for_each(|index| { - let bind = &locals.bloom_binds[index].bind_group; - let view = &views.bloom_tgts[index + 1]; + let bind = &bloom_binds[index].bind_group; + let view = &bloom_tgts[index + 1]; // Do filtering out of non-bright things during the first downsample let (label, pipeline) = if index == 0 { ( format!("downsample filtered {}", index + 1), - &pipelines.bloom.downsample_filtered, + &bloom_pipelines.downsample_filtered, ) } else { ( format!("downsample {}", index + 1), - &pipelines.bloom.downsample, + &bloom_pipelines.downsample, ) }; run_bloom_pass( @@ -300,14 +309,14 @@ impl<'frame> Drawer<'frame> { // Upsample filter passes (0..bloom::NUM_SIZES - 1).for_each(|index| { - let bind = &locals.bloom_binds[bloom::NUM_SIZES - 1 - index].bind_group; - let view = &views.bloom_tgts[bloom::NUM_SIZES - 2 - index]; + let bind = &bloom_binds[bloom::NUM_SIZES - 1 - index].bind_group; + let view = &bloom_tgts[bloom::NUM_SIZES - 2 - index]; let label = format!("upsample {}", index + 1); run_bloom_pass( bind, view, label, - &pipelines.bloom.upsample, + &bloom_pipelines.upsample, if index + 2 == bloom::NUM_SIZES { // Clear for the final image since that is just stuff from the pervious frame. wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT) @@ -400,7 +409,7 @@ impl<'frame> Drawer<'frame> { chunks: impl Clone + Iterator, &'data terrain::BoundLocals)>, ) { - if !self.borrow.mode.shadow.is_map() { + if !self.borrow.pipeline_modes.shadow.is_map() { return; } diff --git a/voxygen/src/render/renderer/locals.rs b/voxygen/src/render/renderer/locals.rs index 8a3c549604..fb3b0301ac 100644 --- a/voxygen/src/render/renderer/locals.rs +++ b/voxygen/src/render/renderer/locals.rs @@ -6,11 +6,17 @@ use super::{ Layouts, }; +pub struct BloomParams<'a> { + pub locals: [Consts; bloom::NUM_SIZES], + pub src_views: [&'a wgpu::TextureView; bloom::NUM_SIZES], + pub final_tgt_view: &'a wgpu::TextureView, +} + pub struct Locals { pub clouds: Consts, pub clouds_bind: clouds::BindGroup, - pub bloom_binds: [bloom::BindGroup; bloom::NUM_SIZES], + pub bloom_binds: Option<[bloom::BindGroup; bloom::NUM_SIZES]>, pub postprocess: Consts, pub postprocess_bind: postprocess::BindGroup, @@ -21,12 +27,10 @@ impl Locals { device: &wgpu::Device, layouts: &Layouts, clouds_locals: Consts, - bloom_locals: [Consts; bloom::NUM_SIZES], postprocess_locals: Consts, tgt_color_view: &wgpu::TextureView, tgt_depth_view: &wgpu::TextureView, - bloom_src_views: [&wgpu::TextureView; bloom::NUM_SIZES], - bloom_final_tgt_view: &wgpu::TextureView, + bloom: Option, tgt_color_pp_view: &wgpu::TextureView, sampler: &wgpu::Sampler, depth_sampler: &wgpu::Sampler, @@ -39,18 +43,22 @@ impl Locals { depth_sampler, &clouds_locals, ); - let bloom_binds = bloom_src_views - .zip(bloom_locals) - .map(|(view, locals)| layouts.bloom.bind(device, view, sampler, locals)); let postprocess_bind = layouts.postprocess.bind( device, tgt_color_pp_view, - bloom_final_tgt_view, + bloom.as_ref().map(|b| b.final_tgt_view), sampler, &postprocess_locals, ); + let bloom_binds = bloom.map(|bloom| { + bloom + .src_views + .zip(bloom.locals) // zip arrays + .map(|(view, locals)| layouts.bloom.bind(device, view, sampler, locals)) + }); + Self { clouds: clouds_locals, clouds_bind, @@ -66,11 +74,9 @@ impl Locals { layouts: &Layouts, // Call when these are recreated and need to be rebound // e.g. resizing - bloom_locals: [Consts; bloom::NUM_SIZES], tgt_color_view: &wgpu::TextureView, tgt_depth_view: &wgpu::TextureView, - bloom_src_views: [&wgpu::TextureView; bloom::NUM_SIZES], - bloom_final_tgt_view: &wgpu::TextureView, + bloom: Option, tgt_color_pp_view: &wgpu::TextureView, sampler: &wgpu::Sampler, depth_sampler: &wgpu::Sampler, @@ -83,15 +89,18 @@ impl Locals { depth_sampler, &self.clouds, ); - self.bloom_binds = bloom_src_views - .zip(bloom_locals) - .map(|(view, locals)| layouts.bloom.bind(device, view, sampler, locals)); self.postprocess_bind = layouts.postprocess.bind( device, tgt_color_pp_view, - bloom_final_tgt_view, + bloom.as_ref().map(|b| b.final_tgt_view), sampler, &self.postprocess, ); + self.bloom_binds = bloom.map(|bloom| { + bloom + .src_views + .zip(bloom.locals) // zip arrays + .map(|(view, locals)| layouts.bloom.bind(device, view, sampler, locals)) + }); } } diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index 10d02ba298..7331504271 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -4,10 +4,10 @@ use super::{ blit, bloom, clouds, debug, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain, ui, }, - AaMode, CloudMode, FluidMode, LightingMode, RenderError, RenderMode, ShadowMode, + AaMode, CloudMode, FluidMode, LightingMode, PipelineModes, RenderError, ShadowMode, }, shaders::Shaders, - Layouts, + ImmutableLayouts, Layouts, }; use common_base::prof_span; use std::sync::Arc; @@ -20,7 +20,7 @@ pub struct Pipelines { pub lod_terrain: lod_terrain::LodTerrainPipeline, pub particle: particle::ParticlePipeline, pub clouds: clouds::CloudsPipeline, - pub bloom: bloom::BloomPipelines, + pub bloom: Option, pub postprocess: postprocess::PostProcessPipeline, // Consider reenabling at some time // player_shadow: figure::FigurePipeline, @@ -40,7 +40,7 @@ pub struct IngamePipelines { lod_terrain: lod_terrain::LodTerrainPipeline, particle: particle::ParticlePipeline, clouds: clouds::CloudsPipeline, - bloom: bloom::BloomPipelines, + pub bloom: Option, postprocess: postprocess::PostProcessPipeline, // Consider reenabling at some time // player_shadow: figure::FigurePipeline, @@ -126,7 +126,7 @@ impl ShaderModules { pub fn new( device: &wgpu::Device, shaders: &Shaders, - mode: &RenderMode, + pipeline_modes: &PipelineModes, has_shadow_views: bool, ) -> Result { prof_span!(_guard, "ShaderModules::new"); @@ -151,16 +151,17 @@ impl ShaderModules { #define CLOUD_MODE {} #define LIGHTING_ALGORITHM {} #define SHADOW_MODE {} +#define BLOOM {} "#, &constants.0, // TODO: Configurable vertex/fragment shader preference. "VOXYGEN_COMPUTATION_PREFERENCE_FRAGMENT", - match mode.fluid { + match pipeline_modes.fluid { FluidMode::Cheap => "FLUID_MODE_CHEAP", FluidMode::Shiny => "FLUID_MODE_SHINY", }, - match mode.cloud { + match pipeline_modes.cloud { CloudMode::None => "CLOUD_MODE_NONE", CloudMode::Minimal => "CLOUD_MODE_MINIMAL", CloudMode::Low => "CLOUD_MODE_LOW", @@ -168,20 +169,25 @@ impl ShaderModules { CloudMode::High => "CLOUD_MODE_HIGH", CloudMode::Ultra => "CLOUD_MODE_ULTRA", }, - match mode.lighting { + match pipeline_modes.lighting { LightingMode::Ashikhmin => "LIGHTING_ALGORITHM_ASHIKHMIN", LightingMode::BlinnPhong => "LIGHTING_ALGORITHM_BLINN_PHONG", LightingMode::Lambertian => "LIGHTING_ALGORITHM_LAMBERTIAN", }, - match mode.shadow { + match pipeline_modes.shadow { ShadowMode::None => "SHADOW_MODE_NONE", ShadowMode::Map(_) if has_shadow_views => "SHADOW_MODE_MAP", ShadowMode::Cheap | ShadowMode::Map(_) => "SHADOW_MODE_CHEAP", }, + if dbg!(pipeline_modes.bloom) { + "BLOOM_ENABLED" + } else { + "BLOOM_DISABLED" + }, ); let anti_alias = shaders - .get(match mode.aa { + .get(match pipeline_modes.aa { AaMode::None => "antialias.none", AaMode::Fxaa => "antialias.fxaa", AaMode::MsaaX4 => "antialias.msaa-x4", @@ -191,7 +197,7 @@ impl ShaderModules { .unwrap(); let cloud = shaders - .get(match mode.cloud { + .get(match pipeline_modes.cloud { CloudMode::None => "include.cloud.none", _ => "include.cloud.regular", }) @@ -234,7 +240,7 @@ impl ShaderModules { create_shader_module(device, &mut compiler, glsl, kind, &file_name, &options) }; - let selected_fluid_shader = ["fluid-frag.", match mode.fluid { + let selected_fluid_shader = ["fluid-frag.", match pipeline_modes.fluid { FluidMode::Cheap => "cheap", FluidMode::Shiny => "shiny", }] @@ -317,7 +323,7 @@ struct PipelineNeeds<'a> { device: &'a wgpu::Device, layouts: &'a Layouts, shaders: &'a ShaderModules, - mode: &'a RenderMode, + pipeline_modes: &'a PipelineModes, sc_desc: &'a wgpu::SwapChainDescriptor, } @@ -380,7 +386,7 @@ fn create_ingame_and_shadow_pipelines( device, layouts, shaders, - mode, + pipeline_modes, sc_desc, } = needs; @@ -416,7 +422,7 @@ fn create_ingame_and_shadow_pipelines( &shaders.debug_frag, &layouts.global, &layouts.debug, - mode.aa, + pipeline_modes.aa, ) }, "debug pipeline creation", @@ -431,7 +437,7 @@ fn create_ingame_and_shadow_pipelines( &shaders.skybox_vert, &shaders.skybox_frag, &layouts.global, - mode.aa, + pipeline_modes.aa, ) }, "skybox pipeline creation", @@ -447,7 +453,7 @@ fn create_ingame_and_shadow_pipelines( &shaders.figure_frag, &layouts.global, &layouts.figure, - mode.aa, + pipeline_modes.aa, ) }, "figure pipeline creation", @@ -463,7 +469,7 @@ fn create_ingame_and_shadow_pipelines( &shaders.terrain_frag, &layouts.global, &layouts.terrain, - mode.aa, + pipeline_modes.aa, ) }, "terrain pipeline creation", @@ -479,7 +485,7 @@ fn create_ingame_and_shadow_pipelines( &shaders.fluid_frag, &layouts.global, &layouts.terrain, - mode.aa, + pipeline_modes.aa, ) }, "fluid pipeline creation", @@ -496,7 +502,7 @@ fn create_ingame_and_shadow_pipelines( &layouts.global, &layouts.sprite, &layouts.terrain, - mode.aa, + pipeline_modes.aa, ) }, "sprite pipeline creation", @@ -511,7 +517,7 @@ fn create_ingame_and_shadow_pipelines( &shaders.particle_vert, &shaders.particle_frag, &layouts.global, - mode.aa, + pipeline_modes.aa, ) }, "particle pipeline creation", @@ -526,7 +532,7 @@ fn create_ingame_and_shadow_pipelines( &shaders.lod_terrain_vert, &shaders.lod_terrain_frag, &layouts.global, - mode.aa, + pipeline_modes.aa, ) }, "lod terrain pipeline creation", @@ -542,7 +548,7 @@ fn create_ingame_and_shadow_pipelines( &shaders.clouds_frag, &layouts.global, &layouts.clouds, - mode.aa, + pipeline_modes.aa, ) }, "clouds pipeline creation", @@ -552,15 +558,17 @@ fn create_ingame_and_shadow_pipelines( let create_bloom = || { bloom_task.run( || { - bloom::BloomPipelines::new( - device, - &shaders.blit_vert, - &shaders.dual_downsample_filtered_frag, - &shaders.dual_downsample_frag, - &shaders.dual_upsample_frag, - wgpu::TextureFormat::Rgba16Float, - &layouts.bloom, - ) + pipeline_modes.bloom.then(|| { + bloom::BloomPipelines::new( + device, + &shaders.blit_vert, + &shaders.dual_downsample_filtered_frag, + &shaders.dual_downsample_frag, + &shaders.dual_upsample_frag, + wgpu::TextureFormat::Rgba16Float, + &layouts.bloom, + ) + }) }, "bloom pipelines creation", ) @@ -614,7 +622,7 @@ fn create_ingame_and_shadow_pipelines( &shaders.point_light_shadows_vert, &layouts.global, &layouts.terrain, - mode.aa, + pipeline_modes.aa, ) }, "point shadow pipeline creation", @@ -629,7 +637,7 @@ fn create_ingame_and_shadow_pipelines( &shaders.light_shadows_directed_vert, &layouts.global, &layouts.terrain, - mode.aa, + pipeline_modes.aa, ) }, "terrain directed shadow pipeline creation", @@ -644,7 +652,7 @@ fn create_ingame_and_shadow_pipelines( &shaders.light_shadows_figure_vert, &layouts.global, &layouts.figure, - mode.aa, + pipeline_modes.aa, ) }, "figure directed shadow pipeline creation", @@ -706,9 +714,9 @@ fn create_ingame_and_shadow_pipelines( /// NOTE: this tries to use all the CPU cores to complete as soon as possible pub(super) fn initial_create_pipelines( device: Arc, - layouts: Arc, + layouts: Layouts, shaders: Shaders, - mode: RenderMode, + pipeline_modes: PipelineModes, sc_desc: wgpu::SwapChainDescriptor, has_shadow_views: bool, ) -> Result< @@ -721,7 +729,7 @@ pub(super) fn initial_create_pipelines( prof_span!(_guard, "initial_create_pipelines"); // Process shaders into modules - let shader_modules = ShaderModules::new(&device, &shaders, &mode, has_shadow_views)?; + let shader_modules = ShaderModules::new(&device, &shaders, &pipeline_modes, has_shadow_views)?; // Create threadpool for parallel portion let pool = rayon::ThreadPoolBuilder::new() @@ -733,7 +741,7 @@ pub(super) fn initial_create_pipelines( device: &device, layouts: &layouts, shaders: &shader_modules, - mode: &mode, + pipeline_modes: &pipeline_modes, sc_desc: &sc_desc, }; @@ -760,7 +768,7 @@ pub(super) fn initial_create_pipelines( device: &device, layouts: &layouts, shaders: &shader_modules, - mode: &mode, + pipeline_modes: &pipeline_modes, sc_desc: &sc_desc, }; @@ -776,14 +784,25 @@ pub(super) fn initial_create_pipelines( /// Use this to recreate all the pipelines in the background. /// TODO: report progress /// NOTE: this tries to use all the CPU cores to complete as soon as possible +#[allow(clippy::type_complexity)] pub(super) fn recreate_pipelines( device: Arc, - layouts: Arc, + immutable_layouts: Arc, shaders: Shaders, - mode: RenderMode, + pipeline_modes: PipelineModes, sc_desc: wgpu::SwapChainDescriptor, has_shadow_views: bool, -) -> PipelineCreation> { +) -> PipelineCreation< + Result< + ( + Pipelines, + ShadowPipelines, + PipelineModes, + Arc, + ), + RenderError, + >, +> { prof_span!(_guard, "recreate_pipelines"); // Create threadpool for parallel portion @@ -811,20 +830,32 @@ pub(super) fn recreate_pipelines( // Process shaders into modules let guard = shader_task.start("process shaders"); - let shader_modules = match ShaderModules::new(&device, &shaders, &mode, has_shadow_views) { - Ok(modules) => modules, - Err(err) => { - result_send.send(Err(err)).expect("Channel disconnected"); - return; - }, - }; + let shader_modules = + match ShaderModules::new(&device, &shaders, &pipeline_modes, has_shadow_views) { + Ok(modules) => modules, + Err(err) => { + result_send.send(Err(err)).expect("Channel disconnected"); + return; + }, + }; drop(guard); + // Create new postprocess layouts + let postprocess_layouts = Arc::new(postprocess::PostProcessLayout::new( + &device, + &pipeline_modes, + )); + + let layouts = Layouts { + immutable: immutable_layouts, + postprocess: postprocess_layouts, + }; + let needs = PipelineNeeds { device: &device, layouts: &layouts, shaders: &shader_modules, - mode: &mode, + pipeline_modes: &pipeline_modes, sc_desc: &sc_desc, }; @@ -837,7 +868,12 @@ pub(super) fn recreate_pipelines( // Send them result_send - .send(Ok((Pipelines::consolidate(interface, ingame), shadow))) + .send(Ok(( + Pipelines::consolidate(interface, ingame), + shadow, + pipeline_modes, + layouts.postprocess, + ))) .expect("Channel disconnected"); }); diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 9fac2b5fff..6ec10087d4 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -518,7 +518,7 @@ impl FigureMgr { let ray_direction = scene_data.get_sun_dir(); let is_daylight = ray_direction.z < 0.0/*0.6*/; // Are shadows enabled at all? - let can_shadow_sun = renderer.render_mode().shadow.is_map() && is_daylight; + let can_shadow_sun = renderer.pipeline_modes().shadow.is_map() && is_daylight; let Dependents { proj_mat: _, view_mat: _, diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index c7659e18ca..4f6d0af4d5 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -681,7 +681,7 @@ impl Scene { let sun_dir = scene_data.get_sun_dir(); let is_daylight = sun_dir.z < 0.0; - if renderer.render_mode().shadow.is_map() && (is_daylight || !lights.is_empty()) { + if renderer.pipeline_modes().shadow.is_map() && (is_daylight || !lights.is_empty()) { let fov = self.camera.get_fov(); let aspect_ratio = self.camera.get_aspect_ratio(); @@ -1062,7 +1062,7 @@ impl Scene { let camera_data = (&self.camera, scene_data.figure_lod_render_distance); // would instead have this as an extension. - if drawer.render_mode().shadow.is_map() && (is_daylight || !self.light_data.is_empty()) { + if drawer.pipeline_modes().shadow.is_map() && (is_daylight || !self.light_data.is_empty()) { if is_daylight { prof_span!("directed shadows"); if let Some(mut shadow_pass) = drawer.shadow_pass() { diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index dae0847392..31d06afd4e 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -1244,7 +1244,7 @@ impl Terrain { return min.partial_cmple(&max).reduce_and(); }; let (visible_light_volume, visible_psr_bounds) = if ray_direction.z < 0.0 - && renderer.render_mode().shadow.is_map() + && renderer.pipeline_modes().shadow.is_map() { let visible_bounding_box = math::Aabb:: { min: math::Vec3::from(visible_bounding_box.min - focus_off), diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index eaf2469d95..23c8bed695 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -1483,8 +1483,7 @@ impl PlayState for SessionState { second_pass.draw_clouds(); } } - // Bloom - // TODO: make optional + // Bloom (call does nothing if bloom is off) { prof_span!("bloom"); drawer.run_bloom_passes() diff --git a/voxygen/src/settings/graphics.rs b/voxygen/src/settings/graphics.rs index 1155a7a131..55cc52ba6b 100644 --- a/voxygen/src/settings/graphics.rs +++ b/voxygen/src/settings/graphics.rs @@ -43,6 +43,7 @@ pub struct GraphicsSettings { pub window_size: [u16; 2], pub fullscreen: FullScreenSettings, pub lod_detail: u32, + pub bloom_enabled: bool, } impl Default for GraphicsSettings { @@ -62,6 +63,7 @@ impl Default for GraphicsSettings { window_size: [1280, 720], fullscreen: FullScreenSettings::default(), lod_detail: 250, + bloom_enabled: false, } } } diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index 4f2c3da9d4..f29c197fb6 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -791,8 +791,7 @@ impl Window { let physical = self.window.inner_size(); self.renderer - .on_resize(Vec2::new(physical.width, physical.height)) - .unwrap(); + .on_resize(Vec2::new(physical.width, physical.height)); // TODO: update users of this event with the fact that it is now the physical // size let winit::dpi::PhysicalSize { width, height } = physical; From 147e4f00f6ce0c8e7960435208db889a15a9b461 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 1 Aug 2021 00:15:20 -0400 Subject: [PATCH 045/155] Enhance bloom::NUM_SIZES docs, add TODO, remove dbgs --- voxygen/src/render/pipelines/bloom.rs | 39 +++++++++++++++++-- voxygen/src/render/renderer.rs | 13 +++---- .../src/render/renderer/pipeline_creation.rs | 2 +- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/voxygen/src/render/pipelines/bloom.rs b/voxygen/src/render/pipelines/bloom.rs index 64463278e2..c1e4d9055b 100644 --- a/voxygen/src/render/pipelines/bloom.rs +++ b/voxygen/src/render/pipelines/bloom.rs @@ -1,4 +1,6 @@ //! Based on: https://community.arm.com/cfs-file/__key/communityserver-blogs-components-weblogfiles/00-00-00-20-66/siggraph2015_2D00_mmg_2D00_marius_2D00_notes.pdf +//! +//! See additional details in the [NUM_SIZES] docs use super::super::Consts; use bytemuck::{Pod, Zeroable}; @@ -6,10 +8,39 @@ use vek::*; // TODO: auto-tune the number of passes to maintain roughly constant blur per // unit of FOV so changing resolution / FOV doesn't change the blur appearance -// significantly -/// Each level is a multiple of 2 smaller in both dimensions. -/// For a total of 8 passes from the largest to the smallest to the largest -/// again. +// significantly. +// +/// Blurring is performed while downsampling to the smaller sizes in steps and +/// then upsampling back up to the original resolution. Each level is half the +/// size in both dimensions from the previous. For instance with 5 distinct +/// sizes there is a total of 8 passes going from the largest to the smallest to +/// the largest again: +/// +/// 1 -> 1/2 -> 1/4 -> 1/8 -> 1/16 -> 1/8 -> 1/4 -> 1/2 -> 1 +/// ~~~~ +/// [downsampling] smallest [upsampling] +/// +/// The textures used for downsampling are re-used when upsampling. +/// +/// Additionally, instead of clearing them the colors are added together in an +/// attempt to obtain a more concentrated bloom near bright areas rather than +/// a uniform blur. In the example above, the added layers would include 1/8, +/// 1/4, and 1/2. The smallest size is not upsampled to and the original full +/// resolution has no blurring and we are already combining the bloom into the +/// full resolution image in a later step, so they are not included here. The 3 +/// extra layers added in mean the total luminosity of the final blurred bloom +/// image will be 4 times more than the input image. To account for this, we +/// divide the bloom intensity by 4 before applying it. +/// +/// Nevertheless, we have not fully evaluated how this visually compares to the +/// bloom obtained without adding with the previous layers so there is the +/// potential for further artistic investigation here. +/// +/// NOTE: This constant includes the full resolution size and it is +/// assumed that there will be at least one smaller image to downsample to and +/// upsample back from (otherwise no blurring would be done). Thus, the minimum +/// valid value is 2 and panicking indexing operations we perform assume this +/// will be at least 2. pub const NUM_SIZES: usize = 5; pub struct BindGroup { diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index a7f2f78d48..86580d0f7a 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -555,12 +555,11 @@ impl Renderer { // We can't cancel the pending recreation even if the new settings are equal // to the current ones becuase the recreation could be triggered by something // else like shader hotloading - if dbg!(self.pipeline_modes != pipeline_modes) - || dbg!( - self.recreation_pending - .as_ref() - .map_or(false, |modes| modes != &pipeline_modes) - ) + if self.pipeline_modes != pipeline_modes + || self + .recreation_pending + .as_ref() + .map_or(false, |modes| modes != &pipeline_modes) { // Recreate pipelines with new modes self.recreate_pipelines(pipeline_modes); @@ -619,7 +618,7 @@ impl Renderer { ); self.views = views; - // appease borrow check + // appease borrow check (TODO: remove after Rust 2021) let device = &self.device; let queue = &self.queue; let views = &self.views; diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index 7331504271..520bec4a8f 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -179,7 +179,7 @@ impl ShaderModules { ShadowMode::Map(_) if has_shadow_views => "SHADOW_MODE_MAP", ShadowMode::Cheap | ShadowMode::Map(_) => "SHADOW_MODE_CHEAP", }, - if dbg!(pipeline_modes.bloom) { + if pipeline_modes.bloom { "BLOOM_ENABLED" } else { "BLOOM_DISABLED" From a1026c36f502365c7b8ab6dbcbaecd198b7ddda8 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sun, 1 Aug 2021 18:50:09 -0400 Subject: [PATCH 046/155] Make bloom intensity configurable, make whether less blurred layers are added in toggleable, hold onto copy of pipeline modes instead of returning it from pipeline creation --- assets/voxygen/shaders/include/constants.glsl | 3 - assets/voxygen/shaders/postprocess-frag.glsl | 14 ++-- voxygen/src/render/mod.rs | 64 ++++++++++++++++++- voxygen/src/render/pipelines/bloom.rs | 13 ++-- voxygen/src/render/pipelines/postprocess.rs | 2 +- voxygen/src/render/renderer.rs | 43 +++++++------ .../src/render/renderer/pipeline_creation.rs | 36 ++++++++--- voxygen/src/settings/graphics.rs | 2 - 8 files changed, 126 insertions(+), 51 deletions(-) diff --git a/assets/voxygen/shaders/include/constants.glsl b/assets/voxygen/shaders/include/constants.glsl index 8cd90ca072..f1bc2a8aa9 100644 --- a/assets/voxygen/shaders/include/constants.glsl +++ b/assets/voxygen/shaders/include/constants.glsl @@ -24,9 +24,6 @@ #define SHADOW_MODE_CHEAP 1 #define SHADOW_MODE_MAP 2 -#define BLOOM_DISABLED 0 -#define BLOOM_ENABLED 1 - /* Unlike the other flags (for now anyway), these are bitmask values */ #define LIGHTING_TYPE_REFLECTION 0x01 #define LIGHTING_TYPE_TRANSMISSION 0x02 diff --git a/assets/voxygen/shaders/postprocess-frag.glsl b/assets/voxygen/shaders/postprocess-frag.glsl index 57df871073..17b90c0895 100644 --- a/assets/voxygen/shaders/postprocess-frag.glsl +++ b/assets/voxygen/shaders/postprocess-frag.glsl @@ -35,7 +35,7 @@ uniform u_locals { mat4 view_mat_inv; }; -#if (BLOOM == BLOOM_ENABLED) +#ifdef BLOOM_FACTOR layout(set = 1, binding = 3) uniform texture2D t_src_bloom; #endif @@ -187,11 +187,13 @@ void main() { vec4 aa_color = aa_apply(t_src_color, s_src_color, uv * screen_res.xy, screen_res.xy); // Bloom - #if (BLOOM == BLOOM_ENABLED) - // divide by 4.0 to account for adding blurred layers together - vec4 bloom = textureLod(sampler2D(t_src_bloom, s_src_color), uv, 0) / 4.0; - float bloom_factor = 0.10; - aa_color = mix(aa_color, bloom, bloom_factor); + #ifdef BLOOM_FACTOR + vec4 bloom = textureLod(sampler2D(t_src_bloom, s_src_color), uv, 0); + #if (BLOOM_UNIFORM_BLUR == false) + // divide by 4.0 to account for adding blurred layers together + bloom /= 4.0; + #endif + aa_color = mix(aa_color, bloom, BLOOM_FACTOR); #endif // Tonemapping diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index a2a8786c01..26006ad843 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -265,6 +265,66 @@ impl From for wgpu::PresentMode { } } +/// Bloom factor +/// Controls fraction of output image luminosity that is blurred bloom +#[derive(PartialEq, Clone, Copy, Debug, Serialize, Deserialize)] +pub enum BloomFactor { + Low, + High, + /// Max valid value is 1.0 + Custom(f32), + // other variant has to be placed last + #[serde(other)] + Standard, +} + +impl Default for BloomFactor { + fn default() -> Self { Self::Standard } +} + +impl BloomFactor { + /// Fraction of output image luminosity that is blurred bloom + pub fn fraction(self) -> f32 { + match self { + Self::Low => 0.05, + Self::Standard => 0.10, + Self::High => 0.25, + Self::Custom(val) => val.max(0.0).min(1.0), + } + } +} + +/// Bloom settings +#[derive(PartialEq, Clone, Copy, Debug, Serialize, Deserialize)] +pub struct BloomConfig { + /// Controls fraction of output image luminosity that is blurred bloom + /// + /// Defaults to `Standard` + factor: BloomFactor, + /// Turning this on make the bloom blur less sharply concentrated around the + /// high intensity phenomena (removes adding in less blurred layers to the + /// final blur) + /// + /// Defaults to `false` + uniform_blur: bool, + // TODO: allow configuring the blur radius and/or the number of passes +} + +#[derive(PartialEq, Clone, Copy, Debug, Serialize, Deserialize)] +pub enum BloomMode { + On(BloomConfig), + #[serde(other)] + Off, +} + +impl Default for BloomMode { + fn default() -> Self { Self::Off } +} + +impl BloomMode { + fn is_on(&self) -> bool { matches!(self, BloomMode::On(_)) } +} + /// Render modes #[derive(PartialEq, Clone, Debug, Default, Serialize, Deserialize)] #[serde(default)] @@ -274,7 +334,7 @@ pub struct RenderMode { pub fluid: FluidMode, pub lighting: LightingMode, pub shadow: ShadowMode, - pub bloom: bool, + pub bloom: BloomMode, pub upscale_mode: UpscaleMode, pub present_mode: PresentMode, @@ -310,7 +370,7 @@ pub struct PipelineModes { fluid: FluidMode, lighting: LightingMode, pub shadow: ShadowMode, - bloom: bool, + bloom: BloomMode, } /// Other render modes that don't effect pipelines diff --git a/voxygen/src/render/pipelines/bloom.rs b/voxygen/src/render/pipelines/bloom.rs index c1e4d9055b..123f25680c 100644 --- a/voxygen/src/render/pipelines/bloom.rs +++ b/voxygen/src/render/pipelines/bloom.rs @@ -2,7 +2,7 @@ //! //! See additional details in the [NUM_SIZES] docs -use super::super::Consts; +use super::super::{BloomConfig, Consts}; use bytemuck::{Pod, Zeroable}; use vek::*; @@ -152,6 +152,7 @@ impl BloomPipelines { upsample_fs_module: &wgpu::ShaderModule, target_format: wgpu::TextureFormat, layout: &BloomLayout, + bloom_config: &BloomConfig, ) -> Self { common_base::span!(_guard, "BloomPipelines::new"); let render_pipeline_layout = @@ -207,18 +208,14 @@ impl BloomPipelines { let upsample_pipeline = create_pipeline( "Bloom upsample pipeline", upsample_fs_module, - Some(wgpu::BlendState { + (!bloom_config.uniform_blur).then(|| wgpu::BlendState { color: wgpu::BlendComponent { src_factor: wgpu::BlendFactor::One, dst_factor: wgpu::BlendFactor::One, operation: wgpu::BlendOperation::Add, }, - // we don't really use this, but... we need something here - alpha: wgpu::BlendComponent { - src_factor: wgpu::BlendFactor::One, - dst_factor: wgpu::BlendFactor::One, - operation: wgpu::BlendOperation::Add, - }, + // We don't reaaly use this but we need something here.. + alpha: wgpu::BlendComponent::REPLACE, }), ); diff --git a/voxygen/src/render/pipelines/postprocess.rs b/voxygen/src/render/pipelines/postprocess.rs index ccb83b52c1..3d67c2d4d4 100644 --- a/voxygen/src/render/pipelines/postprocess.rs +++ b/voxygen/src/render/pipelines/postprocess.rs @@ -66,7 +66,7 @@ impl PostProcessLayout { }, ]; - if pipeline_modes.bloom { + if pipeline_modes.bloom.is_on() { bind_entries.push( // src bloom wgpu::BindGroupLayoutEntry { diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 86580d0f7a..603fb2a915 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -111,19 +111,19 @@ enum State { Complete { pipelines: Pipelines, shadow: Shadow, - recreating: Option< + recreating: Option<( + PipelineModes, PipelineCreation< Result< ( Pipelines, ShadowPipelines, - PipelineModes, Arc, ), RenderError, >, >, - >, + )>, }, } @@ -522,7 +522,7 @@ impl Renderer { /// Returns `Some((total, complete))` if in progress pub fn pipeline_recreation_status(&self) -> Option<(usize, usize)> { if let State::Complete { recreating, .. } = &self.state { - recreating.as_ref().map(|r| r.status()) + recreating.as_ref().map(|(_, c)| c.status()) } else { None } @@ -765,6 +765,7 @@ impl Renderer { let bloom_tgt_views = pipeline_modes .bloom + .is_on() .then(|| bloom_sizes.map(|size| color_view(size.x, size.y))); let tgt_depth_tex = device.create_texture(&wgpu::TextureDescriptor { @@ -964,11 +965,11 @@ impl Renderer { } else if let State::Complete { pipelines, mut shadow, - recreating: Some(recreating), + recreating: Some((new_pipeline_modes, pipeline_creation)), } = state { - match recreating.try_complete() { - Ok(Ok((pipelines, shadow_pipelines, new_pipeline_modes, postprocess_layout))) => { + match pipeline_creation.try_complete() { + Ok(Ok((pipelines, shadow_pipelines, postprocess_layout))) => { if let ( Some(point_pipeline), Some(terrain_directed_pipeline), @@ -1007,10 +1008,10 @@ impl Renderer { } }, // Not complete - Err(recreating) => State::Complete { + Err(pipeline_creation) => State::Complete { pipelines, shadow, - recreating: Some(recreating), + recreating: Some((new_pipeline_modes, pipeline_creation)), }, } } else { @@ -1080,16 +1081,20 @@ impl Renderer { State::Complete { recreating, shadow, .. } => { - *recreating = Some(pipeline_creation::recreate_pipelines( - Arc::clone(&self.device), - Arc::clone(&self.layouts.immutable), - self.shaders.read().clone(), - self.pipeline_modes.clone(), - // NOTE: if present_mode starts to be used to configure pipelines then it needs - // to become a part of the pipeline modes (note here since the present mode is - // accessible through the swap chain descriptor) - self.sc_desc.clone(), // Note: cheap clone - shadow.map.is_enabled(), + *recreating = Some(( + pipeline_modes.clone(), + pipeline_creation::recreate_pipelines( + Arc::clone(&self.device), + Arc::clone(&self.layouts.immutable), + self.shaders.read().clone(), + pipeline_modes, + // NOTE: if present_mode starts to be used to configure pipelines then it + // needs to become a part of the pipeline modes + // (note here since the present mode is accessible + // through the swap chain descriptor) + self.sc_desc.clone(), // Note: cheap clone + shadow.map.is_enabled(), + ), )); }, State::Interface { .. } => { diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index 520bec4a8f..3ec6f4f479 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -4,7 +4,8 @@ use super::{ blit, bloom, clouds, debug, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain, ui, }, - AaMode, CloudMode, FluidMode, LightingMode, PipelineModes, RenderError, ShadowMode, + AaMode, BloomMode, CloudMode, FluidMode, LightingMode, PipelineModes, RenderError, + ShadowMode, }, shaders::Shaders, ImmutableLayouts, Layouts, @@ -151,7 +152,6 @@ impl ShaderModules { #define CLOUD_MODE {} #define LIGHTING_ALGORITHM {} #define SHADOW_MODE {} -#define BLOOM {} "#, &constants.0, @@ -179,13 +179,26 @@ impl ShaderModules { ShadowMode::Map(_) if has_shadow_views => "SHADOW_MODE_MAP", ShadowMode::Cheap | ShadowMode::Map(_) => "SHADOW_MODE_CHEAP", }, - if pipeline_modes.bloom { - "BLOOM_ENABLED" - } else { - "BLOOM_DISABLED" - }, ); + let constants = match pipeline_modes.bloom { + BloomMode::Off => constants, + BloomMode::On(config) => { + format!( + r#" +{} + +#define BLOOM_FACTOR {} +#define BLOOM_UNIFORM_BLUR {} + +"#, + constants, + config.factor.fraction(), + config.uniform_blur, + ) + }, + }; + let anti_alias = shaders .get(match pipeline_modes.aa { AaMode::None => "antialias.none", @@ -558,7 +571,11 @@ fn create_ingame_and_shadow_pipelines( let create_bloom = || { bloom_task.run( || { - pipeline_modes.bloom.then(|| { + match &pipeline_modes.bloom { + BloomMode::Off => None, + BloomMode::On(config) => Some(config), + } + .map(|bloom_config| { bloom::BloomPipelines::new( device, &shaders.blit_vert, @@ -567,6 +584,7 @@ fn create_ingame_and_shadow_pipelines( &shaders.dual_upsample_frag, wgpu::TextureFormat::Rgba16Float, &layouts.bloom, + bloom_config, ) }) }, @@ -797,7 +815,6 @@ pub(super) fn recreate_pipelines( ( Pipelines, ShadowPipelines, - PipelineModes, Arc, ), RenderError, @@ -871,7 +888,6 @@ pub(super) fn recreate_pipelines( .send(Ok(( Pipelines::consolidate(interface, ingame), shadow, - pipeline_modes, layouts.postprocess, ))) .expect("Channel disconnected"); diff --git a/voxygen/src/settings/graphics.rs b/voxygen/src/settings/graphics.rs index 55cc52ba6b..1155a7a131 100644 --- a/voxygen/src/settings/graphics.rs +++ b/voxygen/src/settings/graphics.rs @@ -43,7 +43,6 @@ pub struct GraphicsSettings { pub window_size: [u16; 2], pub fullscreen: FullScreenSettings, pub lod_detail: u32, - pub bloom_enabled: bool, } impl Default for GraphicsSettings { @@ -63,7 +62,6 @@ impl Default for GraphicsSettings { window_size: [1280, 720], fullscreen: FullScreenSettings::default(), lod_detail: 250, - bloom_enabled: false, } } } From dffc91045eeecd4891d8ed6aa0cd186d843728db Mon Sep 17 00:00:00 2001 From: "Dr. Dystopia" Date: Sun, 1 Aug 2021 21:59:09 +0200 Subject: [PATCH 047/155] Move variables closer to usage in 'buttons' file --- voxygen/src/hud/buttons.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/voxygen/src/hud/buttons.rs b/voxygen/src/hud/buttons.rs index d046c8a783..21a8b3f943 100644 --- a/voxygen/src/hud/buttons.rs +++ b/voxygen/src/hud/buttons.rs @@ -126,13 +126,7 @@ impl<'a> Widget for Buttons<'a> { fn update(self, args: widget::UpdateArgs) -> Self::Event { common_base::prof_span!("Buttons::update"); let widget::UpdateArgs { state, ui, .. } = args; - let invs = self.client.inventories(); - let inventory = match invs.get(self.client.entity()) { - Some(inv) => inv, - None => return None, - }; let localized_strings = self.localized_strings; - let arrow_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; //Animation timer let button_tooltip = Tooltip::new({ // Edge images [t, b, r, l] @@ -197,6 +191,11 @@ impl<'a> Widget for Buttons<'a> { state.ids.bag_text, ); } + let invs = self.client.inventories(); + let inventory = match invs.get(self.client.entity()) { + Some(inv) => inv, + None => return None, + }; if !self.show_bag { let space_used = inventory.populated_slots(); let space_max = inventory.slots().count(); @@ -357,6 +356,7 @@ impl<'a> Widget for Buttons<'a> { } // Unspent SP indicator if unspent_sp { + let arrow_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; //Animation timer Image::new(self.imgs.sp_indicator_arrow) .w_h(20.0, 11.0) .graphics_for(state.ids.spellbook_button) From 323e3166f5d279085c2d300f937cba64e920bde4 Mon Sep 17 00:00:00 2001 From: "Dr. Dystopia" Date: Sun, 1 Aug 2021 22:43:41 +0200 Subject: [PATCH 048/155] Create 'animation' file --- voxygen/src/hud/animation.rs | 3 +++ voxygen/src/hud/buffs.rs | 4 ++-- voxygen/src/hud/buttons.rs | 3 ++- voxygen/src/hud/mod.rs | 1 + 4 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 voxygen/src/hud/animation.rs diff --git a/voxygen/src/hud/animation.rs b/voxygen/src/hud/animation.rs new file mode 100644 index 0000000000..ec6a141f3e --- /dev/null +++ b/voxygen/src/hud/animation.rs @@ -0,0 +1,3 @@ +pub fn animation_timer(pulse: f32) -> f32 { + (pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8 //y=0.5cos(4x)+0.8 +} diff --git a/voxygen/src/hud/buffs.rs b/voxygen/src/hud/buffs.rs index da63a601c3..2c3ca35b06 100644 --- a/voxygen/src/hud/buffs.rs +++ b/voxygen/src/hud/buffs.rs @@ -3,7 +3,7 @@ use super::{ BUFF_COLOR, DEBUFF_COLOR, TEXT_COLOR, }; use crate::{ - hud::{self, BuffPosition}, + hud::{self, animation::animation_timer, BuffPosition}, ui::{fonts::Fonts, ImageFrame, Tooltip, TooltipManager, Tooltipable}, GlobalState, }; @@ -104,7 +104,7 @@ impl<'a> Widget for BuffsBar<'a> { let mut event = Vec::new(); let localized_strings = self.localized_strings; let buffs = self.buffs; - let buff_ani = ((self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8) + 0.5; //Animation timer + let buff_ani = animation_timer(self.pulse) + 0.5; //Animation timer let pulsating_col = Color::Rgba(1.0, 1.0, 1.0, buff_ani); let norm_col = Color::Rgba(1.0, 1.0, 1.0, 1.0); let buff_position = self.global_state.settings.interface.buff_position; diff --git a/voxygen/src/hud/buttons.rs b/voxygen/src/hud/buttons.rs index 21a8b3f943..e6d2418276 100644 --- a/voxygen/src/hud/buttons.rs +++ b/voxygen/src/hud/buttons.rs @@ -4,6 +4,7 @@ use super::{ }; use crate::{ game_input::GameInput, + hud::animation::animation_timer, ui::{fonts::Fonts, ImageFrame, Tooltip, TooltipManager, Tooltipable}, window::KeyMouse, GlobalState, @@ -356,7 +357,7 @@ impl<'a> Widget for Buttons<'a> { } // Unspent SP indicator if unspent_sp { - let arrow_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; //Animation timer + let arrow_ani = animation_timer(self.pulse); //Animation timer Image::new(self.imgs.sp_indicator_arrow) .w_h(20.0, 11.0) .graphics_for(state.ids.spellbook_button) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 5250e94d69..ff863b4018 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -1,3 +1,4 @@ +mod animation; mod bag; mod buffs; mod buttons; From e62d903041f192a2dd3afcce660d764547f0793f Mon Sep 17 00:00:00 2001 From: "Dr. Dystopia" Date: Mon, 2 Aug 2021 13:33:52 +0200 Subject: [PATCH 049/155] Add 'UpdateArgs import to 'buttons' file --- voxygen/src/hud/buttons.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/voxygen/src/hud/buttons.rs b/voxygen/src/hud/buttons.rs index e6d2418276..d91df8188c 100644 --- a/voxygen/src/hud/buttons.rs +++ b/voxygen/src/hud/buttons.rs @@ -12,7 +12,7 @@ use crate::{ use client::Client; use common::comp::{SkillSet, Stats}; use conrod_core::{ - widget::{self, Button, Image, Text}, + widget::{self, Button, Image, Text, UpdateArgs}, widget_ids, Color, Colorable, Positionable, Sizeable, UiCell, Widget, WidgetCommon, }; use i18n::Localization; @@ -124,9 +124,9 @@ impl<'a> Widget for Buttons<'a> { fn style(&self) -> Self::Style {} - fn update(self, args: widget::UpdateArgs) -> Self::Event { + fn update(self, args: UpdateArgs) -> Self::Event { common_base::prof_span!("Buttons::update"); - let widget::UpdateArgs { state, ui, .. } = args; + let UpdateArgs { state, ui, .. } = args; let localized_strings = self.localized_strings; let button_tooltip = Tooltip::new({ From 45f94b0bce69817e3f5271b0129d46bb0a38ce20 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 2 Aug 2021 13:08:39 +0100 Subject: [PATCH 050/155] Better Agent API --- common/src/comp/agent.rs | 55 ++++++++++++++---------- common/src/comp/body/quadruped_low.rs | 2 +- common/src/comp/body/quadruped_medium.rs | 2 +- common/src/comp/body/quadruped_small.rs | 2 +- common/src/states/basic_summon.rs | 11 +++-- server/src/cmd.rs | 13 +++--- server/src/pet.rs | 6 +-- server/src/rtsim/tick.rs | 5 +-- server/src/sys/terrain.rs | 23 ++++++---- 9 files changed, 66 insertions(+), 53 deletions(-) diff --git a/common/src/comp/agent.rs b/common/src/comp/agent.rs index 7226c44a9c..30473b8c8f 100644 --- a/common/src/comp/agent.rs +++ b/common/src/comp/agent.rs @@ -341,7 +341,7 @@ pub struct Target { } #[allow(clippy::type_complexity)] -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct Agent { pub rtsim_controller: RtSimController, pub patrol_origin: Option>, @@ -366,11 +366,43 @@ pub struct ActionState { } impl Agent { + pub fn from_body(body: &Body) -> Self { + Agent { + rtsim_controller: RtSimController::default(), + patrol_origin: None, + target: None, + chaser: Chaser::default(), + behavior: Behavior::default(), + psyche: Psyche::from(body), + inbox: VecDeque::new(), + action_state: ActionState::default(), + bearing: Vec2::zero(), + sounds_heard: Vec::new(), + awareness: 0.0, + position_pid_controller: None, + } + } + pub fn with_patrol_origin(mut self, origin: Vec3) -> Self { self.patrol_origin = Some(origin); self } + pub fn with_behavior(mut self, behavior: Behavior) -> Self { + self.behavior = behavior; + self + } + + pub fn with_no_flee(mut self, no_flee: bool) -> Self { + if no_flee { + self.set_no_flee(); + } + self + } + + pub fn set_no_flee(&mut self) { self.psyche.flee_health = 0.0; } + + // TODO: Get rid of this method, it does weird things pub fn with_destination(mut self, pos: Vec3) -> Self { self.psyche.flee_health = 0.0; self.rtsim_controller = RtSimController::with_destination(pos); @@ -386,27 +418,6 @@ impl Agent { self.position_pid_controller = Some(pid); self } - - pub fn new( - patrol_origin: Option>, - body: &Body, - behavior: Behavior, - no_flee: bool, - ) -> Self { - Agent { - patrol_origin, - psyche: if no_flee { - Psyche { - flee_health: 0.0, - ..Psyche::from(body) - } - } else { - Psyche::from(body) - }, - behavior, - ..Default::default() - } - } } impl Component for Agent { diff --git a/common/src/comp/body/quadruped_low.rs b/common/src/comp/body/quadruped_low.rs index 9b39604c0a..5ddd680500 100644 --- a/common/src/comp/body/quadruped_low.rs +++ b/common/src/comp/body/quadruped_low.rs @@ -1,7 +1,7 @@ use crate::{make_case_elim, make_proj_elim}; use rand::{seq::SliceRandom, thread_rng}; use serde::{Deserialize, Serialize}; -use strum::{Display, EnumString}; +use strum_macros::{Display, EnumString}; make_proj_elim!( body, diff --git a/common/src/comp/body/quadruped_medium.rs b/common/src/comp/body/quadruped_medium.rs index 7f8d36ea0f..708c55db9e 100644 --- a/common/src/comp/body/quadruped_medium.rs +++ b/common/src/comp/body/quadruped_medium.rs @@ -1,7 +1,7 @@ use crate::{make_case_elim, make_proj_elim}; use rand::{seq::SliceRandom, thread_rng}; use serde::{Deserialize, Serialize}; -use strum::{Display, EnumString}; +use strum_macros::{Display, EnumString}; make_proj_elim!( body, diff --git a/common/src/comp/body/quadruped_small.rs b/common/src/comp/body/quadruped_small.rs index 75a5428283..fe0cdd9404 100644 --- a/common/src/comp/body/quadruped_small.rs +++ b/common/src/comp/body/quadruped_small.rs @@ -1,7 +1,7 @@ use crate::{make_case_elim, make_proj_elim}; use rand::{seq::SliceRandom, thread_rng}; use serde::{Deserialize, Serialize}; -use strum::{Display, EnumString}; +use strum_macros::{Display, EnumString}; make_proj_elim!( body, diff --git a/common/src/states/basic_summon.rs b/common/src/states/basic_summon.rs index 35f012b5bf..562175c12c 100644 --- a/common/src/states/basic_summon.rs +++ b/common/src/states/basic_summon.rs @@ -174,12 +174,11 @@ impl CharacterBehavior for Data { poise: comp::Poise::new(body), loadout, body, - agent: Some(comp::Agent::new( - None, - &body, - Behavior::from(BehaviorCapability::SPEAK), - true, - )), + agent: Some( + comp::Agent::from_body(&body) + .with_behavior(Behavior::from(BehaviorCapability::SPEAK)) + .with_no_flee(true), + ), alignment: comp::Alignment::Owned(*data.uid), scale: self .static_data diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 2a7bb6f0a4..e319d789b9 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -1005,11 +1005,12 @@ fn handle_spawn( let ai = opt_ai.unwrap_or(true); let pos = position(server, target, "target")?; - let agent = if let comp::Alignment::Owned(_) | comp::Alignment::Npc = alignment { - comp::Agent::default() - } else { - comp::Agent::default().with_patrol_origin(pos.0) - }; + let mut agent = comp::Agent::from_body(&body()); + + // If unowned, the agent should stay in a particular place + if !matches!(alignment, comp::Alignment::Owned(_)) { + agent = agent.with_patrol_origin(pos.0); + } for _ in 0..amount { let vel = Vec3::new( @@ -1160,7 +1161,7 @@ fn handle_spawn_airship( if let Some(pos) = destination { let (kp, ki, kd) = comp::agent::pid_coefficients(&comp::Body::Ship(ship)); fn pure_z(sp: Vec3, pv: Vec3) -> f32 { (sp - pv).z } - let agent = comp::Agent::default() + let agent = comp::Agent::from_body(&comp::Body::Ship(ship)) .with_destination(pos) .with_position_pid_controller(comp::PidController::new(kp, ki, kd, pos, 0.0, pure_z)); builder = builder.with(agent); diff --git a/server/src/pet.rs b/server/src/pet.rs index 1077b6fe9f..ffef6cc3d9 100644 --- a/server/src/pet.rs +++ b/server/src/pet.rs @@ -49,9 +49,9 @@ fn tame_pet_internal(ecs: &specs::World, pet_entity: Entity, owner: Entity, pet: .write_storage() .insert(pet_entity, pet.unwrap_or_default()); - // TODO: Review whether we should be doing this or not, should the Agent always - // be overwritten when taming a pet? - let _ = ecs.write_storage().insert(pet_entity, Agent::default()); + if let Some(agent) = ecs.write_storage::().get_mut(pet_entity) { + agent.set_no_flee(); + } // Add to group system let clients = ecs.read_storage::(); diff --git a/server/src/rtsim/tick.rs b/server/src/rtsim/tick.rs index 5121a7193a..c8c9362bc3 100644 --- a/server/src/rtsim/tick.rs +++ b/server/src/rtsim/tick.rs @@ -103,15 +103,12 @@ impl<'a> System<'a> for Sys { .map(|e| e as f32) + Vec3::new(0.5, 0.5, body.flying_height()); let pos = comp::Pos(spawn_pos); - let agent = Some(comp::Agent::new( - None, - &body, + let agent = Some(comp::Agent::from_body(&body).with_behavior( if matches!(body, comp::Body::Humanoid(_)) { Behavior::from(BehaviorCapability::SPEAK) } else { Behavior::default() }, - false, )); let rtsim_entity = Some(RtSimEntity(id)); diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index 589b742592..c68189a39c 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -296,16 +296,21 @@ impl<'a> System<'a> for Sys { poise, loadout, agent: if entity.has_agency { - Some(comp::Agent::new( - Some(entity.pos), - &body, - Behavior::default() - .maybe_with_capabilities( - can_speak.then(|| BehaviorCapability::SPEAK), + Some( + comp::Agent::from_body(&body) + .with_behavior( + Behavior::default() + .maybe_with_capabilities( + can_speak.then(|| BehaviorCapability::SPEAK), + ) + .with_trade_site(trade_for_site), ) - .with_trade_site(trade_for_site), - matches!(entity.agent_mark, Some(agent::Mark::Guard)), - )) + .with_patrol_origin(entity.pos) + .with_no_flee(!matches!( + entity.agent_mark, + Some(agent::Mark::Guard) + )), + ) } else { None }, From ee704e171d6d912f9196410db649deb27ab9aa51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Mon, 2 Aug 2021 11:05:05 +0200 Subject: [PATCH 051/155] move translation check to seperate ci step note: TAGUUID is used to avoid sqlinjections by choosing a branch name --- .gitlab/CI/build.gitlab-ci.yml | 21 +++++++++++++++++- .gitlab/scripts/translation.sh | 4 ++++ .gitlab/scripts/unittest.sh | 1 - voxygen/i18n/src/analysis.rs | 13 ++++++----- voxygen/i18n/src/lib.rs | 2 +- voxygen/i18n/src/path.rs | 5 ++++- voxygen/i18n/src/stats.rs | 40 ++++++++++++++++++---------------- 7 files changed, 57 insertions(+), 29 deletions(-) create mode 100755 .gitlab/scripts/translation.sh diff --git a/.gitlab/CI/build.gitlab-ci.yml b/.gitlab/CI/build.gitlab-ci.yml index 9e68e7ee91..005dd3ef95 100644 --- a/.gitlab/CI/build.gitlab-ci.yml +++ b/.gitlab/CI/build.gitlab-ci.yml @@ -11,6 +11,25 @@ unittests: retry: max: 2 +translation: + extends: .release + stage: build + image: registry.gitlab.com/veloren/veloren-docker-ci/cache/quality:${CACHE_IMAGE_TAG} + script: + - ln -s /dockercache/target target + - cat ./.gitlab/scripts/translation.sh + - source ./.gitlab/scripts/translation.sh + - TAGUUID="Z$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)" || echo "ignore this returncode, dont ask me why, it works" + - echo $TAGUUID # Use TAGUUID to mitigate https://xkcd.com/327/ in the branch name + - echo 'SET veloren.timestamp = "'"$(git show --no-patch --no-notes --pretty='%cd' HEAD)"'";' > upload.sql + - echo "SET veloren.branch = \$${TAGUUID}\$${CI_COMMIT_REF_NAME}\$${TAGUUID}\$;" >> upload.sql + - echo "SET veloren.sha = \$${TAGUUID}\$${CI_COMMIT_SHA}\$${TAGUUID}\$;" >> upload.sql + - echo '\copy translations ("country_code", "file_name", "translation_key", "status", "git_commit") from '"'translation_analysis.csv' csv header" >> upload.sql + - cat upload.sql + - PGPASSWORD="${CIDBPASSWORD}" PGSSLROOTCERT="./.gitlab/ci-db.crt" psql "sslmode=verify-ca host=grafana.veloren.net port=15432 dbname=translations" -U hgseehzjtsrghtjdcqw -f upload.sql; + retry: + max: 2 + benchmarks: extends: .release stage: build @@ -23,7 +42,7 @@ benchmarks: - cat ./.gitlab/scripts/benchmark.sh - source ./.gitlab/scripts/benchmark.sh - TAGUUID="Z$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)" || echo "ignore this returncode, dont ask me why, it works" - - echo $TAGUUID + - echo $TAGUUID # Use TAGUUID to mitigate https://xkcd.com/327/ in the branch name - echo 'SET veloren.timestamp = "'"$(git show --no-patch --no-notes --pretty='%cd' HEAD)"'";' > upload.sql - echo "SET veloren.branch = \$${TAGUUID}\$${CI_COMMIT_REF_NAME}\$${TAGUUID}\$;" >> upload.sql - echo "SET veloren.sha = \$${TAGUUID}\$${CI_COMMIT_SHA}\$${TAGUUID}\$;" >> upload.sql diff --git a/.gitlab/scripts/translation.sh b/.gitlab/scripts/translation.sh new file mode 100755 index 0000000000..d05fbf0b2a --- /dev/null +++ b/.gitlab/scripts/translation.sh @@ -0,0 +1,4 @@ +#!/bin/bash +export VELOREN_ASSETS="$(pwd)/assets" +rm -r target/debug/incremental/veloren_* || echo "all good" # TMP FIX FOR 2021-03-22-nightly +time cargo test --package veloren-voxygen-i18n --lib test_all_localizations -- --nocapture --ignored \ No newline at end of file diff --git a/.gitlab/scripts/unittest.sh b/.gitlab/scripts/unittest.sh index 4bb46b4995..5e693fbed2 100755 --- a/.gitlab/scripts/unittest.sh +++ b/.gitlab/scripts/unittest.sh @@ -1,7 +1,6 @@ #!/bin/bash export VELOREN_ASSETS="$(pwd)/assets" rm -r target/debug/incremental/veloren_* || echo "all good" # TMP FIX FOR 2021-03-22-nightly -time cargo test --package veloren-voxygen-i18n --lib test_all_localizations -- --nocapture --ignored && time cargo test --package veloren-common-assets asset_tweak::tests --features asset_tweak --lib && ( rm -r target/debug/incremental* || echo "all good" ) && # TMP FIX FOR 2021-03-22-nightly time cargo test \ No newline at end of file diff --git a/voxygen/i18n/src/analysis.rs b/voxygen/i18n/src/analysis.rs index 28b055c908..f1e2d465c7 100644 --- a/voxygen/i18n/src/analysis.rs +++ b/voxygen/i18n/src/analysis.rs @@ -5,7 +5,7 @@ use crate::{ path::{BasePath, LangPath}, raw::{self, RawFragment, RawLanguage}, stats::{ - print_csv_file, print_overall_stats, print_translation_stats, LocalizationAnalysis, + print_csv_stats, print_overall_stats, print_translation_stats, LocalizationAnalysis, LocalizationStats, }, REFERENCE_LANG, @@ -167,10 +167,8 @@ fn gather_results( Some(LocalizationState::Unused) => stats.unused_entries += 1, Some(LocalizationState::UpToDate) => stats.uptodate_entries += 1, }; - if entry.state != Some(LocalizationState::UpToDate) { - let state_keys = state_map.data.get_mut(&entry.state).expect("prefiled"); - state_keys.push((file.clone(), key.to_owned(), entry.commit_id)); - } + let state_keys = state_map.data.get_mut(&entry.state).expect("prefiled"); + state_keys.push((file.clone(), key.to_owned(), entry.commit_id)); } } @@ -209,10 +207,13 @@ pub fn test_specific_localizations( analysis.insert(language_identifier.to_owned(), (state_map, stats)); } + let output = path.root_path().join("translation_analysis.csv"); + let mut f = std::fs::File::create(output).expect("couldn't write csv file"); + //printing for (language_identifier, (state_map, stats)) in &analysis { if csv_enabled { - print_csv_file(state_map); + print_csv_stats(state_map, &mut f); } else { print_translation_stats( language_identifier, diff --git a/voxygen/i18n/src/lib.rs b/voxygen/i18n/src/lib.rs index 249d9e1493..22862c28a8 100644 --- a/voxygen/i18n/src/lib.rs +++ b/voxygen/i18n/src/lib.rs @@ -355,6 +355,6 @@ mod tests { fn test_all_localizations() { // Generate paths let root_dir = common_assets::find_root().expect("Failed to discover repository root"); - crate::analysis::test_all_localizations(&BasePath::new(&root_dir), true, false); + crate::analysis::test_all_localizations(&BasePath::new(&root_dir), true, true); } } diff --git a/voxygen/i18n/src/path.rs b/voxygen/i18n/src/path.rs index a8f961eef5..3f25e55adf 100644 --- a/voxygen/i18n/src/path.rs +++ b/voxygen/i18n/src/path.rs @@ -109,6 +109,8 @@ fn recursive_fragments_paths_in_language( subfolder: &Path, result: &mut Vec, ) -> Result<(), std::io::Error> { + let manifest_path = PathBuf::from(&format!("{}.{}", LANG_MANIFEST_FILE, LANG_EXTENSION)); + let template_path = PathBuf::from(&format!("{}.{}", "template", LANG_EXTENSION)); let search_dir = lpath.sub_path(subfolder); for fragment_file in search_dir.read_dir()?.flatten() { let file_type = fragment_file.file_type()?; @@ -117,7 +119,8 @@ fn recursive_fragments_paths_in_language( if file_type.is_dir() { recursive_fragments_paths_in_language(lpath, relative_path, result)?; } else if file_type.is_file() - && relative_path != Path::new(&format!("{}.{}", LANG_MANIFEST_FILE, LANG_EXTENSION)) + && relative_path != manifest_path + && relative_path != template_path { result.push(relative_path.to_path_buf()); } diff --git a/voxygen/i18n/src/stats.rs b/voxygen/i18n/src/stats.rs index 9ab93fd062..923840d439 100644 --- a/voxygen/i18n/src/stats.rs +++ b/voxygen/i18n/src/stats.rs @@ -31,22 +31,21 @@ impl LocalizationStats { impl LocalizationAnalysis { pub(crate) fn new(language_identifier: &str) -> Self { let mut data = HashMap::new(); - data.insert(Some(LocalizationState::UpToDate), vec![]); - data.insert(Some(LocalizationState::NotFound), vec![]); - data.insert(Some(LocalizationState::Unused), vec![]); - data.insert(Some(LocalizationState::Outdated), vec![]); - data.insert(None, vec![]); + for key in ALL_LOCALIZATION_STATES.iter() { + data.insert(*key, vec![]); + } Self { language_identifier: language_identifier.to_owned(), data, } } - fn show( + fn show( &self, state: Option, ref_language: &RawLanguage, be_verbose: bool, + output: &mut W, ) { let entries = self.data.get(&state).unwrap_or_else(|| { panic!( @@ -57,7 +56,7 @@ impl LocalizationAnalysis { if entries.is_empty() { return; } - println!("\n\t[{}]", LocalizationState::print(&state)); + writeln!(output, "\n\t[{}]", LocalizationState::print(&state)).unwrap(); for (path, key, commit_id) in entries { if be_verbose { let our_commit = LocalizationAnalysis::print_commit(commit_id); @@ -68,28 +67,30 @@ impl LocalizationAnalysis { .and_then(|s| s.commit_id) .map(|s| format!("{}", s)) .unwrap_or_else(|| "None".to_owned()); - println!("{:60}| {:40} | {:40}", key, our_commit, ref_commit,); + writeln!(output, "{:60}| {:40} | {:40}", key, our_commit, ref_commit).unwrap(); } else { - println!("{}", key); + writeln!(output, "{}", key).unwrap(); } } } - fn csv(&self, state: Option) { + fn csv(&self, state: Option, output: &mut W) { let entries = self .data .get(&state) .unwrap_or_else(|| panic!("called on invalid state: {:?}", state)); for (path, key, commit_id) in entries { let our_commit = LocalizationAnalysis::print_commit(commit_id); - println!( + writeln!( + output, "{},{:?},{},{},{}", self.language_identifier, path, key, LocalizationState::print(&state), our_commit - ); + ) + .unwrap(); } } @@ -126,7 +127,7 @@ pub(crate) fn print_translation_stats( if state == &Some(LocalizationState::UpToDate) { continue; } - state_map.show(*state, ref_language, be_verbose); + state_map.show(*state, ref_language, be_verbose, &mut std::io::stdout()); } println!( @@ -144,14 +145,15 @@ pub(crate) fn print_translation_stats( ); } -pub(crate) fn print_csv_file(state_map: &LocalizationAnalysis) { - println!("country_code,file_name,translation_code,status,git_commit"); +pub(crate) fn print_csv_stats(state_map: &LocalizationAnalysis, output: &mut W) { + writeln!( + output, + "country_code,file_name,translation_key,status,git_commit" + ) + .unwrap(); for state in &ALL_LOCALIZATION_STATES { - if state == &Some(LocalizationState::UpToDate) { - continue; - } - state_map.csv(*state); + state_map.csv(*state, output); } } From bceed446141e05dd7a83fbaf012cf26c4774d558 Mon Sep 17 00:00:00 2001 From: Monty Marz Date: Sun, 1 Aug 2021 21:40:06 +0200 Subject: [PATCH 052/155] transp -> opacity --- assets/voxygen/i18n/cz_CZ/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/de_DE/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/en/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/es_ES/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/es_LA/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/fr_FR/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/hu_HU/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/it_IT/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/ja_JP/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/nl_NL/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/no_NB/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/pl_PL/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/pt_BR/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/pt_PT/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/sv_SE/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/tr_TR/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/uk_UA/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/zh_CN/hud/hud_settings.ron | 4 ++-- assets/voxygen/i18n/zh_TW/hud/hud_settings.ron | 4 ++-- voxygen/src/hud/chat.rs | 8 ++++---- voxygen/src/hud/mod.rs | 2 +- voxygen/src/hud/settings_window/chat.rs | 4 ++-- voxygen/src/hud/settings_window/interface.rs | 14 +++++++------- voxygen/src/session/settings_change.rs | 8 ++++---- voxygen/src/settings/chat.rs | 4 ++-- voxygen/src/settings/interface.rs | 4 ++-- 26 files changed, 60 insertions(+), 60 deletions(-) diff --git a/assets/voxygen/i18n/cz_CZ/hud/hud_settings.ron b/assets/voxygen/i18n/cz_CZ/hud/hud_settings.ron index 3244bafc62..5361635bcd 100644 --- a/assets/voxygen/i18n/cz_CZ/hud/hud_settings.ron +++ b/assets/voxygen/i18n/cz_CZ/hud/hud_settings.ron @@ -15,7 +15,7 @@ "hud.settings.relative_scaling": "Relativní škálování", "hud.settings.custom_scaling": "Vlastní škálování", "hud.settings.crosshair": "Zaměřování", - "hud.settings.transparency": "Průhlednost", + "hud.settings.opacity": "Průhlednost", "hud.settings.hotbar": "Hotbar", "hud.settings.toggle_shortcuts": "Povolit Zkratky", "hud.settings.buffs_skillbar": "Buffy u Skillbaru", @@ -33,7 +33,7 @@ "hud.settings.values": "Hodnoty", "hud.settings.percentages": "Procenta", "hud.settings.chat": "Chat", - "hud.settings.background_transparency": "Průhlednost Pozadí", + "hud.settings.background_opacity": "Průhlednost Pozadí", "hud.settings.chat_character_name": "Jména Postav v Chatu", "hud.settings.loading_tips": "Rady v Načítání", "hud.settings.reset_interface": "Výchozí Nastavení", diff --git a/assets/voxygen/i18n/de_DE/hud/hud_settings.ron b/assets/voxygen/i18n/de_DE/hud/hud_settings.ron index b5e65a87e2..79124ffe70 100644 --- a/assets/voxygen/i18n/de_DE/hud/hud_settings.ron +++ b/assets/voxygen/i18n/de_DE/hud/hud_settings.ron @@ -15,7 +15,7 @@ "hud.settings.relative_scaling": "Relative Skalierung", "hud.settings.custom_scaling": "Benutzerdefinierte Skalierung", "hud.settings.crosshair": "Fadenkreuz", - "hud.settings.transparency": "Transparenz", + "hud.settings.opacity": "Sichtbarkeit", "hud.settings.hotbar": "Hotbar", "hud.settings.toggle_shortcuts": "Tastenkürzel umschalten", "hud.settings.buffs_skillbar": "Effekte an der Skillbar", @@ -33,7 +33,7 @@ "hud.settings.values": "Werte", "hud.settings.percentages": "Prozentangaben", "hud.settings.chat": "Chat", - "hud.settings.background_transparency": "Hintergrundtransparenz", + "hud.settings.background_opacity": "Hintergrundsichtbarkeit", "hud.settings.chat_character_name": "Charakternamen im Chat", "hud.settings.loading_tips": "Tipps auf dem Ladebildschirm", "hud.settings.reset_interface": "Auf Standardwerte zurücksetzen", diff --git a/assets/voxygen/i18n/en/hud/hud_settings.ron b/assets/voxygen/i18n/en/hud/hud_settings.ron index 83f6624406..f16d039e63 100644 --- a/assets/voxygen/i18n/en/hud/hud_settings.ron +++ b/assets/voxygen/i18n/en/hud/hud_settings.ron @@ -17,7 +17,7 @@ "hud.settings.relative_scaling": "Relative Scaling", "hud.settings.custom_scaling": "Custom Scaling", "hud.settings.crosshair": "Crosshair", - "hud.settings.transparency": "Transparency", + "hud.settings.opacity": "Opacity", "hud.settings.hotbar": "Hotbar", "hud.settings.toggle_shortcuts": "Toggle Shortcuts", "hud.settings.buffs_skillbar": "Buffs at Skillbar", @@ -35,7 +35,7 @@ "hud.settings.values": "Values", "hud.settings.percentages": "Percentages", "hud.settings.chat": "Chat", - "hud.settings.background_transparency": "Background Transparency", + "hud.settings.background_opacity": "Background Opacity", "hud.settings.chat_character_name": "Character Names in chat", "hud.settings.loading_tips": "Loading Screen Tips", "hud.settings.reset_interface": "Reset to Defaults", diff --git a/assets/voxygen/i18n/es_ES/hud/hud_settings.ron b/assets/voxygen/i18n/es_ES/hud/hud_settings.ron index fd69a2f39c..586de9564a 100644 --- a/assets/voxygen/i18n/es_ES/hud/hud_settings.ron +++ b/assets/voxygen/i18n/es_ES/hud/hud_settings.ron @@ -15,7 +15,7 @@ "hud.settings.relative_scaling": "Escala relativa", "hud.settings.custom_scaling": "Escala personalizada", "hud.settings.crosshair": "Punto de mira", - "hud.settings.transparency": "Transparencia", + "hud.settings.opacity": "Transparencia", "hud.settings.hotbar": "Barra rápida", "hud.settings.toggle_shortcuts": "Alternar atajos", "hud.settings.buffs_skillbar": "Buffs en la barra de habilidades.", @@ -33,7 +33,7 @@ "hud.settings.values": "Valores", "hud.settings.percentages": "Porcentaje", "hud.settings.chat": "Chat", - "hud.settings.background_transparency": "Transparencia del fondo", + "hud.settings.background_opacity": "Transparencia del fondo", "hud.settings.chat_character_name": "Nombres de personajes en el chat", "hud.settings.loading_tips": "Consejos en pantalla de carga", "hud.settings.reset_interface": "Restablecer por defecto", diff --git a/assets/voxygen/i18n/es_LA/hud/hud_settings.ron b/assets/voxygen/i18n/es_LA/hud/hud_settings.ron index 27691237b3..7764217fa7 100644 --- a/assets/voxygen/i18n/es_LA/hud/hud_settings.ron +++ b/assets/voxygen/i18n/es_LA/hud/hud_settings.ron @@ -14,7 +14,7 @@ "hud.settings.relative_scaling": "Escalado Relativo", "hud.settings.custom_scaling": "Escalado Personalizado", "hud.settings.crosshair": "Mira", - "hud.settings.transparency": "Transparencia", + "hud.settings.opacity": "Transparencia", "hud.settings.hotbar": "Inventario Rápido", "hud.settings.toggle_shortcuts": "Alternar Atajos", "hud.settings.buffs_skillbar": "Buffs en la barra de habilidades.", @@ -32,7 +32,7 @@ "hud.settings.values": "Valores", "hud.settings.percentages": "Porcentajes", "hud.settings.chat": "Chat", - "hud.settings.background_transparency": "Transparencia del Fondo", + "hud.settings.background_opacity": "Transparencia del Fondo", "hud.settings.chat_character_name": "Nombres de Personajes en el chat", "hud.settings.loading_tips": "Consejos en Pantalla de Carga", diff --git a/assets/voxygen/i18n/fr_FR/hud/hud_settings.ron b/assets/voxygen/i18n/fr_FR/hud/hud_settings.ron index 73894da599..9c74911606 100644 --- a/assets/voxygen/i18n/fr_FR/hud/hud_settings.ron +++ b/assets/voxygen/i18n/fr_FR/hud/hud_settings.ron @@ -15,7 +15,7 @@ "hud.settings.relative_scaling": "Echelle relative", "hud.settings.custom_scaling": "Echelle personalisée", "hud.settings.crosshair": "Réticule", - "hud.settings.transparency": "Transparence", + "hud.settings.opacity": "Transparence", "hud.settings.hotbar": "Barre d'action", "hud.settings.toggle_shortcuts": "Activer les raccourcis", "hud.settings.buffs_skillbar": "Effets sur la barre de compétences", @@ -33,7 +33,7 @@ "hud.settings.values": "Valeurs", "hud.settings.percentages": "Pourcentages", "hud.settings.chat": "Tchat", - "hud.settings.background_transparency": "Transparence de l'arrière-plan", + "hud.settings.background_opacity": "Transparence de l'arrière-plan", "hud.settings.chat_character_name": "Noms des personnages dans le tchat", "hud.settings.loading_tips": "Astuces sur l'écran de chargement", "hud.settings.reset_interface": "Restaurer par Défaut", diff --git a/assets/voxygen/i18n/hu_HU/hud/hud_settings.ron b/assets/voxygen/i18n/hu_HU/hud/hud_settings.ron index 03d955849e..bde7bc0ecc 100644 --- a/assets/voxygen/i18n/hu_HU/hud/hud_settings.ron +++ b/assets/voxygen/i18n/hu_HU/hud/hud_settings.ron @@ -17,7 +17,7 @@ "hud.settings.relative_scaling": "Relatív méretezés", "hud.settings.custom_scaling": "Egyéni méretezés", "hud.settings.crosshair": "Célkereszt", - "hud.settings.transparency": "Átlátszóság", + "hud.settings.opacity": "Átlátszóság", "hud.settings.hotbar": "Gyorssáv", "hud.settings.toggle_shortcuts": "Gyorsbillentyűk megjelenítése/elrejtése", "hud.settings.buffs_skillbar": "Hatások a gyossávnál", @@ -35,7 +35,7 @@ "hud.settings.values": "Értékek", "hud.settings.percentages": "Százalékok", "hud.settings.chat": "Csevegés", - "hud.settings.background_transparency": "Háttér átlátszósága", + "hud.settings.background_opacity": "Háttér átlátszósága", "hud.settings.chat_character_name": "Karakternevek a csevegésben", "hud.settings.loading_tips": "Tippek a töltőképernyőn", "hud.settings.reset_interface": "Alapértékek visszaállítása", diff --git a/assets/voxygen/i18n/it_IT/hud/hud_settings.ron b/assets/voxygen/i18n/it_IT/hud/hud_settings.ron index 7d00082ec5..0defe68179 100644 --- a/assets/voxygen/i18n/it_IT/hud/hud_settings.ron +++ b/assets/voxygen/i18n/it_IT/hud/hud_settings.ron @@ -15,7 +15,7 @@ "hud.settings.relative_scaling": "Ridimensionamento Relativo", "hud.settings.custom_scaling": "Ridimensionamento Personalizzato", "hud.settings.crosshair": "Mirino", - "hud.settings.transparency": "Trasparenza", + "hud.settings.opacity": "Trasparenza", "hud.settings.hotbar": "Slot Rapido", "hud.settings.toggle_shortcuts": "Attiva/Disattiva Tasti rapidi", "hud.settings.buffs_skillbar": "Buff alla Barra delle Abilità", @@ -33,7 +33,7 @@ "hud.settings.values": "Valori", "hud.settings.percentages": "Percentuali", "hud.settings.chat": "Chat", - "hud.settings.background_transparency": "Trasparenza Sfondo", + "hud.settings.background_opacity": "Trasparenza Sfondo", "hud.settings.chat_character_name": "Nome Personaggi in chat", "hud.settings.loading_tips": "Consigli Schermata di Caricamento", "hud.settings.reset_interface": "Ripristina Predefiniti", diff --git a/assets/voxygen/i18n/ja_JP/hud/hud_settings.ron b/assets/voxygen/i18n/ja_JP/hud/hud_settings.ron index c9bb53334e..10d7ee3d21 100644 --- a/assets/voxygen/i18n/ja_JP/hud/hud_settings.ron +++ b/assets/voxygen/i18n/ja_JP/hud/hud_settings.ron @@ -15,7 +15,7 @@ "hud.settings.relative_scaling": "相対的スケール", "hud.settings.custom_scaling": "カスタムスケール", "hud.settings.crosshair": "十字線", - "hud.settings.transparency": "透明度", + "hud.settings.opacity": "透明度", "hud.settings.hotbar": "ホットバー", "hud.settings.toggle_shortcuts": "ショートカット表示切り替え", "hud.settings.buffs_skillbar": "Buffs at Skillbar", @@ -33,7 +33,7 @@ "hud.settings.values": "数値", "hud.settings.percentages": "パーセント", "hud.settings.chat": "チャット", - "hud.settings.background_transparency": "背景透明度", + "hud.settings.background_opacity": "背景透明度", "hud.settings.chat_character_name": "チャット内にキャラクター名表示", "hud.settings.loading_tips": "ロード画面のヒント表示", "hud.settings.reset_interface": "デフォルトに戻す", diff --git a/assets/voxygen/i18n/nl_NL/hud/hud_settings.ron b/assets/voxygen/i18n/nl_NL/hud/hud_settings.ron index 84318ff1cc..41aba2277e 100644 --- a/assets/voxygen/i18n/nl_NL/hud/hud_settings.ron +++ b/assets/voxygen/i18n/nl_NL/hud/hud_settings.ron @@ -15,7 +15,7 @@ "hud.settings.relative_scaling": "Relatief Schalen", "hud.settings.custom_scaling": "Aangepast Schalen", "hud.settings.crosshair": "Richtkruis", - "hud.settings.transparency": "Doorschijnbaarheid", + "hud.settings.opacity": "Doorschijnbaarheid", "hud.settings.hotbar": "Hotbar", "hud.settings.toggle_shortcuts": "Toon Sneltoetsen", "hud.settings.toggle_bar_experience": "Toon Experience Balk", @@ -31,7 +31,7 @@ "hud.settings.values": "Waarden", "hud.settings.percentages": "Percentages", "hud.settings.chat": "Chat", - "hud.settings.background_transparency": "Transparantie Achtergrond", + "hud.settings.background_opacity": "Transparantie Achtergrond", "hud.settings.chat_character_name": "Karakternamen in de Chat", "hud.settings.loading_tips": "Laadscherm Tips", diff --git a/assets/voxygen/i18n/no_NB/hud/hud_settings.ron b/assets/voxygen/i18n/no_NB/hud/hud_settings.ron index 7c67540070..b57975190c 100644 --- a/assets/voxygen/i18n/no_NB/hud/hud_settings.ron +++ b/assets/voxygen/i18n/no_NB/hud/hud_settings.ron @@ -14,7 +14,7 @@ "hud.settings.relative_scaling": "Relativ Skalering", "hud.settings.custom_scaling": "Tilpasset Skalering", "hud.settings.crosshair": "Retikkel", - "hud.settings.transparency": "Gjennomsiktighet", + "hud.settings.opacity": "Gjennomsiktighet", "hud.settings.hotbar": "Hurtigknappsbar", "hud.settings.toggle_shortcuts": "Veksle Snarveier", "hud.settings.buffs_skillbar": "Ikoner på Ferdighetsbar", @@ -32,7 +32,7 @@ "hud.settings.values": "Verdier", "hud.settings.percentages": "Prosentandeler", "hud.settings.chat": "Chat", - "hud.settings.background_transparency": "Bakgrunnsgjennomsiktighet", + "hud.settings.background_opacity": "Bakgrunnsgjennomsiktighet", "hud.settings.chat_character_name": "Karakternavn i chat", "hud.settings.loading_tips": "Oppstartsskjerm Tips", diff --git a/assets/voxygen/i18n/pl_PL/hud/hud_settings.ron b/assets/voxygen/i18n/pl_PL/hud/hud_settings.ron index f37f2a7957..916aeba80c 100644 --- a/assets/voxygen/i18n/pl_PL/hud/hud_settings.ron +++ b/assets/voxygen/i18n/pl_PL/hud/hud_settings.ron @@ -13,7 +13,7 @@ "hud.settings.relative_scaling": "Relatywne skalowanie", "hud.settings.custom_scaling": "Niestandardowe skalowanie", "hud.settings.crosshair": "Celownik", - "hud.settings.transparency": "Przezroczystość", + "hud.settings.opacity": "Przezroczystość", "hud.settings.hotbar": "Pasek skrótów", "hud.settings.toggle_shortcuts": "Przełącz skróty", "hud.settings.buffs_skillbar": "Wzmocnienia na pasku umiejętności", @@ -31,7 +31,7 @@ "hud.settings.values": "Wartości", "hud.settings.percentages": "Procenty", "hud.settings.chat": "Czat", - "hud.settings.background_transparency": "Przezroczystość tła", + "hud.settings.background_opacity": "Przezroczystość tła", "hud.settings.chat_character_name": "Imiona postaci na czacie", "hud.settings.loading_tips": "Porady na ekranie ładowania", "hud.settings.reset_interface": "Zresetuj ustawienia", diff --git a/assets/voxygen/i18n/pt_BR/hud/hud_settings.ron b/assets/voxygen/i18n/pt_BR/hud/hud_settings.ron index f4ffa2b767..9776ffc7de 100644 --- a/assets/voxygen/i18n/pt_BR/hud/hud_settings.ron +++ b/assets/voxygen/i18n/pt_BR/hud/hud_settings.ron @@ -17,7 +17,7 @@ "hud.settings.relative_scaling": "Escala Relativa", "hud.settings.custom_scaling": "Escala Customizada", "hud.settings.crosshair": "Mira", - "hud.settings.transparency": "Transparência", + "hud.settings.opacity": "Transparência", "hud.settings.hotbar": "Hotbar", "hud.settings.toggle_shortcuts": "Mostar/Ocultar atalhos", "hud.settings.buffs_skillbar": "Buffs na Barra de Habilidades", @@ -35,7 +35,7 @@ "hud.settings.values": "Valores", "hud.settings.percentages": "Porcentagens", "hud.settings.chat": "Chat", - "hud.settings.background_transparency": "Transparência de Fundo", + "hud.settings.background_opacity": "Transparência de Fundo", "hud.settings.chat_character_name": "Nomes de Personagem no chat", "hud.settings.loading_tips": "Dicas na Tela de Carregamento", "hud.settings.reset_interface": "Restaurar Padrões", diff --git a/assets/voxygen/i18n/pt_PT/hud/hud_settings.ron b/assets/voxygen/i18n/pt_PT/hud/hud_settings.ron index bf19f4decb..b99666d496 100644 --- a/assets/voxygen/i18n/pt_PT/hud/hud_settings.ron +++ b/assets/voxygen/i18n/pt_PT/hud/hud_settings.ron @@ -14,7 +14,7 @@ "hud.settings.relative_scaling": "Escala relativa", "hud.settings.custom_scaling": "Escala customizada", "hud.settings.crosshair": "Crosshair", - "hud.settings.transparency": "Transparência", + "hud.settings.opacity": "Transparência", "hud.settings.hotbar": "Hotbar", "hud.settings.toggle_shortcuts": "Mostar/Ocultar atalhos", "hud.settings.toggle_bar_experience": "Mostar/Ocultar barra de experiência", @@ -27,7 +27,7 @@ "hud.settings.values": "Valores", "hud.settings.percentages": "Percentagens", "hud.settings.chat": "Chat", - "hud.settings.background_transparency": "Transparência do fundo", + "hud.settings.background_opacity": "Transparência do fundo", "hud.settings.pan_sensitivity": "Sensibilidade de rotação", "hud.settings.zoom_sensitivity": "Sensibilidade de zoom", diff --git a/assets/voxygen/i18n/sv_SE/hud/hud_settings.ron b/assets/voxygen/i18n/sv_SE/hud/hud_settings.ron index 98024b5a3e..0e69dd102c 100644 --- a/assets/voxygen/i18n/sv_SE/hud/hud_settings.ron +++ b/assets/voxygen/i18n/sv_SE/hud/hud_settings.ron @@ -17,7 +17,7 @@ "hud.settings.relative_scaling": "Relativ skalning", "hud.settings.custom_scaling": "Anpassad skalning", "hud.settings.crosshair": "Hårkors", - "hud.settings.transparency": "Transparens", + "hud.settings.opacity": "Transparens", "hud.settings.hotbar": "Snabbåtkomst", "hud.settings.toggle_shortcuts": "Växla genvägar", "hud.settings.buffs_skillbar": "Buffs at Skillbar", // TODO @@ -35,7 +35,7 @@ "hud.settings.values": "Värden", "hud.settings.percentages": "Procent", "hud.settings.chat": "Konversation", - "hud.settings.background_transparency": "Bakgrundstransparens", + "hud.settings.background_opacity": "Bakgrundstransparens", "hud.settings.chat_character_name": "Karaktärers namn i konverationer", "hud.settings.loading_tips": "Tips på laddningsskärmen", "hud.settings.reset_interface": "Återställ till standard", diff --git a/assets/voxygen/i18n/tr_TR/hud/hud_settings.ron b/assets/voxygen/i18n/tr_TR/hud/hud_settings.ron index 57ae32a996..db24682753 100644 --- a/assets/voxygen/i18n/tr_TR/hud/hud_settings.ron +++ b/assets/voxygen/i18n/tr_TR/hud/hud_settings.ron @@ -15,7 +15,7 @@ "hud.settings.relative_scaling": "Otomatik Ölçek", "hud.settings.custom_scaling": "Sabit Ölçek", "hud.settings.crosshair": "İmleç tipi", - "hud.settings.transparency": "Şeffaflık", + "hud.settings.opacity": "Şeffaflık", "hud.settings.hotbar": "Aksiyon Çubuğu", "hud.settings.toggle_shortcuts": "Kısayolları aç/kapa", "hud.settings.buffs_skillbar": "Etkiler yetenek çubuğunun üstünde", @@ -33,7 +33,7 @@ "hud.settings.values": "Sayılar", "hud.settings.percentages": "Yüzdeler", "hud.settings.chat": "Sohbet", - "hud.settings.background_transparency": "Arkaplan Şeffaflığı", + "hud.settings.background_opacity": "Arkaplan Şeffaflığı", "hud.settings.chat_character_name": "Sohbette karakter isimlerini göster", "hud.settings.loading_tips": "Yükleme ekranı ipuçları", diff --git a/assets/voxygen/i18n/uk_UA/hud/hud_settings.ron b/assets/voxygen/i18n/uk_UA/hud/hud_settings.ron index 6189b2c334..ce0e78db63 100644 --- a/assets/voxygen/i18n/uk_UA/hud/hud_settings.ron +++ b/assets/voxygen/i18n/uk_UA/hud/hud_settings.ron @@ -17,7 +17,7 @@ "hud.settings.relative_scaling": "Відносне", "hud.settings.custom_scaling": "Ручне", "hud.settings.crosshair": "Приціл", - "hud.settings.transparency": "Прозорість", + "hud.settings.opacity": "Прозорість", "hud.settings.hotbar": "Панель швидкого доступу", "hud.settings.toggle_shortcuts": "Гарячі клавіші", "hud.settings.buffs_skillbar": "Бафи біля Панелі Швидкого Доступу", @@ -35,7 +35,7 @@ "hud.settings.values": "Значення", "hud.settings.percentages": "Відсотки", "hud.settings.chat": "Чат", - "hud.settings.background_transparency": "Прозорість фону", + "hud.settings.background_opacity": "Прозорість фону", "hud.settings.chat_character_name": "Імена персонажів в чаті", "hud.settings.loading_tips": "Підказки на екрані завантаження", "hud.settings.reset_interface": "Значення за\n замовчуванням", diff --git a/assets/voxygen/i18n/zh_CN/hud/hud_settings.ron b/assets/voxygen/i18n/zh_CN/hud/hud_settings.ron index d01d5e4a09..64683542a4 100644 --- a/assets/voxygen/i18n/zh_CN/hud/hud_settings.ron +++ b/assets/voxygen/i18n/zh_CN/hud/hud_settings.ron @@ -15,7 +15,7 @@ "hud.settings.relative_scaling": "相对缩放", "hud.settings.custom_scaling": "自定义缩放", "hud.settings.crosshair": "准星", - "hud.settings.transparency": "透明度", + "hud.settings.opacity": "透明度", "hud.settings.hotbar": "快捷键", "hud.settings.toggle_shortcuts": "显示快捷键", "hud.settings.buffs_skillbar": "增益效果显示在技能栏", @@ -33,7 +33,7 @@ "hud.settings.values": "数字", "hud.settings.percentages": "百分比", "hud.settings.chat": "聊天", - "hud.settings.background_transparency": "背景透明度", + "hud.settings.background_opacity": "背景透明度", "hud.settings.chat_character_name": "聊天显示人物名称", "hud.settings.loading_tips": "加载游戏时显示小提示", "hud.settings.reset_interface": "重置为默认", diff --git a/assets/voxygen/i18n/zh_TW/hud/hud_settings.ron b/assets/voxygen/i18n/zh_TW/hud/hud_settings.ron index 49684bed11..c1fe7bd594 100644 --- a/assets/voxygen/i18n/zh_TW/hud/hud_settings.ron +++ b/assets/voxygen/i18n/zh_TW/hud/hud_settings.ron @@ -15,7 +15,7 @@ "hud.settings.relative_scaling": "相對大小", "hud.settings.custom_scaling": "自訂大小", "hud.settings.crosshair": "準星", - "hud.settings.transparency": "透明度", + "hud.settings.opacity": "透明度", "hud.settings.hotbar": "角色資訊", "hud.settings.toggle_shortcuts": "顯示快捷鍵", "hud.settings.toggle_bar_experience": "顯示經驗條", @@ -28,7 +28,7 @@ "hud.settings.values": "數字", "hud.settings.percentages": "百分比", "hud.settings.chat": "聊天欄", - "hud.settings.background_transparency": "背景透明度", + "hud.settings.background_opacity": "背景透明度", "hud.settings.none": "無", "hud.settings.pan_sensitivity": "滑鼠靈敏度", diff --git a/voxygen/src/hud/chat.rs b/voxygen/src/hud/chat.rs index 8a48c212e7..43edfbc071 100644 --- a/voxygen/src/hud/chat.rs +++ b/voxygen/src/hud/chat.rs @@ -375,7 +375,7 @@ impl<'a> Widget for Chat<'a> { _ => 0.0, }; Rectangle::fill([CHAT_BOX_WIDTH, y]) - .rgba(0.0, 0.0, 0.0, chat_settings.chat_transp + 0.1) + .rgba(0.0, 0.0, 0.0, chat_settings.chat_opacity + 0.1) .bottom_left_with_margins_on(ui.window, 10.0, 10.0) .w(CHAT_BOX_WIDTH) .set(state.ids.chat_input_bg, ui); @@ -393,7 +393,7 @@ impl<'a> Widget for Chat<'a> { // Message box Rectangle::fill([CHAT_BOX_WIDTH, CHAT_BOX_HEIGHT]) - .rgba(0.0, 0.0, 0.0, chat_settings.chat_transp) + .rgba(0.0, 0.0, 0.0, chat_settings.chat_opacity) .and(|r| { if input_focused { r.up_from(state.ids.chat_input_bg, 0.0) @@ -518,10 +518,10 @@ impl<'a> Widget for Chat<'a> { .filter(|t| t <= &1.5) { let alpha = 1.0 - (time_since_hover / 1.5).powi(4); - let shading = color::rgba(1.0, 0.82, 0.27, (chat_settings.chat_transp + 0.1) * alpha); + let shading = color::rgba(1.0, 0.82, 0.27, (chat_settings.chat_opacity + 0.1) * alpha); Rectangle::fill([CHAT_BOX_WIDTH, CHAT_TAB_HEIGHT]) - .rgba(0.0, 0.0, 0.0, (chat_settings.chat_transp + 0.1) * alpha) + .rgba(0.0, 0.0, 0.0, (chat_settings.chat_opacity + 0.1) * alpha) .up_from(state.ids.message_box_bg, 0.0) .set(state.ids.chat_tab_align, ui); if ui diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 5250e94d69..0d4e7ac2af 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -1143,7 +1143,7 @@ impl Hud { 1.0, 1.0, 1.0, - self.crosshair_opacity * global_state.settings.interface.crosshair_transp, + self.crosshair_opacity * global_state.settings.interface.crosshair_opacity, ))) .set(self.ids.crosshair_outer, ui_widgets); Image::new(self.imgs.crosshair_inner) diff --git a/voxygen/src/hud/settings_window/chat.rs b/voxygen/src/hud/settings_window/chat.rs index 6f74fcd20b..4c54399464 100644 --- a/voxygen/src/hud/settings_window/chat.rs +++ b/voxygen/src/hud/settings_window/chat.rs @@ -150,7 +150,7 @@ impl<'a> Widget for Chat<'a> { // Chat Transp Text::new( self.localized_strings - .get("hud.settings.background_transparency"), + .get("hud.settings.background_opacity"), ) .down_from(state.ids.general_txt, 20.0) .font_size(self.fonts.cyri.scale(14)) @@ -158,7 +158,7 @@ impl<'a> Widget for Chat<'a> { .color(TEXT_COLOR) .set(state.ids.transp_text, ui); if let Some(new_val) = ImageSlider::continuous( - chat_settings.chat_transp, + chat_settings.chat_opacity, 0.0, 0.9, self.imgs.slider_indicator, diff --git a/voxygen/src/hud/settings_window/interface.rs b/voxygen/src/hud/settings_window/interface.rs index 27f4745a60..8ccc2c8d34 100644 --- a/voxygen/src/hud/settings_window/interface.rs +++ b/voxygen/src/hud/settings_window/interface.rs @@ -159,7 +159,7 @@ impl<'a> Widget for Interface<'a> { .set(state.ids.window_scrollbar, ui); let bar_values = self.global_state.settings.interface.bar_numbers; - let crosshair_transp = self.global_state.settings.interface.crosshair_transp; + let crosshair_opacity = self.global_state.settings.interface.crosshair_opacity; let crosshair_type = self.global_state.settings.interface.crosshair_type; let ui_scale = self.global_state.settings.interface.ui_scale; @@ -441,7 +441,7 @@ impl<'a> Widget for Interface<'a> { 1.0, 1.0, 1.0, - self.global_state.settings.interface.crosshair_transp, + self.global_state.settings.interface.crosshair_opacity, ))) .graphics_for(state.ids.ch_1_bg) .set(state.ids.crosshair_outer_1, ui); @@ -484,7 +484,7 @@ impl<'a> Widget for Interface<'a> { 1.0, 1.0, 1.0, - self.global_state.settings.interface.crosshair_transp, + self.global_state.settings.interface.crosshair_opacity, ))) .graphics_for(state.ids.ch_2_bg) .set(state.ids.crosshair_outer_2, ui); @@ -527,7 +527,7 @@ impl<'a> Widget for Interface<'a> { 1.0, 1.0, 1.0, - self.global_state.settings.interface.crosshair_transp, + self.global_state.settings.interface.crosshair_opacity, ))) .graphics_for(state.ids.ch_3_bg) .set(state.ids.crosshair_outer_3, ui); @@ -544,7 +544,7 @@ impl<'a> Widget for Interface<'a> { .font_id(self.fonts.cyri.conrod_id) .color(TEXT_COLOR) .set(state.ids.ch_title, ui); - Text::new(self.localized_strings.get("hud.settings.transparency")) + Text::new(self.localized_strings.get("hud.settings.opacity")) .right_from(state.ids.ch_3_bg, 20.0) .font_size(self.fonts.cyri.scale(14)) .font_id(self.fonts.cyri.conrod_id) @@ -552,7 +552,7 @@ impl<'a> Widget for Interface<'a> { .set(state.ids.ch_transp_text, ui); if let Some(new_val) = ImageSlider::continuous( - crosshair_transp, + crosshair_opacity, 0.0, 1.0, self.imgs.slider_indicator, @@ -568,7 +568,7 @@ impl<'a> Widget for Interface<'a> { events.push(CrosshairTransp(new_val)); } - Text::new(&format!("{:.2}", crosshair_transp,)) + Text::new(&format!("{:.2}", crosshair_opacity,)) .right_from(state.ids.ch_transp_slider, 8.0) .font_size(self.fonts.cyri.scale(14)) .graphics_for(state.ids.ch_transp_slider) diff --git a/voxygen/src/session/settings_change.rs b/voxygen/src/session/settings_change.rs index 62e18e8547..7d4b63b11e 100644 --- a/voxygen/src/session/settings_change.rs +++ b/voxygen/src/session/settings_change.rs @@ -207,8 +207,8 @@ impl SettingsChange { SettingsChange::Chat(chat_change) => { let chat_tabs = &mut settings.chat.chat_tabs; match chat_change { - Chat::Transp(chat_transp) => { - settings.chat.chat_transp = chat_transp; + Chat::Transp(chat_opacity) => { + settings.chat.chat_opacity = chat_opacity; }, Chat::CharName(chat_char_name) => { settings.chat.chat_character_name = chat_char_name; @@ -453,8 +453,8 @@ impl SettingsChange { Interface::ToggleTips(loading_tips) => { settings.interface.loading_tips = loading_tips; }, - Interface::CrosshairTransp(crosshair_transp) => { - settings.interface.crosshair_transp = crosshair_transp; + Interface::CrosshairTransp(crosshair_opacity) => { + settings.interface.crosshair_opacity = crosshair_opacity; }, Interface::CrosshairType(crosshair_type) => { settings.interface.crosshair_type = crosshair_type; diff --git a/voxygen/src/settings/chat.rs b/voxygen/src/settings/chat.rs index 3df61e1964..ae16c71190 100644 --- a/voxygen/src/settings/chat.rs +++ b/voxygen/src/settings/chat.rs @@ -69,7 +69,7 @@ impl Default for ChatFilter { #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(default)] pub struct ChatSettings { - pub chat_transp: f32, + pub chat_opacity: f32, pub chat_character_name: bool, pub chat_tabs: Vec, pub chat_tab_index: Option, @@ -78,7 +78,7 @@ pub struct ChatSettings { impl Default for ChatSettings { fn default() -> Self { Self { - chat_transp: 0.4, + chat_opacity: 0.4, chat_character_name: true, chat_tabs: vec![ChatTab::default()], chat_tab_index: Some(0), diff --git a/voxygen/src/settings/interface.rs b/voxygen/src/settings/interface.rs index b85caac831..7f20f8b5bc 100644 --- a/voxygen/src/settings/interface.rs +++ b/voxygen/src/settings/interface.rs @@ -17,7 +17,7 @@ pub struct InterfaceSettings { pub sct_damage_batch: bool, pub speech_bubble_dark_mode: bool, pub speech_bubble_icon: bool, - pub crosshair_transp: f32, + pub crosshair_opacity: f32, pub crosshair_type: CrosshairType, pub intro_show: Intro, pub xp_bar: XpBar, @@ -53,7 +53,7 @@ impl Default for InterfaceSettings { sct_damage_batch: false, speech_bubble_dark_mode: false, speech_bubble_icon: true, - crosshair_transp: 0.6, + crosshair_opacity: 0.6, crosshair_type: CrosshairType::Round, intro_show: Intro::Show, xp_bar: XpBar::Always, From 38432cc88044e083217b839718143cf700431973 Mon Sep 17 00:00:00 2001 From: Knightress Paladin Date: Sat, 17 Jul 2021 23:55:22 -0700 Subject: [PATCH 053/155] Restructured logic for staff AI --- .../common/entity/dungeon/tier-5/warlock.ron | 2 + .../common/skillset/dungeon/tier-5/staff.ron | 21 ++++++ .../skillset/dungeon/tier-5/warlock.ron | 5 ++ server/src/sys/agent.rs | 72 +++++++++++-------- 4 files changed, 72 insertions(+), 28 deletions(-) create mode 100644 assets/common/skillset/dungeon/tier-5/staff.ron create mode 100644 assets/common/skillset/dungeon/tier-5/warlock.ron diff --git a/assets/common/entity/dungeon/tier-5/warlock.ron b/assets/common/entity/dungeon/tier-5/warlock.ron index 0ee439d4df..6caba2a001 100644 --- a/assets/common/entity/dungeon/tier-5/warlock.ron +++ b/assets/common/entity/dungeon/tier-5/warlock.ron @@ -11,4 +11,6 @@ EntityConfig ( ])), meta: [], + loadout_asset: None, + skillset_asset: Some("common.skillset.dungeon.tier-5.warlock"), ) diff --git a/assets/common/skillset/dungeon/tier-5/staff.ron b/assets/common/skillset/dungeon/tier-5/staff.ron new file mode 100644 index 0000000000..59d5e9ae24 --- /dev/null +++ b/assets/common/skillset/dungeon/tier-5/staff.ron @@ -0,0 +1,21 @@ +([ + Group(Weapon(Staff)), + + // Fireball + Skill((Staff(BDamage), Some(1))), + Skill((Staff(BRegen), Some(1))), + Skill((Staff(BRadius), Some(1))), + + // Flamethrower + Skill((Staff(FDamage), Some(1))), + Skill((Staff(FRange), Some(1))), + Skill((Staff(FDrain), Some(1))), + Skill((Staff(FVelocity), Some(1))), + + // Shockwave + Skill((Staff(UnlockShockwave), None)), + Skill((Staff(SDamage), Some(1))), + Skill((Staff(SKnockback), Some(1))), + Skill((Staff(SRange), Some(1))), + Skill((Staff(SCost), Some(1))), +]) diff --git a/assets/common/skillset/dungeon/tier-5/warlock.ron b/assets/common/skillset/dungeon/tier-5/warlock.ron new file mode 100644 index 0000000000..a8944845e0 --- /dev/null +++ b/assets/common/skillset/dungeon/tier-5/warlock.ron @@ -0,0 +1,5 @@ +([ + // Gather all warlock skills + Tree("common.skillset.dungeon.tier-5.bow"), + Tree("common.skillset.dungeon.tier-5.staff"), +]) diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index a0ac28315e..fedd4597b0 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -2443,40 +2443,37 @@ impl<'a> AgentData<'a> { tgt_data: &TargetData, read_data: &ReadData, ) { - if self.body.map(|b| b.is_humanoid()).unwrap_or(false) && attack_data.in_min_range() { + //TODO: minimum energy values for skills and rolls are hard coded from + // approximate guesses + if self.body.map(|b| b.is_humanoid()).unwrap_or(false) + && attack_data.in_min_range() + && self.energy.current() > 100 + { + // if a humanoid, have enough stamina, and in melee range, emergency roll controller .actions .push(ControlAction::basic_input(InputKind::Roll)); - } else if attack_data.dist_sqrd < (5.0 * attack_data.min_attack_dist).powi(2) - && attack_data.angle < 15.0 + } else if !matches!(self.char_state, CharacterState::Shockwave(c) if !matches!(c.stage_section, StageSection::Recover)) { - if agent.action_state.timer < 1.5 { - controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0) - .xy() - .rotated_z(0.47 * PI) - .try_normalized() - .unwrap_or_else(Vec2::unit_y); - agent.action_state.timer += read_data.dt.0; - } else if agent.action_state.timer < 3.0 { - controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0) - .xy() - .rotated_z(-0.47 * PI) - .try_normalized() - .unwrap_or_else(Vec2::unit_y); - agent.action_state.timer += read_data.dt.0; - } else { - agent.action_state.timer = 0.0; - } + // only try to use another ability if not already in recover and not casting + // shockwave + let target_approaching_speed = -agent + .target + .as_ref() + .map(|t| t.target) + .and_then(|e| read_data.velocities.get(e)) + .map_or(0.0, |v| v.0.dot(self.ori.look_vec())); if self .skill_set .has_skill(Skill::Staff(StaffSkill::UnlockShockwave)) - && self.energy.current() > 800 - && thread_rng().gen::() > 0.8 + && target_approaching_speed > 20.0 + && self.energy.current() > 200 { + // if enemy is closing distance quickly, use shockwave to knock back controller .actions .push(ControlAction::basic_input(InputKind::Ability(0))); - } else if self.energy.current() > 10 { + } else if self.energy.current() > 100 && attack_data.dist_sqrd < 280.0 { controller .actions .push(ControlAction::basic_input(InputKind::Secondary)); @@ -2485,7 +2482,26 @@ impl<'a> AgentData<'a> { .actions .push(ControlAction::basic_input(InputKind::Primary)); } + } + // Logic to move. Intentionally kept separate from ability logic so duplicated + // work is less necessary. + if attack_data.dist_sqrd < (2.0 * attack_data.min_attack_dist).powi(2) { + // Attempt to move away from target if too close + if let Some((bearing, speed)) = agent.chaser.chase( + &*read_data.terrain, + self.pos.0, + self.vel.0, + tgt_data.pos.0, + TraversalConfig { + min_tgt_dist: 1.25, + ..self.traversal_config + }, + ) { + controller.inputs.move_dir = + -bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed; + } } else if attack_data.dist_sqrd < MAX_PATH_DIST.powi(2) { + // Else attempt to circle target if neither too close nor too far if let Some((bearing, speed)) = agent.chaser.chase( &*read_data.terrain, self.pos.0, @@ -2501,7 +2517,7 @@ impl<'a> AgentData<'a> { self.pos, tgt_data.pos, attack_data.dist_sqrd, - ) && attack_data.angle < 15.0 + ) && attack_data.angle < 45.0 { controller.inputs.move_dir = bearing .xy() @@ -2509,25 +2525,25 @@ impl<'a> AgentData<'a> { .try_normalized() .unwrap_or_else(Vec2::zero) * speed; - controller - .actions - .push(ControlAction::basic_input(InputKind::Primary)); } else { + // Unless cannot see target, then move towards them controller.inputs.move_dir = bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed; self.jump_if(controller, bearing.z > 1.5); controller.inputs.move_z = bearing.z; } } + // Sometimes try to roll if self.body.map(|b| b.is_humanoid()).unwrap_or(false) && attack_data.dist_sqrd < 16.0f32.powi(2) - && thread_rng().gen::() < 0.02 + && thread_rng().gen::() < 0.01 { controller .actions .push(ControlAction::basic_input(InputKind::Roll)); } } else { + // If too far, move towards target self.path_toward_target(agent, controller, tgt_data, read_data, false, false, None); } } From e87bfae5cd33a7f2712a2e3f59def62e2698a273 Mon Sep 17 00:00:00 2001 From: Knightress Paladin Date: Wed, 21 Jul 2021 17:56:51 -0700 Subject: [PATCH 054/155] Allowed staff AI to queue shockwave if occupied by animation --- server/src/sys/agent.rs | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index fedd4597b0..3b465692e4 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -2445,14 +2445,30 @@ impl<'a> AgentData<'a> { ) { //TODO: minimum energy values for skills and rolls are hard coded from // approximate guesses + let mut flamethrower_range = 20.0_f32; + if let Ok(Some(level)) = self.skill_set.skill_level(Skill::Staff(StaffSkill::FRange)) { + flamethrower_range *= 1.25_f32.powi(level.into()); + } + let mut shockwave_cost = 600.0_f32; + if let Ok(Some(level)) = self.skill_set.skill_level(Skill::Staff(StaffSkill::SCost)) { + shockwave_cost *= 0.8_f32.powi(level.into()); + } if self.body.map(|b| b.is_humanoid()).unwrap_or(false) && attack_data.in_min_range() && self.energy.current() > 100 + && !matches!(self.char_state, CharacterState::Shockwave(_)) { // if a humanoid, have enough stamina, and in melee range, emergency roll controller .actions .push(ControlAction::basic_input(InputKind::Roll)); + } else if agent.action_state.condition + && matches!(self.char_state, CharacterState::Wielding) + { + controller + .actions + .push(ControlAction::basic_input(InputKind::Ability(0))); + agent.action_state.condition = false; } else if !matches!(self.char_state, CharacterState::Shockwave(c) if !matches!(c.stage_section, StageSection::Recover)) { // only try to use another ability if not already in recover and not casting @@ -2470,10 +2486,16 @@ impl<'a> AgentData<'a> { && self.energy.current() > 200 { // if enemy is closing distance quickly, use shockwave to knock back - controller - .actions - .push(ControlAction::basic_input(InputKind::Ability(0))); - } else if self.energy.current() > 100 && attack_data.dist_sqrd < 280.0 { + if matches!(self.char_state, CharacterState::Wielding) { + controller + .actions + .push(ControlAction::basic_input(InputKind::Ability(0))); + } else { + agent.action_state.condition = true; + } + } else if self.energy.current() as f32 > shockwave_cost + 100.0 + && attack_data.dist_sqrd < flamethrower_range.powi(2) + { controller .actions .push(ControlAction::basic_input(InputKind::Secondary)); From 998c56c5240b4d1e40cf430593786506bc4c0846 Mon Sep 17 00:00:00 2001 From: Knightress Paladin Date: Fri, 23 Jul 2021 17:59:32 -0700 Subject: [PATCH 055/155] Removed extra Warlock skills and made sceptre cultists rarer --- assets/common/entity/dungeon/tier-5/cultist.ron | 10 +++++----- assets/common/entity/dungeon/tier-5/warlock.ron | 2 -- assets/common/skillset/dungeon/tier-5/warlock.ron | 5 ----- 3 files changed, 5 insertions(+), 12 deletions(-) delete mode 100644 assets/common/skillset/dungeon/tier-5/warlock.ron diff --git a/assets/common/entity/dungeon/tier-5/cultist.ron b/assets/common/entity/dungeon/tier-5/cultist.ron index 88e29509b0..283fd9f054 100644 --- a/assets/common/entity/dungeon/tier-5/cultist.ron +++ b/assets/common/entity/dungeon/tier-5/cultist.ron @@ -6,11 +6,11 @@ EntityConfig ( loot: LootTable("common.loot_tables.dungeon.tier-5.enemy"), hands: TwoHanded(Choice([ - (1.0, Some(Item("common.items.weapons.axe_1h.orichalcum-0"))), - (2.0, Some(Item("common.items.weapons.sword.cultist"))), - (1.0, Some(Item("common.items.weapons.hammer.cultist_purp_2h-0"))), - (1.0, Some(Item("common.items.weapons.hammer_1h.orichalcum-0"))), - (1.0, Some(Item("common.items.weapons.bow.velorite"))), + (2.0, Some(Item("common.items.weapons.axe_1h.orichalcum-0"))), + (4.0, Some(Item("common.items.weapons.sword.cultist"))), + (2.0, Some(Item("common.items.weapons.hammer.cultist_purp_2h-0"))), + (2.0, Some(Item("common.items.weapons.hammer_1h.orichalcum-0"))), + (2.0, Some(Item("common.items.weapons.bow.velorite"))), (1.0, Some(Item("common.items.weapons.sceptre.sceptre_velorite_0"))), ])), diff --git a/assets/common/entity/dungeon/tier-5/warlock.ron b/assets/common/entity/dungeon/tier-5/warlock.ron index 6caba2a001..0ee439d4df 100644 --- a/assets/common/entity/dungeon/tier-5/warlock.ron +++ b/assets/common/entity/dungeon/tier-5/warlock.ron @@ -11,6 +11,4 @@ EntityConfig ( ])), meta: [], - loadout_asset: None, - skillset_asset: Some("common.skillset.dungeon.tier-5.warlock"), ) diff --git a/assets/common/skillset/dungeon/tier-5/warlock.ron b/assets/common/skillset/dungeon/tier-5/warlock.ron deleted file mode 100644 index a8944845e0..0000000000 --- a/assets/common/skillset/dungeon/tier-5/warlock.ron +++ /dev/null @@ -1,5 +0,0 @@ -([ - // Gather all warlock skills - Tree("common.skillset.dungeon.tier-5.bow"), - Tree("common.skillset.dungeon.tier-5.staff"), -]) From a6acdbbfa79858cace62c983d6b814a4ba2fa98f Mon Sep 17 00:00:00 2001 From: Knightress Paladin Date: Tue, 27 Jul 2021 22:26:27 -0700 Subject: [PATCH 056/155] Used adjusted_by_skills to correctly calculate ability values --- server/src/sys/agent.rs | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index 3b465692e4..c0eb38100e 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -12,7 +12,7 @@ use common::{ inventory::{item::ItemTag, slot::EquipSlot}, invite::{InviteKind, InviteResponse}, item::{ - tool::{AbilitySpec, ToolKind}, + tool::{AbilityMap, AbilitySpec, ToolKind}, ConsumableKind, Item, ItemDesc, ItemKind, }, skills::{AxeSkill, BowSkill, HammerSkill, SceptreSkill, Skill, StaffSkill, SwordSkill}, @@ -2443,16 +2443,26 @@ impl<'a> AgentData<'a> { tgt_data: &TargetData, read_data: &ReadData, ) { - //TODO: minimum energy values for skills and rolls are hard coded from - // approximate guesses - let mut flamethrower_range = 20.0_f32; - if let Ok(Some(level)) = self.skill_set.skill_level(Skill::Staff(StaffSkill::FRange)) { - flamethrower_range *= 1.25_f32.powi(level.into()); - } - let mut shockwave_cost = 600.0_f32; - if let Ok(Some(level)) = self.skill_set.skill_level(Skill::Staff(StaffSkill::SCost)) { - shockwave_cost *= 0.8_f32.powi(level.into()); - } + let ability_map = AbilityMap::default(); + let ability_set = ability_map + .get_ability_set(&AbilitySpec::Tool(ToolKind::Staff)) + .unwrap() + .clone(); + let flamethrower = ability_set + .secondary + .adjusted_by_skills(self.skill_set, Some(ToolKind::Staff)); + let flamethrower_range = match flamethrower { + CharacterAbility::BasicBeam { range, .. } => range, + _ => 20.0_f32, + }; + let shockwave = ability_set.abilities[0] + .clone() + .1 + .adjusted_by_skills(self.skill_set, Some(ToolKind::Staff)); + let shockwave_cost = match shockwave { + CharacterAbility::Shockwave { energy_cost, .. } => energy_cost, + _ => 600.0_f32, + }; if self.body.map(|b| b.is_humanoid()).unwrap_or(false) && attack_data.in_min_range() && self.energy.current() > 100 From 8dd2202e1a0ac2ca2903fea44e481be5b40521a3 Mon Sep 17 00:00:00 2001 From: Knightress Paladin Date: Mon, 2 Aug 2021 16:22:22 -0700 Subject: [PATCH 057/155] Restyle logic in Staff AI --- server/src/sys/agent.rs | 55 ++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index c0eb38100e..b9f927165a 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -12,7 +12,7 @@ use common::{ inventory::{item::ItemTag, slot::EquipSlot}, invite::{InviteKind, InviteResponse}, item::{ - tool::{AbilityMap, AbilitySpec, ToolKind}, + tool::{AbilitySpec, ToolKind}, ConsumableKind, Item, ItemDesc, ItemKind, }, skills::{AxeSkill, BowSkill, HammerSkill, SceptreSkill, Skill, StaffSkill, SwordSkill}, @@ -2443,42 +2443,52 @@ impl<'a> AgentData<'a> { tgt_data: &TargetData, read_data: &ReadData, ) { - let ability_map = AbilityMap::default(); - let ability_set = ability_map - .get_ability_set(&AbilitySpec::Tool(ToolKind::Staff)) - .unwrap() - .clone(); - let flamethrower = ability_set - .secondary - .adjusted_by_skills(self.skill_set, Some(ToolKind::Staff)); + let extract_ability = |ability: &CharacterAbility| { + ability + .clone() + .adjusted_by_skills(self.skill_set, Some(ToolKind::Staff)) + }; + let (flamethrower, shockwave) = self + .inventory + .equipped(EquipSlot::ActiveMainhand) + .map(|i| &i.item_config_expect().abilities) + .map(|a| { + ( + Some(a.secondary.clone()), + a.abilities.get(0).map(|(_, s)| s), + ) + }) + .map_or( + (CharacterAbility::default(), CharacterAbility::default()), + |(s, a)| { + ( + extract_ability(&s.unwrap_or_default()), + extract_ability(a.unwrap_or(&CharacterAbility::default())), + ) + }, + ); let flamethrower_range = match flamethrower { CharacterAbility::BasicBeam { range, .. } => range, _ => 20.0_f32, }; - let shockwave = ability_set.abilities[0] - .clone() - .1 - .adjusted_by_skills(self.skill_set, Some(ToolKind::Staff)); - let shockwave_cost = match shockwave { - CharacterAbility::Shockwave { energy_cost, .. } => energy_cost, - _ => 600.0_f32, - }; - if self.body.map(|b| b.is_humanoid()).unwrap_or(false) + let shockwave_cost = shockwave.get_energy_cost(); + if self.body.map_or(false, |b| b.is_humanoid()) && attack_data.in_min_range() - && self.energy.current() > 100 + && self.energy.current() > CharacterAbility::default_roll().get_energy_cost() && !matches!(self.char_state, CharacterState::Shockwave(_)) { // if a humanoid, have enough stamina, and in melee range, emergency roll controller .actions .push(ControlAction::basic_input(InputKind::Roll)); + } else if matches!(self.char_state, CharacterState::Shockwave(_)) { + agent.action_state.condition = false; } else if agent.action_state.condition && matches!(self.char_state, CharacterState::Wielding) { controller .actions .push(ControlAction::basic_input(InputKind::Ability(0))); - agent.action_state.condition = false; } else if !matches!(self.char_state, CharacterState::Shockwave(c) if !matches!(c.stage_section, StageSection::Recover)) { // only try to use another ability if not already in recover and not casting @@ -2503,7 +2513,8 @@ impl<'a> AgentData<'a> { } else { agent.action_state.condition = true; } - } else if self.energy.current() as f32 > shockwave_cost + 100.0 + } else if self.energy.current() + > shockwave_cost + CharacterAbility::default_roll().get_energy_cost() && attack_data.dist_sqrd < flamethrower_range.powi(2) { controller @@ -2566,7 +2577,7 @@ impl<'a> AgentData<'a> { } } // Sometimes try to roll - if self.body.map(|b| b.is_humanoid()).unwrap_or(false) + if self.body.map_or(false, |b| b.is_humanoid()) && attack_data.dist_sqrd < 16.0f32.powi(2) && thread_rng().gen::() < 0.01 { From 427930081a1791611cbde3e33bca85221c460681 Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 2 Aug 2021 23:50:07 -0400 Subject: [PATCH 058/155] Add custom error message when there are no compatible graphics backends available --- CHANGELOG.md | 1 + voxygen/src/main.rs | 27 +++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 339da87968..9712d6266d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Dualwielded, one-handed swords as starting weapons (Will be replaced by daggers in the future!) - Healing sceptre crafting recipe - NPCs can now warn players before engaging in combat +- Custom error message when a supported graphics backend can not be found ### Changed diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index a668bd44df..dd602949d8 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -98,7 +98,7 @@ fn main() { https://www.gitlab.com/veloren/veloren/issues/new\n\ \n\ If you're on the Veloren community Discord server, we'd be \ - grateful if you could also post a message in the #support channel. + grateful if you could also post a message in the #bugs-and-support channel. \n\ > What should I include?\n\ \n\ @@ -209,7 +209,30 @@ fn main() { i18n.set_english_fallback(settings.language.use_english_fallback); // Create window - let (mut window, event_loop) = Window::new(&settings).expect("Failed to create window!"); + use veloren_voxygen::{error::Error, render::RenderError}; + let (mut window, event_loop) = match Window::new(&settings) { + Ok(ok) => ok, + // Custom panic message when a graphics backend could not be found + Err(Error::RenderError(RenderError::CouldNotFindAdapter)) => { + #[cfg(target_os = "windows")] + const POTENTIAL_FIX: &str = + " Updating the graphics drivers on this system may resolve this issue."; + #[cfg(target_os = "macos")] + const POTENTIAL_FIX: &str = ""; + #[cfg(not(any(target_os = "windows", target_os = "macos")))] + const POTENTIAL_FIX: &str = + " Installing or updating vulkan drivers may resolve this issue."; + + panic!( + "Failed to select a rendering backend! No compatible backends were found. We \ + currently support vulkan, metal, dx12, and dx11.{} If the issue persists, please \ + include the operating system and GPU details in your bug report to help us \ + identify the cause.", + POTENTIAL_FIX + ); + }, + Err(error) => panic!("Failed to create window!: {:?}", error), + }; let clipboard = iced_winit::Clipboard::connect(window.window()); From 1b5c3883a441800e53986916ac066183578e5cfb Mon Sep 17 00:00:00 2001 From: Ygor Souza Date: Tue, 3 Aug 2021 06:34:36 +0200 Subject: [PATCH 059/155] Allow axe combo to reward energy without skillpoint When the character does not have the Double Strike Combo skill, the ability's stage_data only contains one element, and thus the stage_data.len() - 1 expression would set the max_energy_regen to 0. This change forces the multiplier to 1 in this specific case, so the axe can still reward energy without the combo skill point, to match the other weapons. --- CHANGELOG.md | 1 + common/src/comp/ability.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 339da87968..911adff707 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Players no longer spawn underground if their waypoint is underground - Map will now zoom around the cursor's position and drag correctly - No more jittering while running down slopes with the glider out +- Axe normal attack rewards energy without skill points ## [0.10.0] - 2021-06-12 diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 98f5935bc7..44241a7607 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -1021,9 +1021,9 @@ impl CharacterAbility { 0 }; *max_energy_gain = *max_energy_gain - * ((energy_level + 1) * stage_data.len() as u16 - 1) as f32 + * ((energy_level + 1) * stage_data.len() as u16 - 1).max(1) as f32 / (Axe(DsRegen).max_level().unwrap() + 1) as f32 - * (stage_data.len() - 1) as f32; + * (stage_data.len() - 1).max(1) as f32; *scales_from_combo = skillset .skill_level(Axe(DsDamage)) .unwrap_or(None) From b338abd761fef7bd9a8f12d7465af0b656fafe09 Mon Sep 17 00:00:00 2001 From: Knightress Paladin Date: Mon, 2 Aug 2021 22:38:16 -0700 Subject: [PATCH 060/155] Fix up comments relating to AI logic --- server/src/sys/agent.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index b9f927165a..64a8a0600f 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -2477,7 +2477,8 @@ impl<'a> AgentData<'a> { && self.energy.current() > CharacterAbility::default_roll().get_energy_cost() && !matches!(self.char_state, CharacterState::Shockwave(_)) { - // if a humanoid, have enough stamina, and in melee range, emergency roll + // if a humanoid, have enough stamina, not in shockwave, and in melee range, + // emergency roll controller .actions .push(ControlAction::basic_input(InputKind::Roll)); @@ -2491,8 +2492,7 @@ impl<'a> AgentData<'a> { .push(ControlAction::basic_input(InputKind::Ability(0))); } else if !matches!(self.char_state, CharacterState::Shockwave(c) if !matches!(c.stage_section, StageSection::Recover)) { - // only try to use another ability if not already in recover and not casting - // shockwave + // only try to use another ability unless in shockwave or recover let target_approaching_speed = -agent .target .as_ref() @@ -2502,8 +2502,8 @@ impl<'a> AgentData<'a> { if self .skill_set .has_skill(Skill::Staff(StaffSkill::UnlockShockwave)) - && target_approaching_speed > 20.0 - && self.energy.current() > 200 + && target_approaching_speed > 12.0 + && self.energy.current() > shockwave_cost { // if enemy is closing distance quickly, use shockwave to knock back if matches!(self.char_state, CharacterState::Wielding) { @@ -2579,7 +2579,8 @@ impl<'a> AgentData<'a> { // Sometimes try to roll if self.body.map_or(false, |b| b.is_humanoid()) && attack_data.dist_sqrd < 16.0f32.powi(2) - && thread_rng().gen::() < 0.01 + && !matches!(self.char_state, CharacterState::Shockwave(_)) + && thread_rng().gen::() < 0.02 { controller .actions From 846233367f47cd5839a5cfb70a3acf26714b761f Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Mon, 2 Aug 2021 14:29:45 +0300 Subject: [PATCH 061/155] Introduce helper functions and deduplicate docs --- common/assets/src/lib.rs | 80 +++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/common/assets/src/lib.rs b/common/assets/src/lib.rs index b23f27bb2f..f504c017f8 100644 --- a/common/assets/src/lib.rs +++ b/common/assets/src/lib.rs @@ -322,32 +322,52 @@ pub mod asset_tweak { const EXTENSION: &'static str = "ron"; } + // helper function to load asset and return value + // asset_specifier is full "path" to asset relative to ASSETS_PATH. + fn read_expect(asset_specifier: &str) -> T + where + T: Clone + Sized + Send + Sync + 'static + DeserializeOwned, + { + let handle = as AssetExt>::load_expect(asset_specifier); + let AssetTweakWrapper(value) = handle.read().clone(); + value + } + + // helper function to create new file to tweak + // the file will be filled with passed value + // returns passed value + fn create_new(tweak_dir: &Path, filename: &str, value: T) -> T + where + T: Clone + Sized + Send + Sync + 'static + DeserializeOwned + Serialize, + { + fs::create_dir_all(tweak_dir).expect("failed to create directory for tweak files"); + let f = fs::File::create(tweak_dir.join(filename)).unwrap_or_else(|error| { + panic!("failed to create file {:?}. Error: {:?}", filename, error) + }); + // TODO: can we not require clone here? + let tweaker = AssetTweakWrapper(value.clone()); + if let Err(e) = to_writer_pretty(f, &tweaker, PrettyConfig::new()) { + panic!("failed to write to file {:?}. Error: {:?}", filename, e); + } + + value + } + /// # Usage - /// Create file with content which represent tweaked value + /// Read value from file using our asset cache machinery. /// - /// Example if you want to tweak integer value - /// ```no_run - /// use veloren_common_assets::asset_tweak; - /// let x: i32 = asset_tweak::tweak_expect("x"); - /// ``` - /// File needs to look like that - /// ```text - /// assets/tweak/x.ron - /// (5) - /// ``` - /// Note the parentheses. + /// Will hot-reload (if corresponded feature is enabled). /// - /// # Panics - /// 1) If given `asset_specifier` does not exists - /// 2) If asseet is broken + /// If you don't have a file or its content is invalid, + /// this function will panic. + /// + /// Read documentation for `tweak_expect_or_create` for more. pub fn tweak_expect(specifier: &str) -> T where T: Clone + Sized + Send + Sync + 'static + DeserializeOwned, { - let asset_specifier: &str = &format!("tweak.{}", specifier); - let handle = as AssetExt>::load_expect(asset_specifier); - let AssetTweakWrapper(value) = handle.read().clone(); - value + let asset_specifier = format!("tweak.{}", specifier); + read_expect(&asset_specifier) } /// # Usage @@ -369,10 +389,6 @@ pub mod asset_tweak { /// (5) /// ``` /// Note the parentheses. - /// - /// # Panics - /// 1) If asset is broken - /// 2) filesystem errors pub fn tweak_expect_or_create(specifier: &str, value: T) -> T where T: Clone + Sized + Send + Sync + 'static + DeserializeOwned + Serialize, @@ -386,22 +402,10 @@ pub mod asset_tweak { let filename = format!("{}.ron", specifier); if Path::new(&tweak_dir.join(&filename)).is_file() { - let asset_specifier: &str = &format!("tweak.{}", specifier); - let handle = as AssetExt>::load_expect(asset_specifier); - let AssetTweakWrapper(new_value) = handle.read().clone(); - - new_value + let asset_specifier = format!("tweak.{}", specifier); + read_expect(&asset_specifier) } else { - fs::create_dir_all(&tweak_dir).expect("failed to create directory for tweak files"); - let f = fs::File::create(tweak_dir.join(&filename)).unwrap_or_else(|err| { - panic!("failed to create file {:?}. Error: {:?}", &filename, err) - }); - to_writer_pretty(f, &AssetTweakWrapper(value.clone()), PrettyConfig::new()) - .unwrap_or_else(|err| { - panic!("failed to write to file {:?}. Error: {:?}", &filename, err) - }); - - value + create_new(&tweak_dir, &filename, value) } } From 99d0c2cb95504f144aaa9bd358b4e0f0945c6f87 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Mon, 2 Aug 2021 16:27:44 +0300 Subject: [PATCH 062/155] Remove clone() for creating new tweak file --- common/assets/src/lib.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/assets/src/lib.rs b/common/assets/src/lib.rs index f504c017f8..a0316c46b0 100644 --- a/common/assets/src/lib.rs +++ b/common/assets/src/lib.rs @@ -322,7 +322,7 @@ pub mod asset_tweak { const EXTENSION: &'static str = "ron"; } - // helper function to load asset and return value + // helper function to load asset and return contained value // asset_specifier is full "path" to asset relative to ASSETS_PATH. fn read_expect(asset_specifier: &str) -> T where @@ -338,14 +338,13 @@ pub mod asset_tweak { // returns passed value fn create_new(tweak_dir: &Path, filename: &str, value: T) -> T where - T: Clone + Sized + Send + Sync + 'static + DeserializeOwned + Serialize, + T: Sized + Send + Sync + 'static + DeserializeOwned + Serialize, { fs::create_dir_all(tweak_dir).expect("failed to create directory for tweak files"); let f = fs::File::create(tweak_dir.join(filename)).unwrap_or_else(|error| { panic!("failed to create file {:?}. Error: {:?}", filename, error) }); - // TODO: can we not require clone here? - let tweaker = AssetTweakWrapper(value.clone()); + let tweaker = AssetTweakWrapper(&value); if let Err(e) = to_writer_pretty(f, &tweaker, PrettyConfig::new()) { panic!("failed to write to file {:?}. Error: {:?}", filename, e); } From 30ebf04e9667d05bf7f63d63e1b78d8142f74280 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Mon, 2 Aug 2021 17:42:28 +0300 Subject: [PATCH 063/155] Add ability to specify directory in asset_tweak --- common/assets/src/lib.rs | 361 ++++++++++++++++++++++++++------------- 1 file changed, 239 insertions(+), 122 deletions(-) diff --git a/common/assets/src/lib.rs b/common/assets/src/lib.rs index a0316c46b0..a03483ab2a 100644 --- a/common/assets/src/lib.rs +++ b/common/assets/src/lib.rs @@ -303,13 +303,31 @@ mod tests { } } +/// Set of functions for easy tweaking values using our asset cache machinery. +/// +/// Will hot-reload (if corresponded feature is enabled). #[cfg(feature = "asset_tweak")] pub mod asset_tweak { - use super::{find_root, Asset, AssetExt, RonLoader}; + use super::{Asset, AssetExt, RonLoader, ASSETS_PATH}; use ron::ser::{to_writer_pretty, PrettyConfig}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use std::{fs, path::Path}; + /// Specifier to use with tweak functions in this module + /// + /// `Tweak("test")` will be interpreted as `/tweak/test.ron`. + /// + /// `Asset(&["path", "to", "file"])` will be interpreted as + /// `/path/to/file.ron` + // TODO: should we care about situation where + // lifetime of slice and lifetime of strings are different? + // + // Should we use references at all? + pub enum Specifier<'a> { + Tweak(&'a str), + Asset(&'a [&'a str]), + } + #[derive(Clone, Deserialize, Serialize)] struct AssetTweakWrapper(T); @@ -322,20 +340,65 @@ pub mod asset_tweak { const EXTENSION: &'static str = "ron"; } - // helper function to load asset and return contained value - // asset_specifier is full "path" to asset relative to ASSETS_PATH. - fn read_expect(asset_specifier: &str) -> T + /// Read value from file, will panic if file doesn't exist. + /// + /// If you don't have a file or its content is invalid, + /// this function will panic. + /// If you want to have some default content, + /// read documentation for [tweak_expect_or_create] for more. + /// + /// # Examples: + /// How not to use. + /// ```should_panic + /// use veloren_common_assets::asset_tweak::{tweak_expect, Specifier}; + /// + /// // will panic if you don't have a file + /// let specifier = Specifier::Asset(&["no_way_we_have_this_directory", "x"]); + /// let x: i32 = tweak_expect(specifier); + /// ``` + /// + /// How to use. + /// ``` + /// use std::fs; + /// use veloren_common_assets::{ + /// asset_tweak::{tweak_expect, Specifier}, + /// ASSETS_PATH, + /// }; + /// + /// // you need to create file first + /// let tweak_path = ASSETS_PATH.join("tweak/y.ron"); + /// // note parentheses + /// fs::write(&tweak_path, b"(10)"); + /// + /// let y: i32 = tweak_expect(Specifier::Tweak("y")); + /// assert_eq!(y, 10); + /// + /// // Specifier::Tweak is just a shorthand + /// // for Specifier::Asset(&["tweak", ..]) + /// let z: i32 = tweak_expect(Specifier::Asset(&["tweak", "y"])); + /// assert_eq!(y, 10); + /// + /// // you may want to remove this file later + /// std::fs::remove_file(tweak_path); + /// ``` + pub fn tweak_expect(specifier: Specifier) -> T where T: Clone + Sized + Send + Sync + 'static + DeserializeOwned, { - let handle = as AssetExt>::load_expect(asset_specifier); + let asset_specifier = match specifier { + Specifier::Tweak(specifier) => format!("tweak.{}", specifier), + Specifier::Asset(path) => path.join("."), + }; + let handle = as AssetExt>::load_expect(&asset_specifier); let AssetTweakWrapper(value) = handle.read().clone(); + value } - // helper function to create new file to tweak - // the file will be filled with passed value - // returns passed value + // Helper function to create new file to tweak. + // + // The file will be filled with passed value + // returns passed value. fn create_new(tweak_dir: &Path, filename: &str, value: T) -> T where T: Sized + Send + Sync + 'static + DeserializeOwned + Serialize, @@ -352,66 +415,71 @@ pub mod asset_tweak { value } - /// # Usage - /// Read value from file using our asset cache machinery. - /// - /// Will hot-reload (if corresponded feature is enabled). - /// - /// If you don't have a file or its content is invalid, - /// this function will panic. - /// - /// Read documentation for `tweak_expect_or_create` for more. - pub fn tweak_expect(specifier: &str) -> T - where - T: Clone + Sized + Send + Sync + 'static + DeserializeOwned, - { - let asset_specifier = format!("tweak.{}", specifier); - read_expect(&asset_specifier) + // Helper function to get directory and file from asset list. + // + // Converts ["path", "to", "file"] to (String("path/to"), "file") + fn directory_and_name<'a>(path: &'a [&'a str]) -> (String, &'a str) { + let (file, path) = path.split_last().expect("empty asset list"); + let directory = path.join("/"); + + (directory, file) } - /// # Usage - /// Will create file "assets/tweak/{specifier}.ron" if not exists - /// and return passed `value`. - /// If file exists will read a value from such file. + /// Read a value from asset, creating file if not exists. /// - /// In release builds (if `debug_assertions` == false) just returns passed - /// `value` + /// If file exists will read a value from such file + /// using [tweak_expect]. /// - /// Example if you want to tweak integer value - /// ```no_run - /// use veloren_common_assets::asset_tweak; - /// let x: i32 = asset_tweak::tweak_expect_or_create("x", 5); - /// ``` - /// File needs to look like that + /// File should look like that (note the parentheses). /// ```text /// assets/tweak/x.ron /// (5) /// ``` - /// Note the parentheses. - pub fn tweak_expect_or_create(specifier: &str, value: T) -> T + /// + /// # Example: + /// Tweaking integer value + /// ``` + /// use veloren_common_assets::{ + /// asset_tweak::{tweak_expect_or_create, Specifier}, + /// ASSETS_PATH, + /// }; + /// + /// // first time it will create the file + /// let x: i32 = tweak_expect_or_create(Specifier::Tweak("x"), 5); + /// let file_path = ASSETS_PATH.join("tweak/x.ron"); + /// assert!(file_path.is_file()); + /// assert_eq!(x, 5); + /// + /// // next time it will read value from file + /// // whatever you will pass as default + /// let x: i32 = tweak_expect_or_create(Specifier::Tweak("x"), 42); + /// assert_eq!(x, 5); + /// + /// // you may want to remove this file later + /// std::fs::remove_file(file_path); + /// ``` + pub fn tweak_expect_or_create(specifier: Specifier, value: T) -> T where T: Clone + Sized + Send + Sync + 'static + DeserializeOwned + Serialize, { - if cfg!(not(debug_assertions)) { - return value; - } + let (dir, filename) = match specifier { + Specifier::Tweak(name) => (ASSETS_PATH.join("tweak"), format!("{}.ron", name)), + Specifier::Asset(list) => { + let (directory, name) = directory_and_name(list); + (ASSETS_PATH.join(directory), format!("{}.ron", name)) + }, + }; - let root = find_root().expect("failed to discover repository_root"); - let tweak_dir = root.join("assets/tweak/"); - let filename = format!("{}.ron", specifier); - - if Path::new(&tweak_dir.join(&filename)).is_file() { - let asset_specifier = format!("tweak.{}", specifier); - read_expect(&asset_specifier) + if Path::new(&dir.join(&filename)).is_file() { + tweak_expect(specifier) } else { - create_new(&tweak_dir, &filename, value) + create_new(&dir, &filename, value) } } #[cfg(test)] mod tests { - use super::{find_root, tweak_expect, tweak_expect_or_create}; - use serial_test::serial; + use super::*; use std::{ convert::AsRef, fmt::Debug, @@ -469,90 +537,139 @@ pub mod asset_tweak { P: AsRef + Debug, { fn drop(&mut self) { - fs::remove_file(&self.file) - .unwrap_or_else(|_| panic!("failed to create file {:?}", &self.file)); + fs::remove_file(&self.file).unwrap_or_else(|e| { + panic!("failed to remove file {:?}. Error: {:?}", &self.file, e) + }); } } - #[test] - #[serial] - fn test_tweaked_string() { - let root = find_root().expect("failed to discover repository_root"); - let tweak_dir = root.join("assets/tweak/"); - let _dir_guard = DirectoryGuard::create(tweak_dir.clone()); + // helper function to create environment with needed directory and file + // and responsible for cleaning + fn run_with_file(tweak_path: &[&str], test: impl Fn(&mut File)) { + let (tweak_dir, tweak_name) = directory_and_name(tweak_path); + let tweak_folder = ASSETS_PATH.join(tweak_dir); + let tweak_file = tweak_folder.join(format!("{}.ron", tweak_name)); - // define test files - let from_int = tweak_dir.join("__test_int_tweak.ron"); - let from_string = tweak_dir.join("__test_string_tweak.ron"); - let from_map = tweak_dir.join("__test_map_tweak.ron"); + let _dir_guard = DirectoryGuard::create(tweak_folder); + let (_file_guard, mut file) = FileGuard::create(tweak_file); - // setup fs guards - let (_file_guard1, mut file1) = FileGuard::create(from_int); - let (_file_guard2, mut file2) = FileGuard::create(from_string); - let (_file_guard3, mut file3) = FileGuard::create(from_map); - - // write to file and check result - file1 - .write_all(b"(5)") - .expect("failed to write to the file"); - let x = tweak_expect::("__test_int_tweak"); - assert_eq!(x, 5); - - // write to file and check result - file2 - .write_all(br#"("Hello Zest")"#) - .expect("failed to write to the file"); - let x = tweak_expect::("__test_string_tweak"); - assert_eq!(x, "Hello Zest".to_owned()); - - // write to file and check result - file3 - .write_all( - br#" - ({ - "wow": 4, - "such": 5, - }) - "#, - ) - .expect("failed to write to the file"); - let x: std::collections::HashMap = tweak_expect("__test_map_tweak"); - let mut map = std::collections::HashMap::new(); - map.insert("wow".to_owned(), 4); - map.insert("such".to_owned(), 5); - assert_eq!(x, map); + test(&mut file); } #[test] - #[serial] - fn test_tweaked_create() { - let root = find_root().expect("failed to discover repository_root"); - let tweak_dir = root.join("assets/tweak/"); + fn test_tweaked_int() { + use Specifier::Asset; - let test_path1 = tweak_dir.join("__test_int_create.ron"); - let _file_guard1 = FileGuard::hold(&test_path1); - let x = tweak_expect_or_create("__test_int_create", 5); - assert_eq!(x, 5); - assert!(test_path1.is_file()); - // Recheck it loads back correctly - let x = tweak_expect_or_create("__test_int_create", 5); - assert_eq!(x, 5); + let tweak_path = &["tweak_test_int", "tweak"]; - let test_path2 = tweak_dir.join("__test_tuple_create.ron"); - let _file_guard2 = FileGuard::hold(&test_path2); - let (x, y, z) = tweak_expect_or_create("__test_tuple_create", (5.0, 6.0, 7.0)); - assert_eq!((x, y, z), (5.0, 6.0, 7.0)); - // Recheck it loads back correctly - let (x, y, z) = tweak_expect_or_create("__test_tuple_create", (5.0, 6.0, 7.0)); - assert_eq!((x, y, z), (5.0, 6.0, 7.0)); + run_with_file(tweak_path, |file| { + file.write_all(b"(5)").expect("failed to write to the file"); + let x: i32 = tweak_expect(Asset(tweak_path)); + assert_eq!(x, 5); + }); + } - // Test that file has stronger priority - let test_path3 = tweak_dir.join("__test_priority.ron"); - let (_file_guard3, mut file) = FileGuard::create(&test_path3); - file.write_all(b"(10)") + #[test] + fn test_tweaked_string() { + use Specifier::Asset; + let tweak_path = &["tweak_test_string", "tweak"]; + + run_with_file(tweak_path, |file| { + file.write_all(br#"("Hello Zest")"#) + .expect("failed to write to the file"); + + let x: String = tweak_expect(Asset(tweak_path)); + assert_eq!(x, "Hello Zest".to_owned()); + }); + } + + #[test] + fn test_tweaked_hashmap() { + use Specifier::Asset; + type Map = std::collections::HashMap; + + let tweak_path = &["tweak_test_map", "tweak"]; + + run_with_file(tweak_path, |file| { + file.write_all( + br#" + ({ + "wow": 4, + "such": 5, + }) + "#, + ) .expect("failed to write to the file"); - let x = tweak_expect_or_create("__test_priority", 6); - assert_eq!(x, 10); + + let x: Map = tweak_expect(Asset(tweak_path)); + + let mut map = Map::new(); + map.insert("wow".to_owned(), 4); + map.insert("such".to_owned(), 5); + assert_eq!(x, map); + }); + } + + fn run_with_path(tweak_path: &[&str], test: impl Fn(&Path)) { + let (tweak_dir, tweak_name) = directory_and_name(tweak_path); + + let tweak_folder = ASSETS_PATH.join(tweak_dir); + let test_path = tweak_folder.join(format!("{}.ron", tweak_name)); + + let _file_guard = FileGuard::hold(&test_path); + + test(&test_path); + } + + #[test] + fn test_create_tweak() { + use Specifier::Asset; + + let tweak_path = &["tweak_create_test", "tweak"]; + + run_with_path(tweak_path, |test_path| { + let x = tweak_expect_or_create(Asset(tweak_path), 5); + assert_eq!(x, 5); + assert!(test_path.is_file()); + // Recheck it loads back correctly + let x = tweak_expect_or_create(Asset(tweak_path), 5); + assert_eq!(x, 5); + }); + } + + #[test] + fn test_create_tweak_deep() { + use Specifier::Asset; + + let tweak_path = &["so_much", "deep_test", "tweak_create_test", "tweak"]; + + run_with_path(tweak_path, |test_path| { + let x = tweak_expect_or_create(Asset(tweak_path), 5); + assert_eq!(x, 5); + assert!(test_path.is_file()); + // Recheck it loads back correctly + let x = tweak_expect_or_create(Asset(tweak_path), 5); + assert_eq!(x, 5); + }); + } + + #[test] + fn test_create_but_prioritize_loaded() { + use Specifier::Asset; + + let tweak_path = &["tweak_create_and_prioritize_test", "tweak"]; + + run_with_path(tweak_path, |test_path| { + let x = tweak_expect_or_create(Asset(tweak_path), 5); + assert_eq!(x, 5); + assert!(test_path.is_file()); + + // Recheck it loads back + // with content as priority + fs::write(test_path, b"(10)").expect("failed to write to the file"); + let x = tweak_expect_or_create(Asset(tweak_path), 5); + assert_eq!(x, 10); + }); } } } From 2ce09af2d897c494aecf4605df8ee869262ce35b Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Tue, 3 Aug 2021 01:44:19 +0300 Subject: [PATCH 064/155] Remove redundant serial_test crate --- Cargo.lock | 23 ----------------------- common/assets/Cargo.toml | 3 +-- 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3132f6e3fc..283b9489c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4831,28 +4831,6 @@ dependencies = [ "syn 1.0.73", ] -[[package]] -name = "serial_test" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0bccbcf40c8938196944a3da0e133e031a33f4d6b72db3bda3cc556e361905d" -dependencies = [ - "lazy_static", - "parking_lot 0.11.1", - "serial_test_derive", -] - -[[package]] -name = "serial_test_derive" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5" -dependencies = [ - "proc-macro2 1.0.27", - "quote 1.0.9", - "syn 1.0.73", -] - [[package]] name = "sha1" version = "0.6.0" @@ -5920,7 +5898,6 @@ dependencies = [ "lazy_static", "ron", "serde", - "serial_test", "tracing", "walkdir 2.3.2", ] diff --git a/common/assets/Cargo.toml b/common/assets/Cargo.toml index 4b46aecac6..ae7fb642c8 100644 --- a/common/assets/Cargo.toml +++ b/common/assets/Cargo.toml @@ -15,11 +15,10 @@ tracing = "0.1" # asset tweak serde = {version = "1.0", features = ["derive"], optional = true} -serial_test = {version = "0.5", optional = true} [dev-dependencies] walkdir = "2.3.2" [features] hot-reloading = ["assets_manager/hot-reloading"] -asset_tweak = ["serial_test", "serde", "hot-reloading"] +asset_tweak = ["serde", "hot-reloading"] From 328e865ed3f04c529eea62bfd7fcc9e5ec2de4fd Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Tue, 3 Aug 2021 16:13:35 +0300 Subject: [PATCH 065/155] Add asset_tweak macros --- common/assets/src/lib.rs | 122 +++++++++++++++++++++++++++++++++++---- 1 file changed, 111 insertions(+), 11 deletions(-) diff --git a/common/assets/src/lib.rs b/common/assets/src/lib.rs index a03483ab2a..80122a52af 100644 --- a/common/assets/src/lib.rs +++ b/common/assets/src/lib.rs @@ -303,11 +303,17 @@ mod tests { } } -/// Set of functions for easy tweaking values using our asset cache machinery. -/// -/// Will hot-reload (if corresponded feature is enabled). #[cfg(feature = "asset_tweak")] pub mod asset_tweak { + //! Set of functions and macros for easy tweaking values + //! using our asset cache machinery. + //! + //! Because of how macros works, you will not find + //! [tweak] and [tweak_from] macros in this module, + //! import it from [assets](super) crate directly. + //! + //! Will hot-reload (if corresponded feature is enabled). + // TODO: don't use the same ASSETS_PATH as game uses? use super::{Asset, AssetExt, RonLoader, ASSETS_PATH}; use ron::ser::{to_writer_pretty, PrettyConfig}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; @@ -366,17 +372,17 @@ pub mod asset_tweak { /// }; /// /// // you need to create file first - /// let tweak_path = ASSETS_PATH.join("tweak/y.ron"); + /// let tweak_path = ASSETS_PATH.join("tweak/year.ron"); /// // note parentheses /// fs::write(&tweak_path, b"(10)"); /// - /// let y: i32 = tweak_expect(Specifier::Tweak("y")); + /// let y: i32 = tweak_expect(Specifier::Tweak("year")); /// assert_eq!(y, 10); /// /// // Specifier::Tweak is just a shorthand /// // for Specifier::Asset(&["tweak", ..]) - /// let z: i32 = tweak_expect(Specifier::Asset(&["tweak", "y"])); - /// assert_eq!(y, 10); + /// let y1: i32 = tweak_expect(Specifier::Asset(&["tweak", "year"])); + /// assert_eq!(y1, 10); /// /// // you may want to remove this file later /// std::fs::remove_file(tweak_path); @@ -445,15 +451,15 @@ pub mod asset_tweak { /// }; /// /// // first time it will create the file - /// let x: i32 = tweak_expect_or_create(Specifier::Tweak("x"), 5); - /// let file_path = ASSETS_PATH.join("tweak/x.ron"); + /// let x: i32 = tweak_expect_or_create(Specifier::Tweak("stars"), 5); + /// let file_path = ASSETS_PATH.join("tweak/stars.ron"); /// assert!(file_path.is_file()); /// assert_eq!(x, 5); /// /// // next time it will read value from file /// // whatever you will pass as default - /// let x: i32 = tweak_expect_or_create(Specifier::Tweak("x"), 42); - /// assert_eq!(x, 5); + /// let x1: i32 = tweak_expect_or_create(Specifier::Tweak("stars"), 42); + /// assert_eq!(x1, 5); /// /// // you may want to remove this file later /// std::fs::remove_file(file_path); @@ -477,6 +483,100 @@ pub mod asset_tweak { } } + /// Convinient macro to quickly tweak value. + /// + /// Will use [Specifier]`::Tweak` specifier and call + /// [tweak_expect] if passed only name + /// or [tweak_expect_or_create] if default is passed. + /// + /// # Examples: + /// ``` + /// // note that you need to export it from `assets` crate, + /// // not from `assets::asset_tweak` + /// use veloren_common_assets::{tweak, ASSETS_PATH}; + /// + /// // you need to create file first + /// let own_path = ASSETS_PATH.join("tweak/grizelda.ron"); + /// // note parentheses + /// std::fs::write(&own_path, b"(10)"); + /// + /// let z: i32 = tweak!("grizelda"); + /// assert_eq!(z, 10); + /// + /// // voila, you don't need to care about creating file first + /// let p: i32 = tweak!("peter", 8); + /// + /// let created_path = ASSETS_PATH.join("tweak/peter.ron"); + /// assert!(created_path.is_file()); + /// assert_eq!(p, 8); + /// + /// // will use default value only first time + /// // if file exists, will load from this file + /// let p: i32 = tweak!("peter", 50); + /// assert_eq!(p, 8); + /// + /// // you may want to remove this file later + /// std::fs::remove_file(own_path); + /// std::fs::remove_file(created_path); + /// ``` + #[macro_export] + macro_rules! tweak { + ($name:literal) => {{ + use $crate::asset_tweak::{tweak_expect, Specifier::Tweak}; + + tweak_expect(Tweak($name)) + }}; + + ($name:literal, $default:expr) => {{ + use $crate::asset_tweak::{tweak_expect_or_create, Specifier::Tweak}; + + tweak_expect_or_create(Tweak($name), $default) + }}; + } + + /// Convinient macro to quickly tweak value from some existing path. + /// + /// Will use [Specifier]`::Asset` specifier and call + /// [tweak_expect] if passed only name + /// or [tweak_expect_or_create] if default is passed. + /// + /// The main use case is when you have some object + /// which needs constant tuning of values, but you can't afford + /// loading a file. + /// So you can use tweak_from! and then just copy values from asset + /// to your object. + /// + /// # Examples: + /// ```no_run + /// // note that you need to export it from `assets` crate, + /// // not from `assets::asset_tweak` + /// use serde::{Deserialize, Serialize}; + /// use veloren_common_assets::{tweak_from, ASSETS_PATH}; + /// + /// #[derive(Clone, PartialEq, Deserialize, Serialize)] + /// struct Data { + /// x: i32, + /// y: i32, + /// } + /// + /// let default = Data { x: 5, y: 7 }; + /// let data: Data = tweak_from!(&["common", "body", "dimensions"], default); + /// ``` + #[macro_export] + macro_rules! tweak_from { + ($path:expr) => {{ + use $crate::asset_tweak::{tweak_expect, Specifier::Asset}; + + tweak_expect(Asset($path)) + }}; + + ($path:expr, $default:expr) => {{ + use $crate::asset_tweak::{tweak_expect_or_create, Specifier::Asset}; + + tweak_expect_or_create(Asset($path), $default) + }}; + } + #[cfg(test)] mod tests { use super::*; From 7d4a8cbfa4b99257fd0fcc480c7c5c2216ff21c3 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Mon, 26 Jul 2021 16:52:43 +0300 Subject: [PATCH 066/155] Add battle_mode server setting and player flag --- common/src/combat.rs | 38 ++++++-- common/src/comp/player.rs | 27 +++++- common/src/effect.rs | 9 ++ common/src/resources.rs | 10 +++ common/systems/src/beam.rs | 29 +++++- common/systems/src/melee.rs | 39 ++++++-- common/systems/src/projectile.rs | 29 +++++- common/systems/src/shockwave.rs | 29 +++++- server/src/events/entity_manipulation.rs | 41 ++++++++- server/src/settings.rs | 4 +- server/src/sys/msg/register.rs | 109 +++++++++++++---------- 11 files changed, 288 insertions(+), 76 deletions(-) diff --git a/common/src/combat.rs b/common/src/combat.rs index 1bd42c2389..a7c923624b 100644 --- a/common/src/combat.rs +++ b/common/src/combat.rs @@ -71,6 +71,13 @@ pub struct TargetInfo<'a> { pub char_state: Option<&'a CharacterState>, } +#[derive(Clone, Copy)] +pub struct AttackOptions { + pub target_dodging: bool, + pub target_group: GroupTarget, + pub avoid_harm: bool, +} + #[cfg(not(target_arch = "wasm32"))] #[derive(Clone, Debug, Serialize, Deserialize)] // TODO: Yeet clone derive pub struct Attack { @@ -158,28 +165,47 @@ impl Attack { 1.0 - (1.0 - damage_reduction) * (1.0 - block_reduction) } + #[allow(clippy::too_many_arguments)] pub fn apply_attack( &self, - target_group: GroupTarget, attacker: Option, target: TargetInfo, dir: Dir, - target_dodging: bool, - // Currently just modifies damage, maybe look into modifying strength of other effects? + options: AttackOptions, + // Currently strength_modifier just modifies damage, + // maybe look into modifying strength of other effects? strength_modifier: f32, attack_source: AttackSource, mut emit: impl FnMut(ServerEvent), mut emit_outcome: impl FnMut(Outcome), ) -> bool { - let mut is_applied = false; + let AttackOptions { + target_dodging, + target_group, + avoid_harm, + } = options; + // target == OutOfGroup is basic heuristic that this + // "attack" has negative effects. + // + // so if target dodges this "attack" or we don't want to harm target, + // it should avoid such "damage" or effect + let avoid_damage = |attack_damage: &AttackDamage| { + matches!(attack_damage.target, Some(GroupTarget::OutOfGroup)) + && (target_dodging || avoid_harm) + }; + let avoid_effect = |attack_effect: &AttackEffect| { + matches!(attack_effect.target, Some(GroupTarget::OutOfGroup)) + && (target_dodging || avoid_harm) + }; let is_crit = thread_rng().gen::() < self.crit_chance; + let mut is_applied = false; let mut accumulated_damage = 0.0; for damage in self .damages .iter() .filter(|d| d.target.map_or(true, |t| t == target_group)) - .filter(|d| !(matches!(d.target, Some(GroupTarget::OutOfGroup)) && target_dodging)) + .filter(|d| !avoid_damage(d)) { is_applied = true; let damage_reduction = Attack::compute_damage_reduction( @@ -294,7 +320,7 @@ impl Attack { .effects .iter() .filter(|e| e.target.map_or(true, |t| t == target_group)) - .filter(|e| !(matches!(e.target, Some(GroupTarget::OutOfGroup)) && target_dodging)) + .filter(|e| !avoid_effect(e)) { if effect.requirements.iter().all(|req| match req { CombatRequirement::AnyDamage => accumulated_damage > 0.0 && target.health.is_some(), diff --git a/common/src/comp/player.rs b/common/src/comp/player.rs index 7a34664569..a9f7ce59bd 100644 --- a/common/src/comp/player.rs +++ b/common/src/comp/player.rs @@ -3,6 +3,8 @@ use specs::{Component, DerefFlaggedStorage, NullStorage}; use specs_idvs::IdvStorage; use uuid::Uuid; +use crate::resources::BattleMode; + const MAX_ALIAS_LEN: usize = 32; #[derive(Debug)] @@ -17,11 +19,34 @@ pub enum DisconnectReason { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Player { pub alias: String, + pub battle_mode: BattleMode, uuid: Uuid, } impl Player { - pub fn new(alias: String, uuid: Uuid) -> Self { Self { alias, uuid } } + pub fn new(alias: String, battle_mode: BattleMode, uuid: Uuid) -> Self { + Self { + alias, + battle_mode, + uuid, + } + } + + /// Currently we allow attacking only if both players are opt-in to PvP. + /// + /// Simple as tea, if they don't want the tea, don't make them drink the tea. + pub fn allow_harm(&self, other: &Player) -> bool { + // TODO: discuss if we want to keep self-harm + matches!( + (self.battle_mode, other.battle_mode), + (BattleMode::PvP, BattleMode::PvP) + ) + } + + /// Inverse of `allow_harm`. Read its doc to learn more. + pub fn disallow_harm(&self, other: &Player) -> bool { + !self.allow_harm(other) + } pub fn is_valid(&self) -> bool { Self::alias_validate(&self.alias).is_ok() } diff --git a/common/src/effect.rs b/common/src/effect.rs index aca9cf0ca8..a1b6b599e3 100644 --- a/common/src/effect.rs +++ b/common/src/effect.rs @@ -28,6 +28,15 @@ impl Effect { } } + pub fn is_harm(&self) -> bool { + match self { + Effect::Health(c) => c.amount < 0, + Effect::PoiseChange(c) => c.amount < 0, + Effect::Damage(_) => true, + Effect::Buff(e) => !e.kind.is_buff(), + } + } + pub fn modify_strength(&mut self, modifier: f32) { match self { Effect::Health(change) => { diff --git a/common/src/resources.rs b/common/src/resources.rs index e6d798ce84..ee57b3242a 100644 --- a/common/src/resources.rs +++ b/common/src/resources.rs @@ -74,3 +74,13 @@ impl PlayerPhysicsSetting { pub struct PlayerPhysicsSettings { pub settings: hashbrown::HashMap, } + +/// Describe how players interact with other players. +/// +/// Probably will be removed when we will discover better way +/// to handle duels and murders +#[derive(Copy, Clone, Debug, Deserialize, Serialize)] +pub enum BattleMode { + PvP, + PvE, +} diff --git a/common/systems/src/beam.rs b/common/systems/src/beam.rs index dae48525d2..0a3a86e93a 100644 --- a/common/systems/src/beam.rs +++ b/common/systems/src/beam.rs @@ -1,9 +1,9 @@ use common::{ - combat::{AttackSource, AttackerInfo, TargetInfo}, + combat::{AttackOptions, AttackSource, AttackerInfo, TargetInfo}, comp::{ agent::{Sound, SoundKind}, Beam, BeamSegment, Body, CharacterState, Combo, Energy, Group, Health, HealthSource, - Inventory, Ori, Pos, Scale, Stats, + Inventory, Ori, Player, Pos, Scale, Stats, }, event::{EventBus, ServerEvent}, outcome::Outcome, @@ -26,6 +26,7 @@ use vek::*; #[derive(SystemData)] pub struct ReadData<'a> { entities: Entities<'a>, + players: ReadStorage<'a, Player>, server_bus: Read<'a, EventBus>, time: Read<'a, Time>, dt: Read<'a, DeltaTime>, @@ -212,12 +213,32 @@ impl<'a> System<'a> for Sys { char_state: read_data.character_states.get(target), }; - beam_segment.properties.attack.apply_attack( + // No luck with dodging beams + let is_dodge = false; + let avoid_harm = { + let players = &read_data.players; + beam_owner.map_or(false, |attacker| { + if let (Some(attacker), Some(target)) = + (players.get(attacker), players.get(target)) + { + attacker.disallow_harm(target) + } else { + false + } + }) + }; + + let attack_options = AttackOptions { + target_dodging: is_dodge, target_group, + avoid_harm, + }; + + beam_segment.properties.attack.apply_attack( attacker_info, target_info, ori.look_dir(), - false, + attack_options, 1.0, AttackSource::Beam, |e| server_events.push(e), diff --git a/common/systems/src/melee.rs b/common/systems/src/melee.rs index 20ac8b54a9..5844b3711d 100644 --- a/common/systems/src/melee.rs +++ b/common/systems/src/melee.rs @@ -1,9 +1,9 @@ use common::{ - combat::{AttackSource, AttackerInfo, TargetInfo}, + combat::{AttackOptions, AttackSource, AttackerInfo, TargetInfo}, comp::{ agent::{Sound, SoundKind}, - Body, CharacterState, Combo, Energy, Group, Health, Inventory, Melee, Ori, Pos, Scale, - Stats, + Body, CharacterState, Combo, Energy, Group, Health, Inventory, Melee, Ori, Player, Pos, + Scale, Stats, }, event::{EventBus, ServerEvent}, outcome::Outcome, @@ -22,6 +22,7 @@ use vek::*; pub struct ReadData<'a> { time: Read<'a, Time>, entities: Entities<'a>, + players: ReadStorage<'a, Player>, uids: ReadStorage<'a, Uid>, positions: ReadStorage<'a, Pos>, orientations: ReadStorage<'a, Ori>, @@ -161,12 +162,40 @@ impl<'a> System<'a> for Sys { char_state: read_data.char_states.get(target), }; - let is_applied = melee_attack.attack.apply_attack( + let avoid_harm = { + let players = &read_data.players; + if let (Some(attacker), Some(target)) = + (players.get(attacker), players.get(target)) + { + attacker.disallow_harm(target) + } else { + false + } + }; + + // FIXME: printf debugging, this shouldn't go to master + if let Some(attacker) = read_data.players.get(attacker) { + println!("attacker battle_mode: {:?}", attacker.battle_mode); + } else { + println!("attacker special casing") + } + if let Some(target) = read_data.players.get(target) { + println!("target battle_mode: {:?}", target.battle_mode); + } else { + println!("target special casing") + } + + let attack_options = AttackOptions { + target_dodging: is_dodge, target_group, + avoid_harm, + }; + + let is_applied = melee_attack.attack.apply_attack( attacker_info, target_info, dir, - is_dodge, + attack_options, 1.0, AttackSource::Melee, |e| server_emitter.emit(e), diff --git a/common/systems/src/projectile.rs b/common/systems/src/projectile.rs index e9d7a5a3e8..73dbbea93e 100644 --- a/common/systems/src/projectile.rs +++ b/common/systems/src/projectile.rs @@ -1,9 +1,9 @@ use common::{ - combat::{AttackSource, AttackerInfo, TargetInfo}, + combat::{AttackOptions, AttackSource, AttackerInfo, TargetInfo}, comp::{ agent::{Sound, SoundKind}, projectile, Body, CharacterState, Combo, Energy, Group, Health, HealthSource, Inventory, - Ori, PhysicsState, Pos, Projectile, Stats, Vel, + Ori, PhysicsState, Player, Pos, Projectile, Stats, Vel, }, event::{EventBus, ServerEvent}, outcome::Outcome, @@ -25,6 +25,7 @@ use vek::*; pub struct ReadData<'a> { time: Read<'a, Time>, entities: Entities<'a>, + players: ReadStorage<'a, Player>, dt: Read<'a, DeltaTime>, uid_allocator: Read<'a, UidAllocator>, server_bus: Read<'a, EventBus>, @@ -152,6 +153,22 @@ impl<'a> System<'a> for Sys { char_state: read_data.character_states.get(target), }; + // They say witchers can dodge arrows, + // but we don't have witchers + let is_dodge = false; + let avoid_harm = { + let players = &read_data.players; + projectile_owner.map_or(false, |attacker| { + if let (Some(attacker), Some(target)) = + (players.get(attacker), players.get(target)) + { + attacker.disallow_harm(target) + } else { + false + } + }) + }; + if let Some(&body) = read_data.bodies.get(entity) { outcomes.push(Outcome::ProjectileHit { pos: pos.0, @@ -165,12 +182,16 @@ impl<'a> System<'a> for Sys { }); } - attack.apply_attack( + let attack_options = AttackOptions { + target_dodging: is_dodge, target_group, + avoid_harm, + }; + attack.apply_attack( attacker_info, target_info, dir, - false, + attack_options, 1.0, AttackSource::Projectile, |e| server_emitter.emit(e), diff --git a/common/systems/src/shockwave.rs b/common/systems/src/shockwave.rs index 2997821811..fbfe31756f 100644 --- a/common/systems/src/shockwave.rs +++ b/common/systems/src/shockwave.rs @@ -1,9 +1,9 @@ use common::{ - combat::{AttackSource, AttackerInfo, TargetInfo}, + combat::{AttackOptions, AttackSource, AttackerInfo, TargetInfo}, comp::{ agent::{Sound, SoundKind}, Body, CharacterState, Combo, Energy, Group, Health, HealthSource, Inventory, Ori, - PhysicsState, Pos, Scale, Shockwave, ShockwaveHitEntities, Stats, + PhysicsState, Player, Pos, Scale, Shockwave, ShockwaveHitEntities, Stats, }, event::{EventBus, ServerEvent}, outcome::Outcome, @@ -25,6 +25,7 @@ pub struct ReadData<'a> { entities: Entities<'a>, server_bus: Read<'a, EventBus>, time: Read<'a, Time>, + players: ReadStorage<'a, Player>, dt: Read<'a, DeltaTime>, uid_allocator: Read<'a, UidAllocator>, uids: ReadStorage<'a, Uid>, @@ -208,12 +209,32 @@ impl<'a> System<'a> for Sys { char_state: read_data.character_states.get(target), }; - shockwave.properties.attack.apply_attack( + // Trying roll during earthquake isn't the best idea + let is_dodge = false; + let avoid_harm = { + let players = &read_data.players; + shockwave_owner.map_or(false, |attacker| { + if let (Some(attacker), Some(target)) = + (players.get(attacker), players.get(target)) + { + attacker.disallow_harm(target) + } else { + false + } + }) + }; + + let attack_options = AttackOptions { + target_dodging: is_dodge, target_group, + avoid_harm, + }; + + shockwave.properties.attack.apply_attack( attacker_info, target_info, dir, - false, + attack_options, 1.0, AttackSource::Shockwave, |e| server_emitter.emit(e), diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 345984e2a2..da92740aba 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -819,6 +819,7 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o let energies = &ecs.read_storage::(); let combos = &ecs.read_storage::(); let inventories = &ecs.read_storage::(); + let players = &ecs.read_storage::(); for ( entity_b, pos_b, @@ -887,12 +888,31 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o char_state: char_state_b_maybe, }; - attack.apply_attack( + let avoid_harm = { + owner_entity.map_or(false, |attacker| { + if let (Some(attacker), Some(target)) = + (players.get(attacker), players.get(entity_b)) + { + attacker.disallow_harm(target) + } else { + false + } + }) + }; + + let attack_options = combat::AttackOptions { + // cool guyz maybe don't look at explosions + // but they still got hurt, it's not Hollywood + target_dodging: false, target_group, + avoid_harm, + }; + + attack.apply_attack( attacker_info, target_info, dir, - false, + attack_options, strength, combat::AttackSource::Explosion, |e| server_eventbus.emit_now(e), @@ -902,6 +922,7 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o } }, RadiusEffect::Entity(mut effect) => { + let players = &ecs.read_storage::(); for (entity_b, pos_b, body_b_maybe) in ( &ecs.entities(), &ecs.read_storage::(), @@ -921,9 +942,23 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o .read_storage::() .get(entity_b) .map_or(true, |h| !h.is_dead); + if is_alive { + let avoid_harm = { + owner_entity.map_or(false, |attacker| { + if let (Some(attacker), Some(target)) = + (players.get(attacker), players.get(entity_b)) + { + attacker.disallow_harm(target) + } else { + false + } + }) + }; effect.modify_strength(strength); - server.state().apply_effect(entity_b, effect.clone(), owner); + if !(effect.is_harm() && avoid_harm) { + server.state().apply_effect(entity_b, effect.clone(), owner); + } } } } diff --git a/server/src/settings.rs b/server/src/settings.rs index ce66969277..db41af5a5d 100644 --- a/server/src/settings.rs +++ b/server/src/settings.rs @@ -14,6 +14,7 @@ pub use server_description::ServerDescription; pub use whitelist::{Whitelist, WhitelistInfo, WhitelistRecord}; use chrono::Utc; +use common::resources::BattleMode; use core::time::Duration; use portpicker::pick_unused_port; use serde::{Deserialize, Serialize}; @@ -48,7 +49,7 @@ pub struct Settings { pub quic_files: Option, pub max_players: usize, pub world_seed: u32, - //pub pvp_enabled: bool, + pub battle_mode: BattleMode, pub server_name: String, pub start_time: f64, /// When set to None, loads the default map file (if available); otherwise, @@ -73,6 +74,7 @@ impl Default for Settings { world_seed: DEFAULT_WORLD_SEED, server_name: "Veloren Alpha".into(), max_players: 100, + battle_mode: BattleMode::PvP, start_time: 9.0 * 3600.0, map_file: None, max_view_distance: Some(65), diff --git a/server/src/sys/msg/register.rs b/server/src/sys/msg/register.rs index 8d3015d946..00923eb490 100644 --- a/server/src/sys/msg/register.rs +++ b/server/src/sys/msg/register.rs @@ -2,7 +2,7 @@ use crate::{ client::Client, login_provider::{LoginProvider, PendingLogin}, metrics::PlayerMetrics, - EditableSettings, + EditableSettings, Settings, }; use common::{ comp::{Admin, Player, Stats}, @@ -17,7 +17,8 @@ use common_net::msg::{ use hashbrown::HashMap; use plugin_api::Health; use specs::{ - storage::StorageEntry, Entities, Join, Read, ReadExpect, ReadStorage, WriteExpect, WriteStorage, + shred::ResourceId, storage::StorageEntry, Entities, Join, Read, ReadExpect, ReadStorage, + SystemData, World, WriteExpect, WriteStorage, }; use tracing::trace; @@ -29,26 +30,32 @@ type ReadPlugin<'a> = Read<'a, PluginMgr>; #[cfg(not(feature = "plugins"))] type ReadPlugin<'a> = Option>; +#[derive(SystemData)] +pub struct ReadData<'a> { + entities: Entities<'a>, + stats: ReadStorage<'a, Stats>, + uids: ReadStorage<'a, Uid>, + clients: ReadStorage<'a, Client>, + server_event_bus: Read<'a, EventBus>, + _health_comp: ReadStorage<'a, Health>, // used by plugin feature + _plugin_mgr: ReadPlugin<'a>, // used by plugin feature + _uid_allocator: Read<'a, UidAllocator>, // used by plugin feature +} + /// This system will handle new messages from clients #[derive(Default)] pub struct Sys; impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( - Entities<'a>, + ReadData<'a>, ReadExpect<'a, PlayerMetrics>, - ReadStorage<'a, Health>, - ReadStorage<'a, Uid>, - ReadStorage<'a, Client>, - WriteStorage<'a, Player>, - WriteStorage<'a, PendingLogin>, - Read<'a, UidAllocator>, - ReadPlugin<'a>, - ReadStorage<'a, Stats>, - WriteExpect<'a, LoginProvider>, - WriteStorage<'a, Admin>, + ReadExpect<'a, Settings>, ReadExpect<'a, EditableSettings>, - Read<'a, EventBus>, + WriteStorage<'a, Player>, + WriteStorage<'a, Admin>, + WriteStorage<'a, PendingLogin>, + WriteExpect<'a, LoginProvider>, ); const NAME: &'static str = "msg::register"; @@ -58,24 +65,23 @@ impl<'a> System<'a> for Sys { fn run( _job: &mut Job, ( - entities, + read_data, player_metrics, - _health_comp, // used by plugin feature - uids, - clients, - mut players, - mut pending_logins, - _uid_allocator, // used by plugin feature - _plugin_mgr, // used by plugin feature - stats, - mut login_provider, - mut admins, + settings, editable_settings, - server_event_bus, + mut players, + mut admins, + mut pending_logins, + mut login_provider, ): Self::SystemData, ) { // Player list to send new players. - let player_list = (&uids, &players, stats.maybe(), admins.maybe()) + let player_list = ( + &read_data.uids, + &players, + read_data.stats.maybe(), + admins.maybe(), + ) .join() .map(|(uid, player, stats, admin)| { (*uid, PlayerInfo { @@ -92,7 +98,7 @@ impl<'a> System<'a> for Sys { let mut new_players = Vec::new(); // defer auth lockup - for (entity, client) in (&entities, &clients).join() { + for (entity, client) in (&read_data.entities, &read_data.clients).join() { let _ = super::try_recv_all(client, 0, |_, msg: ClientRegister| { trace!(?msg.token_or_username, "defer auth lockup"); let pending = login_provider.verify(&msg.token_or_username); @@ -103,15 +109,17 @@ impl<'a> System<'a> for Sys { let mut finished_pending = vec![]; let mut retries = vec![]; - for (entity, client, mut pending) in (&entities, &clients, &mut pending_logins).join() { + for (entity, client, mut pending) in + (&read_data.entities, &read_data.clients, &mut pending_logins).join() + { if let Err(e) = || -> std::result::Result<(), crate::error::Error> { #[cfg(feature = "plugins")] let ecs_world = EcsWorld { - entities: &entities, - health: (&_health_comp).into(), - uid: (&uids).into(), + entities: &read_data.entities, + health: (&read_data._health_comp).into(), + uid: (&read_data.uids).into(), player: (&players).into(), - uid_allocator: &_uid_allocator, + uid_allocator: &read_data._uid_allocator, }; let (username, uuid) = match login_provider.login( @@ -119,7 +127,7 @@ impl<'a> System<'a> for Sys { #[cfg(feature = "plugins")] &ecs_world, #[cfg(feature = "plugins")] - &_plugin_mgr, + &read_data._plugin_mgr, &*editable_settings.admins, &*editable_settings.whitelist, &*editable_settings.banlist, @@ -130,10 +138,12 @@ impl<'a> System<'a> for Sys { trace!(?r, "pending login returned"); match r { Err(e) => { - server_event_bus.emit_now(ServerEvent::ClientDisconnect( - entity, - common::comp::DisconnectReason::Kicked, - )); + read_data + .server_event_bus + .emit_now(ServerEvent::ClientDisconnect( + entity, + common::comp::DisconnectReason::Kicked, + )); client.send(ServerRegisterAnswer::Err(e))?; return Ok(()); }, @@ -143,15 +153,18 @@ impl<'a> System<'a> for Sys { }; // Check if user is already logged-in - if let Some((old_entity, old_client, _)) = (&entities, &clients, &players) - .join() - .find(|(_, _, old_player)| old_player.uuid() == uuid) + if let Some((old_entity, old_client, _)) = + (&read_data.entities, &read_data.clients, &players) + .join() + .find(|(_, _, old_player)| old_player.uuid() == uuid) { // Remove old client - server_event_bus.emit_now(ServerEvent::ClientDisconnect( - old_entity, - common::comp::DisconnectReason::NewerLogin, - )); + read_data + .server_event_bus + .emit_now(ServerEvent::ClientDisconnect( + old_entity, + common::comp::DisconnectReason::NewerLogin, + )); let _ = old_client.send(ServerGeneral::Disconnect(DisconnectReason::Kicked( String::from("You have logged in from another location."), ))); @@ -166,7 +179,7 @@ impl<'a> System<'a> for Sys { return Ok(()); } - let player = Player::new(username, uuid); + let player = Player::new(username, settings.battle_mode, uuid); let admin = editable_settings.admins.get(&uuid); if !player.is_valid() { @@ -215,9 +228,9 @@ impl<'a> System<'a> for Sys { // Handle new players. // Tell all clients to add them to the player list. for entity in new_players { - if let (Some(uid), Some(player)) = (uids.get(entity), players.get(entity)) { + if let (Some(uid), Some(player)) = (read_data.uids.get(entity), players.get(entity)) { let mut lazy_msg = None; - for (_, client) in (&players, &clients).join() { + for (_, client) in (&players, &read_data.clients).join() { if lazy_msg.is_none() { lazy_msg = Some(client.prepare(ServerGeneral::PlayerListUpdate( PlayerListUpdate::Add(*uid, PlayerInfo { From c7fdb640ac8e10d468ce2c873414efff66c67f15 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Wed, 28 Jul 2021 00:57:48 +0300 Subject: [PATCH 067/155] Cleaning --- common/src/combat.rs | 23 +++++++++++++++--- common/src/comp/player.rs | 7 +++--- common/systems/src/beam.rs | 19 +++------------ common/systems/src/melee.rs | 30 +++-------------------- common/systems/src/projectile.rs | 19 +++------------ common/systems/src/shockwave.rs | 19 +++------------ server/src/events/entity_manipulation.rs | 31 ++++++------------------ 7 files changed, 45 insertions(+), 103 deletions(-) diff --git a/common/src/combat.rs b/common/src/combat.rs index a7c923624b..237ddf46a4 100644 --- a/common/src/combat.rs +++ b/common/src/combat.rs @@ -13,7 +13,7 @@ use crate::{ poise::PoiseChange, skills::SkillGroupKind, Body, CharacterState, Combo, Energy, EnergyChange, EnergySource, Health, HealthChange, - HealthSource, Inventory, Ori, SkillSet, Stats, + HealthSource, Inventory, Ori, Player, SkillSet, Stats, }, event::ServerEvent, outcome::Outcome, @@ -53,6 +53,7 @@ pub enum AttackSource { #[derive(Copy, Clone)] pub struct AttackerInfo<'a> { pub entity: EcsEntity, + pub player: Option<&'a Player>, pub uid: Uid, pub energy: Option<&'a Energy>, pub combo: Option<&'a Combo>, @@ -62,6 +63,7 @@ pub struct AttackerInfo<'a> { #[cfg(not(target_arch = "wasm32"))] pub struct TargetInfo<'a> { pub entity: EcsEntity, + pub player: Option<&'a Player>, pub uid: Uid, pub inventory: Option<&'a Inventory>, pub stats: Option<&'a Stats>, @@ -75,7 +77,6 @@ pub struct TargetInfo<'a> { pub struct AttackOptions { pub target_dodging: bool, pub target_group: GroupTarget, - pub avoid_harm: bool, } #[cfg(not(target_arch = "wasm32"))] @@ -165,7 +166,6 @@ impl Attack { 1.0 - (1.0 - damage_reduction) * (1.0 - block_reduction) } - #[allow(clippy::too_many_arguments)] pub fn apply_attack( &self, @@ -183,8 +183,11 @@ impl Attack { let AttackOptions { target_dodging, target_group, - avoid_harm, } = options; + + let avoid_harm = + attacker.map_or(false, |attacker| avoid_harm(attacker.player, target.player)); + // target == OutOfGroup is basic heuristic that this // "attack" has negative effects. // @@ -456,6 +459,18 @@ impl Attack { } } +/// Checks if we should avoid negative effects from one player to another +// FIXME: handle pets? +// This code works only with players. +// You still can kill someone's pet and +// you still can be killed by someone's pet +pub fn avoid_harm(attacker: Option<&Player>, target: Option<&Player>) -> bool { + if let (Some(attacker), Some(target)) = (attacker, target) { + return attacker.disallow_harm(target); + } + false +} + #[cfg(not(target_arch = "wasm32"))] #[derive(Clone, Debug, Serialize, Deserialize)] pub struct AttackDamage { diff --git a/common/src/comp/player.rs b/common/src/comp/player.rs index a9f7ce59bd..f3ab03a081 100644 --- a/common/src/comp/player.rs +++ b/common/src/comp/player.rs @@ -34,7 +34,8 @@ impl Player { /// Currently we allow attacking only if both players are opt-in to PvP. /// - /// Simple as tea, if they don't want the tea, don't make them drink the tea. + /// Simple as tea, if they don't want the tea, don't make them drink the + /// tea. pub fn allow_harm(&self, other: &Player) -> bool { // TODO: discuss if we want to keep self-harm matches!( @@ -44,9 +45,7 @@ impl Player { } /// Inverse of `allow_harm`. Read its doc to learn more. - pub fn disallow_harm(&self, other: &Player) -> bool { - !self.allow_harm(other) - } + pub fn disallow_harm(&self, other: &Player) -> bool { !self.allow_harm(other) } pub fn is_valid(&self) -> bool { Self::alias_validate(&self.alias).is_ok() } diff --git a/common/systems/src/beam.rs b/common/systems/src/beam.rs index 0a3a86e93a..b22bca06f8 100644 --- a/common/systems/src/beam.rs +++ b/common/systems/src/beam.rs @@ -196,6 +196,7 @@ impl<'a> System<'a> for Sys { .zip(beam_segment.owner) .map(|(entity, uid)| AttackerInfo { entity, + player: read_data.players.get(entity), uid, energy: read_data.energies.get(entity), combo: read_data.combos.get(entity), @@ -204,6 +205,7 @@ impl<'a> System<'a> for Sys { let target_info = TargetInfo { entity: target, + player: read_data.players.get(target), uid: *uid_b, inventory: read_data.inventories.get(target), stats: read_data.stats.get(target), @@ -214,24 +216,11 @@ impl<'a> System<'a> for Sys { }; // No luck with dodging beams - let is_dodge = false; - let avoid_harm = { - let players = &read_data.players; - beam_owner.map_or(false, |attacker| { - if let (Some(attacker), Some(target)) = - (players.get(attacker), players.get(target)) - { - attacker.disallow_harm(target) - } else { - false - } - }) - }; + let target_dodging = false; let attack_options = AttackOptions { - target_dodging: is_dodge, + target_dodging, target_group, - avoid_harm, }; beam_segment.properties.attack.apply_attack( diff --git a/common/systems/src/melee.rs b/common/systems/src/melee.rs index 5844b3711d..d7134396ff 100644 --- a/common/systems/src/melee.rs +++ b/common/systems/src/melee.rs @@ -116,7 +116,7 @@ impl<'a> System<'a> for Sys { let rad_b = body_b.radius() * scale_b; // Check if entity is dodging - let is_dodge = read_data + let target_dodging = read_data .char_states .get(target) .map_or(false, |c_s| c_s.is_melee_dodge()); @@ -145,6 +145,7 @@ impl<'a> System<'a> for Sys { let attacker_info = Some(AttackerInfo { entity: attacker, + player: read_data.players.get(attacker), uid: *uid, energy: read_data.energies.get(attacker), combo: read_data.combos.get(attacker), @@ -153,6 +154,7 @@ impl<'a> System<'a> for Sys { let target_info = TargetInfo { entity: target, + player: read_data.players.get(target), uid: *uid_b, inventory: read_data.inventories.get(target), stats: read_data.stats.get(target), @@ -162,33 +164,9 @@ impl<'a> System<'a> for Sys { char_state: read_data.char_states.get(target), }; - let avoid_harm = { - let players = &read_data.players; - if let (Some(attacker), Some(target)) = - (players.get(attacker), players.get(target)) - { - attacker.disallow_harm(target) - } else { - false - } - }; - - // FIXME: printf debugging, this shouldn't go to master - if let Some(attacker) = read_data.players.get(attacker) { - println!("attacker battle_mode: {:?}", attacker.battle_mode); - } else { - println!("attacker special casing") - } - if let Some(target) = read_data.players.get(target) { - println!("target battle_mode: {:?}", target.battle_mode); - } else { - println!("target special casing") - } - let attack_options = AttackOptions { - target_dodging: is_dodge, + target_dodging, target_group, - avoid_harm, }; let is_applied = melee_attack.attack.apply_attack( diff --git a/common/systems/src/projectile.rs b/common/systems/src/projectile.rs index 73dbbea93e..e19430d328 100644 --- a/common/systems/src/projectile.rs +++ b/common/systems/src/projectile.rs @@ -135,6 +135,7 @@ impl<'a> System<'a> for Sys { owner_entity.zip(projectile.owner).map(|(entity, uid)| { AttackerInfo { entity, + player: read_data.players.get(entity), uid, energy: read_data.energies.get(entity), combo: read_data.combos.get(entity), @@ -144,6 +145,7 @@ impl<'a> System<'a> for Sys { let target_info = TargetInfo { entity: target, + player: read_data.players.get(target), uid: other, inventory: read_data.inventories.get(target), stats: read_data.stats.get(target), @@ -155,19 +157,7 @@ impl<'a> System<'a> for Sys { // They say witchers can dodge arrows, // but we don't have witchers - let is_dodge = false; - let avoid_harm = { - let players = &read_data.players; - projectile_owner.map_or(false, |attacker| { - if let (Some(attacker), Some(target)) = - (players.get(attacker), players.get(target)) - { - attacker.disallow_harm(target) - } else { - false - } - }) - }; + let target_dodging = false; if let Some(&body) = read_data.bodies.get(entity) { outcomes.push(Outcome::ProjectileHit { @@ -183,9 +173,8 @@ impl<'a> System<'a> for Sys { } let attack_options = AttackOptions { - target_dodging: is_dodge, + target_dodging, target_group, - avoid_harm, }; attack.apply_attack( attacker_info, diff --git a/common/systems/src/shockwave.rs b/common/systems/src/shockwave.rs index fbfe31756f..19f49f7f1c 100644 --- a/common/systems/src/shockwave.rs +++ b/common/systems/src/shockwave.rs @@ -192,6 +192,7 @@ impl<'a> System<'a> for Sys { .zip(shockwave.owner) .map(|(entity, uid)| AttackerInfo { entity, + player: read_data.players.get(entity), uid, energy: read_data.energies.get(entity), combo: read_data.combos.get(entity), @@ -200,6 +201,7 @@ impl<'a> System<'a> for Sys { let target_info = TargetInfo { entity: target, + player: read_data.players.get(target), uid: *uid_b, inventory: read_data.inventories.get(target), stats: read_data.stats.get(target), @@ -210,24 +212,11 @@ impl<'a> System<'a> for Sys { }; // Trying roll during earthquake isn't the best idea - let is_dodge = false; - let avoid_harm = { - let players = &read_data.players; - shockwave_owner.map_or(false, |attacker| { - if let (Some(attacker), Some(target)) = - (players.get(attacker), players.get(target)) - { - attacker.disallow_harm(target) - } else { - false - } - }) - }; + let target_dodging = false; let attack_options = AttackOptions { - target_dodging: is_dodge, + target_dodging, target_group, - avoid_harm, }; shockwave.properties.attack.apply_attack( diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index da92740aba..aab9831833 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -871,6 +871,7 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o .zip(owner) .map(|(entity, uid)| combat::AttackerInfo { entity, + player: players.get(entity), uid, energy: energies.get(entity), combo: combos.get(entity), @@ -879,6 +880,7 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o let target_info = combat::TargetInfo { entity: entity_b, + player: players.get(entity_b), uid: *uid_b, inventory: inventories.get(entity_b), stats: stats_b_maybe, @@ -888,24 +890,11 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o char_state: char_state_b_maybe, }; - let avoid_harm = { - owner_entity.map_or(false, |attacker| { - if let (Some(attacker), Some(target)) = - (players.get(attacker), players.get(entity_b)) - { - attacker.disallow_harm(target) - } else { - false - } - }) - }; - let attack_options = combat::AttackOptions { // cool guyz maybe don't look at explosions // but they still got hurt, it's not Hollywood target_dodging: false, target_group, - avoid_harm, }; attack.apply_attack( @@ -944,17 +933,11 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o .map_or(true, |h| !h.is_dead); if is_alive { - let avoid_harm = { - owner_entity.map_or(false, |attacker| { - if let (Some(attacker), Some(target)) = - (players.get(attacker), players.get(entity_b)) - { - attacker.disallow_harm(target) - } else { - false - } - }) - }; + let avoid_harm = owner_entity.map_or(false, |attacker| { + let attacker = players.get(attacker); + let target = players.get(entity_b); + combat::avoid_harm(attacker, target) + }); effect.modify_strength(strength); if !(effect.is_harm() && avoid_harm) { server.state().apply_effect(entity_b, effect.clone(), owner); From 61416faec3a4c6a098877c1582b86f3c56420512 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Wed, 28 Jul 2021 13:38:53 +0300 Subject: [PATCH 068/155] Refactor Aura system, add avoid_harm flag + fix bug where you cast OutOfGroup on yourself and your group --- common/src/comp/buff.rs | 32 +++--- common/systems/src/aura.rs | 215 +++++++++++++++++++++++-------------- 2 files changed, 152 insertions(+), 95 deletions(-) diff --git a/common/src/comp/buff.rs b/common/src/comp/buff.rs index a8640f6a10..e87d301a1a 100644 --- a/common/src/comp/buff.rs +++ b/common/src/comp/buff.rs @@ -81,22 +81,22 @@ impl BuffKind { /// Checks if buff is buff or debuff pub fn is_buff(self) -> bool { match self { - BuffKind::Regeneration => true, - BuffKind::Saturation => true, - BuffKind::Bleeding => false, - BuffKind::Cursed => false, - BuffKind::Potion => true, - BuffKind::CampfireHeal => true, - BuffKind::IncreaseMaxEnergy => true, - BuffKind::IncreaseMaxHealth => true, - BuffKind::Invulnerability => true, - BuffKind::ProtectingWard => true, - BuffKind::Burning => false, - BuffKind::Crippled => false, - BuffKind::Frenzied => true, - BuffKind::Frozen => false, - BuffKind::Wet => false, - BuffKind::Ensnared => false, + BuffKind::Regeneration + | BuffKind::Saturation + | BuffKind::Potion + | BuffKind::CampfireHeal + | BuffKind::IncreaseMaxEnergy + | BuffKind::IncreaseMaxHealth + | BuffKind::Invulnerability + | BuffKind::ProtectingWard => true, + BuffKind::Bleeding + | BuffKind::Cursed + | BuffKind::Burning + | BuffKind::Crippled + | BuffKind::Frenzied + | BuffKind::Frozen + | BuffKind::Wet + | BuffKind::Ensnared => false, } } diff --git a/common/systems/src/aura.rs b/common/systems/src/aura.rs index da19ac5762..38873a9632 100644 --- a/common/systems/src/aura.rs +++ b/common/systems/src/aura.rs @@ -1,24 +1,26 @@ use common::{ + combat, comp::{ aura::{AuraChange, AuraKey, AuraKind, AuraTarget}, - buff::{self, BuffCategory}, + buff::{Buff, BuffCategory, BuffChange, BuffSource}, group::Group, - Auras, BuffKind, Buffs, CharacterState, Health, Pos, + Aura, Auras, BuffKind, Buffs, CharacterState, Health, Player, Pos, }, - event::{EventBus, ServerEvent}, + event::{Emitter, EventBus, ServerEvent}, resources::DeltaTime, uid::{Uid, UidAllocator}, }; use common_ecs::{Job, Origin, Phase, System}; use specs::{ - saveload::MarkerAllocator, shred::ResourceId, Entities, Join, Read, ReadStorage, SystemData, - World, WriteStorage, + saveload::MarkerAllocator, shred::ResourceId, Entities, Entity as EcsEntity, Join, Read, + ReadStorage, SystemData, World, WriteStorage, }; use std::time::Duration; #[derive(SystemData)] pub struct ReadData<'a> { entities: Entities<'a>, + players: ReadStorage<'a, Player>, dt: Read<'a, DeltaTime>, server_bus: Read<'a, EventBus>, uid_allocator: Read<'a, UidAllocator>, @@ -101,92 +103,43 @@ impl<'a> System<'a> for Sys { Some(buff) => buff, None => return, }; + // Ensure entity is within the aura radius if target_pos.0.distance_squared(pos.0) < aura.radius.powi(2) { - if let AuraTarget::GroupOf(uid) = aura.target { - let same_group = read_data + // Ensure the entity is in the group we want to target + let same_group = |uid: Uid| { + read_data .uid_allocator .retrieve_entity_internal(uid.into()) .and_then(|e| read_data.groups.get(e)) .map_or(false, |owner_group| { Some(owner_group) == read_data.groups.get(target) }) - || *target_uid == uid; + || *target_uid == uid + }; - if !same_group { - return; - } - } - - // TODO: When more aura kinds (besides Buff) are - // implemented, match on them here - match aura.aura_kind { - AuraKind::Buff { - kind, - data, - category, - source, - } => { - let apply_buff = match kind { - BuffKind::CampfireHeal => { - matches!( - read_data.char_states.get(target), - Some(CharacterState::Sit) - ) && health.current() < health.maximum() - }, - // Add other specific buff conditions here - _ => true, - }; - if apply_buff { - // Checks that target is not already receiving a buff from - // an aura, where - // the buff is of the same kind, and is of at least - // the same strength and of at least the same duration - // If no such buff is present, adds the buff - let emit_buff = !target_buffs.buffs.iter().any(|(_, buff)| { - buff.cat_ids.iter().any(|cat_id| { - matches!(cat_id, BuffCategory::FromAura(_)) - }) && buff.kind == kind - && buff.data.strength >= data.strength - && buff.time.map_or(true, |dur| { - data.duration.map_or(false, |dur_2| dur >= dur_2) - }) - }); - if emit_buff { - use buff::*; - server_emitter.emit(ServerEvent::Buff { - entity: target, - buff_change: BuffChange::Add(Buff::new( - kind, - data, - vec![category, BuffCategory::FromAura(true)], - source, - )), - }); - } - // Finds all buffs on target that are from an aura, are of - // the - // same buff kind, and are of at most the same strength - // For any such buffs, marks it as recently applied - for (_, buff) in - target_buffs.buffs.iter_mut().filter(|(_, buff)| { - buff.cat_ids.iter().any(|cat_id| { - matches!(cat_id, BuffCategory::FromAura(_)) - }) && buff.kind == kind - && buff.data.strength <= data.strength - }) - { - if let Some(cat_id) = - buff.cat_ids.iter_mut().find(|cat_id| { - matches!(cat_id, BuffCategory::FromAura(false)) - }) - { - *cat_id = BuffCategory::FromAura(true); - } - } + match aura.target { + AuraTarget::GroupOf(uid) => { + if !same_group(uid) { + return; } }, + AuraTarget::NotGroupOf(uid) => { + if same_group(uid) { + return; + } + }, + AuraTarget::All => {}, } + + activate_aura( + aura, + target, + health, + &mut target_buffs, + &read_data, + &mut server_emitter, + ); } }); } @@ -201,3 +154,107 @@ impl<'a> System<'a> for Sys { buffs.set_event_emission(true); } } + +#[warn(clippy::pedantic)] +//#[warn(clippy::nursery)] +fn activate_aura( + aura: &Aura, + target: EcsEntity, + health: &Health, + target_buffs: &mut Buffs, + read_data: &ReadData, + server_emitter: &mut Emitter, +) { + let should_activate = |aura: &Aura| { + match aura.aura_kind { + AuraKind::Buff { kind, source, .. } => { + let owner = match source { + BuffSource::Character { by } => { + read_data.uid_allocator.retrieve_entity_internal(by.into()) + }, + _ => None, + }; + let avoid_harm = owner.map_or(false, |attacker| { + let attacker = read_data.players.get(attacker); + let target = read_data.players.get(target); + combat::avoid_harm(attacker, target) + }); + let conditions_held = match kind { + BuffKind::CampfireHeal => { + let target_state = read_data.char_states.get(target); + matches!(target_state, Some(CharacterState::Sit)) + && health.current() < health.maximum() + }, + // Add other specific buff conditions here + _ => true, + }; + + if conditions_held { + if kind.is_buff() { true } else { !avoid_harm } + } else { + false + } + }, + } + }; + + // TODO: When more aura kinds (besides Buff) are + // implemented, match on them here + match aura.aura_kind { + AuraKind::Buff { + kind, + data, + category, + source, + } => { + if !should_activate(aura) { + return; + } + // Checks that target is not already receiving a buff from + // an aura, where + // the buff is of the same kind, and is of at least + // the same strength and of at least the same duration + // If no such buff is present, adds the buff + let emit_buff = !target_buffs.buffs.iter().any(|(_, buff)| { + buff.cat_ids + .iter() + .any(|cat_id| matches!(cat_id, BuffCategory::FromAura(_))) + && buff.kind == kind + && buff.data.strength >= data.strength + && buff.time.map_or(true, |dur| { + data.duration.map_or(false, |dur_2| dur >= dur_2) + }) + }); + if emit_buff { + server_emitter.emit(ServerEvent::Buff { + entity: target, + buff_change: BuffChange::Add(Buff::new( + kind, + data, + vec![category, BuffCategory::FromAura(true)], + source, + )), + }); + } + // Finds all buffs on target that are from an aura, are of + // the + // same buff kind, and are of at most the same strength + // For any such buffs, marks it as recently applied + for (_, buff) in target_buffs.buffs.iter_mut().filter(|(_, buff)| { + buff.cat_ids + .iter() + .any(|cat_id| matches!(cat_id, BuffCategory::FromAura(_))) + && buff.kind == kind + && buff.data.strength <= data.strength + }) { + if let Some(cat_id) = buff + .cat_ids + .iter_mut() + .find(|cat_id| matches!(cat_id, BuffCategory::FromAura(false))) + { + *cat_id = BuffCategory::FromAura(true); + } + } + }, + } +} From 229e7b9ceca24b76235c1ed98ff99d13e972e8d4 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Wed, 28 Jul 2021 14:36:36 +0300 Subject: [PATCH 069/155] Add CHANGELOG note about battle_mode setting --- CHANGELOG.md | 1 + common/src/resources.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9712d6266d..0f39c3f7e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Healing sceptre crafting recipe - NPCs can now warn players before engaging in combat - Custom error message when a supported graphics backend can not be found +- Add server setting with PvE/PvP switch ### Changed diff --git a/common/src/resources.rs b/common/src/resources.rs index ee57b3242a..2b08b6407b 100644 --- a/common/src/resources.rs +++ b/common/src/resources.rs @@ -77,7 +77,7 @@ pub struct PlayerPhysicsSettings { /// Describe how players interact with other players. /// -/// Probably will be removed when we will discover better way +/// May be removed when we will discover better way /// to handle duels and murders #[derive(Copy, Clone, Debug, Deserialize, Serialize)] pub enum BattleMode { From 9300353c98143216d7e78fbaaa90b22eefd54e84 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Thu, 29 Jul 2021 20:11:39 +0300 Subject: [PATCH 070/155] Use emitter.emit() in server/sys/msg/register --- server/src/sys/msg/register.rs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/server/src/sys/msg/register.rs b/server/src/sys/msg/register.rs index 00923eb490..9f2e22f3b4 100644 --- a/server/src/sys/msg/register.rs +++ b/server/src/sys/msg/register.rs @@ -75,6 +75,7 @@ impl<'a> System<'a> for Sys { mut login_provider, ): Self::SystemData, ) { + let mut server_emitter = read_data.server_event_bus.emitter(); // Player list to send new players. let player_list = ( &read_data.uids, @@ -138,12 +139,10 @@ impl<'a> System<'a> for Sys { trace!(?r, "pending login returned"); match r { Err(e) => { - read_data - .server_event_bus - .emit_now(ServerEvent::ClientDisconnect( - entity, - common::comp::DisconnectReason::Kicked, - )); + server_emitter.emit(ServerEvent::ClientDisconnect( + entity, + common::comp::DisconnectReason::Kicked, + )); client.send(ServerRegisterAnswer::Err(e))?; return Ok(()); }, @@ -159,12 +158,10 @@ impl<'a> System<'a> for Sys { .find(|(_, _, old_player)| old_player.uuid() == uuid) { // Remove old client - read_data - .server_event_bus - .emit_now(ServerEvent::ClientDisconnect( - old_entity, - common::comp::DisconnectReason::NewerLogin, - )); + server_emitter.emit(ServerEvent::ClientDisconnect( + old_entity, + common::comp::DisconnectReason::NewerLogin, + )); let _ = old_client.send(ServerGeneral::Disconnect(DisconnectReason::Kicked( String::from("You have logged in from another location."), ))); From aaf2df19d482bd2707aae911a24dc9b11f55fb49 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Thu, 29 Jul 2021 21:17:19 +0300 Subject: [PATCH 071/155] Make Veloren compile again --- common/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/Cargo.toml b/common/Cargo.toml index 98b2d0f288..c332b5f9eb 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -26,7 +26,8 @@ enum-iterator = "0.6" vek = { version = "=0.14.1", features = ["serde"] } # Strum -strum = "0.21" +strum = { version = "0.21", features = ["derive"] } +# TODO: remove this and rewrite every use of strum_macros to strum strum_macros = "0.21" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] From 7413e7fd113d737321689595161dc6e8eece578d Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Thu, 29 Jul 2021 22:04:40 +0300 Subject: [PATCH 072/155] Prettify aura system --- common/systems/src/aura.rs | 96 +++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 53 deletions(-) diff --git a/common/systems/src/aura.rs b/common/systems/src/aura.rs index 38873a9632..96638d4067 100644 --- a/common/systems/src/aura.rs +++ b/common/systems/src/aura.rs @@ -118,28 +118,22 @@ impl<'a> System<'a> for Sys { || *target_uid == uid }; - match aura.target { - AuraTarget::GroupOf(uid) => { - if !same_group(uid) { - return; - } - }, - AuraTarget::NotGroupOf(uid) => { - if same_group(uid) { - return; - } - }, - AuraTarget::All => {}, - } + let is_target = match aura.target { + AuraTarget::GroupOf(uid) => same_group(uid), + AuraTarget::NotGroupOf(uid) => !same_group(uid), + AuraTarget::All => true, + }; - activate_aura( - aura, - target, - health, - &mut target_buffs, - &read_data, - &mut server_emitter, - ); + if is_target { + activate_aura( + aura, + target, + health, + &mut target_buffs, + &read_data, + &mut server_emitter, + ); + } } }); } @@ -165,39 +159,39 @@ fn activate_aura( read_data: &ReadData, server_emitter: &mut Emitter, ) { - let should_activate = |aura: &Aura| { - match aura.aura_kind { - AuraKind::Buff { kind, source, .. } => { + let should_activate = match aura.aura_kind { + AuraKind::Buff { kind, source, .. } => { + let conditions_held = match kind { + BuffKind::CampfireHeal => { + let target_state = read_data.char_states.get(target); + matches!(target_state, Some(CharacterState::Sit)) + && health.current() < health.maximum() + }, + // Add other specific buff conditions here + _ => true, + }; + let avoid_harm = || { let owner = match source { BuffSource::Character { by } => { read_data.uid_allocator.retrieve_entity_internal(by.into()) }, _ => None, }; - let avoid_harm = owner.map_or(false, |attacker| { + owner.map_or(false, |attacker| { let attacker = read_data.players.get(attacker); let target = read_data.players.get(target); combat::avoid_harm(attacker, target) - }); - let conditions_held = match kind { - BuffKind::CampfireHeal => { - let target_state = read_data.char_states.get(target); - matches!(target_state, Some(CharacterState::Sit)) - && health.current() < health.maximum() - }, - // Add other specific buff conditions here - _ => true, - }; + }) + }; - if conditions_held { - if kind.is_buff() { true } else { !avoid_harm } - } else { - false - } - }, - } + conditions_held && (kind.is_buff() || !avoid_harm()) + }, }; + if !should_activate { + return; + } + // TODO: When more aura kinds (besides Buff) are // implemented, match on them here match aura.aura_kind { @@ -207,14 +201,11 @@ fn activate_aura( category, source, } => { - if !should_activate(aura) { - return; - } - // Checks that target is not already receiving a buff from - // an aura, where - // the buff is of the same kind, and is of at least - // the same strength and of at least the same duration - // If no such buff is present, adds the buff + // Checks that target is not already receiving a buff + // from an aura, where the buff is of the same kind, + // and is of at least the same strength + // and of at least the same duration. + // If no such buff is present, adds the buff. let emit_buff = !target_buffs.buffs.iter().any(|(_, buff)| { buff.cat_ids .iter() @@ -237,9 +228,8 @@ fn activate_aura( }); } // Finds all buffs on target that are from an aura, are of - // the - // same buff kind, and are of at most the same strength - // For any such buffs, marks it as recently applied + // the same buff kind, and are of at most the same strength. + // For any such buffs, marks it as recently applied. for (_, buff) in target_buffs.buffs.iter_mut().filter(|(_, buff)| { buff.cat_ids .iter() From 497a94cd7a4161401f599442b4c100afb0c9f876 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Fri, 30 Jul 2021 14:34:05 +0300 Subject: [PATCH 073/155] Post review refactoring * inline `target_dodging` into struct declaration as they are named anyway * move `avoid_harm` check out of `Attack::apply_attack` so we don't need to pass whole Player component. * another cosmetic things --- common/src/combat.rs | 9 +++------ common/src/comp/player.rs | 11 +++++++---- common/systems/src/aura.rs | 2 +- common/systems/src/beam.rs | 14 ++++++++------ common/systems/src/melee.rs | 10 +++++++--- common/systems/src/projectile.rs | 19 +++++++++++-------- common/systems/src/shockwave.rs | 15 ++++++++------- server/src/events/entity_manipulation.rs | 21 +++++++++++++-------- server/src/sys/msg/register.rs | 6 +++--- 9 files changed, 61 insertions(+), 46 deletions(-) diff --git a/common/src/combat.rs b/common/src/combat.rs index 237ddf46a4..a3a66c81be 100644 --- a/common/src/combat.rs +++ b/common/src/combat.rs @@ -53,7 +53,6 @@ pub enum AttackSource { #[derive(Copy, Clone)] pub struct AttackerInfo<'a> { pub entity: EcsEntity, - pub player: Option<&'a Player>, pub uid: Uid, pub energy: Option<&'a Energy>, pub combo: Option<&'a Combo>, @@ -63,7 +62,6 @@ pub struct AttackerInfo<'a> { #[cfg(not(target_arch = "wasm32"))] pub struct TargetInfo<'a> { pub entity: EcsEntity, - pub player: Option<&'a Player>, pub uid: Uid, pub inventory: Option<&'a Inventory>, pub stats: Option<&'a Stats>, @@ -76,6 +74,7 @@ pub struct TargetInfo<'a> { #[derive(Clone, Copy)] pub struct AttackOptions { pub target_dodging: bool, + pub avoid_harm: bool, pub target_group: GroupTarget, } @@ -182,12 +181,10 @@ impl Attack { ) -> bool { let AttackOptions { target_dodging, + avoid_harm, target_group, } = options; - let avoid_harm = - attacker.map_or(false, |attacker| avoid_harm(attacker.player, target.player)); - // target == OutOfGroup is basic heuristic that this // "attack" has negative effects. // @@ -464,7 +461,7 @@ impl Attack { // This code works only with players. // You still can kill someone's pet and // you still can be killed by someone's pet -pub fn avoid_harm(attacker: Option<&Player>, target: Option<&Player>) -> bool { +pub fn avoid_player_harm(attacker: Option<&Player>, target: Option<&Player>) -> bool { if let (Some(attacker), Some(target)) = (attacker, target) { return attacker.disallow_harm(target); } diff --git a/common/src/comp/player.rs b/common/src/comp/player.rs index f3ab03a081..c2666ef11c 100644 --- a/common/src/comp/player.rs +++ b/common/src/comp/player.rs @@ -23,6 +23,12 @@ pub struct Player { uuid: Uuid, } +impl BattleMode { + pub fn allow_harm(self, other: Self) -> bool { + matches!((self, other), (BattleMode::PvP, BattleMode::PvP)) + } +} + impl Player { pub fn new(alias: String, battle_mode: BattleMode, uuid: Uuid) -> Self { Self { @@ -38,10 +44,7 @@ impl Player { /// tea. pub fn allow_harm(&self, other: &Player) -> bool { // TODO: discuss if we want to keep self-harm - matches!( - (self.battle_mode, other.battle_mode), - (BattleMode::PvP, BattleMode::PvP) - ) + self.battle_mode.allow_harm(other.battle_mode) } /// Inverse of `allow_harm`. Read its doc to learn more. diff --git a/common/systems/src/aura.rs b/common/systems/src/aura.rs index 96638d4067..1d9f2cb3a0 100644 --- a/common/systems/src/aura.rs +++ b/common/systems/src/aura.rs @@ -180,7 +180,7 @@ fn activate_aura( owner.map_or(false, |attacker| { let attacker = read_data.players.get(attacker); let target = read_data.players.get(target); - combat::avoid_harm(attacker, target) + combat::avoid_player_harm(attacker, target) }) }; diff --git a/common/systems/src/beam.rs b/common/systems/src/beam.rs index b22bca06f8..959c61cd7f 100644 --- a/common/systems/src/beam.rs +++ b/common/systems/src/beam.rs @@ -1,5 +1,5 @@ use common::{ - combat::{AttackOptions, AttackSource, AttackerInfo, TargetInfo}, + combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo}, comp::{ agent::{Sound, SoundKind}, Beam, BeamSegment, Body, CharacterState, Combo, Energy, Group, Health, HealthSource, @@ -196,7 +196,6 @@ impl<'a> System<'a> for Sys { .zip(beam_segment.owner) .map(|(entity, uid)| AttackerInfo { entity, - player: read_data.players.get(entity), uid, energy: read_data.energies.get(entity), combo: read_data.combos.get(entity), @@ -205,7 +204,6 @@ impl<'a> System<'a> for Sys { let target_info = TargetInfo { entity: target, - player: read_data.players.get(target), uid: *uid_b, inventory: read_data.inventories.get(target), stats: read_data.stats.get(target), @@ -215,11 +213,15 @@ impl<'a> System<'a> for Sys { char_state: read_data.character_states.get(target), }; - // No luck with dodging beams - let target_dodging = false; + let avoid_harm = combat::avoid_player_harm( + beam_owner.and_then(|owner| read_data.players.get(owner)), + read_data.players.get(target), + ); let attack_options = AttackOptions { - target_dodging, + // No luck with dodging beams + target_dodging: false, + avoid_harm, target_group, }; diff --git a/common/systems/src/melee.rs b/common/systems/src/melee.rs index d7134396ff..aefdee9db1 100644 --- a/common/systems/src/melee.rs +++ b/common/systems/src/melee.rs @@ -1,5 +1,5 @@ use common::{ - combat::{AttackOptions, AttackSource, AttackerInfo, TargetInfo}, + combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo}, comp::{ agent::{Sound, SoundKind}, Body, CharacterState, Combo, Energy, Group, Health, Inventory, Melee, Ori, Player, Pos, @@ -145,7 +145,6 @@ impl<'a> System<'a> for Sys { let attacker_info = Some(AttackerInfo { entity: attacker, - player: read_data.players.get(attacker), uid: *uid, energy: read_data.energies.get(attacker), combo: read_data.combos.get(attacker), @@ -154,7 +153,6 @@ impl<'a> System<'a> for Sys { let target_info = TargetInfo { entity: target, - player: read_data.players.get(target), uid: *uid_b, inventory: read_data.inventories.get(target), stats: read_data.stats.get(target), @@ -164,8 +162,14 @@ impl<'a> System<'a> for Sys { char_state: read_data.char_states.get(target), }; + let avoid_harm = combat::avoid_player_harm( + read_data.players.get(attacker), + read_data.players.get(target), + ); + let attack_options = AttackOptions { target_dodging, + avoid_harm, target_group, }; diff --git a/common/systems/src/projectile.rs b/common/systems/src/projectile.rs index e19430d328..a183306bbd 100644 --- a/common/systems/src/projectile.rs +++ b/common/systems/src/projectile.rs @@ -1,5 +1,5 @@ use common::{ - combat::{AttackOptions, AttackSource, AttackerInfo, TargetInfo}, + combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo}, comp::{ agent::{Sound, SoundKind}, projectile, Body, CharacterState, Combo, Energy, Group, Health, HealthSource, Inventory, @@ -115,6 +115,7 @@ impl<'a> System<'a> for Sys { } let projectile = &mut *projectile; + // FIXME: this code is highway to hell, resolve this for effect in projectile.hit_entity.drain(..) { match effect { projectile::Effect::Attack(attack) => { @@ -135,7 +136,6 @@ impl<'a> System<'a> for Sys { owner_entity.zip(projectile.owner).map(|(entity, uid)| { AttackerInfo { entity, - player: read_data.players.get(entity), uid, energy: read_data.energies.get(entity), combo: read_data.combos.get(entity), @@ -145,7 +145,6 @@ impl<'a> System<'a> for Sys { let target_info = TargetInfo { entity: target, - player: read_data.players.get(target), uid: other, inventory: read_data.inventories.get(target), stats: read_data.stats.get(target), @@ -155,10 +154,6 @@ impl<'a> System<'a> for Sys { char_state: read_data.character_states.get(target), }; - // They say witchers can dodge arrows, - // but we don't have witchers - let target_dodging = false; - if let Some(&body) = read_data.bodies.get(entity) { outcomes.push(Outcome::ProjectileHit { pos: pos.0, @@ -172,8 +167,16 @@ impl<'a> System<'a> for Sys { }); } + let avoid_harm = combat::avoid_player_harm( + owner_entity.and_then(|owner| read_data.players.get(owner)), + read_data.players.get(target), + ); + let attack_options = AttackOptions { - target_dodging, + // They say witchers can dodge arrows, + // but we don't have witchers + target_dodging: false, + avoid_harm, target_group, }; attack.apply_attack( diff --git a/common/systems/src/shockwave.rs b/common/systems/src/shockwave.rs index 19f49f7f1c..6e6a66bd65 100644 --- a/common/systems/src/shockwave.rs +++ b/common/systems/src/shockwave.rs @@ -1,5 +1,5 @@ use common::{ - combat::{AttackOptions, AttackSource, AttackerInfo, TargetInfo}, + combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo}, comp::{ agent::{Sound, SoundKind}, Body, CharacterState, Combo, Energy, Group, Health, HealthSource, Inventory, Ori, @@ -192,7 +192,6 @@ impl<'a> System<'a> for Sys { .zip(shockwave.owner) .map(|(entity, uid)| AttackerInfo { entity, - player: read_data.players.get(entity), uid, energy: read_data.energies.get(entity), combo: read_data.combos.get(entity), @@ -201,7 +200,6 @@ impl<'a> System<'a> for Sys { let target_info = TargetInfo { entity: target, - player: read_data.players.get(target), uid: *uid_b, inventory: read_data.inventories.get(target), stats: read_data.stats.get(target), @@ -211,11 +209,14 @@ impl<'a> System<'a> for Sys { char_state: read_data.character_states.get(target), }; - // Trying roll during earthquake isn't the best idea - let target_dodging = false; - + let avoid_harm = combat::avoid_player_harm( + shockwave_owner.and_then(|owner| read_data.players.get(owner)), + read_data.players.get(target), + ); let attack_options = AttackOptions { - target_dodging, + // Trying roll during earthquake isn't the best idea + target_dodging: false, + avoid_harm, target_group, }; diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index aab9831833..ea10d993ad 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -871,7 +871,6 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o .zip(owner) .map(|(entity, uid)| combat::AttackerInfo { entity, - player: players.get(entity), uid, energy: energies.get(entity), combo: combos.get(entity), @@ -880,7 +879,6 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o let target_info = combat::TargetInfo { entity: entity_b, - player: players.get(entity_b), uid: *uid_b, inventory: inventories.get(entity_b), stats: stats_b_maybe, @@ -890,10 +888,15 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o char_state: char_state_b_maybe, }; + let avoid_harm = combat::avoid_player_harm( + owner_entity.and_then(|owner| players.get(owner)), + players.get(entity_b), + ); let attack_options = combat::AttackOptions { // cool guyz maybe don't look at explosions // but they still got hurt, it's not Hollywood target_dodging: false, + avoid_harm, target_group, }; @@ -926,6 +929,13 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o 1.0 - distance_squared / explosion.radius.powi(2) }; + let avoid_harm = || { + owner_entity.map_or(false, |attacker| { + let attacker = players.get(attacker); + let target = players.get(entity_b); + combat::avoid_player_harm(attacker, target) + }) + }; if strength > 0.0 { let is_alive = ecs .read_storage::() @@ -933,13 +943,8 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o .map_or(true, |h| !h.is_dead); if is_alive { - let avoid_harm = owner_entity.map_or(false, |attacker| { - let attacker = players.get(attacker); - let target = players.get(entity_b); - combat::avoid_harm(attacker, target) - }); effect.modify_strength(strength); - if !(effect.is_harm() && avoid_harm) { + if !(effect.is_harm() && avoid_harm()) { server.state().apply_effect(entity_b, effect.clone(), owner); } } diff --git a/server/src/sys/msg/register.rs b/server/src/sys/msg/register.rs index 9f2e22f3b4..f67d4c35c3 100644 --- a/server/src/sys/msg/register.rs +++ b/server/src/sys/msg/register.rs @@ -37,8 +37,8 @@ pub struct ReadData<'a> { uids: ReadStorage<'a, Uid>, clients: ReadStorage<'a, Client>, server_event_bus: Read<'a, EventBus>, - _health_comp: ReadStorage<'a, Health>, // used by plugin feature - _plugin_mgr: ReadPlugin<'a>, // used by plugin feature + _healths: ReadStorage<'a, Health>, // used by plugin feature + _plugin_mgr: ReadPlugin<'a>, // used by plugin feature _uid_allocator: Read<'a, UidAllocator>, // used by plugin feature } @@ -117,7 +117,7 @@ impl<'a> System<'a> for Sys { #[cfg(feature = "plugins")] let ecs_world = EcsWorld { entities: &read_data.entities, - health: (&read_data._health_comp).into(), + health: (&read_data._healths).into(), uid: (&read_data.uids).into(), player: (&players).into(), uid_allocator: &read_data._uid_allocator, From 1efc3188ef20f10d2922628df37840ebc4442099 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Fri, 30 Jul 2021 19:41:12 +0300 Subject: [PATCH 074/155] Refactor projectile system --- common/systems/src/projectile.rs | 268 +++++++++++++++++++------------ 1 file changed, 168 insertions(+), 100 deletions(-) diff --git a/common/systems/src/projectile.rs b/common/systems/src/projectile.rs index a183306bbd..941e6f6254 100644 --- a/common/systems/src/projectile.rs +++ b/common/systems/src/projectile.rs @@ -5,7 +5,7 @@ use common::{ projectile, Body, CharacterState, Combo, Energy, Group, Health, HealthSource, Inventory, Ori, PhysicsState, Player, Pos, Projectile, Stats, Vel, }, - event::{EventBus, ServerEvent}, + event::{Emitter, EventBus, ServerEvent}, outcome::Outcome, resources::{DeltaTime, Time}, uid::{Uid, UidAllocator}, @@ -15,8 +15,8 @@ use common::{ use common_ecs::{Job, Origin, Phase, System}; use rand::{thread_rng, Rng}; use specs::{ - saveload::MarkerAllocator, shred::ResourceId, Entities, Join, Read, ReadStorage, SystemData, - World, Write, WriteStorage, + saveload::MarkerAllocator, shred::ResourceId, Entities, Entity as EcsEntity, Join, Read, + ReadStorage, SystemData, World, Write, WriteStorage, }; use std::time::Duration; use vek::*; @@ -115,106 +115,36 @@ impl<'a> System<'a> for Sys { } let projectile = &mut *projectile; - // FIXME: this code is highway to hell, resolve this + + let entity_of = + |uid: Uid| read_data.uid_allocator.retrieve_entity_internal(uid.into()); for effect in projectile.hit_entity.drain(..) { - match effect { - projectile::Effect::Attack(attack) => { - if let Some(target) = read_data - .uid_allocator - .retrieve_entity_internal(other.into()) - { - if let (Some(pos), Some(ori)) = - (read_data.positions.get(target), orientations.get(entity)) - { - let dir = ori.look_dir(); + let owner = projectile.owner.and_then(entity_of); + let projectile_info = ProjectileInfo { + entity, + effect, + owner_uid: projectile.owner, + owner, + ori: orientations.get(entity), + pos, + }; - let owner_entity = projectile.owner.and_then(|u| { - read_data.uid_allocator.retrieve_entity_internal(u.into()) - }); + let target = entity_of(other); + let projectile_target_info = ProjectileTargetInfo { + uid: other, + entity: target, + target_group, + ori: target.and_then(|target| orientations.get(target)), + }; - let attacker_info = - owner_entity.zip(projectile.owner).map(|(entity, uid)| { - AttackerInfo { - entity, - uid, - energy: read_data.energies.get(entity), - combo: read_data.combos.get(entity), - inventory: read_data.inventories.get(entity), - } - }); - - let target_info = TargetInfo { - entity: target, - uid: other, - inventory: read_data.inventories.get(target), - stats: read_data.stats.get(target), - health: read_data.healths.get(target), - pos: pos.0, - ori: orientations.get(target), - char_state: read_data.character_states.get(target), - }; - - if let Some(&body) = read_data.bodies.get(entity) { - outcomes.push(Outcome::ProjectileHit { - pos: pos.0, - body, - vel: read_data - .velocities - .get(entity) - .map_or(Vec3::zero(), |v| v.0), - source: projectile.owner, - target: read_data.uids.get(target).copied(), - }); - } - - let avoid_harm = combat::avoid_player_harm( - owner_entity.and_then(|owner| read_data.players.get(owner)), - read_data.players.get(target), - ); - - let attack_options = AttackOptions { - // They say witchers can dodge arrows, - // but we don't have witchers - target_dodging: false, - avoid_harm, - target_group, - }; - attack.apply_attack( - attacker_info, - target_info, - dir, - attack_options, - 1.0, - AttackSource::Projectile, - |e| server_emitter.emit(e), - |o| outcomes.push(o), - ); - } - } - }, - projectile::Effect::Explode(e) => { - server_emitter.emit(ServerEvent::Explosion { - pos: pos.0, - explosion: e, - owner: projectile.owner, - }); - }, - projectile::Effect::Vanish => { - server_emitter.emit(ServerEvent::Destroy { - entity, - cause: HealthSource::World, - }); - projectile_vanished = true; - }, - projectile::Effect::Possess => { - if other != projectile.owner.unwrap() { - if let Some(owner) = projectile.owner { - server_emitter.emit(ServerEvent::Possess(owner, other)); - } - } - }, - _ => {}, - } + dispatch_hit( + projectile_info, + projectile_target_info, + &read_data, + &mut projectile_vanished, + &mut outcomes, + &mut server_emitter, + ); } if projectile_vanished { @@ -266,3 +196,141 @@ impl<'a> System<'a> for Sys { } } } + +struct ProjectileInfo<'a> { + entity: EcsEntity, + effect: projectile::Effect, + owner_uid: Option, + owner: Option, + ori: Option<&'a Ori>, + pos: &'a Pos, +} + +struct ProjectileTargetInfo<'a> { + uid: Uid, + entity: Option, + target_group: GroupTarget, + ori: Option<&'a Ori>, +} + +fn dispatch_hit( + projectile_info: ProjectileInfo, + projectile_target_info: ProjectileTargetInfo, + read_data: &ReadData, + projectile_vanished: &mut bool, + outcomes: &mut Vec, + server_emitter: &mut Emitter, +) { + match projectile_info.effect { + projectile::Effect::Attack(attack) => { + let target_uid = projectile_target_info.uid; + let target = if let Some(entity) = projectile_target_info.entity { + entity + } else { + return; + }; + + let (target_pos, projectile_dir) = { + let target_pos = read_data.positions.get(target); + let projectile_ori = projectile_info.ori; + match target_pos.zip(projectile_ori) { + Some((tgt_pos, proj_ori)) => { + let Pos(tgt_pos) = tgt_pos; + (*tgt_pos, proj_ori.look_dir()) + }, + None => return, + } + }; + + let owner = projectile_info.owner; + let projectile_entity = projectile_info.entity; + + let attacker_info = + owner + .zip(projectile_info.owner_uid) + .map(|(entity, uid)| AttackerInfo { + entity, + uid, + energy: read_data.energies.get(entity), + combo: read_data.combos.get(entity), + inventory: read_data.inventories.get(entity), + }); + + let target_info = TargetInfo { + entity: target, + uid: target_uid, + inventory: read_data.inventories.get(target), + stats: read_data.stats.get(target), + health: read_data.healths.get(target), + pos: target_pos, + ori: projectile_target_info.ori, + char_state: read_data.character_states.get(target), + }; + + // TODO: Is it possible to have projectile without body?? + if let Some(&body) = read_data.bodies.get(projectile_entity) { + outcomes.push(Outcome::ProjectileHit { + pos: target_pos, + body, + vel: read_data + .velocities + .get(projectile_entity) + .map_or(Vec3::zero(), |v| v.0), + source: projectile_info.owner_uid, + target: read_data.uids.get(target).copied(), + }); + } + + let avoid_harm = combat::avoid_player_harm( + owner.and_then(|owner| read_data.players.get(owner)), + read_data.players.get(target), + ); + + let attack_options = AttackOptions { + // They say witchers can dodge arrows, + // but we don't have witchers + target_dodging: false, + avoid_harm, + target_group: projectile_target_info.target_group, + }; + + attack.apply_attack( + attacker_info, + target_info, + projectile_dir, + attack_options, + 1.0, + AttackSource::Projectile, + |e| server_emitter.emit(e), + |o| outcomes.push(o), + ); + }, + projectile::Effect::Explode(e) => { + let Pos(pos) = *projectile_info.pos; + let owner_uid = projectile_info.owner_uid; + server_emitter.emit(ServerEvent::Explosion { + pos, + explosion: e, + owner: owner_uid, + }); + }, + projectile::Effect::Vanish => { + let entity = projectile_info.entity; + server_emitter.emit(ServerEvent::Destroy { + entity, + cause: HealthSource::World, + }); + *projectile_vanished = true; + }, + projectile::Effect::Possess => { + let target_uid = projectile_target_info.uid; + let owner_uid = projectile_info.owner_uid; + if let Some(owner_uid) = owner_uid { + if target_uid != owner_uid { + server_emitter.emit(ServerEvent::Possess(owner_uid, target_uid)); + } + } + }, + projectile::Effect::Stick => {}, + } +} From d9e2d501cde0b103d72f40545d93e9522447522b Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Fri, 30 Jul 2021 23:27:25 +0300 Subject: [PATCH 075/155] Prettify server/sys/msg/register.rs --- server/src/sys/msg/register.rs | 54 ++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/server/src/sys/msg/register.rs b/server/src/sys/msg/register.rs index f67d4c35c3..bb6a0b5d81 100644 --- a/server/src/sys/msg/register.rs +++ b/server/src/sys/msg/register.rs @@ -37,6 +37,9 @@ pub struct ReadData<'a> { uids: ReadStorage<'a, Uid>, clients: ReadStorage<'a, Client>, server_event_bus: Read<'a, EventBus>, + player_metrics: ReadExpect<'a, PlayerMetrics>, + settings: ReadExpect<'a, Settings>, + editable_settings: ReadExpect<'a, EditableSettings>, _healths: ReadStorage<'a, Health>, // used by plugin feature _plugin_mgr: ReadPlugin<'a>, // used by plugin feature _uid_allocator: Read<'a, UidAllocator>, // used by plugin feature @@ -49,9 +52,6 @@ impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] type SystemData = ( ReadData<'a>, - ReadExpect<'a, PlayerMetrics>, - ReadExpect<'a, Settings>, - ReadExpect<'a, EditableSettings>, WriteStorage<'a, Player>, WriteStorage<'a, Admin>, WriteStorage<'a, PendingLogin>, @@ -66,9 +66,6 @@ impl<'a> System<'a> for Sys { _job: &mut Job, ( read_data, - player_metrics, - settings, - editable_settings, mut players, mut admins, mut pending_logins, @@ -129,9 +126,9 @@ impl<'a> System<'a> for Sys { &ecs_world, #[cfg(feature = "plugins")] &read_data._plugin_mgr, - &*editable_settings.admins, - &*editable_settings.whitelist, - &*editable_settings.banlist, + &*read_data.editable_settings.admins, + &*read_data.editable_settings.whitelist, + &*read_data.editable_settings.banlist, ) { None => return Ok(()), Some(r) => { @@ -176,8 +173,8 @@ impl<'a> System<'a> for Sys { return Ok(()); } - let player = Player::new(username, settings.battle_mode, uuid); - let admin = editable_settings.admins.get(&uuid); + let player = Player::new(username, read_data.settings.battle_mode, uuid); + let admin = read_data.editable_settings.admins.get(&uuid); if !player.is_valid() { // Invalid player @@ -188,7 +185,7 @@ impl<'a> System<'a> for Sys { if let Ok(StorageEntry::Vacant(v)) = players.entry(entity) { // Add Player component to this client, if the entity exists. v.insert(player); - player_metrics.players_connected.inc(); + read_data.player_metrics.players_connected.inc(); // Give the Admin component to the player if their name exists in // admin list @@ -225,21 +222,26 @@ impl<'a> System<'a> for Sys { // Handle new players. // Tell all clients to add them to the player list. for entity in new_players { - if let (Some(uid), Some(player)) = (read_data.uids.get(entity), players.get(entity)) { - let mut lazy_msg = None; - for (_, client) in (&players, &read_data.clients).join() { - if lazy_msg.is_none() { - lazy_msg = Some(client.prepare(ServerGeneral::PlayerListUpdate( - PlayerListUpdate::Add(*uid, PlayerInfo { - player_alias: player.alias.clone(), - is_online: true, - is_moderator: admins.get(entity).is_some(), - character: None, // new players will be on character select. - }), - ))); - } - lazy_msg.as_ref().map(|msg| client.send_prepared(msg)); + let player_info = read_data.uids.get(entity).zip(players.get(entity)); + let (uid, player) = if let Some((uid, player)) = player_info { + (uid, player) + } else { + continue; + }; + + let mut lazy_msg = None; + for (_, client) in (&players, &read_data.clients).join() { + if lazy_msg.is_none() { + lazy_msg = Some(client.prepare(ServerGeneral::PlayerListUpdate( + PlayerListUpdate::Add(*uid, PlayerInfo { + player_alias: player.alias.clone(), + is_online: true, + is_moderator: admins.get(entity).is_some(), + character: None, // new players will be on character select. + }), + ))); } + lazy_msg.as_ref().map(|msg| client.send_prepared(msg)); } } } From 5e6007db0365ea84711804e7b7817f1b6f58ebae Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Sat, 31 Jul 2021 01:32:29 +0300 Subject: [PATCH 076/155] Return self-harm --- common/src/comp/player.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/comp/player.rs b/common/src/comp/player.rs index c2666ef11c..183e2dc21d 100644 --- a/common/src/comp/player.rs +++ b/common/src/comp/player.rs @@ -42,9 +42,9 @@ impl Player { /// /// Simple as tea, if they don't want the tea, don't make them drink the /// tea. + /// You can make tea for yourself though. pub fn allow_harm(&self, other: &Player) -> bool { - // TODO: discuss if we want to keep self-harm - self.battle_mode.allow_harm(other.battle_mode) + self.battle_mode.allow_harm(other.battle_mode) || self.uuid == other.uuid } /// Inverse of `allow_harm`. Read its doc to learn more. From 44916383c6f6b5992da0a299898e13739ceb57d2 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Sat, 31 Jul 2021 12:01:13 +0300 Subject: [PATCH 077/155] continue -> filter_map to handle new players --- server/src/sys/msg/register.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/server/src/sys/msg/register.rs b/server/src/sys/msg/register.rs index bb6a0b5d81..816640be05 100644 --- a/server/src/sys/msg/register.rs +++ b/server/src/sys/msg/register.rs @@ -221,14 +221,11 @@ impl<'a> System<'a> for Sys { // Handle new players. // Tell all clients to add them to the player list. - for entity in new_players { + let player_info = |entity| { let player_info = read_data.uids.get(entity).zip(players.get(entity)); - let (uid, player) = if let Some((uid, player)) = player_info { - (uid, player) - } else { - continue; - }; - + player_info.map(|(u, p)| (entity, u, p)) + }; + for (entity, uid, player) in new_players.into_iter().filter_map(player_info) { let mut lazy_msg = None; for (_, client) in (&players, &read_data.clients).join() { if lazy_msg.is_none() { From 3952d8b86fd710a2f47260addfb58110e0b90eb2 Mon Sep 17 00:00:00 2001 From: Yusuf Bera Ertan Date: Mon, 2 Aug 2021 22:21:12 +0300 Subject: [PATCH 078/155] chore(deps): update nix flake deps --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index 9c1d6b3ff6..196d6d02bb 100644 --- a/flake.lock +++ b/flake.lock @@ -24,11 +24,11 @@ "rustOverlay": "rustOverlay" }, "locked": { - "lastModified": 1627752074, - "narHash": "sha256-iuOGIbJC4hn1XqwrBjiol6j0Xj+AImND6Z9fP/6Za74=", + "lastModified": 1627940369, + "narHash": "sha256-KtY837WKsX9B/pIKFDKzN0wl1t3et1JZjMjGa7SAZxI=", "owner": "yusdacra", "repo": "nix-cargo-integration", - "rev": "47e6414440c66bfd44a0ea07d64ca62075470f62", + "rev": "fac8518469e226db4805ff80788979c847b0c322", "type": "github" }, "original": { @@ -39,11 +39,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1627533199, - "narHash": "sha256-NyIUcNevwtsMBINn56jnDF8wz3TV1AFxw+Vw6JMnkyE=", + "lastModified": 1627814220, + "narHash": "sha256-P+MDgdZw2CBk9X1ZZaUgHgN+32pTfLFf3XVIBOXirI4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "dd98b100651cfbb8804f32d852f75ef7c97a6b74", + "rev": "ab5b6828af26215bf2646c31961da5d3749591ef", "type": "github" }, "original": { @@ -62,11 +62,11 @@ "rustOverlay": { "flake": false, "locked": { - "lastModified": 1627697717, - "narHash": "sha256-ij7rk2VkPpNf0NTbpP5jfbwuIWfrLXN00pZ+pizGnGM=", + "lastModified": 1627870491, + "narHash": "sha256-0Myg04QOIcTN1RhgfRNx0i/iCRyVyf/Z6rJxZUmot5k=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "6d957c2105a5a548211c412fbc97bae81b7b8eb6", + "rev": "71d825269cfaa30605d058bd92381be9af87b0be", "type": "github" }, "original": { From 521b2bf46bca79903f3d87266ae6e1eff6669d48 Mon Sep 17 00:00:00 2001 From: Yusuf Bera Ertan Date: Tue, 3 Aug 2021 00:02:29 +0300 Subject: [PATCH 079/155] build(nix): remove useless override (upstreamed), fix crate name --- flake.nix | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/flake.nix b/flake.nix index b6d8c63207..8f121f9fda 100644 --- a/flake.nix +++ b/flake.nix @@ -67,16 +67,10 @@ # veloren-world = oldAttrs: { # crateBin = lib.filter (bin: bin.name != "chunk_compression_benchmarks") oldAttrs.crateBin; # }; - shaderc-sys = _: - let SHADERC_LIB_DIR = "${common.pkgs.shaderc.lib}/lib"; in - { - inherit SHADERC_LIB_DIR; - propagatedEnv = { inherit SHADERC_LIB_DIR; }; - }; veloren-client = oldAttrs: { crateBin = lib.filter (bin: bin.name != "bot") oldAttrs.crateBin; }; - veloren-i18n = oldAttrs: { + veloren-voxygen-i18n = oldAttrs: { crateBin = lib.filter (bin: bin.name != "i18n-check") oldAttrs.crateBin; }; veloren-common = oldAttrs: { From 88eca50c364cf0174fc08b1d179bec08a710ef9e Mon Sep 17 00:00:00 2001 From: Yusuf Bera Ertan Date: Tue, 3 Aug 2021 00:45:01 +0300 Subject: [PATCH 080/155] docs(nix): add notice for vulkan driver error potentially relating to nixpkgs mismatches --- nix/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nix/README.md b/nix/README.md index 5bc94b991c..5ee218f80b 100644 --- a/nix/README.md +++ b/nix/README.md @@ -22,6 +22,11 @@ git lfs install --local && git lfs fetch && git lfs checkout ``` This should be automatically done if you use the development shell. +If you get an issue such as `WARN gfx_backend_vulkan: Unable to create Vulkan instance: VkError(ERROR_INCOMPATIBLE_DRIVER)`, +it might be that your system nixpkgs version and veloren repo nixpkgs version might be too far apart. In that case, you can try +changing your system nixpkgs to the unstable channel, or change the `nixpkgs` input in the `flake.nix` to match your system +nixpkgs. + ## Usage for players ### With flakes From aa371147e7a440eba7313f11a361b4f6fc3424b4 Mon Sep 17 00:00:00 2001 From: Yusuf Bera Ertan Date: Tue, 3 Aug 2021 18:16:55 +0300 Subject: [PATCH 081/155] build: update keyboard-keynames --- Cargo.lock | 12 ++++++------ voxygen/Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3132f6e3fc..87d0becd56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2718,7 +2718,7 @@ dependencies = [ [[package]] name = "keyboard-keynames" version = "0.1.0" -source = "git+https://gitlab.com/Frinksy/keyboard-keynames.git?rev=9ae8f89014d0b0c5b61d0e821c5aeb6140c5c0dc#9ae8f89014d0b0c5b61d0e821c5aeb6140c5c0dc" +source = "git+https://gitlab.com/Frinksy/keyboard-keynames.git?rev=721c8b301f8003332d0cc767ab2649fdd330e842#721c8b301f8003332d0cc767ab2649fdd330e842" dependencies = [ "libc", "memmap", @@ -2726,7 +2726,7 @@ dependencies = [ "winapi 0.3.9", "winit", "xcb", - "xkbcommon-sys 0.7.5 (git+https://github.com/Frinksy/rust-xkbcommon-sys.git?rev=d5d69e05a81f7ee8d2f65a824ae692610ed7cb14)", + "xkbcommon-sys 0.7.6", ] [[package]] @@ -3063,7 +3063,7 @@ dependencies = [ "winapi 0.3.9", "x11-dl", "xkb", - "xkbcommon-sys 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "xkbcommon-sys 0.7.5", ] [[package]] @@ -7082,7 +7082,7 @@ checksum = "aec02bc5de902aa579f3d2f2c522edaf40fa42963cbaffe645b058ddcc68fdb2" dependencies = [ "bitflags", "libc", - "xkbcommon-sys 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "xkbcommon-sys 0.7.5", ] [[package]] @@ -7098,8 +7098,8 @@ dependencies = [ [[package]] name = "xkbcommon-sys" -version = "0.7.5" -source = "git+https://github.com/Frinksy/rust-xkbcommon-sys.git?rev=d5d69e05a81f7ee8d2f65a824ae692610ed7cb14#d5d69e05a81f7ee8d2f65a824ae692610ed7cb14" +version = "0.7.6" +source = "git+https://github.com/Frinksy/rust-xkbcommon-sys.git?rev=8f615dd6cd90a4ab77c45627830dde49b592b9b5#8f615dd6cd90a4ab77c45627830dde49b592b9b5" dependencies = [ "libc", "pkg-config", diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 6ded232b41..eab7fa4639 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -65,7 +65,7 @@ iced = {package = "iced_native", git = "https://github.com/Imberflur/iced", tag iced_winit = {git = "https://github.com/Imberflur/iced", tag = "winit-0.25"} window_clipboard = "0.2" glyph_brush = "0.7.0" -keyboard-keynames = { git = "https://gitlab.com/Frinksy/keyboard-keynames.git", rev = "9ae8f89014d0b0c5b61d0e821c5aeb6140c5c0dc" } +keyboard-keynames = { git = "https://gitlab.com/Frinksy/keyboard-keynames.git", rev = "721c8b301f8003332d0cc767ab2649fdd330e842" } # EGUI egui = {version = "0.12", optional = true } From 4766450258d74971baa730b0b838b8a8f1703436 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Sat, 31 Jul 2021 20:53:09 +0300 Subject: [PATCH 082/155] Avoid negative bounds in harm checks * disallow_harm -> allow_harm to avoid negative reasoning since it mostly requires double negation in code * allow_harm -> may_harm to specify side-effect free --- common/src/combat.rs | 19 +++++++++--------- common/src/comp/player.rs | 9 ++------- common/systems/src/aura.rs | 16 +++++++++++---- common/systems/src/beam.rs | 4 ++-- common/systems/src/melee.rs | 4 ++-- common/systems/src/projectile.rs | 4 ++-- common/systems/src/shockwave.rs | 4 ++-- server/src/events/entity_manipulation.rs | 25 +++++++++++++++++------- 8 files changed, 49 insertions(+), 36 deletions(-) diff --git a/common/src/combat.rs b/common/src/combat.rs index a3a66c81be..56f8b12dfa 100644 --- a/common/src/combat.rs +++ b/common/src/combat.rs @@ -74,7 +74,7 @@ pub struct TargetInfo<'a> { #[derive(Clone, Copy)] pub struct AttackOptions { pub target_dodging: bool, - pub avoid_harm: bool, + pub may_harm: bool, pub target_group: GroupTarget, } @@ -181,7 +181,7 @@ impl Attack { ) -> bool { let AttackOptions { target_dodging, - avoid_harm, + may_harm, target_group, } = options; @@ -192,11 +192,11 @@ impl Attack { // it should avoid such "damage" or effect let avoid_damage = |attack_damage: &AttackDamage| { matches!(attack_damage.target, Some(GroupTarget::OutOfGroup)) - && (target_dodging || avoid_harm) + && (target_dodging || !may_harm) }; let avoid_effect = |attack_effect: &AttackEffect| { matches!(attack_effect.target, Some(GroupTarget::OutOfGroup)) - && (target_dodging || avoid_harm) + && (target_dodging || !may_harm) }; let is_crit = thread_rng().gen::() < self.crit_chance; let mut is_applied = false; @@ -456,16 +456,15 @@ impl Attack { } } -/// Checks if we should avoid negative effects from one player to another +/// Checks if we should allow negative effects from one player to another // FIXME: handle pets? // This code works only with players. // You still can kill someone's pet and // you still can be killed by someone's pet -pub fn avoid_player_harm(attacker: Option<&Player>, target: Option<&Player>) -> bool { - if let (Some(attacker), Some(target)) = (attacker, target) { - return attacker.disallow_harm(target); - } - false +pub fn may_harm(attacker: Option<&Player>, target: Option<&Player>) -> bool { + attacker + .zip(target) + .map_or(true, |(attacker, target)| attacker.may_harm(target)) } #[cfg(not(target_arch = "wasm32"))] diff --git a/common/src/comp/player.rs b/common/src/comp/player.rs index 183e2dc21d..76db8ddc55 100644 --- a/common/src/comp/player.rs +++ b/common/src/comp/player.rs @@ -24,7 +24,7 @@ pub struct Player { } impl BattleMode { - pub fn allow_harm(self, other: Self) -> bool { + pub fn may_harm(self, other: Self) -> bool { matches!((self, other), (BattleMode::PvP, BattleMode::PvP)) } } @@ -43,12 +43,7 @@ impl Player { /// Simple as tea, if they don't want the tea, don't make them drink the /// tea. /// You can make tea for yourself though. - pub fn allow_harm(&self, other: &Player) -> bool { - self.battle_mode.allow_harm(other.battle_mode) || self.uuid == other.uuid - } - - /// Inverse of `allow_harm`. Read its doc to learn more. - pub fn disallow_harm(&self, other: &Player) -> bool { !self.allow_harm(other) } + pub fn may_harm(&self, other: &Player) -> bool { self.battle_mode.may_harm(other.battle_mode) } pub fn is_valid(&self) -> bool { Self::alias_validate(&self.alias).is_ok() } diff --git a/common/systems/src/aura.rs b/common/systems/src/aura.rs index 1d9f2cb3a0..f9201b3d8d 100644 --- a/common/systems/src/aura.rs +++ b/common/systems/src/aura.rs @@ -170,21 +170,29 @@ fn activate_aura( // Add other specific buff conditions here _ => true, }; - let avoid_harm = || { + + // TODO: this check will disable friendly fire with PvE switch. + // + // Which means that you can't apply debuffs on you and your group + // even if it's intented mechanics. + // + // Not that we have this for now, but think about this + // when we will add this. + let may_harm = || { let owner = match source { BuffSource::Character { by } => { read_data.uid_allocator.retrieve_entity_internal(by.into()) }, _ => None, }; - owner.map_or(false, |attacker| { + owner.map_or(true, |attacker| { let attacker = read_data.players.get(attacker); let target = read_data.players.get(target); - combat::avoid_player_harm(attacker, target) + combat::may_harm(attacker, target) }) }; - conditions_held && (kind.is_buff() || !avoid_harm()) + conditions_held && (kind.is_buff() || may_harm()) }, }; diff --git a/common/systems/src/beam.rs b/common/systems/src/beam.rs index 959c61cd7f..86854bd814 100644 --- a/common/systems/src/beam.rs +++ b/common/systems/src/beam.rs @@ -214,14 +214,14 @@ impl<'a> System<'a> for Sys { }; - let avoid_harm = combat::avoid_player_harm( + let may_harm = combat::may_harm( beam_owner.and_then(|owner| read_data.players.get(owner)), read_data.players.get(target), ); let attack_options = AttackOptions { // No luck with dodging beams target_dodging: false, - avoid_harm, + may_harm, target_group, }; diff --git a/common/systems/src/melee.rs b/common/systems/src/melee.rs index aefdee9db1..433f6b48c5 100644 --- a/common/systems/src/melee.rs +++ b/common/systems/src/melee.rs @@ -162,14 +162,14 @@ impl<'a> System<'a> for Sys { char_state: read_data.char_states.get(target), }; - let avoid_harm = combat::avoid_player_harm( + let may_harm = combat::may_harm( read_data.players.get(attacker), read_data.players.get(target), ); let attack_options = AttackOptions { target_dodging, - avoid_harm, + may_harm, target_group, }; diff --git a/common/systems/src/projectile.rs b/common/systems/src/projectile.rs index 941e6f6254..4b48cf0d4d 100644 --- a/common/systems/src/projectile.rs +++ b/common/systems/src/projectile.rs @@ -281,7 +281,7 @@ fn dispatch_hit( }); } - let avoid_harm = combat::avoid_player_harm( + let may_harm = combat::may_harm( owner.and_then(|owner| read_data.players.get(owner)), read_data.players.get(target), ); @@ -290,7 +290,7 @@ fn dispatch_hit( // They say witchers can dodge arrows, // but we don't have witchers target_dodging: false, - avoid_harm, + may_harm, target_group: projectile_target_info.target_group, }; diff --git a/common/systems/src/shockwave.rs b/common/systems/src/shockwave.rs index 6e6a66bd65..86ad74eca7 100644 --- a/common/systems/src/shockwave.rs +++ b/common/systems/src/shockwave.rs @@ -209,14 +209,14 @@ impl<'a> System<'a> for Sys { char_state: read_data.character_states.get(target), }; - let avoid_harm = combat::avoid_player_harm( + let may_harm = combat::may_harm( shockwave_owner.and_then(|owner| read_data.players.get(owner)), read_data.players.get(target), ); let attack_options = AttackOptions { // Trying roll during earthquake isn't the best idea target_dodging: false, - avoid_harm, + may_harm, target_group, }; diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index ea10d993ad..c9e4fbff3f 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -888,7 +888,7 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o char_state: char_state_b_maybe, }; - let avoid_harm = combat::avoid_player_harm( + let may_harm = combat::may_harm( owner_entity.and_then(|owner| players.get(owner)), players.get(entity_b), ); @@ -896,7 +896,7 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o // cool guyz maybe don't look at explosions // but they still got hurt, it's not Hollywood target_dodging: false, - avoid_harm, + may_harm, target_group, }; @@ -929,11 +929,22 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o 1.0 - distance_squared / explosion.radius.powi(2) }; - let avoid_harm = || { + // Player check only accounts for PvP/PvE flag. + // + // But bombs are intented to do + // friendly fire. + // + // What exactly friendly fire is subject to discussion. + // As we probably want to minimize possibility of being dick + // even to your group members, the only exception is when + // you want to harm yourself. + // + // This can be changed later. + let may_harm = || { owner_entity.map_or(false, |attacker| { - let attacker = players.get(attacker); - let target = players.get(entity_b); - combat::avoid_player_harm(attacker, target) + let attacker_player = players.get(attacker); + let target_player = players.get(entity_b); + combat::may_harm(attacker_player, target_player) || attacker == entity_b }) }; if strength > 0.0 { @@ -944,7 +955,7 @@ pub fn handle_explosion(server: &Server, pos: Vec3, explosion: Explosion, o if is_alive { effect.modify_strength(strength); - if !(effect.is_harm() && avoid_harm()) { + if !effect.is_harm() || may_harm() { server.state().apply_effect(entity_b, effect.clone(), owner); } } From cae8005a184c778c6987c8ad30f48426deec2d13 Mon Sep 17 00:00:00 2001 From: Enrico Marconi Date: Tue, 3 Aug 2021 21:09:05 +0000 Subject: [PATCH 083/155] fix issue #1260: give a warning if an error occurs on language files load --- voxygen/i18n/src/lib.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/voxygen/i18n/src/lib.rs b/voxygen/i18n/src/lib.rs index 22862c28a8..c5e09530b4 100644 --- a/voxygen/i18n/src/lib.rs +++ b/voxygen/i18n/src/lib.rs @@ -113,17 +113,25 @@ impl common_assets::Compound for Language { // Walk through files in the folder, collecting localization fragment to merge // inside the asked_localization let mut fragments = HashMap::new(); - for fragment_asset in cache + for id in cache .load_dir::>(asset_key, true)? - .iter() + .ids() { - let id = fragment_asset.id(); - // don't try to load ._manifest files - if id.ends_with("._manifest") { + // Don't try to load manifests + if id.ends_with(&[".", LANG_MANIFEST_FILE].concat()) { continue; } - let read = fragment_asset.read(); - fragments.insert(PathBuf::from(id), read.clone()); + + match cache.load(id) { + Ok(handle) => { + let fragment: &RawFragment = &*handle.read(); + + fragments.insert(PathBuf::from(id), fragment.clone()); + }, + Err(e) => { + warn!("Unable to load asset {}, error={:?}", id, e); + }, + } } Ok(Language::from(RawLanguage { From 8822c6409eda70ef3458b025d62f533c879d2e89 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Wed, 4 Aug 2021 00:22:03 +0100 Subject: [PATCH 084/155] Fix pets without agency --- server/src/pet.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server/src/pet.rs b/server/src/pet.rs index ffef6cc3d9..cead1eb894 100644 --- a/server/src/pet.rs +++ b/server/src/pet.rs @@ -49,8 +49,11 @@ fn tame_pet_internal(ecs: &specs::World, pet_entity: Entity, owner: Entity, pet: .write_storage() .insert(pet_entity, pet.unwrap_or_default()); - if let Some(agent) = ecs.write_storage::().get_mut(pet_entity) { - agent.set_no_flee(); + // Create an agent for this entity using its body + if let Some(body) = ecs.read_storage().get(pet_entity) { + let _ = ecs + .write_storage() + .insert(pet_entity, Agent::from_body(body)); } // Add to group system From 31a49d26a9bdfbb460d9fa77dc0dbab6562ffbef Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Wed, 4 Aug 2021 14:04:56 +0100 Subject: [PATCH 085/155] Added action timer system for agent code --- common/src/comp/agent.rs | 88 +++++++++++++++++++++++++++++++++++++++- server/src/sys/agent.rs | 79 ++++++++++++++++++++---------------- 2 files changed, 131 insertions(+), 36 deletions(-) diff --git a/common/src/comp/agent.rs b/common/src/comp/agent.rs index 30473b8c8f..72cd5bc641 100644 --- a/common/src/comp/agent.rs +++ b/common/src/comp/agent.rs @@ -9,11 +9,13 @@ use serde::Deserialize; use specs::{Component, Entity as EcsEntity}; use specs_idvs::IdvStorage; use std::{collections::VecDeque, fmt}; +use strum::IntoEnumIterator; +use strum_macros::EnumIter; use vek::*; use super::dialogue::Subject; -pub const DEFAULT_INTERACTION_TIME: f32 = 1.0; +pub const DEFAULT_INTERACTION_TIME: f32 = 3.0; pub const TRADE_INTERACTION_TIME: f32 = 300.0; #[derive(Copy, Clone, Debug, PartialEq, Deserialize)] @@ -340,6 +342,88 @@ pub struct Target { pub aggro_on: bool, } +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, EnumIter)] +pub enum TimerAction { + Interact, +} + +/// A time used for managing agent-related timeouts. The timer is designed to +/// keep track of the start of any number of previous actions. However, +/// starting/progressing an action will end previous actions. Therefore, the +/// timer should be used for actions that are mutually-exclusive. +#[derive(Clone, Debug)] +pub struct Timer { + action_starts: Vec>, + last_action: Option, +} + +impl Default for Timer { + fn default() -> Self { + Self { + action_starts: TimerAction::iter().map(|_| None).collect(), + last_action: None, + } + } +} + +impl Timer { + fn idx_for(action: TimerAction) -> usize { + TimerAction::iter() + .enumerate() + .find(|(_, a)| a == &action) + .unwrap() + .0 // Can't fail, EnumIter is exhaustive + } + + /// Reset the timer for the given action, returning true if the timer was + /// not already reset. + pub fn reset(&mut self, action: TimerAction) -> bool { + std::mem::replace(&mut self.action_starts[Self::idx_for(action)], None).is_some() + } + + /// Start the timer for the given action, even if it was already started. + pub fn start(&mut self, time: f64, action: TimerAction) { + self.action_starts[Self::idx_for(action)] = Some(time); + self.last_action = Some(action); + } + + /// Continue timing the given action, starting it if it was not already + /// started. + pub fn progress(&mut self, time: f64, action: TimerAction) { + if self.last_action != Some(action) { + self.start(time, action); + } + } + + /// Return the time that the given action was last performed at. + pub fn time_of_last(&self, action: TimerAction) -> Option { + self.action_starts[Self::idx_for(action)] + } + + /// Return `true` if the time since the action was last started exceeds the + /// given timeout. + pub fn time_since_exceeds(&self, time: f64, action: TimerAction, timeout: f64) -> bool { + self.time_of_last(action) + .map_or(true, |last_time| (time - last_time).max(0.0) > timeout) + } + + /// Return `true` while the time since the action was last started is less + /// than the given period. Once the time has elapsed, reset the timer. + pub fn timeout_elapsed( + &mut self, + time: f64, + action: TimerAction, + timeout: f64, + ) -> Option { + if self.time_since_exceeds(time, action, timeout) { + Some(self.reset(action)) + } else { + self.progress(time, action); + None + } + } +} + #[allow(clippy::type_complexity)] #[derive(Clone, Debug)] pub struct Agent { @@ -351,6 +435,7 @@ pub struct Agent { pub psyche: Psyche, pub inbox: VecDeque, pub action_state: ActionState, + pub timer: Timer, pub bearing: Vec2, pub sounds_heard: Vec, pub awareness: f32, @@ -376,6 +461,7 @@ impl Agent { psyche: Psyche::from(body), inbox: VecDeque::new(), action_state: ActionState::default(), + timer: Timer::default(), bearing: Vec2::zero(), sounds_heard: Vec::new(), awareness: 0.0, diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index 64a8a0600f..5e27677d9a 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -3,7 +3,8 @@ use common::{ comp::{ self, agent::{ - AgentEvent, Sound, SoundKind, Target, DEFAULT_INTERACTION_TIME, TRADE_INTERACTION_TIME, + AgentEvent, Sound, SoundKind, Target, TimerAction, DEFAULT_INTERACTION_TIME, + TRADE_INTERACTION_TIME, }, buff::{BuffKind, Buffs}, compass::{Direction, Distance}, @@ -383,7 +384,6 @@ impl<'a> System<'a> for Sys { |agent: &mut Agent, controller: &mut Controller, event_emitter: &mut Emitter| { - agent.target = None; data.idle_tree(agent, controller, &read_data, event_emitter); }; @@ -608,27 +608,43 @@ impl<'a> AgentData<'a> { agent.action_state.timer = 0.1; } } - if agent.action_state.timer > 0.0 { - if agent.action_state.timer - < (if agent.behavior.is(BehaviorState::TRADING) { - TRADE_INTERACTION_TIME - } else { - DEFAULT_INTERACTION_TIME - }) - { - self.interact(agent, controller, read_data, event_emitter); - } else { - agent.action_state.timer = 0.0; - agent.target = None; - controller.actions.push(ControlAction::Stand); - self.idle(agent, controller, read_data); - } - } else if thread_rng().gen::() < 0.1 { - self.choose_target(agent, controller, read_data, event_emitter); - } else if agent.awareness > AWARENESS_INVESTIGATE_THRESHOLD { - self.handle_elevated_awareness(agent, controller, read_data); + + // If we receive a new interaction, start the interaction timer + if can_speak(agent) && self.recv_interaction(agent, controller, read_data, event_emitter) { + agent.timer.start(read_data.time.0, TimerAction::Interact); + } + + let timeout = if agent.behavior.is(BehaviorState::TRADING) { + TRADE_INTERACTION_TIME } else { - self.idle(agent, controller, read_data); + DEFAULT_INTERACTION_TIME + }; + + match agent + .timer + .timeout_elapsed(read_data.time.0, TimerAction::Interact, timeout as f64) + { + None => { + // Look toward the interacting entity for a while + if let Some(Target { target, .. }) = &agent.target { + self.look_toward(controller, read_data, *target); + controller.actions.push(ControlAction::Talk); + } + }, + Some(just_ended) => { + if just_ended { + agent.target = None; + controller.actions.push(ControlAction::Stand); + } + + if thread_rng().gen::() < 0.1 { + self.choose_target(agent, controller, read_data, event_emitter); + } else if agent.awareness > AWARENESS_INVESTIGATE_THRESHOLD { + self.handle_elevated_awareness(agent, controller, read_data); + } else { + self.idle(agent, controller, read_data); + } + }, } } @@ -967,13 +983,13 @@ impl<'a> AgentData<'a> { } } - fn interact( + fn recv_interaction( &self, agent: &mut Agent, controller: &mut Controller, read_data: &ReadData, event_emitter: &mut Emitter<'_, ServerEvent>, - ) { + ) -> bool { // TODO: Process group invites // TODO: Add Group AgentEvent // let accept = false; // set back to "matches!(alignment, Alignment::Npc)" @@ -1302,18 +1318,11 @@ impl<'a> AgentData<'a> { } } }, - _ => { - if can_speak(agent) { - // No new events, continue looking towards the last - // interacting player for some time - if let Some(Target { target, .. }) = &agent.target { - self.look_toward(controller, read_data, *target); - } else { - agent.action_state.timer = 0.0; - } - } - }, + Some(AgentEvent::ServerSound(_)) => {}, + Some(AgentEvent::Hurt) => {}, + None => return false, } + true } fn look_toward( From 665951946ffe092bd4e43e82da112bf05424b1a2 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Wed, 4 Aug 2021 14:12:10 +0100 Subject: [PATCH 086/155] Fixed block snapping --- common/systems/src/phys.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common/systems/src/phys.rs b/common/systems/src/phys.rs index 8c8104a1ce..d5e294e75d 100644 --- a/common/systems/src/phys.rs +++ b/common/systems/src/phys.rs @@ -1540,7 +1540,10 @@ fn box_voxel_collision<'a, T: BaseVol + ReadVol>( .unwrap_or(0.0); vel.0.z = 0.0; pos.0.z = (pos.0.z - 0.1).floor() + snap_height; - physics_state.on_ground = on_ground; + physics_state.on_ground = terrain + .get(Vec3::new(pos.0.x, pos.0.y, pos.0.z - 0.01).map(|e| e.floor() as i32)) + .ok() + .copied(); } let player_aabb = Aabb { From c4214fedbeb3e117eaf9e78f47be64530cf0afd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Wed, 4 Aug 2021 23:14:08 +0100 Subject: [PATCH 087/155] Don't use derivatives in vertex shader --- assets/voxygen/shaders/include/lod.glsl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/voxygen/shaders/include/lod.glsl b/assets/voxygen/shaders/include/lod.glsl index 74f73849cf..e40da75ea8 100644 --- a/assets/voxygen/shaders/include/lod.glsl +++ b/assets/voxygen/shaders/include/lod.glsl @@ -105,10 +105,10 @@ vec2 textureBicubic16(texture2D tex, sampler sampl, vec2 texCoords) { /* // Correct for map rotaton. offset.zw = 1.0 - offset.zw; */ - vec4 sample0_v4 = texture(sampler2D(tex, sampl), offset.xz); - vec4 sample1_v4 = texture(sampler2D(tex, sampl), offset.yz); - vec4 sample2_v4 = texture(sampler2D(tex, sampl), offset.xw); - vec4 sample3_v4 = texture(sampler2D(tex, sampl), offset.yw); + vec4 sample0_v4 = textureLod(sampler2D(tex, sampl), offset.xz, 0); + vec4 sample1_v4 = textureLod(sampler2D(tex, sampl), offset.yz, 0); + vec4 sample2_v4 = textureLod(sampler2D(tex, sampl), offset.xw, 0); + vec4 sample3_v4 = textureLod(sampler2D(tex, sampl), offset.yw, 0); vec2 sample0 = sample0_v4.rb / 256.0 + sample0_v4.ga; vec2 sample1 = sample1_v4.rb / 256.0 + sample1_v4.ga; vec2 sample2 = sample2_v4.rb / 256.0 + sample2_v4.ga; From cbd7c4481ca6f6ce10f3469d99eb5058b6ceec1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20B=C3=B6klin?= Date: Thu, 5 Aug 2021 08:34:21 +0200 Subject: [PATCH 088/155] Make character upright itself even while idle --- common/src/states/utils.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 3e0553982a..e3d8c2ca2d 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -349,18 +349,17 @@ pub fn handle_forced_movement( } pub fn handle_orientation(data: &JoinData<'_>, update: &mut StateUpdate, efficiency: f32) { - if let Some(dir) = (is_strafing(data, update) || update.character.is_attack()) + let dir = (is_strafing(data, update) || update.character.is_attack()) .then(|| data.inputs.look_dir.to_horizontal().unwrap_or_default()) .or_else(|| Dir::from_unnormalized(data.inputs.move_dir.into())) - { - let rate = { - let angle = update.ori.look_dir().angle_between(*dir); - data.body.base_ori_rate() * efficiency * std::f32::consts::PI / angle - }; - update.ori = update - .ori - .slerped_towards(dir.into(), (data.dt.0 * rate).min(1.0)); + .unwrap_or_else(|| data.ori.to_horizontal().look_dir()); + let rate = { + let angle = update.ori.look_dir().angle_between(*dir); + data.body.base_ori_rate() * efficiency * std::f32::consts::PI / angle }; + update.ori = update + .ori + .slerped_towards(dir.into(), (data.dt.0 * rate).min(1.0)); } /// Updates components to move player as if theyre swimming From fadf53a6ba1d1796203e8c17acf47612506ad1cc Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Thu, 5 Aug 2021 02:13:01 +0300 Subject: [PATCH 089/155] Nerf pillars * make platforms one block high --- world/src/site2/plot/dungeon.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/world/src/site2/plot/dungeon.rs b/world/src/site2/plot/dungeon.rs index 3b0bbae244..6ba239ee9a 100644 --- a/world/src/site2/plot/dungeon.rs +++ b/world/src/site2/plot/dungeon.rs @@ -1264,14 +1264,15 @@ impl Floor { min: (tile_center - Vec2::broadcast(1 + pillar_thickness - 1)) .with_z(floor_z), max: (tile_center + Vec2::broadcast(1 + pillar_thickness)) - .with_z(floor_z + 3), + .with_z(floor_z + 1), })); let scale = (pillar_thickness + 2) as f32 / pillar_thickness as f32; let mut lights = prim(Primitive::Scale(pillar, Vec2::broadcast(scale).with_z(1.0))); lights = prim(Primitive::And(lighting_plane, lights)); - // Only add the base (and shift the lights up) for boss-room pillars + // Only add the base (and shift the lights up) + // for boss-rooms pillars if room.kind == RoomKind::Boss { lights = prim(Primitive::Translate(lights, 3 * Vec3::unit_z())); pillar = prim(Primitive::Or(pillar, base)); From edd37ad4919413d6d43f455b0c1f0ab255159ae3 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Thu, 5 Aug 2021 02:13:31 +0300 Subject: [PATCH 090/155] Agent code TODO-s --- server/src/sys/agent.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index 5e27677d9a..ef1d033b65 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -1787,10 +1787,20 @@ impl<'a> AgentData<'a> { 0.0 }; - // FIXME: Retrieve actual projectile speed! + // FIXME: + // 1) Retrieve actual projectile speed! // We have to assume projectiles are faster than base speed because there are // skills that increase it, and in most cases this will cause agents to // overshoot + // + // 2) We use eye_offset-s which isn't actually ideal. + // Some attacks (beam for example) may use different offsets, + // we should probably use offsets from corresponding states. + // + // 3) Should we even have this big switch? + // Not all attacks may want their direction overwritten. + // And this is quite hard to debug when you don't see it in actual + // attack handler. if let Some(dir) = match tactic { Tactic::Bow | Tactic::FixedTurret From 8a83ecf57fdced7a2b1239bcf8f0437ba9a88cbd Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Thu, 5 Aug 2021 02:14:10 +0300 Subject: [PATCH 091/155] Fix Beam orientation, remove orientation_behavior * make old OrientationBehavior::FromOri default behaviour * use rotation formed from look_dir instead of constructing ori on the fly (which is altered after normalization). --- .../abilities/custom/basilisk/petrify.ron | 1 - .../custom/birdlargebreathe/flamethrower.ron | 1 - .../custom/birdlargefire/flamethrower.ron | 1 - .../abilities/custom/claygolem/laser.ron | 1 - .../abilities/custom/harvester/firebreath.ron | 1 - .../custom/mindflayer/cursedflames.ron | 1 - .../custom/quadlowbeam/lifestealbeam.ron | 1 - .../custom/quadlowbreathe/flamethrower.ron | 1 - .../abilities/custom/tidalwarrior/bubbles.ron | 1 - .../abilities/custom/turret/flamethrower.ron | 1 - .../abilities/custom/yeti/frostbreath.ron | 1 - .../abilities/sceptre/lifestealbeam.ron | 1 - .../common/abilities/staff/flamethrower.ron | 1 - .../abilities/staffsimple/flamethrower.ron | 1 - common/src/comp/ability.rs | 4 -- common/src/states/basic_beam.rs | 54 +++++++++---------- 16 files changed, 24 insertions(+), 48 deletions(-) diff --git a/assets/common/abilities/custom/basilisk/petrify.ron b/assets/common/abilities/custom/basilisk/petrify.ron index 20b6022fb7..3ef55daf04 100644 --- a/assets/common/abilities/custom/basilisk/petrify.ron +++ b/assets/common/abilities/custom/basilisk/petrify.ron @@ -14,7 +14,6 @@ BasicBeam( ))), energy_regen: 0, energy_drain: 0, - orientation_behavior: Normal, ori_rate: 0.3, specifier: Cultist, ) diff --git a/assets/common/abilities/custom/birdlargebreathe/flamethrower.ron b/assets/common/abilities/custom/birdlargebreathe/flamethrower.ron index dfbd2227dc..cf3e4c63b6 100644 --- a/assets/common/abilities/custom/birdlargebreathe/flamethrower.ron +++ b/assets/common/abilities/custom/birdlargebreathe/flamethrower.ron @@ -14,7 +14,6 @@ BasicBeam( ))), energy_regen: 0, energy_drain: 0, - orientation_behavior: Normal, ori_rate: 0.3, specifier: Flamethrower, ) diff --git a/assets/common/abilities/custom/birdlargefire/flamethrower.ron b/assets/common/abilities/custom/birdlargefire/flamethrower.ron index dfbd2227dc..cf3e4c63b6 100644 --- a/assets/common/abilities/custom/birdlargefire/flamethrower.ron +++ b/assets/common/abilities/custom/birdlargefire/flamethrower.ron @@ -14,7 +14,6 @@ BasicBeam( ))), energy_regen: 0, energy_drain: 0, - orientation_behavior: Normal, ori_rate: 0.3, specifier: Flamethrower, ) diff --git a/assets/common/abilities/custom/claygolem/laser.ron b/assets/common/abilities/custom/claygolem/laser.ron index c93f0f7ce8..95782454f0 100644 --- a/assets/common/abilities/custom/claygolem/laser.ron +++ b/assets/common/abilities/custom/claygolem/laser.ron @@ -14,7 +14,6 @@ BasicBeam( ))), energy_regen: 50, energy_drain: 0, - orientation_behavior: FromOri, ori_rate: 0.07, specifier: ClayGolem, ) diff --git a/assets/common/abilities/custom/harvester/firebreath.ron b/assets/common/abilities/custom/harvester/firebreath.ron index 94f0a66de4..ac52ce7561 100644 --- a/assets/common/abilities/custom/harvester/firebreath.ron +++ b/assets/common/abilities/custom/harvester/firebreath.ron @@ -14,7 +14,6 @@ BasicBeam( ))), energy_regen: 0, energy_drain: 0, - orientation_behavior: Normal, ori_rate: 0.2, specifier: Flamethrower, ) diff --git a/assets/common/abilities/custom/mindflayer/cursedflames.ron b/assets/common/abilities/custom/mindflayer/cursedflames.ron index b74005d138..8ce5a5cfb5 100644 --- a/assets/common/abilities/custom/mindflayer/cursedflames.ron +++ b/assets/common/abilities/custom/mindflayer/cursedflames.ron @@ -14,7 +14,6 @@ BasicBeam( ))), energy_regen: 0, energy_drain: 0, - orientation_behavior: FromOri, ori_rate: 0.2, specifier: Cultist, ) diff --git a/assets/common/abilities/custom/quadlowbeam/lifestealbeam.ron b/assets/common/abilities/custom/quadlowbeam/lifestealbeam.ron index 97262f80f0..bf9f67567c 100644 --- a/assets/common/abilities/custom/quadlowbeam/lifestealbeam.ron +++ b/assets/common/abilities/custom/quadlowbeam/lifestealbeam.ron @@ -9,7 +9,6 @@ BasicBeam( damage_effect: Some(Lifesteal(0.15)), energy_regen: 25, energy_drain: 0, - orientation_behavior: Normal, ori_rate: 0.3, specifier: LifestealBeam, ) diff --git a/assets/common/abilities/custom/quadlowbreathe/flamethrower.ron b/assets/common/abilities/custom/quadlowbreathe/flamethrower.ron index 5f4dab269a..5d6fd2895e 100644 --- a/assets/common/abilities/custom/quadlowbreathe/flamethrower.ron +++ b/assets/common/abilities/custom/quadlowbreathe/flamethrower.ron @@ -14,7 +14,6 @@ BasicBeam( ))), energy_regen: 0, energy_drain: 0, - orientation_behavior: Normal, ori_rate: 0.3, specifier: Flamethrower, ) diff --git a/assets/common/abilities/custom/tidalwarrior/bubbles.ron b/assets/common/abilities/custom/tidalwarrior/bubbles.ron index a34d1cb777..3d35c86f50 100644 --- a/assets/common/abilities/custom/tidalwarrior/bubbles.ron +++ b/assets/common/abilities/custom/tidalwarrior/bubbles.ron @@ -14,7 +14,6 @@ BasicBeam( ))), energy_regen: 0, energy_drain: 0, - orientation_behavior: Normal, ori_rate: 0.3, specifier: Bubbles, ) diff --git a/assets/common/abilities/custom/turret/flamethrower.ron b/assets/common/abilities/custom/turret/flamethrower.ron index 33f5dc51c9..da84dd0160 100644 --- a/assets/common/abilities/custom/turret/flamethrower.ron +++ b/assets/common/abilities/custom/turret/flamethrower.ron @@ -14,7 +14,6 @@ BasicBeam( ))), energy_regen: 0, energy_drain: 0, - orientation_behavior: Normal, ori_rate: 0.3, specifier: Flamethrower, ) diff --git a/assets/common/abilities/custom/yeti/frostbreath.ron b/assets/common/abilities/custom/yeti/frostbreath.ron index 7f35a26ae7..2f29bf5e94 100644 --- a/assets/common/abilities/custom/yeti/frostbreath.ron +++ b/assets/common/abilities/custom/yeti/frostbreath.ron @@ -14,7 +14,6 @@ BasicBeam( ))), energy_regen: 0, energy_drain: 0, - orientation_behavior: FromOri, ori_rate: 0.1, specifier: Frost, ) diff --git a/assets/common/abilities/sceptre/lifestealbeam.ron b/assets/common/abilities/sceptre/lifestealbeam.ron index 5236219eb4..7d37405d23 100644 --- a/assets/common/abilities/sceptre/lifestealbeam.ron +++ b/assets/common/abilities/sceptre/lifestealbeam.ron @@ -9,7 +9,6 @@ BasicBeam( damage_effect: Some(Lifesteal(0.125)), energy_regen: 50, energy_drain: 0, - orientation_behavior: Normal, ori_rate: 0.3, specifier: LifestealBeam ) diff --git a/assets/common/abilities/staff/flamethrower.ron b/assets/common/abilities/staff/flamethrower.ron index 8f5c80ac0a..aefa0236b8 100644 --- a/assets/common/abilities/staff/flamethrower.ron +++ b/assets/common/abilities/staff/flamethrower.ron @@ -14,7 +14,6 @@ BasicBeam( ))), energy_regen: 0, energy_drain: 350, - orientation_behavior: Normal, ori_rate: 0.3, specifier: Flamethrower, ) diff --git a/assets/common/abilities/staffsimple/flamethrower.ron b/assets/common/abilities/staffsimple/flamethrower.ron index b024bae2e4..d676f32c10 100644 --- a/assets/common/abilities/staffsimple/flamethrower.ron +++ b/assets/common/abilities/staffsimple/flamethrower.ron @@ -14,7 +14,6 @@ BasicBeam( ))), energy_regen: 0, energy_drain: 350, - orientation_behavior: FromOri, ori_rate: 0.3, specifier: Flamethrower, ) diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 44241a7607..3295e3b821 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -251,7 +251,6 @@ pub enum CharacterAbility { damage_effect: Option, energy_regen: f32, energy_drain: f32, - orientation_behavior: basic_beam::OrientationBehavior, ori_rate: f32, specifier: beam::FrontendSpecifier, }, @@ -745,7 +744,6 @@ impl CharacterAbility { ref mut damage_effect, energy_regen: _, ref mut energy_drain, - orientation_behavior: _, ori_rate: _, specifier: _, } => { @@ -1878,7 +1876,6 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState { damage_effect, energy_regen, energy_drain, - orientation_behavior, ori_rate, specifier, } => CharacterState::BasicBeam(basic_beam::Data { @@ -1894,7 +1891,6 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState { energy_regen: *energy_regen, energy_drain: *energy_drain, ability_info, - orientation_behavior: *orientation_behavior, ori_rate: *ori_rate, specifier: *specifier, }, diff --git a/common/src/states/basic_beam.rs b/common/src/states/basic_beam.rs index 31080f42c0..0d1e1025f5 100644 --- a/common/src/states/basic_beam.rs +++ b/common/src/states/basic_beam.rs @@ -10,6 +10,7 @@ use crate::{ utils::*, }, uid::Uid, + util::Dir, }; use serde::{Deserialize, Serialize}; use std::time::Duration; @@ -38,8 +39,6 @@ pub struct StaticData { pub energy_regen: f32, /// Energy drained per second pub energy_drain: f32, - /// Used to dictate how orientation functions in this state - pub orientation_behavior: OrientationBehavior, /// How fast enemy can rotate with beam pub ori_rate: f32, /// What key is used to press ability @@ -64,9 +63,6 @@ impl CharacterBehavior for Data { let mut update = StateUpdate::from(data); let ori_rate = self.static_data.ori_rate; - if self.static_data.orientation_behavior == OrientationBehavior::Turret { - update.ori = Ori::from(data.inputs.look_dir); - } handle_orientation(data, &mut update, ori_rate); handle_move(data, &mut update, 0.4); @@ -142,16 +138,25 @@ impl CharacterBehavior for Data { Body::Golem(_) => data.body.height() * 0.9 + data.inputs.look_dir.z * 3.0, _ => data.body.height() * 0.5, }; - let (body_offsets, ori) = match self.static_data.orientation_behavior { - OrientationBehavior::Normal | OrientationBehavior::Turret => ( - Vec3::new( - body_offsets_r * data.inputs.look_dir.x, - body_offsets_r * data.inputs.look_dir.y, - body_offsets_z, - ), - Ori::from(data.inputs.look_dir), - ), - OrientationBehavior::FromOri => ( + let (body_offsets, ori) = { + // We want Beam to use Ori. + // But we also want beam to use Z part of where you look. + // This means that we need to merge this data to one Ori. + // + // This code just gets look_dir without Z part + // and normalizes it. This is what `xy_dir is`. + // + // Then we find rotation between xy_dir and look_dir + // which gives us quaternion how of what rotation we need + // to do to get Z part we want. + // + // Then we construct Ori without Z part + // and applying `pitch` to get needed orientation. + let look_dir = data.inputs.look_dir; + let xy_dir = Dir::from_unnormalized(Vec3::new(look_dir.x, look_dir.y, 0.0)) + .unwrap_or_else(Dir::default); + let pitch = xy_dir.rotation_between(look_dir); + ( Vec3::new( body_offsets_r * update.ori.look_vec().x, body_offsets_r * update.ori.look_vec().y, @@ -160,9 +165,10 @@ impl CharacterBehavior for Data { Ori::from(Vec3::new( update.ori.look_vec().x, update.ori.look_vec().y, - data.inputs.look_dir.z, - )), - ), + 0.0, + )) + .prerotated(pitch), + ) }; let pos = Pos(data.pos.0 + body_offsets); // Create beam segment @@ -218,15 +224,3 @@ impl CharacterBehavior for Data { update } } - -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] -pub enum OrientationBehavior { - /// Uses look_dir as direction of beam - Normal, - /// Uses look_dir as direction of beam, sets orientation to same direction - /// as look_dir - Turret, - /// Uses orientation x and y and look_dir z as direction of beam (z from - /// look_dir as orientation will only go through 2d rotations naturally) - FromOri, -} From 3386805765f10111360eefac882085c06008ca9f Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Thu, 5 Aug 2021 20:27:12 +0300 Subject: [PATCH 092/155] Give TrainingDummy hitbox --- common/src/comp/body/object.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/src/comp/body/object.rs b/common/src/comp/body/object.rs index b452715362..45140e2a3b 100644 --- a/common/src/comp/body/object.rs +++ b/common/src/comp/body/object.rs @@ -377,6 +377,8 @@ impl Body { Body::SeaLantern => Vec3::new(0.5, 0.5, 1.0), Body::Snowball => Vec3::broadcast(2.5), Body::Tornado => Vec3::new(2.0, 2.0, 3.4), + Body::TrainingDummy => Vec3::new(1.5, 1.5, 3.0), + // FIXME: this *must* be exhaustive match _ => Vec3::broadcast(0.5), } } From 4029d4a720b9a12e47fa97ebd556f5fbe5f7fdcd Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Thu, 5 Aug 2021 21:00:28 +0300 Subject: [PATCH 093/155] Change beam offsets * Make it so that beam starts from inside hitbox of owner. Without it it's possible to cheese beem attack just making close enough to its owner. --- common/src/states/basic_beam.rs | 54 +++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/common/src/states/basic_beam.rs b/common/src/states/basic_beam.rs index 0d1e1025f5..b94533972d 100644 --- a/common/src/states/basic_beam.rs +++ b/common/src/states/basic_beam.rs @@ -131,16 +131,9 @@ impl CharacterBehavior for Data { owner: Some(*data.uid), specifier: self.static_data.specifier, }; - // Gets offsets - let body_offsets_r = data.body.radius() + 1.0; - let body_offsets_z = match data.body { - Body::BirdLarge(_) => data.body.height() * 0.8, - Body::Golem(_) => data.body.height() * 0.9 + data.inputs.look_dir.z * 3.0, - _ => data.body.height() * 0.5, - }; - let (body_offsets, ori) = { - // We want Beam to use Ori. - // But we also want beam to use Z part of where you look. + let beam_ori = { + // We want Beam to use Ori of owner. + // But we also want beam to use Z part of where owner looks. // This means that we need to merge this data to one Ori. // // This code just gets look_dir without Z part @@ -156,26 +149,41 @@ impl CharacterBehavior for Data { let xy_dir = Dir::from_unnormalized(Vec3::new(look_dir.x, look_dir.y, 0.0)) .unwrap_or_else(Dir::default); let pitch = xy_dir.rotation_between(look_dir); - ( - Vec3::new( - body_offsets_r * update.ori.look_vec().x, - body_offsets_r * update.ori.look_vec().y, - body_offsets_z, - ), - Ori::from(Vec3::new( - update.ori.look_vec().x, - update.ori.look_vec().y, - 0.0, - )) - .prerotated(pitch), + + Ori::from(Vec3::new( + update.ori.look_vec().x, + update.ori.look_vec().y, + 0.0, + )) + .prerotated(pitch) + }; + // Gets offsets + let body_offsets = { + let body_radius = data.body.radius(); + + // TODO: make it public function to use in Agent code + // to help with aim. + let body_offsets_z = match data.body { + Body::BirdLarge(_) => data.body.height() * 0.8, + Body::Golem(_) => { + data.body.height() * 0.9 + data.inputs.look_dir.z * 3.0 + }, + _ => data.body.height() * 0.5, + }; + + Vec3::new( + body_radius * update.ori.look_vec().x * 1.1, + body_radius * update.ori.look_vec().y * 1.1, + body_offsets_z, ) }; let pos = Pos(data.pos.0 + body_offsets); + // Create beam segment update.server_events.push_front(ServerEvent::BeamSegment { properties, pos, - ori, + ori: beam_ori, }); update.character = CharacterState::BasicBeam(Data { timer: tick_attack_or_default(data, self.timer, None), From c0f3dfe6bd07942508427a6573cb3a0d015a87e5 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Fri, 6 Aug 2021 11:57:42 +0300 Subject: [PATCH 094/155] Normalize masses in range 75-100. + Remove match on body_type --- common/src/comp/body.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 0e52fc50c8..d4ec2262f9 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -205,19 +205,18 @@ impl Body { Body::FishSmall(_) => 1.0, Body::Golem(_) => 10_000.0, Body::Humanoid(humanoid) => { - match (humanoid.species, humanoid.body_type) { - (humanoid::Species::Orc, humanoid::BodyType::Male) => 120.0, - (humanoid::Species::Orc, humanoid::BodyType::Female) => 120.0, - (humanoid::Species::Human, humanoid::BodyType::Male) => 77.0, // ~✅ - (humanoid::Species::Human, humanoid::BodyType::Female) => 59.0, // ~✅ - (humanoid::Species::Elf, humanoid::BodyType::Male) => 77.0, - (humanoid::Species::Elf, humanoid::BodyType::Female) => 59.0, - (humanoid::Species::Dwarf, humanoid::BodyType::Male) => 70.0, - (humanoid::Species::Dwarf, humanoid::BodyType::Female) => 70.0, - (humanoid::Species::Undead, humanoid::BodyType::Male) => 70.0, - (humanoid::Species::Undead, humanoid::BodyType::Female) => 50.0, - (humanoid::Species::Danari, humanoid::BodyType::Male) => 80.0, - (humanoid::Species::Danari, humanoid::BodyType::Female) => 60.0, + // Understand that chaning the mass values can have effects + // on multiple systems. + // + // If you want to change that value, consult with + // Physics and Combat teams + match humanoid.species { + humanoid::Species::Orc => 100.0, + humanoid::Species::Elf => 85.0, + humanoid::Species::Human => 85.0, + humanoid::Species::Dwarf => 80.0, + humanoid::Species::Undead => 75.0, + humanoid::Species::Danari => 75.0, } }, Body::Object(obj) => obj.mass().0, From c956ca18630a99ad9ce85b0bbc29f38f24331a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Fri, 6 Aug 2021 11:41:02 +0200 Subject: [PATCH 095/155] write header only once --- voxygen/i18n/src/analysis.rs | 6 ++++++ voxygen/i18n/src/stats.rs | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/voxygen/i18n/src/analysis.rs b/voxygen/i18n/src/analysis.rs index f1e2d465c7..93150dbee6 100644 --- a/voxygen/i18n/src/analysis.rs +++ b/voxygen/i18n/src/analysis.rs @@ -210,6 +210,12 @@ pub fn test_specific_localizations( let output = path.root_path().join("translation_analysis.csv"); let mut f = std::fs::File::create(output).expect("couldn't write csv file"); + use std::io::Write; + writeln!( + f, + "country_code,file_name,translation_key,status,git_commit" + ) + .unwrap(); //printing for (language_identifier, (state_map, stats)) in &analysis { if csv_enabled { diff --git a/voxygen/i18n/src/stats.rs b/voxygen/i18n/src/stats.rs index 923840d439..534b3de8cc 100644 --- a/voxygen/i18n/src/stats.rs +++ b/voxygen/i18n/src/stats.rs @@ -146,12 +146,6 @@ pub(crate) fn print_translation_stats( } pub(crate) fn print_csv_stats(state_map: &LocalizationAnalysis, output: &mut W) { - writeln!( - output, - "country_code,file_name,translation_key,status,git_commit" - ) - .unwrap(); - for state in &ALL_LOCALIZATION_STATES { state_map.csv(*state, output); } From bdce07e7a02cd74b960504d3394f46b018bdfa99 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Fri, 6 Aug 2021 12:57:29 +0300 Subject: [PATCH 096/155] Adress review, add test for structs --- common/assets/src/lib.rs | 63 +++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/common/assets/src/lib.rs b/common/assets/src/lib.rs index 80122a52af..fb21436cfa 100644 --- a/common/assets/src/lib.rs +++ b/common/assets/src/lib.rs @@ -325,10 +325,6 @@ pub mod asset_tweak { /// /// `Asset(&["path", "to", "file"])` will be interpreted as /// `/path/to/file.ron` - // TODO: should we care about situation where - // lifetime of slice and lifetime of strings are different? - // - // Should we use references at all? pub enum Specifier<'a> { Tweak(&'a str), Asset(&'a [&'a str]), @@ -658,34 +654,30 @@ pub mod asset_tweak { #[test] fn test_tweaked_int() { - use Specifier::Asset; - let tweak_path = &["tweak_test_int", "tweak"]; run_with_file(tweak_path, |file| { file.write_all(b"(5)").expect("failed to write to the file"); - let x: i32 = tweak_expect(Asset(tweak_path)); + let x: i32 = tweak_expect(Specifier::Asset(tweak_path)); assert_eq!(x, 5); }); } #[test] fn test_tweaked_string() { - use Specifier::Asset; let tweak_path = &["tweak_test_string", "tweak"]; run_with_file(tweak_path, |file| { file.write_all(br#"("Hello Zest")"#) .expect("failed to write to the file"); - let x: String = tweak_expect(Asset(tweak_path)); + let x: String = tweak_expect(Specifier::Asset(tweak_path)); assert_eq!(x, "Hello Zest".to_owned()); }); } #[test] fn test_tweaked_hashmap() { - use Specifier::Asset; type Map = std::collections::HashMap; let tweak_path = &["tweak_test_map", "tweak"]; @@ -701,7 +693,7 @@ pub mod asset_tweak { ) .expect("failed to write to the file"); - let x: Map = tweak_expect(Asset(tweak_path)); + let x: Map = tweak_expect(Specifier::Asset(tweak_path)); let mut map = Map::new(); map.insert("wow".to_owned(), 4); @@ -710,6 +702,37 @@ pub mod asset_tweak { }); } + #[test] + fn test_tweaked_with_macro_struct() { + // partial eq and debug because of assert_eq in this test + #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)] + struct Wow { + such: i32, + field: f32, + } + + let tweak_path = &["tweak_test_struct", "tweak"]; + + run_with_file(tweak_path, |file| { + file.write_all( + br#" + (( + such: 5, + field: 35.752346, + )) + "#, + ) + .expect("failed to write to the file"); + + let x: Wow = crate::tweak_from!(tweak_path); + let expected = Wow { + such: 5, + field: 35.752_346, + }; + assert_eq!(x, expected); + }); + } + fn run_with_path(tweak_path: &[&str], test: impl Fn(&Path)) { let (tweak_dir, tweak_name) = directory_and_name(tweak_path); @@ -723,51 +746,45 @@ pub mod asset_tweak { #[test] fn test_create_tweak() { - use Specifier::Asset; - let tweak_path = &["tweak_create_test", "tweak"]; run_with_path(tweak_path, |test_path| { - let x = tweak_expect_or_create(Asset(tweak_path), 5); + let x = tweak_expect_or_create(Specifier::Asset(tweak_path), 5); assert_eq!(x, 5); assert!(test_path.is_file()); // Recheck it loads back correctly - let x = tweak_expect_or_create(Asset(tweak_path), 5); + let x = tweak_expect_or_create(Specifier::Asset(tweak_path), 5); assert_eq!(x, 5); }); } #[test] fn test_create_tweak_deep() { - use Specifier::Asset; - let tweak_path = &["so_much", "deep_test", "tweak_create_test", "tweak"]; run_with_path(tweak_path, |test_path| { - let x = tweak_expect_or_create(Asset(tweak_path), 5); + let x = tweak_expect_or_create(Specifier::Asset(tweak_path), 5); assert_eq!(x, 5); assert!(test_path.is_file()); // Recheck it loads back correctly - let x = tweak_expect_or_create(Asset(tweak_path), 5); + let x = tweak_expect_or_create(Specifier::Asset(tweak_path), 5); assert_eq!(x, 5); }); } #[test] fn test_create_but_prioritize_loaded() { - use Specifier::Asset; - let tweak_path = &["tweak_create_and_prioritize_test", "tweak"]; run_with_path(tweak_path, |test_path| { - let x = tweak_expect_or_create(Asset(tweak_path), 5); + let x = tweak_expect_or_create(Specifier::Asset(tweak_path), 5); assert_eq!(x, 5); assert!(test_path.is_file()); // Recheck it loads back // with content as priority fs::write(test_path, b"(10)").expect("failed to write to the file"); - let x = tweak_expect_or_create(Asset(tweak_path), 5); + let x = tweak_expect_or_create(Specifier::Asset(tweak_path), 5); assert_eq!(x, 10); }); } From ea5de81f9b4a4eb924d7dea4099b58fa1a32221a Mon Sep 17 00:00:00 2001 From: Xeriab Nabil Date: Thu, 5 Aug 2021 23:08:56 +0300 Subject: [PATCH 097/155] UI: Fixes and enhancements to trading window --- assets/voxygen/element/ui/bag/inv_bg_bag.png | 4 +- .../voxygen/element/ui/bag/inv_frame_bag.png | 4 +- .../element/ui/bag/inv_middle_bg_bag.png | 3 + .../element/ui/bag/inv_middle_frame.png | 3 + .../ui/bag/second_phase_scrollbar_bg.png | 3 + assets/voxygen/i18n/en/hud/trade.ron | 4 +- voxygen/src/hud/bag.rs | 37 ++++++-- voxygen/src/hud/img_ids.rs | 3 + voxygen/src/hud/trade.rs | 88 ++++++++++++------- 9 files changed, 105 insertions(+), 44 deletions(-) create mode 100644 assets/voxygen/element/ui/bag/inv_middle_bg_bag.png create mode 100644 assets/voxygen/element/ui/bag/inv_middle_frame.png create mode 100644 assets/voxygen/element/ui/bag/second_phase_scrollbar_bg.png diff --git a/assets/voxygen/element/ui/bag/inv_bg_bag.png b/assets/voxygen/element/ui/bag/inv_bg_bag.png index 8e76c879e1..78ae8c5ddd 100644 --- a/assets/voxygen/element/ui/bag/inv_bg_bag.png +++ b/assets/voxygen/element/ui/bag/inv_bg_bag.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d70b26aad275d29436a70e3685e29ab3cf2022ed6718f389053b7557a82f810 -size 66660 +oid sha256:60daf4d970056a953036c0bfb7b43f1bad6d2475eaa2730882f5ee4091222142 +size 93156 diff --git a/assets/voxygen/element/ui/bag/inv_frame_bag.png b/assets/voxygen/element/ui/bag/inv_frame_bag.png index cefd5e2c46..63b9f051e1 100644 --- a/assets/voxygen/element/ui/bag/inv_frame_bag.png +++ b/assets/voxygen/element/ui/bag/inv_frame_bag.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63cf18de0cbe0c6273e5a56841ee390465aec38592678dad08fb5c4ae6fe773c -size 5045 +oid sha256:2deacf661a411b7618576b9c17ae9372ec85be88cb456cc2baa07b7e091504c7 +size 12547 diff --git a/assets/voxygen/element/ui/bag/inv_middle_bg_bag.png b/assets/voxygen/element/ui/bag/inv_middle_bg_bag.png new file mode 100644 index 0000000000..ed4e02a4c7 --- /dev/null +++ b/assets/voxygen/element/ui/bag/inv_middle_bg_bag.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bcffc1d6a59746ac94c48e93c1b221b9b732d89f992ec05acb80d5bb56df3a03 +size 75628 diff --git a/assets/voxygen/element/ui/bag/inv_middle_frame.png b/assets/voxygen/element/ui/bag/inv_middle_frame.png new file mode 100644 index 0000000000..820b15825c --- /dev/null +++ b/assets/voxygen/element/ui/bag/inv_middle_frame.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b78da1728ccd631bbf4aec58253cc26d12d5e71997a003eec0c4a43217bb4cc +size 12360 diff --git a/assets/voxygen/element/ui/bag/second_phase_scrollbar_bg.png b/assets/voxygen/element/ui/bag/second_phase_scrollbar_bg.png new file mode 100644 index 0000000000..4a6277fe21 --- /dev/null +++ b/assets/voxygen/element/ui/bag/second_phase_scrollbar_bg.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a729f672e0b7d1fbe2138fe6d144d92a58b04ec82a7f947bb13b7c78f4d720fd +size 5778 diff --git a/assets/voxygen/i18n/en/hud/trade.ron b/assets/voxygen/i18n/en/hud/trade.ron index 5a855ed754..8528c3a5ca 100644 --- a/assets/voxygen/i18n/en/hud/trade.ron +++ b/assets/voxygen/i18n/en/hud/trade.ron @@ -3,7 +3,7 @@ /// Localization for "global" English ( string_map: { - "hud.trade.trade_window": "Trade window", + "hud.trade.trade_window": "Trade", "hud.trade.phase1_description": "Drag the items you want to trade\n into the corresponding area.", "hud.trade.phase2_description": "The trade is now locked to give you\n time to review it.", /// Phase3 should only be visible for a few milliseconds if everything is working properly, but is included for completeness @@ -21,6 +21,8 @@ "hud.trade.coin": "coin(s)", "hud.trade.tooltip_hint_1": "", "hud.trade.tooltip_hint_2": "", + "hud.trade.your_offer": "Your offer", + "hud.trade.their_offer": "Their offer", }, diff --git a/voxygen/src/hud/bag.rs b/voxygen/src/hud/bag.rs index a3c676dc33..7cb2daf6d8 100644 --- a/voxygen/src/hud/bag.rs +++ b/voxygen/src/hud/bag.rs @@ -56,7 +56,9 @@ widget_ids! { inventory_title, inventory_title_bg, scrollbar_bg, + second_phase_scrollbar_bg, scrollbar_slots, + left_scrollbar_slots, } } @@ -138,11 +140,11 @@ impl<'a> InventoryScroller<'a> { } else { self.imgs.inv_bg_armor }) - .w_h(424.0, 708.0); + .w_h(424.0, if self.show_bag_inv { 548.0 } else { 708.0 }); if self.on_right { - bg = bg.bottom_right_with_margins_on(ui.window, 60.0, 5.0); + bg = bg.bottom_right_with_margins_on(ui.window, 70.0, 5.0); } else { - bg = bg.bottom_left_with_margins_on(ui.window, 60.0, 5.0); + bg = bg.bottom_left_with_margins_on(ui.window, 230.0, 5.0); } bg.color(Some(UI_MAIN)).set(self.bg_ids.bg, ui); Image::new(if self.show_bag_inv { @@ -150,7 +152,7 @@ impl<'a> InventoryScroller<'a> { } else { self.imgs.inv_frame }) - .w_h(424.0, 708.0) + .w_h(424.0, if self.show_bag_inv { 548.0 } else { 708.0 }) .middle_of(self.bg_ids.bg) .color(Some(UI_HIGHLIGHT_0)) .set(self.bg_ids.bg_frame, ui); @@ -187,6 +189,7 @@ impl<'a> InventoryScroller<'a> { ui: &mut UiCell<'_>, ) { let space_max = self.inventory.slots().count(); + // Slots Scrollbar if space_max > 45 && !self.show_bag_inv { // Scrollbar-BG @@ -217,12 +220,34 @@ impl<'a> InventoryScroller<'a> { .middle_of(state.ids.scrollbar_bg) .set(state.ids.scrollbar_slots, ui); }; + + // This is just for the offeror inventory scrollbar + if space_max >= 108 && self.show_bag_inv { + // Left bag scrollbar background + Image::new(self.imgs.second_phase_scrollbar_bg) + .w_h(9.0, 434.0) + .bottom_right_with_margins_on(self.bg_ids.bg_frame, 42.0, 3.0) + .color(Some(UI_HIGHLIGHT_0)) + .set(state.ids.second_phase_scrollbar_bg, ui); + // Left bag scrollbar + Scrollbar::y_axis(state.ids.inv_alignment) + .thickness(5.0) + .h(384.0) + .color(UI_MAIN) + .middle_of(state.ids.second_phase_scrollbar_bg) + .set(state.ids.left_scrollbar_slots, ui); + } + // Alignment for Grid Rectangle::fill_with( - [362.0, if self.show_bag_inv { 600.0 } else { 200.0 }], + [362.0, if self.show_bag_inv { 440.0 } else { 200.0 }], color::TRANSPARENT, ) - .bottom_left_with_margins_on(self.bg_ids.bg_frame, 29.0, 46.5) + .bottom_left_with_margins_on( + self.bg_ids.bg_frame, + 29.0, + if self.show_bag_inv { 28.0 } else { 46.5 }, + ) .scroll_kids_vertically() .set(state.ids.inv_alignment, ui); diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index ba0badbcbe..f929736b22 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -441,6 +441,8 @@ image_ids! { inv_frame: "voxygen.element.ui.bag.inv_frame", inv_frame_bag: "voxygen.element.ui.bag.inv_frame_bag", inv_bg_bag: "voxygen.element.ui.bag.inv_bg_bag", + inv_middle_bg_bag: "voxygen.element.ui.bag.inv_middle_bg_bag", + inv_middle_frame: "voxygen.element.ui.bag.inv_middle_frame", char_art: "voxygen.element.ui.bag.icons.character", inv_slot: "voxygen.element.ui.bag.buttons.inv_slot", inv_slot_grey: "voxygen.element.ui.bag.buttons.inv_slot_grey", @@ -453,6 +455,7 @@ image_ids! { inv_slot_sel: "voxygen.element.ui.bag.buttons.inv_slot_sel", scrollbar_bg: "voxygen.element.ui.generic.slider.scrollbar", scrollbar_bg_big: "voxygen.element.ui.generic.slider.scrollbar_1", + second_phase_scrollbar_bg: "voxygen.element.ui.bag.second_phase_scrollbar_bg", inv_tab_active: "voxygen.element.ui.bag.buttons.inv_tab_active", inv_tab_inactive: "voxygen.element.ui.bag.buttons.inv_tab_inactive", inv_tab_inactive_hover: "voxygen.element.ui.bag.buttons.inv_tab_inactive", diff --git a/voxygen/src/hud/trade.rs b/voxygen/src/hud/trade.rs index 83023f4e7d..cc62427d78 100644 --- a/voxygen/src/hud/trade.rs +++ b/voxygen/src/hud/trade.rs @@ -1,17 +1,12 @@ -use super::{ - img_ids::{Imgs, ImgsRot}, - item_imgs::ItemImgs, - slots::{SlotManager, TradeSlot}, - TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN, -}; -use crate::{ - hud::bag::{BackgroundIds, InventoryScroller}, - ui::{ - fonts::Fonts, - slot::{ContentSize, SlotMaker}, - ImageFrame, ItemTooltip, ItemTooltipManager, ItemTooltipable, - }, +use conrod_core::{ + color, + position::Relative, + widget::{self, Button, Image, Rectangle, State as ConrodState, Text}, + widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, UiCell, Widget, WidgetCommon, }; +use specs::Entity as EcsEntity; +use vek::*; + use client::Client; use common::{ comp::{ @@ -21,15 +16,23 @@ use common::{ trade::{PendingTrade, SitePrices, TradeAction, TradePhase}, }; use common_net::sync::WorldSyncExt; -use conrod_core::{ - color, - position::Relative, - widget::{self, Button, Image, Rectangle, State as ConrodState, Text}, - widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, UiCell, Widget, WidgetCommon, -}; use i18n::Localization; -use specs::Entity as EcsEntity; -use vek::*; + +use crate::{ + hud::bag::{BackgroundIds, InventoryScroller}, + ui::{ + fonts::Fonts, + slot::{ContentSize, SlotMaker}, + ImageFrame, ItemTooltip, ItemTooltipManager, ItemTooltipable, + }, +}; + +use super::{ + img_ids::{Imgs, ImgsRot}, + item_imgs::ItemImgs, + slots::{SlotManager, TradeSlot}, + TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN, +}; pub struct State { ids: Ids, @@ -99,17 +102,18 @@ impl<'a> Trade<'a> { } } } + const MAX_TRADE_SLOTS: usize = 16; impl<'a> Trade<'a> { fn background(&mut self, state: &mut ConrodState<'_, State>, ui: &mut UiCell<'_>) { - Image::new(self.imgs.inv_bg_bag) - .w_h(424.0, 708.0) - .middle() + Image::new(self.imgs.inv_middle_bg_bag) + .w_h(424.0, 500.0) .color(Some(UI_MAIN)) + .mid_bottom_with_margin_on(ui.window, 281.0) .set(state.ids.bg, ui); - Image::new(self.imgs.inv_frame_bag) - .w_h(424.0, 708.0) + Image::new(self.imgs.inv_middle_frame) + .w_h(424.0, 500.0) .middle_of(state.ids.bg) .color(Some(UI_HIGHLIGHT_0)) .set(state.ids.bg_frame, ui); @@ -173,9 +177,9 @@ impl<'a> Trade<'a> { let inventory = inventories.get(entity)?; // Alignment for Grid - let mut alignment = Rectangle::fill_with([200.0, 340.0], color::TRANSPARENT); + let mut alignment = Rectangle::fill_with([200.0, 180.0], color::TRANSPARENT); if !ours { - alignment = alignment.top_left_with_margins_on(state.ids.bg, 180.0, 46.5); + alignment = alignment.top_left_with_margins_on(state.ids.bg, 180.0, 32.5); } else { alignment = alignment.right_from(state.ids.inv_alignment[1 - who], 0.0); } @@ -198,9 +202,27 @@ impl<'a> Trade<'a> { .unwrap_or_else(|| format!("Player {}", who)); let offer_header = self - .localized_strings - .get("hud.trade.persons_offer") - .replace("{playername}", &name); + .client + .player_list() + .get(&uid) + .map(|_| { + self.localized_strings + .get("hud.trade.your_offer") + .to_owned() + }) + .or_else(|| { + self.client + .state() + .read_storage::() + .get(entity) + .map(|_| { + self.localized_strings + .get("hud.trade.their_offer") + .to_owned() + }) + }) + .unwrap_or_else(|| format!("Player {}", who)); + Text::new(&offer_header) .up_from(state.ids.inv_alignment[who], 20.0) .font_id(self.fonts.cyri.conrod_id) @@ -214,7 +236,7 @@ impl<'a> Trade<'a> { .get("hud.trade.has_accepted") .replace("{playername}", &name); Text::new(&accept_indicator) - .down_from(state.ids.inv_alignment[who], 20.0) + .down_from(state.ids.inv_alignment[who], 50.0) .font_id(self.fonts.cyri.conrod_id) .font_size(self.fonts.cyri.scale(20)) .color(Color::Rgba( @@ -461,7 +483,7 @@ impl<'a> Trade<'a> { .w_h(31.0 * 5.0, 12.0 * 2.0) .hover_image(self.imgs.button_hover) .press_image(self.imgs.button_press) - .bottom_left_with_margins_on(state.ids.bg, 80.0, 60.0) + .bottom_left_with_margins_on(state.ids.bg, 110.0, 47.0) .label(self.localized_strings.get("hud.trade.accept")) .label_font_size(self.fonts.cyri.scale(14)) .label_color(TEXT_COLOR) From abf5a7e1367cd78a108fc0e69dbef9764ccf00cc Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Fri, 6 Aug 2021 21:57:34 +0300 Subject: [PATCH 098/155] Add option to toggle egui debug --- voxygen/src/run.rs | 4 +++- voxygen/src/settings/interface.rs | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/voxygen/src/run.rs b/voxygen/src/run.rs index ed21b503da..e704baf0bc 100644 --- a/voxygen/src/run.rs +++ b/voxygen/src/run.rs @@ -196,7 +196,9 @@ fn handle_main_events_cleared( last.render(&mut drawer, &global_state.settings); #[cfg(feature = "egui-ui")] - if last.egui_enabled() && global_state.settings.interface.toggle_debug { + if last.egui_enabled() + && global_state.settings.interface.toggle_debug + && global_state.settings.interface.toggle_egui_debug { drawer.draw_egui(&mut global_state.egui_state.platform, scale_factor); } }; diff --git a/voxygen/src/settings/interface.rs b/voxygen/src/settings/interface.rs index 7f20f8b5bc..673caa753a 100644 --- a/voxygen/src/settings/interface.rs +++ b/voxygen/src/settings/interface.rs @@ -10,6 +10,7 @@ use vek::*; #[serde(default)] pub struct InterfaceSettings { pub toggle_debug: bool, + pub toggle_egui_debug: bool, pub toggle_hitboxes: bool, pub toggle_chat: bool, pub sct: bool, @@ -46,6 +47,7 @@ impl Default for InterfaceSettings { fn default() -> Self { Self { toggle_debug: false, + toggle_egui_debug: false, toggle_hitboxes: false, toggle_chat: true, sct: true, From 16c72b866763ce6cde01a220e4e84e76060c375b Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Fri, 6 Aug 2021 22:22:05 +0300 Subject: [PATCH 099/155] Add hotkey to toggle Egui Debug --- assets/voxygen/i18n/en/gameinput.ron | 1 + voxygen/src/controller.rs | 4 ++++ voxygen/src/game_input.rs | 3 +++ voxygen/src/hud/mod.rs | 6 ++++++ voxygen/src/settings/control.rs | 2 ++ voxygen/src/settings/gamepad.rs | 4 ++++ 6 files changed, 20 insertions(+) diff --git a/assets/voxygen/i18n/en/gameinput.ron b/assets/voxygen/i18n/en/gameinput.ron index ab2605acb3..316b489ace 100644 --- a/assets/voxygen/i18n/en/gameinput.ron +++ b/assets/voxygen/i18n/en/gameinput.ron @@ -21,6 +21,7 @@ "gameinput.help": "Toggle Help Window", "gameinput.toggleinterface": "Toggle Interface", "gameinput.toggledebug": "Toggle FPS and Debug Info", + "gameinput.toggle_egui_debug": "Toggle EGUI Debug Info", "gameinput.togglechat": "Toggle Chat", "gameinput.screenshot": "Take Screenshot", "gameinput.toggleingameui": "Toggle Nametags", diff --git a/voxygen/src/controller.rs b/voxygen/src/controller.rs index b9eec9aa82..b64860e9e0 100644 --- a/voxygen/src/controller.rs +++ b/voxygen/src/controller.rs @@ -150,6 +150,10 @@ impl From<&crate::settings::GamepadSettings> for ControllerSettings { map.entry(settings.game_buttons.toggle_debug) .or_default() .push(GameInput::ToggleDebug); + #[cfg(feature = "egui-ui")] + map.entry(settings.game_buttons.toggle_debug) + .or_default() + .push(GameInput::ToggleEguiDebug); map.entry(settings.game_buttons.toggle_chat) .or_default() .push(GameInput::ToggleChat); diff --git a/voxygen/src/game_input.rs b/voxygen/src/game_input.rs index db75015f1b..6756330cd7 100644 --- a/voxygen/src/game_input.rs +++ b/voxygen/src/game_input.rs @@ -106,6 +106,9 @@ pub enum GameInput { Help, #[strum(serialize = "gameinput.toggledebug")] ToggleDebug, + #[cfg(feature = "egui-ui")] + #[strum(serialize = "gameinput.toggle_egui_debug")] + ToggleEguiDebug, #[strum(serialize = "gameinput.togglechat")] ToggleChat, #[strum(serialize = "gameinput.fullscreen")] diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 92fa442b93..342c94023c 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -3656,6 +3656,12 @@ impl Hud { self.show.debug = global_state.settings.interface.toggle_debug; true }, + #[cfg(feature = "egui-ui")] + GameInput::ToggleEguiDebug if state => { + global_state.settings.interface.toggle_egui_debug = + !global_state.settings.interface.toggle_egui_debug; + true + }, GameInput::ToggleChat if state => { global_state.settings.interface.toggle_chat = !global_state.settings.interface.toggle_chat; diff --git a/voxygen/src/settings/control.rs b/voxygen/src/settings/control.rs index 213a82f1f3..faa53ba8f1 100644 --- a/voxygen/src/settings/control.rs +++ b/voxygen/src/settings/control.rs @@ -144,6 +144,8 @@ impl ControlSettings { GameInput::Help => KeyMouse::Key(VirtualKeyCode::F1), GameInput::ToggleInterface => KeyMouse::Key(VirtualKeyCode::F2), GameInput::ToggleDebug => KeyMouse::Key(VirtualKeyCode::F3), + #[cfg(feature = "egui-ui")] + GameInput::ToggleEguiDebug => KeyMouse::Key(VirtualKeyCode::F7), GameInput::ToggleChat => KeyMouse::Key(VirtualKeyCode::F5), GameInput::Fullscreen => KeyMouse::Key(VirtualKeyCode::F11), GameInput::Screenshot => KeyMouse::Key(VirtualKeyCode::F4), diff --git a/voxygen/src/settings/gamepad.rs b/voxygen/src/settings/gamepad.rs index 1fe8b25739..4cc7d0e78d 100644 --- a/voxygen/src/settings/gamepad.rs +++ b/voxygen/src/settings/gamepad.rs @@ -77,6 +77,8 @@ pub mod con_settings { pub help: Button, pub toggle_interface: Button, pub toggle_debug: Button, + #[cfg(feature = "egui-ui")] + pub toggle_egui_debug: Button, pub toggle_chat: Button, pub fullscreen: Button, pub screenshot: Button, @@ -168,6 +170,8 @@ pub mod con_settings { help: Button::Simple(GilButton::Unknown), toggle_interface: Button::Simple(GilButton::Unknown), toggle_debug: Button::Simple(GilButton::Unknown), + #[cfg(feature = "egui-ui")] + toggle_egui_debug: Button::Simple(GilButton::Unknown), toggle_chat: Button::Simple(GilButton::Unknown), fullscreen: Button::Simple(GilButton::Unknown), screenshot: Button::Simple(GilButton::Unknown), From 3411ccc7ee620e432e5bb431a01f0cfb5acffec5 Mon Sep 17 00:00:00 2001 From: juliancoffee Date: Fri, 6 Aug 2021 22:53:51 +0300 Subject: [PATCH 100/155] Shift egui debug window right --- voxygen/egui/src/lib.rs | 4 +++- voxygen/src/run.rs | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/voxygen/egui/src/lib.rs b/voxygen/egui/src/lib.rs index d851f714c3..c92f120c68 100644 --- a/voxygen/egui/src/lib.rs +++ b/voxygen/egui/src/lib.rs @@ -14,7 +14,7 @@ use core::mem; use egui::{ plot::{Plot, Value}, widgets::plot::Curve, - CollapsingHeader, Color32, Grid, Label, ScrollArea, Slider, Ui, Window, + CollapsingHeader, Color32, Grid, Label, Pos2, ScrollArea, Slider, Ui, Window, }; fn two_col_row(ui: &mut Ui, label: impl Into