From 75d109ef6e5f4176be5c89b4db7ebb01b9b64549 Mon Sep 17 00:00:00 2001 From: Samuel Lopes Mastrofrancisco Date: Sat, 21 May 2022 00:11:04 +0000 Subject: [PATCH 001/229] Update common.ron pt_BR. Added some variables and edited a few. --- assets/voxygen/i18n/pt_BR/common.ron | 33 ++++++++++++++++++---------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/assets/voxygen/i18n/pt_BR/common.ron b/assets/voxygen/i18n/pt_BR/common.ron index 5513b5aa31..04eee34157 100644 --- a/assets/voxygen/i18n/pt_BR/common.ron +++ b/assets/voxygen/i18n/pt_BR/common.ron @@ -37,6 +37,8 @@ "common.automatic": "Auto", "common.random": "Aleatório", "common.empty": "Vazio", + "common.confirm": "Confirmar", + "common.delete_server": "Deletar Servidor", // Títulos da Janela de Configurações "common.interface_settings": "Configurações de Interface", @@ -61,10 +63,11 @@ O cliente está atualizado?"#, "common.species.danari": "Danari", "common.weapons.axe": "Machado", - "common.weapons.sword": "Espada", + "common.weapons.dagger": "Adaga", "common.weapons.greatsword": "Espada Larga", "common.weapons.shortswords": "Espada Curta", - "common.weapons.staff": "Cajado", + "common.weapons.sword": "Espada", + "common.weapons.staff": "Cajado de Fogo", "common.weapons.bow": "Arco", "common.weapons.hammer": "Martelo", "common.weapons.general": "Combate Geral", @@ -77,11 +80,12 @@ O cliente está atualizado?"#, "common.weapons.axe_simple": "Machado Simples", "common.weapons.bow_simple": "Arco Simples", "common.weapons.unique": "Único", - "common.tool.debug": "Debug", + "common.tool.debug": "Depuração", "common.tool.farming": "Ferramenta Agrícola", "common.tool.pick": "Picareta", "common.tool.mining": "Mineração", "common.kind.modular_component": "Componente Modular", + "common.kind.modular_component_partial": "Componente", "common.kind.glider": "Planador", "common.kind.consumable": "Consumível", "common.kind.throwable": "Arremessável", @@ -91,21 +95,24 @@ O cliente está atualizado?"#, "common.hands.one": "Uma mão", "common.hands.two": "Duas mãos", - "common.rand_appearance": "Aparência e nome aleatórios", + "common.rand_appearance": "Aparência aleatória", "common.rand_name": "Nome Aleatório", - "common.stats.combat_rating": "CR", + "common.stats.combat_rating": "Nivel de Combate", "common.stats.power": "Poder", "common.stats.speed": "Velocidade", "common.stats.poise": "Veneno", - "common.stats.crit_chance": "Chance de Crit", - "common.stats.crit_mult": "Multiplicador de Crit", + "common.stats.range": "Alcance", + "common.stats.energy_efficiency": "Eficiência Energética", + "common.stats.buff_strength": "Buff de força", + "common.stats.crit_chance": "Chance de Crítico", + "common.stats.crit_mult": "Multiplicador de Crítico", "common.stats.armor": "Armadura", - "common.stats.poise_res":"Resist Paralisia", - "common.stats.energy_max": "Energia Max", - "common.stats.energy_reward": "Captura de energia", - "common.stats.crit_power": "Crit Power", - "common.stats.stealth": "Stealth", + "common.stats.poise_res":"Resistência a Atordoamento", + "common.stats.energy_max": "Energia Máxima", + "common.stats.energy_reward": "Recompensa de Energia", + "common.stats.crit_power": "Poder Crítico", + "common.stats.stealth": "Furtividade", "common.stats.slots": "Espaços", "common.material.metal": "Metal", @@ -113,6 +120,8 @@ O cliente está atualizado?"#, "common.material.stone": "Pedra", "common.material.cloth": "Tecido", "common.material.hide": "Couro", + + "common.sprite.chest": "Baú", }, From 88eaef3145ef1e4f65e843888d297a4f3abf0459 Mon Sep 17 00:00:00 2001 From: Euryn Date: Sun, 22 May 2022 10:06:36 +0000 Subject: [PATCH 002/229] Add Thai translation --- CHANGELOG.md | 1 + assets/common/credits.ron | 9 +- assets/voxygen/font/Sarabun-Regular.ttf | 3 + assets/voxygen/font/Sarabun-license.txt | 93 +++++++ assets/voxygen/i18n/th_TH/_manifest.ron | 32 +++ assets/voxygen/i18n/th_TH/buff.ron | 54 ++++ assets/voxygen/i18n/th_TH/char_selection.ron | 32 +++ assets/voxygen/i18n/th_TH/common.ron | 130 +++++++++ assets/voxygen/i18n/th_TH/esc_menu.ron | 13 + assets/voxygen/i18n/th_TH/gameinput.ron | 77 ++++++ assets/voxygen/i18n/th_TH/hud/bag.ron | 49 ++++ assets/voxygen/i18n/th_TH/hud/char_window.ron | 21 ++ assets/voxygen/i18n/th_TH/hud/chat.ron | 49 ++++ assets/voxygen/i18n/th_TH/hud/crafting.ron | 53 ++++ assets/voxygen/i18n/th_TH/hud/group.ron | 24 ++ assets/voxygen/i18n/th_TH/hud/map.ron | 41 +++ assets/voxygen/i18n/th_TH/hud/misc.ron | 63 +++++ assets/voxygen/i18n/th_TH/hud/sct.ron | 14 + assets/voxygen/i18n/th_TH/hud/settings.ron | 145 ++++++++++ assets/voxygen/i18n/th_TH/hud/skills.ron | 258 ++++++++++++++++++ assets/voxygen/i18n/th_TH/hud/social.ron | 22 ++ assets/voxygen/i18n/th_TH/hud/trade.ron | 32 +++ assets/voxygen/i18n/th_TH/main.ron | 154 +++++++++++ assets/voxygen/i18n/th_TH/npc.ron | 250 +++++++++++++++++ assets/voxygen/i18n/th_TH/template.ron | 12 + 25 files changed, 1630 insertions(+), 1 deletion(-) create mode 100644 assets/voxygen/font/Sarabun-Regular.ttf create mode 100644 assets/voxygen/font/Sarabun-license.txt create mode 100644 assets/voxygen/i18n/th_TH/_manifest.ron create mode 100644 assets/voxygen/i18n/th_TH/buff.ron create mode 100644 assets/voxygen/i18n/th_TH/char_selection.ron create mode 100644 assets/voxygen/i18n/th_TH/common.ron create mode 100644 assets/voxygen/i18n/th_TH/esc_menu.ron create mode 100644 assets/voxygen/i18n/th_TH/gameinput.ron create mode 100644 assets/voxygen/i18n/th_TH/hud/bag.ron create mode 100644 assets/voxygen/i18n/th_TH/hud/char_window.ron create mode 100644 assets/voxygen/i18n/th_TH/hud/chat.ron create mode 100644 assets/voxygen/i18n/th_TH/hud/crafting.ron create mode 100644 assets/voxygen/i18n/th_TH/hud/group.ron create mode 100644 assets/voxygen/i18n/th_TH/hud/map.ron create mode 100644 assets/voxygen/i18n/th_TH/hud/misc.ron create mode 100644 assets/voxygen/i18n/th_TH/hud/sct.ron create mode 100644 assets/voxygen/i18n/th_TH/hud/settings.ron create mode 100644 assets/voxygen/i18n/th_TH/hud/skills.ron create mode 100644 assets/voxygen/i18n/th_TH/hud/social.ron create mode 100644 assets/voxygen/i18n/th_TH/hud/trade.ron create mode 100644 assets/voxygen/i18n/th_TH/main.ron create mode 100644 assets/voxygen/i18n/th_TH/npc.ron create mode 100644 assets/voxygen/i18n/th_TH/template.ron diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b1ea72812..46e0cc2882 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add stealth stat on Bag UI - Water caves - Modular weapons +- Added Thai translation ### Changed diff --git a/assets/common/credits.ron b/assets/common/credits.ron index 8ad77d49e4..4a54dad80a 100644 --- a/assets/common/credits.ron +++ b/assets/common/credits.ron @@ -101,7 +101,14 @@ license_link: "https://creativecommons.org/licenses/by-sa/3.0/", modifications: "Added additional characters.", notes: "Derived from Wizard", - )], + ), ( + name: "Sarabun", + authors: ["Suppakit Chalermlarp"], + asset_path: "voxygen/font/Sarabun-Regular.ttf", + // License appears to be satisfied by inclusion of its text file. + license: "OFL", + license_link: "https://scripts.sil.org/OFL", + ),], other_art: [], /// Entry format: /// ``` diff --git a/assets/voxygen/font/Sarabun-Regular.ttf b/assets/voxygen/font/Sarabun-Regular.ttf new file mode 100644 index 0000000000..b4d51dc427 --- /dev/null +++ b/assets/voxygen/font/Sarabun-Regular.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8150084e25734e6f31696c57ff009f5564efa09d295848b717d9e2328c0311d +size 83080 diff --git a/assets/voxygen/font/Sarabun-license.txt b/assets/voxygen/font/Sarabun-license.txt new file mode 100644 index 0000000000..a7d3a12618 --- /dev/null +++ b/assets/voxygen/font/Sarabun-license.txt @@ -0,0 +1,93 @@ +Copyright 2018 The Sarabun Project Authors (https://github.com/cadsondemak/Sarabun) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/assets/voxygen/i18n/th_TH/_manifest.ron b/assets/voxygen/i18n/th_TH/_manifest.ron new file mode 100644 index 0000000000..f6509a4c62 --- /dev/null +++ b/assets/voxygen/i18n/th_TH/_manifest.ron @@ -0,0 +1,32 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + metadata: ( + language_name: "Thai", + language_identifier: "th_TH", + ), + convert_utf8_to_ascii: false, + fonts: { + "opensans": Font ( + asset_key: "voxygen.font.Sarabun-Regular", + scale_ratio: 1.0, + ), + "metamorph": Font ( + asset_key: "voxygen.font.Sarabun-Regular", + scale_ratio: 1.0, + ), + "alkhemi": Font ( + asset_key: "voxygen.font.Sarabun-Regular", + scale_ratio: 1.0, + ), + "wizard": Font ( + asset_key: "voxygen.font.Sarabun-Regular", + scale_ratio: 1.0, + ), + "cyri": Font ( + asset_key: "voxygen.font.Sarabun-Regular", + scale_ratio: 1.0, + ), + } +) diff --git a/assets/voxygen/i18n/th_TH/buff.ron b/assets/voxygen/i18n/th_TH/buff.ron new file mode 100644 index 0000000000..8e4d85b9fa --- /dev/null +++ b/assets/voxygen/i18n/th_TH/buff.ron @@ -0,0 +1,54 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + string_map: { + // Buffs + "buff.remove": "กดเพื่อปิด", + "buff.title.missing": "ไม่มีชื่อ", + "buff.desc.missing": "ไม่มีคำบรรยาย", + "buff.title.heal": "สถานะฟื้นฟู", + "buff.desc.heal": "ฟื้นฟูพลังชีวิตเป็นช่วง ๆ", + "buff.title.potion": "ยา", + "buff.desc.potion": "กำลังดื่มด่ำกับยา...", + "buff.title.saturation": "สถานะท้องอิ่ม", + "buff.desc.saturation": "พื้นฟูพลังชีวิตเป็นช่วง ๆ เมื่อทานอาหาร", + "buff.title.campfire_heal": "พักผ่อน ณ แคมป์ไฟ", + "buff.desc.campfire_heal": "เมื่อนั่งพักที่แคมป์ไฟจะช่วยพื้นฟูพลังชีวิต {rate}% ต่อวินาที", + "buff.title.invulnerability": "สถานะอมตะ", + "buff.desc.invulnerability": "ไม่เสียพลังชีวิตเมื่อถูกโจมตี", + "buff.title.protectingward": "สถานะพรคุ้มครอง", + "buff.desc.protectingward": "พระกำลังคุ้มครอง เสียพลังชีวิตเล็กน้อยเมื่อถูกโจมตี", + "buff.title.frenzied": "สถานะบ้าคลั่ง", + "buff.desc.frenzied": "วิ่งเร็วขึ้นอย่างมาก ความเสียหลายเล้กน้อยไม่สามารถหยุดคุณได้", + "buff.title.hastened": "สถานะเครื่องติด", + "buff.desc.hastened": "ความเร็วในการโจมตีและเคลื่อนที่เพิ่มขึ้น", + // Debuffs + "buff.title.bleed": "สถานะเลือดไหล", + "buff.desc.bleed": "ได้รับความเสียหายแบบธรรมดา ๆ", + "buff.title.cursed": "สถานะต้องสาป", + "buff.desc.cursed": "ฉันขอฉาบแก!", + "buff.title.burn": "สถานะไฟลุก", + "buff.desc.burn": "ก้าวแรกไม่เป็นไร ก้าวต่อไป...", + "buff.title.crippled": "สถานะขาหัก", + "buff.desc.crippled": "ขาได้รับบาดเจ็บ เคลื่อนไหวได้ช้าลง", + "buff.title.frozen": "สถานะแช่แข็ง", + "buff.desc.frozen": "ความเร็วในการโจมตีและเคลื่อนที่ลดลง", + "buff.title.wet": "สถานะเปียก", + "buff.desc.wet": "พื้นลื่นมาก ๆ ระวังหกล้ม", + "buff.title.ensnared": "สถานะพฤกษาบ่วงรัด", + "buff.desc.ensnared": "เถาวัลย์กำลังรัดขา ขยับไปไหนไม่ได้เลย", + // Buffs stats + "buff.stat.health": "ฟื้นฟูพลังชีวิต {str_total} หน่วย", + "buff.stat.increase_max_energy": "เพิ่มพลังงานสูงสุด {strength} หน่วย", + "buff.stat.increase_max_health": "เพิ่มพลังชีวิตสูงสุด {strength} หน่วย", + "buff.stat.invulnerability": "มอบ สถานะอมตา", + // Text + "buff.text.over_seconds": "ในช่วงเวลา {dur_secs} วินาที", + "buff.text.for_seconds": "เป็นเวลา {dur_secs} วินาที", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/th_TH/char_selection.ron b/assets/voxygen/i18n/th_TH/char_selection.ron new file mode 100644 index 0000000000..5dc52f5f5c --- /dev/null +++ b/assets/voxygen/i18n/th_TH/char_selection.ron @@ -0,0 +1,32 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + string_map: { + "char_selection.loading_characters": "อยู่ระหว่างการโหลดตัวละคร ...", + "char_selection.delete_permanently": "ลบตัวละครทิ้งหรือไม่?", + "char_selection.deleting_character": "อยู่ระหว่างการลบตัวละคร ...", + "char_selection.change_server": "เปลี่ยนเซิร์ฟเวอร์", + "char_selection.enter_world": "เข้าสู่โลก", + "char_selection.logout": "ออกจากเกม", + "char_selection.create_new_character": "สร้างตัวละครใหม่", + "char_selection.creating_character": "อยู่ระหว่างการสร้างตัวละคร...", + "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.eye_color": "สีตา", + "char_selection.skin": "ผิว", + "char_selection.eyeshape": "รายละเอียดดวงตา", + "char_selection.accessories": "เครื่องประดับ", + "char_selection.create_info_name": "ตัวละครต้องมีชื่อนะ!", + "char_selection.version_mismatch": "คำเตือน! เวอร์ชั่นเกมของคุณกับของเซิร์ฟเวอร์ไม่ตรงกัน กรุณาอัปเดทเกม", + }, + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/th_TH/common.ron b/assets/voxygen/i18n/th_TH/common.ron new file mode 100644 index 0000000000..913fb126e4 --- /dev/null +++ b/assets/voxygen/i18n/th_TH/common.ron @@ -0,0 +1,130 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + 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.chat": "พูดคุย", + "common.resume": "เริ่มเกมต่อ", + "common.characters": "ตัวละคร", + "common.close": "ปิด", + "common.yes": "ตกลก", + "common.no": "ปฏิเสธ", + "common.back": "กลับ", + "common.create": "สร้าง", + "common.okay": "โอเค", + "common.add": "เพิ่ม", + "common.accept": "ยอมรับ", + "common.decline": "ปฏิเสธ", + "common.disclaimer": "ระวัง", + "common.cancel": "ยกเลิก", + "common.none": "ไม่มี", + "common.error": "ผิดพลาด", + "common.fatal_error": "ผิดพลาดรุนแรง", + "common.you": "คุณ", + "common.automatic": "ออโต้", + "common.random": "สุ่ม", + "common.empty": "ว่าง", + "common.confirm": "ตกลง", + "common.delete_server": "ลบเซิร์ฟเวอร์", + + // Settings Window title + "common.interface_settings": "ตั้งค่าหน้าจอ", + "common.gameplay_settings": "ตั้งค่าเกมเพลย์", + "common.controls_settings": "ตั้งค่าปุ่มควบคุม", + "common.video_settings": "ตั้งค่ากราฟฟิก", + "common.sound_settings": "ตั้งค่าเสียง", + "common.language_settings": "ตั้งค่าภาษา", + "common.chat_settings": "ตั้งค่าการสนทนา", + + // Message when connection to the server is lost + "common.connection_lost": r#"โอ๊ะโอ้ว การเชื่อมต่อจะถูกจากเซิร์ฟเวอร์ +อาจะเป็นเพราะเซิร์ฟเวอร์ถูกปิด +หรือเพราะตัวเกมไม่ใช่เวอร์ชั่นล่าสุด"#, + + + "common.species.orc": "ออร์ค", + "common.species.human": "มนุษย์", + "common.species.dwarf": "คนแคระ", + "common.species.elf": "เอลฟ์", + "common.species.undead": "ภูตผี", + "common.species.danari": "ดานาริ", + + "common.weapons.axe": "ขวาน", + "common.weapons.dagger": "มีดสั้น", + "common.weapons.greatsword": "ดาบใหญ่", + "common.weapons.shortswords": "ดาบสั้น", + "common.weapons.sword": "ดาบ", + "common.weapons.staff": "คถาอัคนี", + "common.weapons.bow": "ธนู", + "common.weapons.hammer": "ค้อน", + "common.weapons.general": "ทั่วไป", + "common.weapons.sceptre": "คถาอภิรักษ์", + "common.weapons.shield": "โล่", + "common.weapons.spear": "หอก", + "common.weapons.hammer_simple": "ค้อนอย่างง่าย", + "common.weapons.sword_simple": "ดาบอย่างง่าย", + "common.weapons.staff_simple": "คถาอัคนีอย่างง่าย", + "common.weapons.axe_simple": "ขวานอย่างง่าย", + "common.weapons.bow_simple": "ธนูอย่างง่าย", + "common.weapons.unique": "แปลกไม่เหมือนใคร", + "common.tool.debug": "ดีบัค", + "common.tool.farming": "เครื่องมือการเกษตร", + "common.tool.pick": "พลั่ว", + "common.tool.mining": "การขุดหิน", + "common.kind.modular_component": "ส่วนประกอบ", + "common.kind.modular_component_partial": "วัสดุ", + "common.kind.glider": "เครื่องร่อน", + "common.kind.consumable": "ของใช้", + "common.kind.throwable": "ของใช้ชนิดปา", + "common.kind.utility": "อุปกรณ์ของใช้", + "common.kind.ingredient": "วัตถุดิบ", + "common.kind.lantern": "ตะเกียง", + "common.hands.one": "จับมือเดียว", + "common.hands.two": "จับสองมือ", + + "common.rand_appearance": "สุ่มภาพลักษณ์", + "common.rand_name": "สุ่มชื่อ", + + "common.stats.combat_rating": "ค่าอุปกรณ์", + "common.stats.power": "พลังโจมตี", + "common.stats.speed": "ความเร็ว", + "common.stats.poise": "ค่าทรงตัว", + "common.stats.range": "ระยะโจมตี", + "common.stats.energy_efficiency": "ประสิทธิภาพพลังงาน", + "common.stats.buff_strength": "เสริมพลังความแข็งแกร่ง", + "common.stats.crit_chance": "โอกาสคริติคอล", + "common.stats.crit_mult": "ความรุนแรงคริติคอล", + "common.stats.armor": "เกราะ", + "common.stats.poise_res":"ความคงทน", + "common.stats.energy_max": "พลังงานสูงสุด", + "common.stats.energy_reward": "อัตราฟื้นฟูพลังงาน", + "common.stats.crit_power": "ความรุนแรงของคริติคอล", + "common.stats.stealth": "ลดการถูกตรวจจับ", + "common.stats.slots": "จำนวนช่อง", + + "common.material.metal": "โลหะ", + "common.material.wood": "ไม้", + "common.material.stone": "หิน", + "common.material.cloth": "ผ้า", + "common.material.hide": "หนังสัตว์", + + "common.sprite.chest": "กล่องสมบัติ", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/th_TH/esc_menu.ron b/assets/voxygen/i18n/th_TH/esc_menu.ron new file mode 100644 index 0000000000..70527325ba --- /dev/null +++ b/assets/voxygen/i18n/th_TH/esc_menu.ron @@ -0,0 +1,13 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + string_map: { + "esc_menu.logout": "ออกจากระบบ", + "esc_menu.quit_game": "ออกจากเกม", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/th_TH/gameinput.ron b/assets/voxygen/i18n/th_TH/gameinput.ron new file mode 100644 index 0000000000..56fef5e92c --- /dev/null +++ b/assets/voxygen/i18n/th_TH/gameinput.ron @@ -0,0 +1,77 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + string_map: { + "gameinput.primary": "โจมตีปกติ", + "gameinput.secondary": "โจมตีพิเศษ", + "gameinput.block": "บล็อค", + "gameinput.slot1": "แถบของใช้ช่องที่ 1", + "gameinput.slot2": "แถบของใช้ช่องที่ 2", + "gameinput.slot3": "แถบของใช้ช่องที่ 3", + "gameinput.slot4": "แถบของใช้ช่องที่ 4", + "gameinput.slot5": "แถบของใช้ช่องที่ 5", + "gameinput.slot6": "แถบของใช้ช่องที่ 6", + "gameinput.slot7": "แถบของใช้ช่องที่ 7", + "gameinput.slot8": "แถบของใช้ช่องที่ 8", + "gameinput.slot9": "แถบของใช้ช่องที่ 9", + "gameinput.slot10": "แถบของใช้ช่องที่ 10", + "gameinput.swaploadout": "สลับอุปกรณ์สวมใส่", + "gameinput.togglecursor": "เปิด/ปิดเมาส์", + "gameinput.help": "เปิด/ปิดข้อความช่วยเหลือ", + "gameinput.toggleinterface": "เปิด/ปิดหน้าต่างข้อมูล", + "gameinput.toggledebug": "เปิด/ปิดข้อมูลดีบัค", + "gameinput.toggle_egui_debug": "เปิด/ปิดข้อมูลดีบัคของ GUI", + "gameinput.togglechat": "เปิด/ปิดช่องสนทนา", + "gameinput.screenshot": "ถ่ายภาพหน้าจอ", + "gameinput.toggleingameui": "เปิด/ปิดชื่อผู้เล่น", + "gameinput.fullscreen": "ใช้โหมด Fullscreen", + "gameinput.moveforward": "เดินหน้า", + "gameinput.moveleft": "เดินทางซ้าย", + "gameinput.moveright": "เดินทางขวา", + "gameinput.moveback": "ถอยหลัง", + "gameinput.jump": "กระโดด", + "gameinput.glide": "ใช้เครื่องร่อน", + "gameinput.roll": "กลิ้ง", + "gameinput.climb": "ปีน", + "gameinput.climbdown": "ปีนลง", + "gameinput.wallleap": "กระโดดข้ามกำแพง", + "gameinput.togglelantern": "จุด/ดับตะเกียง", + "gameinput.mount": "ขี่สัตว์เลี้ยง", + "gameinput.chat": "สนทนากับผู้เล่น", + "gameinput.command": "คำสั่ง", + "gameinput.escape": "หนีจากพื้นที่", + "gameinput.map": "แผนที่", + "gameinput.bag": "กระเป๋า", + "gameinput.trade": "แลกของ", + "gameinput.social": "สังคม", + "gameinput.sit": "นั่ง", + "gameinput.spellbook": "หนังสือเวทย์มนต์", + "gameinput.settings": "การตั้งค่า", + "gameinput.respawn": "เกิดใหม่", + "gameinput.charge": "ชสร์ต", + "gameinput.togglewield": "สลับมือ", + "gameinput.interact": "สัมผัสสิ่งของ", + "gameinput.freelook": "ปลดล็อคกล้อง", + "gameinput.autowalk": "เดินหน้าอัตโนมัต", + "gameinput.cameraclamp": "ล็อคหน้าจอ", + "gameinput.dance": "เต้น", + "gameinput.select": "เลือกสิ่งต่าง ๆ", + "gameinput.acceptgroupinvite": "ยอมรับคำเชิญเข้าปาร์ตี้", + "gameinput.declinegroupinvite": "ปฏิเสธคำเชิญเข้าปาร์ตี้", + "gameinput.cyclecamera": "หมุนมุมกล้อง", + "gameinput.crafting": "สร้างสิ่งของ", + "gameinput.fly": "บิน", + "gameinput.sneak": "ย่อง", + "gameinput.swimdown": "ดำน้ำ", + "gameinput.swimup": "ขึ้นสู่ผิวน้ำ", + "gameinput.mapzoomin": "ซูมเข้าแผนที่", + "gameinput.mapzoomout": "ซูมออกแผนที่", + "gameinput.greet": "ทักทาย", + "gameinput.map.locationmarkerbutton": "ปักหมุดในแผนที่" + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/th_TH/hud/bag.ron b/assets/voxygen/i18n/th_TH/hud/bag.ron new file mode 100644 index 0000000000..86467a01ee --- /dev/null +++ b/assets/voxygen/i18n/th_TH/hud/bag.ron @@ -0,0 +1,49 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + string_map: { + // Inventory + "hud.bag.inventory": "สัมภาระของ {playername}", + "hud.bag.stats_title": "ข้อมูลสถานะของ {playername}", + "hud.bag.exp": "ค่าประสบการณ์", + "hud.bag.armor": "เกราะ", + "hud.bag.stats": "สถานะ", + "hud.bag.head": "ศรีษะ", + "hud.bag.neck": "คอ", + "hud.bag.tabard": "ชุดทับเกราะ", + "hud.bag.shoulders": "ไหล่", + "hud.bag.chest": "ลำตัว", + "hud.bag.hands": "มือ", + "hud.bag.lantern": "ตะเกียง", + "hud.bag.glider": "เครื่องร่อน", + "hud.bag.belt": "เข็มขัด", + "hud.bag.ring": "แหวน", + "hud.bag.back": "หลัง", + "hud.bag.legs": "ขา", + "hud.bag.feet": "เท่า", + "hud.bag.mainhand": "มือข้างถนัด", + "hud.bag.offhand": "มืออีกข้าง", + "hud.bag.inactive_mainhand": "มือข้างถนัด (ไม่ได้ใช้งาน)", + "hud.bag.inactive_offhand": "มืออีกข้าง (ไม่ได้ใช้งาน)", + "hud.bag.swap_equipped_weapons_title": "สลับอาวุธที่ส่วมอยู่", + "hud.bag.swap_equipped_weapons_desc": "กด {key}", + "hud.bag.bag": "กระเป๋า", + "hud.bag.health": "พลังชีวิต", + "hud.bag.energy": "พลังงาน", + "hud.bag.combat_rating": "ค่าอุปกรณ์", + "hud.bag.protection": "ค่าการป้องกัน", + "hud.bag.stun_res": "ความต้านทานต่อการถูกสตัน", + "hud.bag.stealth": "อัตราการตรวจับ", + "hud.bag.combat_rating_desc": "นับจากอุปกรณ์ที่คุณกำลังสวมใส่และพลังชีวิต", + "hud.bag.protection_desc": "ลดความเสียหายที่ได้รับ", + "hud.bag.stun_res_desc": "ความทนทานต่อการถูกสตันเมื่อถูกโจมตี พื้นฟูเหมือนพลังชีวิตและพลังงาน", + "hud.bag.sort_by_name": "จัดเรียงตามชื่อ", + "hud.bag.sort_by_quality": "จัดเรียงตามคุณภาพ", + "hud.bag.sort_by_category": "จัดเรียงตามประเภท", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/th_TH/hud/char_window.ron b/assets/voxygen/i18n/th_TH/hud/char_window.ron new file mode 100644 index 0000000000..110cb95581 --- /dev/null +++ b/assets/voxygen/i18n/th_TH/hud/char_window.ron @@ -0,0 +1,21 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + string_map: { + "character_window.character_name": "ชื่อตัวละคร", + // Character stats + "character_window.character_stats": r#"ความอึด + +ความฟิต + +ความมุ่งมั่น + +พลังป้องกัน +"#, + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/th_TH/hud/chat.ron b/assets/voxygen/i18n/th_TH/hud/chat.ron new file mode 100644 index 0000000000..10fce985c0 --- /dev/null +++ b/assets/voxygen/i18n/th_TH/hud/chat.ron @@ -0,0 +1,49 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + string_map: { + "hud.chat.all": "ทั้งหมด", + "hud.chat.chat_tab_hover_tooltip": "คลิกขวาเพื่อตั้งค่า", + + // Debuff outcomes + "hud.outcome.burning": "เสียชีวิต เพราะถูกไฟคลอก", + "hud.outcome.curse": "เสียชีวิต เพราะถูกคำสาป", + "hud.outcome.bleeding": "เสียชีวิต เพราะเลือดไหล", + "hud.outcome.crippled": "เสียชีวิต เพราะขาหัก", + "hud.outcome.frozen": "เสียชีวิต เพราะกลายเป็นไอศกรีมแช่แข็ง", + + // Chat outputs + "hud.chat.online_msg": "[{name}] กำลังออนไลน์", + "hud.chat.offline_msg": "[{name}] ออกจากเกม", + + "hud.chat.default_death_msg": "[{name}] เสียชีวิต", + "hud.chat.environmental_kill_msg": "name}] เสียชีวิตในสภาพแวดล้อม {environment}", + "hud.chat.fall_kill_msg": "[{name}] เสียชีวิต เพราะตกพื้นแรงไปหน่อย", + "hud.chat.suicide_msg": "[{name}] เสียชีวิต เพราะทำร้ายตัวเอง (???)", + + "hud.chat.died_of_pvp_buff_msg": "[{victim}] ถูกสังหารโดย [{attacker}] จากการใช้ {died_of_buff}", + "hud.chat.pvp_melee_kill_msg": "[{attacker}] สังหาร [{victim}]", + "hud.chat.pvp_ranged_kill_msg": "[{victim}] โดนลั่นหัวคม ๆ โดย [{attacker}]", + "hud.chat.pvp_explosion_kill_msg": "[{victim}] โดนระเบิดเป็นชิ้น ๆ โดย [{attacker}]", + "hud.chat.pvp_energy_kill_msg": "[{attacker}] สังหาร [{victim}] ด้วยไสยเวทย์", + + "hud.chat.died_of_buff_nonexistent_msg": "[{victim}] เสียชีวิต เพราะ {died_of_buff}", + + "hud.chat.died_of_npc_buff_msg": "[{victim}] ถูกสังหารโดย {attacker} จากการใช้ {died_of_buff} น่าเเห็นใจ", + "hud.chat.npc_melee_kill_msg": "{attacker} สังหาร [{victim}] น่าเเห็นใจ", + "hud.chat.npc_ranged_kill_msg": "[{victim}] โดนลั่นหัวคม ๆ โดย {attacker} น่าเห็นใจ", + "hud.chat.npc_explosion_kill_msg": "[{victim}] โดนระเบิดเป็นชิ้น ๆ โดย {attacker} น่าเเห็นใจ", + "hud.chat.npc_energy_kill_msg": "{attacker} สังหาร [{victim}] ด้วยไสยเวทย์ น่าเเห็นใจ", + "hud.chat.npc_other_kill_msg": "[{victim}] ถูกสังหารโดย {attacker} น่าเเห็นใจ", + + "hud.chat.loot_msg": "ได้รับ [{item}]", + "hud.chat.loot_fail": "กระเป๋าเต็มแล้ว", + "hud.chat.goodbye": "ลาก่อน", + "hud.chat.connection_lost": "ถูกตัดการเชื่อมต่อ เชื่อมต่อใหม่ในอีก {time} วินาที", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/th_TH/hud/crafting.ron b/assets/voxygen/i18n/th_TH/hud/crafting.ron new file mode 100644 index 0000000000..8f2d6f00d2 --- /dev/null +++ b/assets/voxygen/i18n/th_TH/hud/crafting.ron @@ -0,0 +1,53 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + string_map: { + "hud.crafting": "สร้างสิ่งของ", + "hud.crafting.recipes": "สูตรการสร้าง", + "hud.crafting.ingredients": "วัตถุดิบ:", + "hud.crafting.craft": "สร้าง", + "hud.crafting.tool_cata": "สิ่งที่ต้องใช้:", + // Crafting Stations + "hud.crafting.req_crafting_station": "สิ่งที่ต้องใช้:", + "hud.crafting.anvil": "ทั่ง", + "hud.crafting.cauldron": "หม้อต้มยา", + "hud.crafting.cooking_pot": "หม้อธรรมดา", + "hud.crafting.crafting_bench": "โต๊ะของช่าง", + "hud.crafting.forge": "เตาหลอม", + "hud.crafting.loom": "กี่ทอผ้า", + "hud.crafting.spinning_wheel": "เครื่องกรอไหม", + "hud.crafting.tanning_rack": "ราวตากหนังสัตว์", + "hud.crafting.salvaging_station": "โต๊ะย่อย", + "hud.crafting.campfire": "แคมป์ไฟ", + // Tabs + "hud.crafting.tabs.all": "ทุกอย่าง", + "hud.crafting.tabs.armor": "เกราะ", + "hud.crafting.tabs.dismantle": "ย่อย", + "hud.crafting.tabs.food": "อาหาร", + "hud.crafting.tabs.glider": "เครื่องร่อย", + "hud.crafting.tabs.potion": "ยา", + "hud.crafting.tabs.tool": "เครื่องมือ", + "hud.crafting.tabs.utility": "อื่น ๆ", + "hud.crafting.tabs.weapon": "อาวุธ", + "hud.crafting.tabs.bag": "กระเป๋า", + "hud.crafting.tabs.processed_material": "แร่หลอมแล้วและอัญมนี", + "hud.crafting.dismantle_title": "การย่อย", + "hud.crafting.dismantle_explanation" : "เอาไปในชี้ที่กระเป๋าเพื่อดูไอเทมที่สามารถย่อยได้\nคลิกสองครั้งเพื่อย่อยไอเทม", + "hud.crafting.modular_desc": "หยิบส่วนประกอบมาวางเพื่อสร้างอาวุธ", + "hud.crafting.mod_weap_prim_slot_title": "ส่วนประกอบหลักของอาวุธ", + "hud.crafting.mod_weap_prim_slot_desc": "นำส่วนประกอบหลักของอาวุธมาวางที่นี้ (เช่น ตัวดาบ, หัวขวาน หรือคันธนู)", + "hud.crafting.mod_weap_sec_slot_title": "ส่วนประกอบรองของอาวุธ", + "hud.crafting.mod_weap_sec_slot_desc": "นำส่วนประกอบรองของอาวุธมาวางที่นี้ (เช่น ด้ามดาบ, ที่จับคันธนู, หรือแกนคถา).", + "hud.crafting.mod_comp_metal_prim_slot_title": "แท่งโลหะ", + "hud.crafting.mod_comp_metal_prim_slot_desc": "นำแท่งโลหะมาวางที่นี้ โลหะบางชนิดไม่สามารถนำมาประกอบเป็นอาวุธได้", + "hud.crafting.mod_comp_wood_prim_slot_title": "ไม้", + "hud.crafting.mod_comp_wood_prim_slot_desc": "นำไม้มาวางที่นี้ ไม้บางชนิดไม่สามารถนำมาประกอบอาวุธได้", + "hud.crafting.mod_comp_sec_slot_title": "สัตว์วัตถุ", + "hud.crafting.mod_comp_sec_slot_desc": "สามารถใช้ชิ้นส่วนสัตว์เพื่อเพิ่มประสิทธิภาพของอาวุธ ชิ้นส่วนจากสัตว์บางชนิดไม่สามารถนำมาใช้เพิ่มประสิทธิภาพได้", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/th_TH/hud/group.ron b/assets/voxygen/i18n/th_TH/hud/group.ron new file mode 100644 index 0000000000..8412fc6be6 --- /dev/null +++ b/assets/voxygen/i18n/th_TH/hud/group.ron @@ -0,0 +1,24 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + string_map: { + "hud.group": "ปาร์ตี้", + "hud.group.invite_to_join": "ผู้เล่น [{name}] ต้องการชวนคุณเข้าปาร์ตี้!", + "hud.group.invite_to_trade": "ผู้เล่น [{name}] ต้องการแลกของกับคุณ", + "hud.group.invite": "เชิญชวน", + "hud.group.kick": "เตะออก", + "hud.group.assign_leader": "มอบตำแหน่งหัวหน้า", + "hud.group.leave": "ออกจากปาร์ตี้", + "hud.group.dead" : "เสียชีวิต", + "hud.group.out_of_range": "อยู่นอกระยะ", + "hud.group.add_friend": "เพิ่มในรานชื่อเพื่อน", + "hud.group.link_group": "เชื่อมปาร์ตี้", + "hud.group.in_menu": "อยู่ในหน้าต่างเมนู", + "hud.group.members": "รายชื่อสมาชิก", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/th_TH/hud/map.ron b/assets/voxygen/i18n/th_TH/hud/map.ron new file mode 100644 index 0000000000..9b5863367f --- /dev/null +++ b/assets/voxygen/i18n/th_TH/hud/map.ron @@ -0,0 +1,41 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + string_map: { + // Map and Questlog + "hud.map.map_title": "แผนที่", + "hud.map.qlog_title": "ภารกิจ", + "hud.map.topo_map": "แผ่นที่ความสูง", + "hud.map.difficulty": "ระดับความยาก", + "hud.map.towns": "หมู่บ้านแขนง", + "hud.map.castles": "ปราสาทแขนง", + "hud.map.dungeons": "ดันเจียนแขนง", + "hud.map.caves": "ถ้ำแขนง", + "hud.map.cave": "ถ้ำเดี่ยว", + "hud.map.peaks": "ภูเขา", + "hud.map.biomes": "เขตภูมิภาค", + "hud.map.voxel_map": "แผนที่ Voxel ", + "hud.map.trees": "ต้นไม้ยักษ์แขนง", + "hud.map.tree": "ต้นไม้ยักษ์เดี่ยว", + "hud.map.town": "หมู่บ้านเดี่ยว", + "hud.map.castle": "ปารสาทเดี่ยว", + "hud.map.dungeon": "ปราสาทเดี่ยว", + "hud.map.difficulty_dungeon": "ดันเจี่ยน\n\nความยาก: {difficulty} ดาว", + "hud.map.drag": "ลาก", + "hud.map.zoom": "ซูม", + "hud.map.mid_click": "ปักหมุด", + "hud.map.recenter": "กลับมาที่ผู้เล่น", + "hud.map.marked_location": "สถานที่ที่ปักหมุด", + "hud.map.marked_location_remove": "กดเพื่อนำออก", + "hud.map.change_map_mode": "เปลี่ยนโหมดแผนที่", + "hud.map.toggle_minimap_voxel": "เปลี่ยนโหมดมินิแมพ", + "hud.map.zoom_minimap_explanation": "ซูมเข้าในมินิแมพเพื่อเพิ่มความคมชัด", + "hud.map.gnarling": "ฐานทัพของเหล่า Gnarling", + "hud.map.placed_by": "ปักโดย {name}", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/th_TH/hud/misc.ron b/assets/voxygen/i18n/th_TH/hud/misc.ron new file mode 100644 index 0000000000..22243a96b4 --- /dev/null +++ b/assets/voxygen/i18n/th_TH/hud/misc.ron @@ -0,0 +1,63 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + string_map: { + "hud.do_not_show_on_startup": "ไมม่ต้องแสดงเมื่อเปิดเกม", + "hud.show_tips": "แสดงคำแนะนำ", + "hud.quests": "ภารกิจ", + "hud.you_died": "สิ้นชีพ", + "hud.waypoint_saved": "จดจำจุดเกิด", + "hud.sp_arrow_txt": "แต้มทักษะ", + "hud.inventory_full": "กระเป๋าเต็ม", + + "hud.press_key_to_show_keybindings_fmt": "[{key}] ปุ่มควบคุม", + "hud.press_key_to_toggle_lantern_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} เพื่อเกิดใหม่ที่จุดเกิด"#, + + // Tutorial Button + "hud.tutorial_btn": r#"วิธีเล่น"#, + "hud.tutorial_click_here": r#"กด [ {key} ] เพื่อปล่อยเมาส์และกดที่ปุ่นนี้สิ!"#, + "hud.tutorial_elements": r#"การสร้างสิ่งของ"#, + +"hud.temp_quest_headline": r#"สวัสดี คุณนักเดินทาง!"#, +"hud.temp_quest_text": r#"ถ้าไม่รู้จะเริ่มยังไง ลองเดินดูรอบหมู่บ้านดูก่อนก็ได้ ถ้ามีของอะไรที่ถูกใจก็หยิบเอาได้เลย ไม่ต้องเกรงใจนะ + +ถือว่าเราช่วย ๆ กันก็แล้วกัน ฮ่าฮ่าฮ่าฮ่าฮ่า + +มุมขวาล่างของจอจะเป็นของสำคัญอย่างสัมภาระ, เมนูสร้างสิ่งของ และที่ขาดไม่ได้แผนที่ + +สามารถสร้างสิ่งของจำเป็นอย่างเช่น อาวุธ, เกราะ, อาหาร แล้วก็อื่น ๆ อีกเต็มเลย ที่โต๊ะของช่าง + +สัตว์ที่อยู่รอบ ๆ นี้ก็เป็นแหล่ง Animal Hide ชั้นดีเลยทีเดียว ติดกระเป๋าไว้บางก็ไม่เสียหายนะ + +ถ้าของพร้อม คนพร้อมก็เริ่มออกเดินทางได้เลย! +"#, + + "hud.spell": "เวทย์มนต์คาถา", + // Diary + "hud.diary": "ไดอาร่", + + "hud.free_look_indicator": "กำลังปลดล็อคกล้อง กด {key} เพื่อปิด", + "hud.camera_clamp_indicator": "กำลังล็อคหน้าจอในแนวตั้ง กด {key} เพื่อปิด", + "hud.auto_walk_indicator": "กำลังเดินแบบอัตโนมัต", + "hud.collect": "เก็บ", + "hud.pick_up": "หยิบ", + "hud.open": "เปิด", + "hud.use": "ใช้", + "hud.mine": "ขุด", + "hud.talk": "คุย", + "hud.trade": "แลกเปลี่ยน", + "hud.mount": "ขี่", + "hud.sit": "นั่ง", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/th_TH/hud/sct.ron b/assets/voxygen/i18n/th_TH/hud/sct.ron new file mode 100644 index 0000000000..5351e76011 --- /dev/null +++ b/assets/voxygen/i18n/th_TH/hud/sct.ron @@ -0,0 +1,14 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + string_map: { + // SCT outputs + "hud.sct.experience": "{amount} Exp", + "hud.sct.block": "ป้องกันสำเร็จ", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/th_TH/hud/settings.ron b/assets/voxygen/i18n/th_TH/hud/settings.ron new file mode 100644 index 0000000000..bc56a89191 --- /dev/null +++ b/assets/voxygen/i18n/th_TH/hud/settings.ron @@ -0,0 +1,145 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + 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.show_hitboxes": "แสดง Hitbox", + "hud.settings.show_chat": "แสดงช่องสนทนา", + "hud.settings.show_hotkey_hints": "แสดงตัวช่วยแถบของใช้", + "hud.settings.tips_on_startup": "แสดงคำแนะนำตอนเปิดเกม", + "hud.settings.ui_scale": "ขนาดเมนู", + "hud.settings.relative_scaling": "กำหนดให้", + "hud.settings.custom_scaling": "กำหนดเอง", + "hud.settings.crosshair": "เป้า", + "hud.settings.opacity": "ความเข้มของเป้า", + "hud.settings.hotbar": "แถบของใช้", + "hud.settings.toggle_shortcuts": "เปิด/ปิดปุ่มลัด", + "hud.settings.buffs_skillbar": "แสดงสถานะที่แถบสกิล", + "hud.settings.buffs_mmap": "แสดงสถานะที่แผนที่", + "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.speech_bubble": "ลูกโป่งคำพูด", + "hud.settings.speech_bubble_self": "แสดงลูกโป่งคำพูด", + "hud.settings.speech_bubble_dark_mode": "แสดงลูกดป่งคำพูดแบบมืด", + "hud.settings.speech_bubble_icon": "ไอคอนของลูกโป่งคำพูด", + "hud.settings.energybar_numbers": "แสดงตัวเลขที่แถบพลังงาน", + "hud.settings.always_show_bars": "แสดงแถบพลังงานตลอดเวลา", + "hud.settings.values": "ค่า", + "hud.settings.percentages": "ร้อยละ", + "hud.settings.chat": "สนทนา", + "hud.settings.background_opacity": "ความเข้มจางของพื้นหลัง", + "hud.settings.chat_character_name": "ชื่อผู้เล่นในช่องสนทนา", + "hud.settings.loading_tips": "คำแนะนำตอนโหลดเกม", + "hud.settings.reset_interface": "ใช้ค่าเริ่มต้น", + + "hud.settings.pan_sensitivity": "ความเร็วเมาส์แนวนอน", + "hud.settings.zoom_sensitivity": "ความเร็วในการซูมเข้า/ออก", + "hud.settings.camera_clamp_angle": "องศามุมเงยเมื่อล็อคมุมกล้องในแนวตั้ง", + "hud.settings.invert_scroll_zoom": "สลับการซูมเข้า/ออก", + "hud.settings.invert_mouse_y_axis": "สลับทิศทางเมาส์ในแนวตั้ง", + "hud.settings.invert_controller_y_axis": "สลับทิศทางจอยในแนวตั้ง", + "hud.settings.enable_mouse_smoothing": "ขยับเมาส์แบบนุ่มนวล", + "hud.settings.free_look_behavior": "พฤติกรรมเมื่อปลดล็อคกล้อง", + "hud.settings.auto_walk_behavior": "พฤติกรรมเมื่อเดินอัตโนมัต", + "hud.settings.camera_clamp_behavior": "พฤติกรรมเมื่อล็อคมุมกล้อง", + "hud.settings.player_physics_behavior": "ใช้ฟิสิกส์กับตัวละคร (ระหว่างการทดลอง)", + "hud.settings.stop_auto_walk_on_input": "หยุดการเดินอัตโนมัตเมื่อขยับเอง", + "hud.settings.auto_camera": "มุมกล้องอัตโนมัต", + "hud.settings.reset_gameplay": "ใช้ค่าเริ่มต้น", + + "hud.settings.view_distance": "ระยะการมองเห็น", + "hud.settings.lod_distance": "ระยะ LoD", + "hud.settings.sprites_view_distance": "ระยะการมองเห็นพื้นหลัง", + "hud.settings.figures_view_distance": "ระยะการมองเห็นตัวละคร", + "hud.settings.maximum_fps": "เฟรมเรทสูงสุด", + "hud.settings.background_fps": "เฟรมเรทเมื่อพับจอ", + "hud.settings.present_mode": "โหมด Present", + "hud.settings.present_mode.fifo": "Fifo", + "hud.settings.present_mode.mailbox": "Mailbox", + "hud.settings.present_mode.immediate": "Immediate", + "hud.settings.fov": "องศาการมองเห็น", + "hud.settings.gamma": "ความสว่าง", + "hud.settings.exposure": "ปริมาณแสงที่ตกที่กล้อง", + "hud.settings.ambiance": "ความสว่างของพื้นที่", + "hud.settings.antialiasing_mode": "โหมดการลบรอยหยัก (Anti Aliasing)", + "hud.settings.upscale_factor": "ความคมชัดภายใน", + "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.minimal": "น้อย", + "hud.settings.cloud_rendering_mode.low": "ต้ำ", + "hud.settings.cloud_rendering_mode.medium": "กลาง", + "hud.settings.cloud_rendering_mode.high": "สูง", + "hud.settings.cloud_rendering_mode.ultra": "สูงที่สุด", + "hud.settings.fullscreen": "เต็มหน้าจอ", + "hud.settings.fullscreen_mode": "โหมดเต็มหน้าจอ", + "hud.settings.fullscreen_mode.exclusive": "Exclusive", + "hud.settings.fullscreen_mode.borderless": "เต็มจอแบบไร้ขอบ (Borderless)", + "hud.settings.gpu_profiler": "เปิดการเร่งด้วย GPU (อาจไม่รองรับ)", + "hud.settings.particles": "อนุภาค", + "hud.settings.lossy_terrain_compression": "บีบอัดการโหลดพื้น", + "hud.settings.weapon_trails": "เส้นอาวุธเมื่อโจมตี", + "hud.settings.resolution": "ความคมชัด", + "hud.settings.bit_depth": "ความคมชัดสี", + "hud.settings.refresh_rate": "เฟรมเรท", + "hud.settings.lighting_rendering_mode": "คุณภาพแสง", + "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": "คุณภาพเงา", + "hud.settings.shadow_rendering_mode.none": "ปิดเงา", + "hud.settings.shadow_rendering_mode.cheap": "ต่ำ", + "hud.settings.shadow_rendering_mode.map": "แมพ", + "hud.settings.shadow_rendering_mode.map.resolution": "Resolution", + "hud.settings.lod_detail": "รายละเอียด LoD", + "hud.settings.save_window_size": "บันทึกขนาดหน้าจอ", + "hud.settings.reset_graphics": "ใช้ค่าเริ่มต้น", + "hud.settings.bloom": "แสงฟุ้ง (Bloom)", + "hud.settings.point_glow": "จุดเรืองแสง", + + "hud.settings.master_volume": "ระดับเสียงทั้งหมด", + "hud.settings.inactive_master_volume_perc": "ระดับเสียเมื่อพับจอ", + "hud.settings.music_volume": "ระดับเสียงเพลง", + "hud.settings.sound_effect_volume": "ระดับเสียงเอฟเฟค", + "hud.settings.audio_device": "อุปกรร์กระจายเสียง", + "hud.settings.reset_sound": "ใช้ค่าเริ่มต้น", + + "hud.settings.english_fallback": "แสดงภาษาอังกฤษในกรณีที่ไม่มีคำแปล", + + "hud.settings.awaitingkey": "กดปุ่มเพื่อตั้ง...", + "hud.settings.unbound": "ไม่มี", + "hud.settings.reset_keybinds": "ใช้ค่าเริ่มต้น", + + "hud.settings.chat_tabs": "แถบการสนทนา", + "hud.settings.label": "คำอธิบาย:", + "hud.settings.delete": "ลบ", + "hud.settings.show_all": "แสดงทั้งหมด", + "hud.settings.messages": "ข้อความ", + "hud.settings.activity": "ความเคลื่อนไหว", + "hud.settings.death": "เสียชีวิต", + "hud.settings.group": "ปาร์ตี้", + "hud.settings.faction": "ฝ่าย", + "hud.settings.world": "โลก", + "hud.settings.region": "ภูมิภาค", + "hud.settings.say": "พูด", + "hud.settings.all": "ทั้งหมด", + "hud.settings.group_only": "ปาร์ตี้เท่านั้น", + "hud.settings.reset_chat" : "ใช้ค่าเริ่มต้น", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/th_TH/hud/skills.ron b/assets/voxygen/i18n/th_TH/hud/skills.ron new file mode 100644 index 0000000000..c19833e671 --- /dev/null +++ b/assets/voxygen/i18n/th_TH/hud/skills.ron @@ -0,0 +1,258 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + string_map: { + "hud.rank_up": "ได้รับแต้มทักษะ", + "hud.skill.sp_available": "แต้มทักษะที่ใช้ได้ {number} แต้ม", + "hud.skill.not_unlocked": "ยังไม่ปลดล็อค", + "hud.skill.req_sp": "\n\nใช้แต้มทักษะ {number} แต้ม", + // Skills + // General + "hud.skill.inc_health_title": "พลังชีวิต", + "hud.skill.inc_health": "เพิ่มพลังชีวิตสูงสุด {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": "ปลดล็อคอาวุธ ขวาน", + "hud.skill.unlck_axe": "ปลดล็อคทักษะพิเศษของขวาน{SP}", + "hud.skill.unlck_hammer_title": "ปลดล็อคอาวุธ ค้อน", + "hud.skill.unlck_hammer": "ปลดล็อคทักษะพิเศษของค้อน{SP}", + "hud.skill.unlck_bow_title": "ปลดล็อคอาวุธ ธนู", + "hud.skill.unlck_bow": "ปลดล็อคทักษะพิเศษของธนู{SP}", + "hud.skill.unlck_staff_title": "ปลดล็อคอาวุธ คถาอัคนี", + "hud.skill.unlck_staff": "ปลดล็อคทักษะพิเศษของคถาอัคนี{SP}", + "hud.skill.unlck_sceptre_title": "ปลดล็อคอาวุธ คถาอภิรักษ์", + "hud.skill.unlck_sceptre": "ปลดล็อคทักษะพิเศษของคถาอภิรักษ์{SP}", + "hud.skill.dodge_title": "กลิ้งหลบ", + "hud.skill.dodge": "กลิ้งหลบด้วยการกดเมาส์กลาง และไม่ได้รับความเสียหาย (iframe) จากการโจมตีระยะใกล้ในขณะที่กำลังกลิ้ง", + "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": "ระยะเวลาการกลิ้งหลบ", + "hud.skill.roll_dur": "ระยะเวลาในการกลิ้งจะเพิ่มขึ้น {boost}% {SP}", + "hud.skill.climbing_title": "ปีน", + "hud.skill.climbing": "กระโดดสูงขึ้น", + "hud.skill.climbing_cost_title": "พลังงานการปีน", + "hud.skill.climbing_cost": "การปีนจะใช้พลังงานน้อยลง {boost}% {SP}", + "hud.skill.climbing_speed_title": "ความเร็วการปีน", + "hud.skill.climbing_speed": "ปีนเร็วขึ้น {boost}% {SP}", + "hud.skill.swim_title": "ว่ายน้ำ", + "hud.skill.swim": "การเคลื่อนในของเหลว", + "hud.skill.swim_speed_title": "ความเร็วในการว่าย", + "hud.skill.swim_speed": "ว่ายน้ำเร็วขึ้น {boost}% {SP}", + // Sceptre + "hud.skill.sc_lifesteal_title": "ลำแสงดูดเลือด", + "hud.skill.sc_lifesteal": "ดูดพลังชีวิตจากผู้โชคร้ายมาเป็นของตัวเอง", + "hud.skill.sc_lifesteal_damage_title": "เพิ่มความเสียหาย", + "hud.skill.sc_lifesteal_damage": "ลำแสงดูดเลือดสร้างความเสียหายมากขึ้น {boost}% {SP}", + "hud.skill.sc_lifesteal_range_title": "เพิ่มระยะ", + "hud.skill.sc_lifesteal_range": "ความยาวของลำแสงดูดเลือดเพิ่มขึ้น {boost}% {SP}", + "hud.skill.sc_lifesteal_lifesteal_title": "อำนาจการดูด", + "hud.skill.sc_lifesteal_lifesteal": "เปลี่ยนความเสียหาย {boost}% ที่ทำได้เป็นพลังชีวิต {SP}", + "hud.skill.sc_lifesteal_regen_title": "พื้นพลังงาน", + "hud.skill.sc_lifesteal_regen": "ฟื้นฟูพลังงาน {boost}% {SP}", + "hud.skill.sc_heal_title": "อาณาอภิรักษ์", + "hud.skill.sc_heal": "ฟื้นฟูพลังชีวิตของคุณและเพื่อนร่วมปาร์ตี้ ต้องมี Combo ถึงจะใช้ได้", + "hud.skill.sc_heal_heal_title": "ทรงพลัง", + "hud.skill.sc_heal_heal": "ฟื้นฟูพลังชีวิตของคุณและเพื่อนร่วมปาร์ตี้อีก {boost}% {SP}", + "hud.skill.sc_heal_cost_title": "ลดพลังงาน", + "hud.skill.sc_heal_cost": "อาณาอภิรักษ์จะใช้พลังงานน้อย {boost}% ในการร่าย {SP}", + "hud.skill.sc_heal_duration_title": "ยื้อเวลา", + "hud.skill.sc_heal_duration": "อาณาอภิรักษ์จะมีระยะเวลานานขึ้น {boost}% {SP}", + "hud.skill.sc_heal_range_title": "รัศมี", + "hud.skill.sc_heal_range": "อาณาอภิรักษ์จะมีขนาดกว้างขึ้น {boost}% {SP}", + "hud.skill.sc_wardaura_unlock_title": "อาณาปกปัก", + "hud.skill.sc_wardaura_unlock": "ป้องกันคุณและเพื่อนร่วมปาร์ตี้ ไม่ได้รับความเสียหาย{SP}", + "hud.skill.sc_wardaura_strength_title": "ทรงพลัง", + "hud.skill.sc_wardaura_strength": "อาณาปกปักป้องกันความเสียหายได้มากขึ้น {boost}% {SP}", + "hud.skill.sc_wardaura_duration_title": "ยื้อเวลา", + "hud.skill.sc_wardaura_duration": "อาณาปกปักมีระยะเวลานานขึ้น {boost}% {SP}", + "hud.skill.sc_wardaura_range_title": "รัศมี", + "hud.skill.sc_wardaura_range": "อาณาปกปักมีขอบเขตกว้าขึ้น {boost}% {SP}", + "hud.skill.sc_wardaura_cost_title": "ลดพลังงาน", + "hud.skill.sc_wardaura_cost": "อาณาปกปักใช้พลังงานน้อย {boost}% ในการร่าย {SP}", + // Staff + "hud.skill.st_shockwave_range_title" : "รัศมี", + "hud.skill.st_shockwave_range" : "คลื่นกระแทกมีรัศมีเพิ่มขึ้น {boost}% {SP}", + "hud.skill.st_shockwave_cost_title" : "ลดพลังงาน", + "hud.skill.st_shockwave_cost" : "คลื่นกระแทกใช้พลังงานน้อยลง {boost}% ในการร่าย {SP}", + "hud.skill.st_shockwave_knockback_title" : "กระเด็น", + "hud.skill.st_shockwave_knockback" : "คลื่นกระแทกผลักศัตรูออกไปไกลขึ้น {boost}% {SP}", + "hud.skill.st_shockwave_damage_title" : "ทรงพลัง", + "hud.skill.st_shockwave_damage" : "คลื่นกระแทกสร้างความเสียหายมากขึ้น {boost}% {SP}", + "hud.skill.st_shockwave_unlock_title" : "คลื่นกระแทก", + "hud.skill.st_shockwave_unlock" : "ผลักศัตรู้ที่อยู่ใกล้ ๆ ออกและสร้างความเสียหาย {SP}", + "hud.skill.st_flamethrower_title" : "เพลิงกิเลน", + "hud.skill.st_flamethrower" : "เผาให้หมด เผาให้ราบ", + "hud.skill.st_flame_velocity_title" : "เร่งความเร็ว", + "hud.skill.st_flame_velocity" : "เพลิงกิเลนเคลื่อนที่เร็วขึ้น {boost}% {SP}", + "hud.skill.st_flamethrower_range_title" : "เพิ่มระยะ", + "hud.skill.st_flamethrower_range" : "เพลิงกิเลนเดินทางได้ไกลขึ้น {boost}% {SP}", + "hud.skill.st_energy_drain_title" : "ลดพลังงาน", + "hud.skill.st_energy_drain" : "เพลิงกิเลนใช้พลังงานลดลง {boost}% {SP}", + "hud.skill.st_flamethrower_damage_title" : "ทรงพลัง", + "hud.skill.st_flamethrower_damage" : "เพลิงกิเลนสร้างความเสียหายมากขึ้น {boost}% {SP}", + "hud.skill.st_explosion_radius_title" : "รัศมี", + "hud.skill.st_explosion_radius" : "ลูกไฟกัมปนาทมีระยะกว้างขึ้น {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" : "ทรงพลัง", + "hud.skill.st_damage" : "ลูกไฟกัมปนาทสร้างความเสียหายมากขึ้น {boost}% {SP}", + // Bow + "hud.skill.bow_projectile_speed_title" : "เร่งความเร็ว", + "hud.skill.bow_projectile_speed" : "ลูกธนูเดินทางเร็วขึ้นและระยะทางเพิ่มขึ้น {boost}% {SP}", + "hud.skill.bow_charged_title" : "ขอเล็งก่อน", + "hud.skill.bow_charged" : "ขอบคุณที่รอกัน", + "hud.skill.bow_charged_damage_title" : "ทรงพลัง", + "hud.skill.bow_charged_damage" : "เมื่อชักคันธนูค้างไว้ ลูกธนูจะสร้างความเสียหายมากขึ้น {boost}% {SP}", + "hud.skill.bow_charged_energy_regen_title" : "พื้นฟูพลังงาน", + "hud.skill.bow_charged_energy_regen" : "เมื่อชักคันธนูค้างไว้ พื้นฟูพลังงานมากขึ้น {boost}%{SP}", + "hud.skill.bow_charged_knockback_title" : "อันกระเด็น", + "hud.skill.bow_charged_knockback" : "เมื่อชักคันธนูค้างไว้ ศัตรูจะถูกผลักให้กระเด็ดออกไกลขึ้น {boost}%{SP}", + "hud.skill.bow_charged_speed_title" : "มือไว", + "hud.skill.bow_charged_speed" : "ยิงธนูได้เร็วขึ้น {boost}% {SP}", + "hud.skill.bow_charged_move_title" : "คล่องตัว", + "hud.skill.bow_charged_move" : "ขณะชักคันธนู เคลื่อนที่ได้เร็วขึ้น {boost}% {SP}", + "hud.skill.bow_repeater_title" : "กระหน่ำยิง", + "hud.skill.bow_repeater" : "เพิ่มความเร็วในการยิงธนูเมื่อยิงต่อเนื่อง", + "hud.skill.bow_repeater_damage_title" : "ทรงพลัง", + "hud.skill.bow_repeater_damage" : "สร้างความเสียหายเพิ่มขึ้น {boost}% {SP}", + "hud.skill.bow_repeater_cost_title" : "ลดพลังงาน", + "hud.skill.bow_repeater_cost" : "กระหน่ำใช้พลังงานน้อยลง {boost}% {SP}", + "hud.skill.bow_repeater_speed_title" : "เร่งความเร็ว", + "hud.skill.bow_repeater_speed" : "กระหน่ำยิง เพิ่มความเร็วโจมตีอีก {boost}% {SP}", + "hud.skill.bow_shotgun_unlock_title" : "ยิงกระจาย", + "hud.skill.bow_shotgun_unlock" : "ยิงธนูได้หลายดอกพร้อมกัน {SP}", + "hud.skill.bow_shotgun_damage_title" : "ทรงพลัง", + "hud.skill.bow_shotgun_damage" : "ยิงกระจายสร้างความเสียหายเพิ่มขึ้น {boost}% {SP}", + "hud.skill.bow_shotgun_cost_title" : "ลดพลังงาน", + "hud.skill.bow_shotgun_cost" : "ยิงกระจายใช้พลังงานน้อยลง {boost}% {SP}", + "hud.skill.bow_shotgun_arrow_count_title" : "จำนวนลูกธนู", + "hud.skill.bow_shotgun_arrow_count" : "เพิ่มจำนวนลูกธนูที่ยิงกระจายใช้ {boost} {SP}", + "hud.skill.bow_shotgun_spread_title" : "จุดตาย", + "hud.skill.bow_shotgun_spread" : "ลดความกระจายของลูกธนูลง {boost}% {SP}", + // Hammer + "hud.skill.hmr_leap_radius_title" : "รัศมี", + "hud.skill.hmr_leap_radius" : "กระโดดทุมมีขอบเขตเพิ่มขึ้นเป็น {boost} เมตร {SP}", + "hud.skill.hmr_leap_distance_title" : "แชมป์กระโดดไกล", + "hud.skill.hmr_leap_distance" : "กระโดนทุบมีระยะทางเพิ่มขึ้น {boost}% {SP}", + "hud.skill.hmr_leap_cost_title" : "ลดพลังงาน", + "hud.skill.hmr_leap_cost" : "กระโดดทุบใช้พลังงานน้อยลง {boost}% {SP}", + "hud.skill.hmr_leap_knockback_title" : "กระเด็ดออก", + "hud.skill.hmr_leap_knockback" : "ศัตรูที่ถูกกระโดดทุบจะกระเด็นออกไกลขึ้น {boost}% {SP}", + "hud.skill.hmr_leap_damage_title" : "ทรงพลัง", + "hud.skill.hmr_leap_damage" : "กระโดดทุบสร้างความเสียหายมากขึ้น {boost}% {SP}", + "hud.skill.hmr_unlock_leap_title" : "กระโดดทุบ", + "hud.skill.hmr_unlock_leap" : "กระโดดขึ้นไปในอากาศแล้วฟาดค้อนใส่ศัตรู{SP}", + "hud.skill.hmr_charged_melee_title" : "หน้าสะบัด", + "hud.skill.hmr_charged_melee" : "ง้างค้อนแล้วฟาดใส่ศัตรูอย่างรุนแรง", + "hud.skill.hmr_charged_rate_title" : "ง้างเร็ว", + "hud.skill.hmr_charged_rate" : "ง้างค้อนได้เร็วขึ้น {boost}% {SP}", + "hud.skill.hmr_charged_melee_nrg_drain_title" : "ลดพลังงาน", + "hud.skill.hmr_charged_melee_nrg_drain" : "ลดพลังงานทมี่ใช้ในการง้างค้อนลง {boost}% {SP}", + "hud.skill.hmr_charged_melee_damage_title" : "ทรงพลัง", + "hud.skill.hmr_charged_melee_damage" : "เมื่อง้างค้อน สร้างเสียหายกับศัตรูเพิ่มขึ้น {boost}% {SP}", + "hud.skill.hmr_charged_melee_knockback_title" : "กระเด็ดออก", + "hud.skill.hmr_charged_melee_knockback" : "เมื่อง้างค้อน ศัตรูจะกระเด็ดออกไปไกลขึ้น {boost}% {SP}", + "hud.skill.hmr_single_strike_title" : "ฟาดค้อน", + "hud.skill.hmr_single_strike" : "ฟาดค้อนใส่ศัตรู", + "hud.skill.hmr_single_strike_regen_title" : "ฟื้นฟูพลังงาน", + "hud.skill.hmr_single_strike_regen" : "พื้นฟูพลังงาน เมื่อฟาดค้อนใส่ศัตรูสำเร็จ {SP}", + "hud.skill.hmr_single_strike_speed_title" : "กล้ามแขนเป็นมัด ๆ", + "hud.skill.hmr_single_strike_speed" : "ความเร็วโจมตีเพิ่มขึ้น เมื่อฟาดค้อนใส่ศัตรูสำเร็จต่อเนื่องกัน{SP}", + "hud.skill.hmr_single_strike_damage_title" : "ทรงพลัง", + "hud.skill.hmr_single_strike_damage" : "ฟาดค้อนสร้างความเสียหายมากขึ้น {SP}", + "hud.skill.hmr_single_strike_knockback_title" : "กระเด็ดออก", + "hud.skill.hmr_single_strike_knockback" : "เมื่อถูกฟาด ศัตรูจะกระเด็ดออกไปไกลขึ้น {boost}% {SP}", + // Sword + "hud.skill.sw_trip_str_title": "ระบำดาบ", + "hud.skill.sw_trip_str": "ฟาดฟันศัตรูด้วยดาบ ต่อเนื่องสูงสุด 3 ครั้ง", + "hud.skill.sw_trip_str_combo_title": "ระบำดาบทรงพลัง", + "hud.skill.sw_trip_str_combo": "สร้างความเสียหายมากขึ้นตามจำนวนคอมโบ {SP}", + "hud.skill.sw_trip_str_dmg_title": "ระบำดาบทรงพลัง", + "hud.skill.sw_trip_str_dmg": "การฟาดฟันแต่ละครั้งจะสร้างความเสียหายมากขึ้น {SP}", + "hud.skill.sw_trip_str_sp_title": "ระบำดาบร่ายรำ", + "hud.skill.sw_trip_str_sp": "การฟาดฟันแต่ละครั้งจะเพิ่มความเร็วโจมตี {SP}", + "hud.skill.sw_trip_str_reg_title": "ระบำดาบนิรันตร", + "hud.skill.sw_trip_str_reg": "การฟาดฟันแต่ละครั้งจะช่วยฟื้นฟูพลังงาน {SP}", + "hud.skill.sw_dash_title": "พุ่งใส่", + "hud.skill.sw_dash": "พุ่งใส่ศัตรูที่โชคไม่ดี", + "hud.skill.sw_dash_dmg_title": "ทรงพลัง", + "hud.skill.sw_dash_dmg": "พุ่งใส่สร้างความเสรหายเพิ่มขึ้น {boost}% {SP}", + "hud.skill.sw_dash_drain_title": "เหนื่อยยาก", + "hud.skill.sw_dash_drain": "ลดพลังงานที่ใช้ขณะพุ่งลง {boost}% {SP}", + "hud.skill.sw_dash_cost_title": "ลดพลังงาน", + "hud.skill.sw_dash_cost": "พุ่งใส่ใช้พลังงานลดลง {boost}% ในช่วงแรก {SP}", + "hud.skill.sw_dash_speed_title": "ว่องไว", + "hud.skill.sw_dash_speed": "ขณะพุ่ง ความเร็วเคลื่อนที่เพิ่มขึ้น {boost}% {SP}", + "hud.skill.sw_dash_charge_through_title": "พุ่งทะลุ", + "hud.skill.sw_dash_charge_through": "สามมารถพุ่งทะลุศัตรูตัวแรก {SP}", + "hud.skill.sw_dash_scale_title": "โมเมนตัม", + "hud.skill.sw_dash_scale": "สร้างความเสียหายเพิ่มขึ้นตามระยะที่ทำได้ {boost}% {SP}", + "hud.skill.sw_spin_title": "หมุน", + "hud.skill.sw_spin": "เหวี่ยงดาบไปรอบตัว {SP}", + "hud.skill.sw_spin_dmg_title": "ทรงพลัง", + "hud.skill.sw_spin_dmg": "หมุนสร้างความเสียหายเพิ่มขึ้น {boost}% {SP}", + "hud.skill.sw_spin_spd_title": "รวดเร็ว", + "hud.skill.sw_spin_spd": "ความเร็วในการหมุนเพิ่มขึ้น {boost}% {SP}", + "hud.skill.sw_spin_cost_title": "ลดพลังงาน", + "hud.skill.sw_spin_cost": "ลดพลังงานที่ใช้ในการหมุนลง {boost}% {SP}", + "hud.skill.sw_spin_spins_title": "จำนวน", + "hud.skill.sw_spin_spins": "เพิ่มจำนวนรอบที่หมุน {SP}", + "hud.skill.sw_interrupt_title": "รำบำดาบขั้นสูง", + "hud.skill.sw_interrupt": "สามมารถฟันดาบต่อเนื่องติดต่อกันได้ {SP}", + // Axe + "hud.skill.axe_double_strike_title": "ฟันคู่", + "hud.skill.axe_double_strike": "ฟันให้ราบ", + "hud.skill.axe_double_strike_combo_title": "ฟันคู่ต่อเนื่อง", + "hud.skill.axe_double_strike_combo": "สามารถฟันติดต่อกันได้ {SP}", + "hud.skill.axe_double_strike_damage_title": "ทรงพลัง", + "hud.skill.axe_double_strike_damage": "การฟันแต่ละครั้งสร้างความเสียหายเพิ่มขึ้น {SP}", + "hud.skill.axe_double_strike_speed_title": "รวดเร็ว", + "hud.skill.axe_double_strike_speed": "การฟันแต่ละครั้งเพิ่มความเร็วโจมตี {SP}", + "hud.skill.axe_double_strike_regen_title": "ฟื้นฟูพลังงาน", + "hud.skill.axe_double_strike_regen": "การฟันแต่ละครั้งจะช่วยฟื้นฟูพลังงาน {SP}", + "hud.skill.axe_spin_title": "เอามือขึ้นแล้ว หมุน หมุน", + "hud.skill.axe_spin": "ชูมือขึ้นโบกไปมา", + "hud.skill.axe_infinite_axe_spin_title": "ไม่เวียนอีก", + "hud.skill.axe_infinite_axe_spin": "เหวียงขวานได้เรื่อย ๆ จนกว่าพลังงานจะหมด {SP}", + "hud.skill.axe_spin_damage_title": "ทรงพลัง", + "hud.skill.axe_spin_damage": "เหวียงขวานสร้างความเสียหมายเพิ่มขึ้น {boost}% {SP}", + "hud.skill.axe_spin_helicopter_title": "พลศาสตร์แรงยก", + "hud.skill.axe_spin_helicopter": "ตกถึงพื้นช้าลงในขณะที่เหวี่ยงขวาน {SP}", + "hud.skill.axe_spin_speed_title": "ความมเร็ว", + "hud.skill.axe_spin_speed": "เหวี่ยงขวานเร็วขึ้น {boost}% {SP}", + "hud.skill.axe_spin_cost_title": "ลดพลังงาน", + "hud.skill.axe_spin_cost": "เหวี่ยงขวานใช้พลังงานน้อยลง {boost}% {SP}", + "hud.skill.axe_unlock_leap_title": "กระโดดฟัน", + "hud.skill.axe_unlock_leap": "กระโดดขึ้นไปในอากาศ และฟันศัตรู{SP}", + "hud.skill.axe_leap_damage_title": "ทรงพลัง", + "hud.skill.axe_leap_damage": "กระโดดฟันสร้างความเสียหายเพิ่มขึ้น {boost}% {SP}", + "hud.skill.axe_leap_knockback_title": "กระเด็นออก", + "hud.skill.axe_leap_knockback": "กระโดดฟันจะผลักศัตรูออกไปไกลขึ้น {boost}%{SP}", + "hud.skill.axe_leap_cost_title": "ลดพลังงาน", + "hud.skill.axe_leap_cost": "กระโดดฟันใช้พลังงานน้อยลง {boost}% {SP}", + "hud.skill.axe_leap_distance_title": "กระโดดไกล", + "hud.skill.axe_leap_distance": "ระยะในการกระโดดเพิ่มขึ้น{boost}% {SP}", + // Mining + "hud.skill.mining_title": "ขุดหิน", + "hud.skill.pick_strike_title": "ขุด ขุด ขุด", + "hud.skill.pick_strike": "Hit rocks with the pickaxe to gain ore, gems and experience", + "hud.skill.pick_strike": "เมื่อขุดหินจะได้รับแร่หรืออัญมนีตามชินของหินที่ขุด", + "hud.skill.pick_strike_speed_title": "แข็งแรง", + "hud.skill.pick_strike_speed": "ขุดหินได้เร็วขึ้น {SP}", + "hud.skill.pick_strike_oregain_title": "โชคลาภ แร่", + "hud.skill.pick_strike_oregain": "มีโอกาสได้รับแร่มากขึ้น ({boost}% ต่อเลเเวล) {SP}", + "hud.skill.pick_strike_gemgain_title": "โชคลาภ อัญมนี", + "hud.skill.pick_strike_gemgain": "มีโอกาสได้รับอัญมนีมากขึ้น ({boost}% ต่อเลเวล){SP}", + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/th_TH/hud/social.ron b/assets/voxygen/i18n/th_TH/hud/social.ron new file mode 100644 index 0000000000..4599cc2452 --- /dev/null +++ b/assets/voxygen/i18n/th_TH/hud/social.ron @@ -0,0 +1,22 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + 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} คน กำลังออนไลน์", + "hud.social.name": "ชื่อ", + "hud.social.level": "เลเวล", + "hud.social.zone": "เขตพื้นที่", + "hud.social.account": "บัญชี", + }, + + + vector_map: { + } +) + diff --git a/assets/voxygen/i18n/th_TH/hud/trade.ron b/assets/voxygen/i18n/th_TH/hud/trade.ron new file mode 100644 index 0000000000..cf8c906881 --- /dev/null +++ b/assets/voxygen/i18n/th_TH/hud/trade.ron @@ -0,0 +1,32 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + string_map: { + "hud.trade.trade_window": "แลกสิ่งของ", + "hud.trade.phase1_description": "หยิบสิ่งของที่ต้องการแลกไปไว้ในพื้นที่ที่กำหนด", + "hud.trade.phase2_description": "กรุณาตรวจสิ่งของที่ต้องการแลกเปลี่ยน", + /// Phase3 should only be visible for a few milliseconds if everything is working properly, but is included for completeness + "hud.trade.phase3_description": "อยู่ระหว่างการแลกเปลี่ยนสิ่งของ", + "hud.trade.persons_offer": "ผู้เล่น {playername} ต้องการแลกเปลี่ยนสิ่งของ", + "hud.trade.has_accepted": "ผู้เล่น {playername} ยอมรับการแลกเปลี่ยน", + "hud.trade.accept": "ยอมรับ", + "hud.trade.decline": "ปฏิเสธ", + "hud.trade.invite_sent": "คำขอเพื่อแลฃกเปลี่ยนสิ่งของถูกส่งไปให้ผู้เล่น {playername}.", + "hud.trade.result.completed": "การแลกเปลี่ยนเสร็จสมบูรณ์", + "hud.trade.result.declined": "ปฏิเสธการแลกเปลี่ยน", + "hud.trade.result.nospace": "ช่องสัมภาระไม่พอ การแลกเปลี่ยนถูกยกเลิก", + "hud.trade.buy_price": "ราคาซื้อ", + "hud.trade.sell_price": "ราคาขาย", + "hud.trade.coin": "เหรียญ", + "hud.trade.tooltip_hint_1": "", + "hud.trade.tooltip_hint_2": "", + "hud.trade.your_offer": "สิ่งของที่คุณต้องการแลก", + "hud.trade.their_offer": "สิ่งของที่เขาต้องการแลก", + "hud.trade.amount_input": "เลือกสิ่งของ" + }, + + + vector_map: { + } +) diff --git a/assets/voxygen/i18n/th_TH/main.ron b/assets/voxygen/i18n/th_TH/main.ron new file mode 100644 index 0000000000..73ca7f4d4b --- /dev/null +++ b/assets/voxygen/i18n/th_TH/main.ron @@ -0,0 +1,154 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + string_map: { + /// Start Main screen section + "main.username": "ชื่อผู้ใช้", + "main.server": "เซิร์ฟเวอร์", + "main.password": "รหัสผ่าน", + "main.connecting": "อยู่ระหว่างการเชื่อมต่อ", + "main.creating_world": "อยู่ระหว่างการสร้างโลก", + "main.tip": "คำแนะนำ:", + "main.unbound_key_tip": "ยกเลิกปุ่ม", + + // Welcome notice that appears the first time Veloren is started + "main.notice": r#"ยินดีต้อนรับเข้าสู่โลกเวโลเรน (ในเวอร์ชั่นอัลฟา)! + +แต่ก่อนที่ความสนุกจะเริ่ม สิ่งที่คุณควรรู้คือ + +- ตัวเกมอยู่ในช่วงแรกของการพัฒนา ดังนั้น ตัวเกมจึงยังไม่สมบูรณ์ บางองค์ประกอบอาจขาดหายหรือทำงานผิดพลาด + +- หากคุณต้องการให้คำแนะนำเกี่ยวกับเกมหรือแจ้งบัค คุณสามารถติดต่อเราได้ที่ Reddit, GitLab หรือผ่านทาง Discord ของเรา + +- เวโลเรนจัดอยู่ในหมวดหมู่ลิขสิทธิ์ของ GPL-3 คือ อนุญาตให้ใช้งาน, ดัดแปลง และแจกจ่ายได้โดยไม่คิดค่าใช้จ่าย (แต่ต้องอยู่ภายลิขสิทธิ์เดียวกัน) + +- เวโลเรนเป็นเกมที่สร้างขึ้นโดยไม่หวังผลกำไร ผู้ที่มีส่วนร่วมทุกคนเป็นอาสาสมัคร +ดังนั้นถ้าคุณสนใจอยากเข้าร่วม ทางทีมพัฒนายินดีต้อนรับเสมอ + +ท้ายที่สุดเราขอขอบคุณที่สละเวลาอ่านสาส์นน้อย ๆ เล่มนี้ เราหวังว่าคุณจะได้รับสนุกจากเกมของเรา + +~ ด้วยความเคารพ ทีมผู้พัฒนา + +Welcome to the alpha version of Veloren! + +Before you dive into the fun, please keep a few things in mind: + +- This is a very early alpha. Expect bugs, extremely unfinished gameplay, unpolished mechanics, and missing features. + +- If you have constructive feedback or bug reports, you can contact us via Reddit, GitLab, or our community Discord server. + +- Veloren is licensed under the GPL 3 open-source licence. That means you're free to play, modify, and redistribute the game however + you wish (provided derived work is also under GPL 3). + +- Veloren is a non-profit community project, and everybody working on it is a volunteer. +If you like what you see, you're welcome to join the development or art teams! + +Thanks for taking the time to read this notice, we hope you enjoy the game! + +~ The Veloren Devs"#, + + // Login process description + "main.login_process": r#"ขั้นตอนการเข้าเกม: + +คุณอาจจำเป็นจะต้องสมัครรหัสเพื่อเข้าเล่นบางเซิร์ฟเวอร์ + +สร้างรหัสได้ที่ + +https://veloren.net/account/."#, + "main.login.server_not_found": r#"ไม่พบเซิร์ฟเวอร์ +Server not found"#, + "main.login.authentication_error": r#"ยินยันรหัสผิดพลาด +Auth error on server"#, + "main.login.internal_error": r#"เกิดข้อผิดพลาดขึ้นกับตัวเกม (ตัวละครอาจถูกลบไปแล้ว) +Internal error on client (most likely, player character was deleted)"#, + "main.login.failed_auth_server_url_invalid": r#"ไม่สามารถยืนยันรหัสได้ +Failed to connect to auth server"#, + "main.login.insecure_auth_scheme": r#"ไม่อนุญาตให้ยืนยันตัวตนผ่านรูปแบบ HTTP เนื่องจากความปลอดภัย อนุญาตให้ใช้ HTTP ก็ต่อเมื่อทำการดีบัคหรือเมื่อรันบน localhost เท่านั้น +The auth Scheme HTTP is NOT supported. It's insecure! For development purposes, HTTP is allowed for 'localhost' or debug builds"#, + "main.login.server_full": r#"เซิร์ฟเวอร์เต็ม +Server is full"#, + "main.login.untrusted_auth_server": r#"เซิร์ฟเวอร์ที่ใช้ในการยืนยันรหัสไม่น่าไว้วางใจ +Auth server not trusted"#, + "main.login.outdated_client_or_server": r#"เซิร์ฟเวอร์ล้มเหลว: อาจเกิดจากตัวเกมไม่ได้รับการอัพเดท โปรดอัพเดทตัวเกม +ServerWentMad: Probably versions are incompatible, check for updates."#, + "main.login.timeout": r#"หมดเวลา: เซิร์ฟเวอร์ไม่ตอบกลับในเวลาที่กำหนด (เซิร์ฟเวอร์อาจเต็มหรือเกิดปัญหากับเคลือข่าย) +Timeout: Server did not respond in time. (Overloaded or network issues)."#, + "main.login.server_shut_down": r#"เซิร์ฟเวอร์ปิดอยู่ +Server shut down"#, + "main.login.network_error": r#"เคลือข่ายขัดข้อง +Network error"#, + "main.login.network_wrong_version": r#"เวอร์ชั่นของตัวเกมและเซิร์ฟเวอร์ไม่ตรงกัน โปรดอัพเดทตัวเกม +Mismatched server and client version, please update your game client."#, + "main.login.failed_sending_request": r#"ยืนยันรหัสล้มเหลว +Request to Auth server failed"#, + "main.login.invalid_character": r#"ไม่สามารถเลือกตัวละครได้ +The selected character is invalid"#, + "main.login.client_crashed": r#"ตัวเกมปิดตัวลงกระทันหัน +Client crashed"#, + "main.login.not_on_whitelist": r#"ต้องได้รับคำอนุญาตในการเชื่อมต่อเข้าเซิร์ฟเวอร์ +You need a Whitelist entry by an Admin to join"#, + "main.login.banned": "ถูกแบนจากเซิร์ฟเวอร์ เนื่องจากเหตุผลต่อไปนี้", + "main.login.kicked": "ถูกเตะจากเซิร์ฟเวอร์ เนื่องจากเหตุผลต่อไปนี้", + "main.login.select_language": "เลือกภาษา", + "main.login.client_version": "เวอร์ชั่นของตัวเกม", + "main.login.server_version": "เวอร์ชั่นของเซิร์ฟเวอร์", + "main.login.client_init_failed": r#"ไม่สามารถเริ่มตัวเกมได้ เนื่องจาก {init_fail_reason} +Client failed to initialize: {init_fail_reason}"#, + "main.login.username_bad_characters": "ชื่อประกอบตัวตัวอักษรต้องห้าม (อนุญาตให้ใช้ตัวอักษร a-z, 0-9, '_' และ '-' เท่านั้น)", + "main.login.username_too_long": "ชื่อยาวเกินไป เต็มที่ {max_len} ตัวอักษร", + "main.servers.select_server": "เลือกเซิร์ฟเวอร์", + "main.servers.singleplayer_error": r#"ไม่สามารถเข้าเล่มโหมดผู้เล่นคนเดียวได้ ข้อผิดพลาด:{sp_error} +Failed to connect to internal server: {sp_error}"#, + "main.servers.network_error": r#"เกิดความผิดพลาดขึ้นกับเคลือข่าย ข้อผิดพลาด: {raw_error} +Server network/socket error: {raw_error}"#, + "main.servers.participant_error": r#"โปรโตคอลผิดพลาด ข้อผิดพลาด: {raw_error} +Participant disconnect/protocol error: {raw_error}"#, + "main.servers.stream_error": r#"เกิดข้อผิดพลาดกับการเชื่อมต่อ, การบีบอัดข้อมูล หรือการอ่านข้อมูล: {raw_error} +Client connection/compression/(de)serialization error: {raw_error}"#, + "main.servers.database_error": r#"ฐานข้อมูลของเซิร์ฟเวอร์ล้มเหลว ข้อผิดพลาด: {raw_error} +Server database error: {raw_error}"#, + "main.servers.persistence_error": r#"เซิร์ฟเวอร์ไม่สามารถรักษาข้อมูลได้ ข้อผิดพลาด: {raw_error} +Server persistence error (Probably Asset/Character Data related): {raw_error}"#, + "main.servers.other_error": "Server general error: {raw_error}", + + // Credits screen + "main.credits": "เครดิต", + "main.credits.created_by": "โดย", + "main.credits.music": "เพลง", + "main.credits.fonts": "ตัวหนังสือ", + "main.credits.other_art": "การออกแบบอื่น ๆ", + "main.credits.contributors": "ผู้สนับสนุน", + + /// End Main screen section + }, + + + vector_map: { + // The keybinding names can be found in voxygen/src/game_input.rs in the GameInput enum + "loading.tips": [ + "ในโลกที่มืดมิดกด '{gameinput.togglelantern}' เพื่อจุดตะเกียงได้นะ", + "กด '{gameinput.help}' เพื่อดูปุ่มควมคุมต่าง ๆ ได้", + "ใช้คำสั่ง /say หรือ /s ในช่องสนทนาเพื่อพูดคุยกับผู้เล่นที่อยู่ใกล้ ๆ", + "ใช้คำสั่ง /region หรือ /r ในช่องสนทนาเพื่อพูดคุยกับผู้เล่นที่ในระยะหนึ่งบล็อค", + "ผู้ที่เป็นแอดมินสามารถใช้คำสั่ง /build เพื่อเข้าสู่โหมดสร้างได้", + "ใช้คำสั่ง /group หรือ /g ในช่องสนทนาเพื่อพูดคุยกับผู้เล่นที่อยู่ในปาร์ตี้", + "อยากคุยกับใครเป็นการส่วนตัว ใช้คำสั่ง /tell ตามด้วยชื่อผู้เล่นและข้อความ เพื่อกระซิบ", + "อาหาร, ไห และกล่องสมบัติสามารถพบได้ทั่วไป ลองหาดูดี ๆ นะ", + "กระเป๋าเต็มเพราะอาหารเยอะใช่ไหม? ลองทำอาหารที่ดีกว่าจากอาหารที่มีอยู่สิ", + "นั่งว่าง ๆ ไม่มีอะไรทำหรอ? ลองไปตะลุยดันเจียนสักหน่อยไหมหล่ะ?", + "อย่าลืมตั้งค่ากราฟฟิกให้เหมาะสมกับหน้าจอของตัวเองนะ กด '{gameinput.settings}' เพื่อเปิดเมนูตั้งค่า", + "เล่นกับเพื่อนจะยิ่งสนุกกว่า กด '{gameinput.social}' เพื่อดูว่าเพื่อนคนไหนกำลังออนไลน์", + "กด '{gameinput.dance}' เพื่อเต้น ไหนเอาท่าเต้นมาดูหน่อยสิ!", + "กด '{gameinput.glide}' เพื่อใช้เครื่องร่อน วันนี้เราจะไปแตะขอบฟ้ากัน!", + "ถึงแม้ว่าเวโลเรนจะยังอยู่ในช่วง Pre-Aplha แต่พวกเราก็ตั้งใจพัฒนาเกมทุกวันนะ!", + "อยากมีส่วนร่วมในการพัฒนาเวโลเรนหรืออยากคุยกับทีมพัฒนาใช่ไหม มาเจอเราใน Discord สิ!", + "คุณสามารถปิดตัวเลขที่แสดงพลังชีวิตได้ด้วยการตั้งค่า", + "นั่งพักใกล้ ๆ แคมป์ไฟ (กด '{gameinput.sit}') เพื่อฟื้นฟูพลังชีวิตและความเหนื่อยล้า", + "ประสบปัญหากระเป๋าเต็มหรือเกราะไม่โหดพอใช่ไหม สร้างกระเป๋าและเกราะที่โหดขึ้นกว่าเดิมได้โดยการเปิดเมนูสร้างของ กด '{gameinput.crafting}'", + "กด '{gameinput.roll}' เพื่อหลบการโจมตีแบบดิจิทัล", + "ไม่แน่ใจว่าวัตถุในการสร้างของหาจากไหนหรอ? พิม 'input:' ในแถบด้านบนเพื่อดูวัตถุที่ต้องใช้", + "ถ่ายรูปเท่ห์ ๆ ไปอวดเพื่อนด้วย '{gameinput.screenshot}'", + ], + } +) diff --git a/assets/voxygen/i18n/th_TH/npc.ron b/assets/voxygen/i18n/th_TH/npc.ron new file mode 100644 index 0000000000..9c9006eb69 --- /dev/null +++ b/assets/voxygen/i18n/th_TH/npc.ron @@ -0,0 +1,250 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for ไทย (Thai) +( + string_map: { + }, + + vector_map: { + "npc.speech.villager": [ + "ฮืมมมม ชีส", + ], + "npc.speech.villager_open": [ + "วัวคิดอะไรตอนกินหญ้านะ คิดเหมือนตอนเรากินข้าวหรือเปล่า?", + "สงสัยไหมว่าทำไม Glowing Remains ถึงเรืองแสงได้", + "เคยเห็น Land Shark ไหม ฉันได้ข่าวว่ามีคนเจอแถบทะเลทราย", + "อีกฝากของภูเขามีศัตรูอยู่ใช่ไหม?", + "เคยฝากขนมไว้ให้กับน้อง แล้วพอกลับมาเอาคืนขนมหายไปไหม? น่าแปลกใจจริง ๆ", + "เคยจับหิ้งห้อยไหม? เคยหรอ?", + "เขาลือกันว่าในถ้ำมีอัญมนีเต็มไปหมดเลยนะ เชื่อไหม", + "Sauroks พวกนี้มากจากไหนกันนะเต็มไปหมดเลย", + ], + "npc.speech.villager_adventurous": [ + "สักวันฉันจะสร้างเครื่องร่อนแล้วบินไปแตะขอบฟ้าให้ได้เลย", + "ไวฉันโตกว่านี้อีกนิดหนึ่งชั้นจะเข้าไปตะลุยถ้ำนั้นให้รู้แล้วรู้รอด", + ], + "npc.speech.villager_closed": [ + "หน้าตาไม่คุ้นเลย ทำตัวตามสบายนะคนแปลกหน้า", + "หมู่บ้านเราสุดยอดที่สุดแล้วในระแวงนี้หน่ะนะ", + "มีคนเคยผ่านมาแล้วเล่าให้ฟังว่า Mushroom เนี่ยดีต่อสุขภาพสุด ๆ ฉันก็ไม่รู้หรอกนะว่าจริงแท้ขนาดไหน", + "จะทำดี หรือจะไม่ทำดี กลับบ้านไปเลี้ยงวัวดีกว่า", + ], + "npc.speech.villager_conscientious": [ + "ฉันไม่ใช่นักเดินทางหรอก แต่ก็มีอะไรให้ทำตลอดนั่นแหละ", + "เชื่อไหมว่ามีคนคนหนึ่งสั่งฝนให้ตกได้ด้วยนะ", + ], + "npc.speech.villager_busybody": [ + "ฉันกำลังยุ่งมาก ๆ ขอโทษทีนะ", + ], + "npc.speech.villager_unconscientious": [ + "อาหารเช้าเป็นสิ่งสำคัญนะ มากินข้าว(รอบที่สอง)กันดีกว่า", + "บ้านฉันไม่เรียบร้อยเท่าไหร่ แต่ถ้าฉันคิดแบบนั้นฉันก็ต้องเก็บกวาดอยู่ ไม่เอาดีกว่า ฮ่าฮ่าฮ่า", + "เป็นเรื่องแล้วไง... แว่นตาหาย", + ], + "npc.speech.villager_extroverted": [ + "เมื่อวันก่อนนะพี่ แหม่ไม่อยากจะเล่า", + "อรุณเบิกฟ้า นกกาโบยบิน", + "ว่าไงคุณนักเดินทาง อากาศแจ๋มเลยใช่ไหมหล่ะ", + "ฉันได้บอกคุณหรือยังว่าฉันชอบชีสมาก ๆ เลย", + "วันนี้เป็นอย่างไรบ้างคุณนักเดินทาง!", + "ชีสคนแคระนี้ช่างอร่อยเกินบรรยายจริง ๆ ถ้าทำกินเองได้คงจะดีน่าดู", + "คุณทำนายฝันเป็นไหม? เมื่อคืนฉันฝันว่ามีชีสก้อนเบ้อเร่อมารัดด้วยแหละ", + "ฉันชอบน้ำผึ้งนะ แต่ไม่ถูกใจผึ้งเท่าไหร่ มีที่ไหนต่อยเขาแล้วตายเอง???", + ], + "npc.speech.villager_sociable": [ + "นั่งพักกินชีสกับเราก่อนไหมคุณนักเดินทาง? ฉันรับประกันว่าอร่อย", + "อยากเห็นสวนสุดรักของพวกเรารึเปล่า ! ไม่หรอ?, โอเค..งั้ไว้ครั้งหน้าก็ได้.", + "ฉันปลูกดอกไม้ไว้เต็มเลย อยากดูไหมคุณนักเดินทาง? ไม่อยากหรอ? แย่จัง", + ], + "npc.speech.villager_introverted": [ + "มิงกาลาบา", + "ฉันก็แค่ชาวบ้านธรรมดา ๆ ที่ผ่านทางมาก็เท่านั้นแหละ", + ], + "npc.speech.villager_agreeable": [ + "วันนี้อากาศเย็นสบาย ใช่ไหมคุณนักเดินทาง", + "ถ้ามีอะไรให้ช่วยบอกฉันได้เลยนะ", + "แมวฉัน แมวฉันหาย มีใครเห็นแมวฉันไหม!?", + ], + "npc.speech.villager_worried": [ + "ฉันมีลางสังหรณ์ไม่ดีเลย ระวังตัวด้วยนะคุณนักเดินทาง ฉันเป็นห่วงคุณเหลือเกิน", + ], + "npc.speech.villager_disagreeable": [ + "คนสมัยนี้พูดตรงไปก็ไม่ชอบ พูดอ้อมไปก็ไม่ชอบ เอาแต่ใจจริง ๆ", + "เดี๋ยวนี้คนเป็นอะไรไปหมดเปราะบางกันเหลือเกิน", + ], + "npc.speech.villager_neurotic": [ + "มีดันเจียนอยู่ใกล้ ๆ แบบนี้ฉันรู้สึกไม่สบายใจเลย เมื่อไหร่จะมีคนไปกำจัดมอสเตอร์พวกนั้นนะ", + "ต้องมีคนไปจัดพวก Cultist ให้ราบคาบไปสักที แค่ออกความเห็นนะ ไม่ได้จะอาสา", + "ท้องไส้ไม่ดีเลย รู้สึกเหมือนเรื่องร้าย ๆ จะเกิดขึ้น", + "พวก Wolf ชักจะเข้ามาใกล้หมู่บ้านเกินไปแล้ว ต้องหาคนฝีมือดีไปไล่", + ], + "npc.speech.villager_sad_loner": [ + "เหงาจัง", + "... ขอโทษที พอดีว่าฉันน่ะคุยไม่ค่อยเก่งเท่าไหร่", + ], + "npc.speech.villager_seeker": [ + "ฉันอยากไปเห็นโลกภายนอก นอกกำแพงนี้ นั่นแหละความฝันของฉันเอเรน เย...", + ], + "npc.speech.villager_stable": [ + "วันนี้เป็นวันที่สงบดีจริง ๆ", + "ชีวิตมันก็... ไม่ได้แย่ขนานนั้นนะ", + "ช่างเป็นวันที่สดใส นกร้องขับขาน ดอกไม้เบ่งบาน ในวันแบบนี้คนแบบคุณควรไปเดินเล่นในป่า!", + ], + "npc.speech.villager_decline_trade": [ + "ขอโทษที ฉันไม่ของอะไรจะแลกหรอก", + "ชาวบ้านอย่างฉันจะมีของอะไรไปแลกกับคุณ", + "บ้านหลังนี้ฉันยังโปะไม่หมดน่ะ คงจะแลกไม่ได้หรอกนะ!", + ], + "npc.speech.merchant_advertisement": [ + "แวะดูสักนิด แวะพักสักหน่อย อาจจะเจอของที่ถูกใจนะคุณนักเดินทาง", + "อยากซื้อขายรึเปล่าเอ่ย?", + "ฉันมีของเด็ด เด็ดเยอะแยะเลยนะ อยากจะดูไหมหล่ะ?" + ], + "npc.speech.merchant_busy": [ + "ช้าก่อนสหาย ฉันมีแค่สองมือ", + "สักครู่นะ ใกล้จะเสร็จแล้ว", + "ฉันยุ่งมากเลย ขอเวลาอีกสักพักรพ", + ], + "npc.speech.merchant_busy_rude": [ + "เด็กสมัยนี้รอไม่เป็นเลยรึ", + "กลับไปต่อแถวซะ เจ้าคนไร้สามัญสำนึก", + "แซงคิวแบบนี้ นิสัยไม่ดีเลยนะ", + ], + "npc.speech.merchant_trade_successful": [ + "ยินดีที่ได้ทำธุริกจร่วมกัน สหาย", + "ขอบคุณนะ", + ], + "npc.speech.merchant_trade_declined": [ + "แหม่ น่าเสียดายจริง ๆ ไว้คราวหน้าก็แล้วก็", + "อินิดูก่อนแล้วกลับมาซื้อทีหลังได้นะจ๊ะนายจ๋า" + ], + "npc.speech.villager_cultist_alarm": [ + "ทุกคนระวัง! พวก Cultist กำลังมา!", + "ผู้ชายมาทางนี้! พวก Cultist บุกแล้ว!", + "ใจกล้ามากที่จะตีหมู่บ้านของเรา เจ้าพวก Cultist!", + "ทำให้มันเสียใจที่มาบุกหมู่บ้านเรา!", + "อย่าให้พวกมันคิดว่าเราอ่อนแอ แสดงให้มันเห็นว่าไม่กลัวมัน", + "เจ้าพวก Cultist สารเลว", + "เป็นไงรสชาติคมดาบฉันถูกปากไหม เจ้าพวก Cultist โสมม", + "ชีวิตของคนบริสุทธิ์ที่ไร้ทางสู้ พวกแกจะต้องชดใช้", + "พระเจ้าช่วยกล้วยทอด มีพวก Cultist ปลอมตัวมาในหมู่พวกเรา", + "ความชั่วร้ายของพวกแก จะจบอยู่ที่นี้!", + "อย่างแกเนี่ยต้องเจอคนอย่างฉัน!", + "สวดมนต์อ้อนวอนไปก็เท่านั้นแหละ เจ้าพวก Cultist", + "มันอยู่ตรงนั้น พวกลุย", + "ตรงหน้าสิบสองนาฬิกา พวกเราจัดให้มันสักดอก", + "ตรงนั้น อย่ามันรอดไปได้", + "สนใจรับความตายร้อน ๆ สักจอกไหมหล่ะ เดี๋ยวฉันเลี้ยงเอง", + "ฉันจะไม่วันลืมสิ่งที่แกทำกับฉัน ไม่มีวัน!", + "ชีวิตที่น่าสังเวช จบสิ้นเพียงเท่านี้", + "ลัทธิอันโสโครก สิ้นสุดแล้ว", + "กรรมติดคมดาบ", + "ขอโทษที แต่พวกเราไม่ต้อนรับ", + "อยู่แบบหลบ ๆ ซ่อน ๆ ก็ดีอยู่แล้ว", + ], + "npc.speech.villager_under_attack": [ + "ทางนี้! ช่วยด้วย!", + "ทางนี้! ช่วยด้วย!", + "โอ้ย! เล่นแรงจัง โป้ง! ไม่เล่นด้วยแล้ว", + "โอ้ย! เล่นแรงจัง โป้ง! ไม่เล่นด้วยแล้ว", + "ฉันพลาดท่าแล้ว ช่วยด้วย! ทางนี้!", + "ได้ทีขี่ม้าไล่เลยนะ ใครก็ได้ช่วยmu!", + "ช่วยด้วย!", + "เจ็บเหลือเกิน ใครก็ได้ช่วยฉันmy!", + "อั๊ก ช่วย...ด้วย ได้โปรด", + "ทางนี้! ทางนี้!", + "ทางนี้! ทางนี้! เร็วเข้า!", + "ฉันต้านไว้ได้อีกไม่นาน", + "บ้าที่สุด! ขอกำลังเสริมด่วน!", + "บัดสบเอ๊ย! ขอกำลังเสริมด่วน!", + "ใครก็ได้ช่วยพวกเราด้วย!", + "ฆาตกรเต็มไปหมด ช่วยฉันที!", + "ฆาตกรเต็มไปหมด ทุกคนต้านไว้!", + "ช่วยด้วย! พวกมันจะฆ่าฉัน", + "ทหาร ทางนี้เร็วเข้า!", + "ทหาร ทางนี้!", + "ทหาร! ได้โปรดปกป้องฉันด้วย", + "ทหาร! ใครก็ได้! ฉันกลัวเหลือเกิน", + "ทหาร! มีเรื่องแล้ว!", + "ทหาร! ทหาร!", + "ทหาร! มีผู้ร้ายอยู่ตรงนี้!", + "ใครก็ได้ จัดการคนพวกนี้ที!", + "ทหาร! มีคนจะทำร้ายฉัน", + "พระเจ้าคุ้มครอง", + "ทหารหายไปไหนกันหมด ฉันอยู่ตรงนี้! ช่วยด้วย!", + "สารเลว!", + "ได้โปรด ฉันยังไม่อยากตาย", + "ได้โปรด พระเจ้าช่วยคุ้มครองลูกด้วย", + "โอ้ย! เจ็บนะ!", + "พวกมันกำลังจะมาฆ่าฉัน", + "พวกมันจะบูชาฉัน ช่วยด้วย!", + "ความรุนแรง ช่างเป็นวงจรที่อุบาวท์เสียจริง", + "แค่นี้ ไกลหัวใจ (ปอด)", + "พอใจหรือยัง", + "ฉันไปทำอะให้แค้นเคืองกันหรือยังไง", + "อย่าทำอะไรฉันอีกเลย ฉันกลัวแล้ว", + "ถือมีดระวังหน่อยสิ เกิดผีผลักขึ้นมาจะทำยังไง!", + "ฉันขอสาปแช่งพวกแกทุกตน", + "ได้โปรด ได้โปรด", + "ชักจะมีน้ำโหขึ้นมาแล้วนะ!", + "อาการมันเป็นยังไงหนิ พี่บ่าว", + "ฉันเอาคืนให้สาสมเลยคอยดู", + "ฉันไม่ของมีค่าอะไรหรอก อย่าทำอะไรฉันเลย", + "หยุดนะ ไม่งั้นฉันจะไปฟ้องพ่อ ให้มาจัดการคุณ", + "แงงงงง แม่จ้าช่วยหนูด้วยยยย", + "เทวดาฟ้าดินเป็นพยาน", + "สหาย อย่าทำแบบนี้เลย มันบาปนะ", + "นี้! นิสัยไม่ดีเลยนะ", + "พอได้หรือยังพ่อคุณ รู้แล้วว่าเก่ง", + "ไว้ชีวิตข้าน้อยด้วย", + "ฉันมีครอบครัวที่ต้องเลี้ยง ถ้าฉันตายพวกเขาจะอยู่ยังไง", + "ฉันยังเด็กอย่าทำอะไรฉันเลย", + "ค่อย ๆ พูด ค่อย ๆ จากันก่อนสหาย", + "ใช้ความรุนแรงแก้ปัญหาไม่ได้นะ มันไม่ถูกต้อง!", + "ถึงว่าหล่ะ เมื่อเช้าจิ้งจกทัก...", + "อุ๊ย เจ็บนะ ระวังหน่อยสิ!", + "ว๊ายยยยยยยยยย", + "ไร้มารยาทสิ้นดี", + "พอเถอะก่อนจะบานปลาย", + "สาธุ ของให้หน้าเป็นสิว", + "สนุกอยู่คนเดียวแบบนี้ ใช้่ไม่ได้", + "รู้ไหมว่าฉันเป็นลูกใคร!?", + "ระวังเถอะ เวรกรรมจะตามทัน", + "หยุดเถอะ ก่อนจะเจ็บตัว", + "ช้าก่อน ฉันไม่อยากมีเรื่อง", + "ต้องมีเรื่องอะไรเข้าใจผิดกันแน่ ๆ", + "เราอย่าใช้กำลังคุยกันเลยนะ", + "ไส่หัวไป เจ้าคนสถุน", + "เจ็บไปหมดแล้ว", + "มาอารมณ์ไหนอีกละเนี่ย", + "ฉันชักจะรำคาญแล้วสิ ", + "จ จำคนผิดแล้ววววว", + "เสี่ยส่งคนมาจริง ๆ หรอเนี่ย?", + "พอเถอะนะ เอาจริง ๆ จากใจเลย", + "ทหาร! เอามันไปขัง", + "ส่งหมาไปกัดซะดีไหม", + "ฉันผิดอารายยยยย", + ], + "npc.speech.villager_enemy_killed": [ + "ต่อหน้าข้า ศัตรูพ่ายแพ้เช่นเคย", + "ความสงบสุขกลับมาอีกครั้ง", + "... เรา มาทำอะไรอยู่ตรงนี้กันนะ", + ], + "npc.speech.menacing": [ + "อย่าบอกว่าไม่เตือนนะ", + "ห่าง ๆ หน่อยสหาย", + "น่ากลัวตายหล่ะ", + "ไปไหนก็ไป", + "อยากหลับแบบไม่ง่วงสิท่า", + "ไม่ชอบขี้หน้าเลยแหะ", + ], + "npc.speech.cultist_low_health_fleeing": [ + "พี่น้องข้า กลับไปตั้งหลัก!", + "พี่น้องข้า ถอย!", + "ฝากไว้ก่อนเถอะ", + "ความอัปยศนี้ ข้าจะตามล้างแค้นทุกชาติไป", + "เหนื่อยเหลือเกิน ต้อง... หนี", + "ทุกอย่าง ดู... มืดไปหมด", + ] + } +) diff --git a/assets/voxygen/i18n/th_TH/template.ron b/assets/voxygen/i18n/th_TH/template.ron new file mode 100644 index 0000000000..f0d8b704da --- /dev/null +++ b/assets/voxygen/i18n/th_TH/template.ron @@ -0,0 +1,12 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for "global" English +( + string_map: { + + }, + + + vector_map: { + } +) From d18483756b12a99839af6d14fdbff515d831cca1 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 22 May 2022 19:37:52 +0100 Subject: [PATCH 003/229] Fixed frozen character when wall-run into water horizontally --- common/src/states/wallrun.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/common/src/states/wallrun.rs b/common/src/states/wallrun.rs index 4b802f1cbe..a7a7594a3a 100644 --- a/common/src/states/wallrun.rs +++ b/common/src/states/wallrun.rs @@ -31,8 +31,13 @@ impl CharacterBehavior for Data { .max(0.2); } - // fall off wall or hit ground - if data.physics.on_wall.is_none() || data.physics.on_ground.is_some() { + // fall off wall, hit ground, or enter water + // TODO: Rugged way to determine when state change occurs and we need to leave + // this state + if data.physics.on_wall.is_none() + || data.physics.on_ground.is_some() + || data.physics.in_fluid.is_some() + { update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); } From fe11d6d5bcb9a3b02ebf9677e2e68e57cd5a6f4e Mon Sep 17 00:00:00 2001 From: Hugo Peixoto Date: Thu, 12 May 2022 00:56:47 +0100 Subject: [PATCH 004/229] Split sky shader's twilight into dawn and dusk Instead of having the same color profiles for the sky's color, light, and halo, we now have the ability to define different values for dawn and dusk. The dusk values were unchanged and the dawn values are similar, but with less red. These should probably be tweaked a bit more. --- assets/voxygen/shaders/include/sky.glsl | 31 +++++++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/assets/voxygen/shaders/include/sky.glsl b/assets/voxygen/shaders/include/sky.glsl index 585a5ef5f4..9c2b9bd0ce 100644 --- a/assets/voxygen/shaders/include/sky.glsl +++ b/assets/voxygen/shaders/include/sky.glsl @@ -18,6 +18,12 @@ struct DirectionalLight { const float PI = 3.141592; +const vec3 SKY_DAWN_TOP = vec3(0.10, 0.1, 0.10); +const vec3 SKY_DAWN_MID = vec3(1.2, 0.3, 0.2); +const vec3 SKY_DAWN_BOT = vec3(0.0, 0.1, 0.23); +const vec3 DAWN_LIGHT = vec3(5.0, 2.0, 1.15); +const vec3 SUN_HALO_DAWN = vec3(8.2, 3.0, 2.1); + const vec3 SKY_DAY_TOP = vec3(0.1, 0.5, 0.9); const vec3 SKY_DAY_MID = vec3(0.02, 0.28, 0.8); const vec3 SKY_DAY_BOT = vec3(0.1, 0.2, 0.3); @@ -143,9 +149,11 @@ float get_moon_brightness(/*vec3 moon_dir*/) { } vec3 get_sun_color(/*vec3 sun_dir*/) { + vec3 light = (sun_dir.x > 0) ? DUSK_LIGHT : DAWN_LIGHT; + return mix( mix( - DUSK_LIGHT * magnetosphere_tint, + light * magnetosphere_tint, NIGHT_LIGHT, max(sun_dir.z, 0) ), @@ -450,9 +458,22 @@ vec3 get_sky_light(vec3 dir, float time_of_day, bool with_stars) { star = is_star_at(star_dir); } + vec3 sky_twilight_top = vec3(0.0, 0.0, 0.0); + vec3 sky_twilight_mid = vec3(0.0, 0.0, 0.0); + vec3 sky_twilight_bot = vec3(0.0, 0.0, 0.0); + if (sun_dir.x > 0) { + sky_twilight_top = SKY_DUSK_TOP; + sky_twilight_mid = SKY_DUSK_MID; + sky_twilight_bot = SKY_DUSK_BOT; + } else { + sky_twilight_top = SKY_DAWN_TOP; + sky_twilight_mid = SKY_DAWN_MID; + sky_twilight_bot = SKY_DAWN_BOT; + } + vec3 sky_top = mix( mix( - SKY_DUSK_TOP * magnetosphere_tint, + sky_twilight_top * magnetosphere_tint, SKY_NIGHT_TOP, pow(max(sun_dir.z, 0.0), 0.2) ) + star, @@ -462,7 +483,7 @@ vec3 get_sky_light(vec3 dir, float time_of_day, bool with_stars) { vec3 sky_mid = mix( mix( - SKY_DUSK_MID * magnetosphere_tint, + sky_twilight_mid * magnetosphere_tint, SKY_NIGHT_MID, pow(max(sun_dir.z, 0.0), 0.1) ), @@ -472,7 +493,7 @@ vec3 get_sky_light(vec3 dir, float time_of_day, bool with_stars) { vec3 sky_bot = mix( mix( - SKY_DUSK_BOT * magnetosphere_tint, + sky_twilight_bot * magnetosphere_tint, SKY_NIGHT_BOT, pow(max(sun_dir.z, 0.0), 0.2) ), @@ -507,7 +528,7 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q const vec3 SUN_SURF_COLOR = vec3(1.5, 0.9, 0.35) * 50.0; vec3 sun_halo_color = mix( - SUN_HALO_DUSK * magnetosphere_tint, + (sun_dir.x > 0 ? SUN_HALO_DUSK : SUN_HALO_DAWN)* magnetosphere_tint, SUN_HALO_DAY, pow(max(-sun_dir.z, 0.0), 0.5) ); From 5ac9c720a179efd6b3b36e5e878ea59d90033605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Grupi=C5=84ski?= Date: Sun, 3 Apr 2022 20:07:04 +0000 Subject: [PATCH 005/229] MR3316 "Draft: Updated translations" without the directory movement and squashed: Renewed Polish translations Added spaces and change sequences so code fits to English version --- assets/voxygen/i18n/pl_PL/_manifest.ron | 4 +- assets/voxygen/i18n/pl_PL/buff.ron | 17 ++++++- assets/voxygen/i18n/pl_PL/char_selection.ron | 2 + assets/voxygen/i18n/pl_PL/common.ron | 35 +++++++++++--- assets/voxygen/i18n/pl_PL/esc_menu.ron | 2 + assets/voxygen/i18n/pl_PL/gameinput.ron | 7 +++ assets/voxygen/i18n/pl_PL/hud/bag.ron | 11 +++-- assets/voxygen/i18n/pl_PL/hud/char_window.ron | 2 + assets/voxygen/i18n/pl_PL/hud/chat.ron | 18 ++++++-- assets/voxygen/i18n/pl_PL/hud/crafting.ron | 21 +++++++-- assets/voxygen/i18n/pl_PL/hud/group.ron | 2 + assets/voxygen/i18n/pl_PL/hud/map.ron | 21 +++++++-- assets/voxygen/i18n/pl_PL/hud/misc.ron | 28 +++++++---- assets/voxygen/i18n/pl_PL/hud/sct.ron | 2 + assets/voxygen/i18n/pl_PL/hud/settings.ron | 46 ++++++++++++++++--- assets/voxygen/i18n/pl_PL/hud/skills.ron | 17 ++++++- assets/voxygen/i18n/pl_PL/hud/social.ron | 2 +- assets/voxygen/i18n/pl_PL/hud/trade.ron | 9 +++- assets/voxygen/i18n/pl_PL/main.ron | 32 +++++++++++-- assets/voxygen/i18n/pl_PL/npc.ron | 25 +++++++++- 20 files changed, 256 insertions(+), 47 deletions(-) diff --git a/assets/voxygen/i18n/pl_PL/_manifest.ron b/assets/voxygen/i18n/pl_PL/_manifest.ron index 01c06b652f..c45b621503 100644 --- a/assets/voxygen/i18n/pl_PL/_manifest.ron +++ b/assets/voxygen/i18n/pl_PL/_manifest.ron @@ -1,4 +1,6 @@ -/// Localization for Polish / Tłumaczenia dla języka polskiego +/// Localization for Polish + +/// Tłumaczenia dla języka polskiego ( metadata: ( language_name: "Polish", diff --git a/assets/voxygen/i18n/pl_PL/buff.ron b/assets/voxygen/i18n/pl_PL/buff.ron index 283575691e..7aa52b2bf2 100644 --- a/assets/voxygen/i18n/pl_PL/buff.ron +++ b/assets/voxygen/i18n/pl_PL/buff.ron @@ -1,4 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { // Buffs @@ -12,11 +14,15 @@ "buff.title.saturation": "Najedzenie", "buff.desc.saturation": "Odzyskaj zdrowie jedząc żywność.", "buff.title.campfire_heal": "Odpoczynek przy ognisku", - "buff.desc.campfire_heal": "Odpoczywanie przy ognisku odzyskuje {rate}% zdrowia na sekundę.", + "buff.desc.campfire_heal": "Odpoczywanie przy ognisku odnawia {rate}% zdrowia na sekundę.", "buff.title.invulnerability": "Nietykalność", "buff.desc.invulnerability": "Nie można Cię zranić.", "buff.title.protectingward": "Totem ochronny", "buff.desc.protectingward": "Ochrona, poniekąd, przed atakami.", + "buff.title.frenzied": "Oszalały", + "buff.desc.frenzied": "Jesteś wypełniony nienaturalną prędkością i ignorujesz pomniejsze obrażenia.", + "buff.title.hastened": "Szybkość", + "buff.desc.hastened": "Twoje ruchy i ataki są szybsze.", // Debuffs "buff.title.bleed": "Krwawienie", "buff.desc.bleed": "Zadaje regularne obrażenia.", @@ -24,6 +30,14 @@ "buff.desc.cursed": "Jesteś przeklęty.", "buff.title.burn": "Płoniesz", "buff.desc.burn": "Palisz się żywcem", + "buff.title.crippled": "Okaleczony", + "buff.desc.crippled": "Ruszasz się jak kaleka, gdyż twoje nogi są bardzo poranione.", + "buff.title.frozen": "Zmrożony", + "buff.desc.frozen": "Twoje ruchy i ataki są spowolnione.", + "buff.title.wet": "Mokry", + "buff.desc.wet": "Ciężko Ci się zatrzymać? W końcu się ślizgasz!", + "buff.title.ensnared": "Spętany", + "buff.desc.ensnared": "Pnącza oplotły twoje nogi, utrudniając Ci ruch.", // Buffs stats "buff.stat.health": "Odnawia {str_total} Zdrowia", "buff.stat.increase_max_energy": "Podnosi Maksymalną Wytrzymałość o {strength}", @@ -34,6 +48,7 @@ "buff.text.for_seconds": "na {dur_secs} sekund", }, + vector_map: { } ) diff --git a/assets/voxygen/i18n/pl_PL/char_selection.ron b/assets/voxygen/i18n/pl_PL/char_selection.ron index 3950c77217..4b7b51c6bf 100644 --- a/assets/voxygen/i18n/pl_PL/char_selection.ron +++ b/assets/voxygen/i18n/pl_PL/char_selection.ron @@ -1,4 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { "char_selection.loading_characters": "Ładowanie postaci...", diff --git a/assets/voxygen/i18n/pl_PL/common.ron b/assets/voxygen/i18n/pl_PL/common.ron index 08a30d983a..d5a10d4c41 100644 --- a/assets/voxygen/i18n/pl_PL/common.ron +++ b/assets/voxygen/i18n/pl_PL/common.ron @@ -1,8 +1,10 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { // Texts used in multiple locations with the same formatting - "common.username": "nazwa konta", + "common.username": "Nazwa konta", "common.singleplayer": "Tryb jednoosobowy", "common.multiplayer": "Tryb wieloosobowy", "common.servers": "Serwery", @@ -14,6 +16,7 @@ "common.controls": "Sterowanie", "common.video": "Grafika", "common.sound": "Dźwięk", + "common.chat": "Czat", "common.resume": "Kontynuuj", "common.characters": "Postacie", "common.close": "Zamknij", @@ -34,6 +37,8 @@ "common.automatic": "Automatyczne", "common.random": "Losowo", "common.empty": "Pusty", + "common.confirm": "Potwierdź", + "common.delete_server": "Usuń serwer", // Settings Window title "common.interface_settings": "Ustawienia interfejsu", @@ -42,12 +47,14 @@ "common.video_settings": "Ustawienia grafiki", "common.sound_settings": "Ustawienia dźwięku", "common.language_settings": "Ustawienia języka", + "common.chat_settings": "Ustawienia czatu", // Message when connection to the server is lost - "common.connection_lost": r#"Stracono połączenia! + "common.connection_lost": r#"Stracono połączenie! Serwer jest restartowany? Czy masz aktualną wersję gry?"#, + "common.species.orc": "Ork", "common.species.human": "Człowiek", "common.species.dwarf": "Krasnolud", @@ -56,6 +63,9 @@ Czy masz aktualną wersję gry?"#, "common.species.danari": "Danari", "common.weapons.axe": "Siekiera", + "common.weapons.dagger": "Sztylet", + "common.weapons.greatsword": "Wielki miecz", + "common.weapons.shortswords": "Krótki miecz", "common.weapons.sword": "Miecz", "common.weapons.staff": "Kostur maga", "common.weapons.bow": "Łuk", @@ -73,6 +83,7 @@ Czy masz aktualną wersję gry?"#, "common.tool.debug": "Debug", "common.tool.farming": "Narzędzie do uprawy", "common.tool.pick": "Kilof", + "common.tool.mining": "Wykopywanie", "common.kind.modular_component": "Modularny komponent", "common.kind.glider": "Lotnia", "common.kind.consumable": "Jadalne", @@ -89,12 +100,24 @@ Czy masz aktualną wersję gry?"#, "common.stats.combat_rating": "CR", "common.stats.power": "Moc", "common.stats.speed": "Prędkość", - "common.stats.poise": "Odp. na ogłu.", - "common.stats.crit_chance": "Krytyczne%", - "common.stats.crit_mult": "Krytytyczne*", + "common.stats.poise": "Odporność", + "common.stats.crit_chance": "% na cios kryt.", + "common.stats.crit_mult": "Mnożnik ciosu kryt.", "common.stats.armor": "Obrona", - "common.stats.poise_res": "Odp. na ogłu.", + "common.stats.poise_res": "Odp. na ogłuszenie", + "common.stats.energy_max": "Maksymalna energia", + "common.stats.energy_reward": "Bonus energii", + "common.stats.crit_power": "Moc ciosu kryt.", + "common.stats.stealth": "Skradanie", "common.stats.slots": "Sloty", + + "common.material.metal": "Metal", + "common.material.wood": "Drewno", + "common.material.stone": "Kamień", + "common.material.cloth": "Płótno", + "common.material.hide": "Skóra", + + "common.sprite.chest": "Skrzynia", }, diff --git a/assets/voxygen/i18n/pl_PL/esc_menu.ron b/assets/voxygen/i18n/pl_PL/esc_menu.ron index 524ac23292..ce8ee707e0 100644 --- a/assets/voxygen/i18n/pl_PL/esc_menu.ron +++ b/assets/voxygen/i18n/pl_PL/esc_menu.ron @@ -1,4 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { "esc_menu.logout": "Wyloguj", diff --git a/assets/voxygen/i18n/pl_PL/gameinput.ron b/assets/voxygen/i18n/pl_PL/gameinput.ron index a492049fb1..7f2ad228f5 100644 --- a/assets/voxygen/i18n/pl_PL/gameinput.ron +++ b/assets/voxygen/i18n/pl_PL/gameinput.ron @@ -1,4 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { "gameinput.primary": "Prosty atak", @@ -19,6 +21,8 @@ "gameinput.help": "Pokaż/schowaj okno pomocy", "gameinput.toggleinterface": "Pokaż/schowaj interfejs", "gameinput.toggledebug": "Pokaż/schowaj FPS i debugowanie", + "gameinput.toggle_egui_debug": "Włącz debugowanie EGUI", + "gameinput.togglechat": "Włącz czat", "gameinput.screenshot": "Zrób zrzut ekranu", "gameinput.toggleingameui": "Pokaż/schowaj imiona i nazwy", "gameinput.fullscreen": "Przełącz pełny ekran", @@ -63,8 +67,11 @@ "gameinput.swimup": "Wynurz", "gameinput.mapzoomin": "Przybliż mapę", "gameinput.mapzoomout": "Oddal mapę", + "gameinput.greet": "Pozdrów", + "gameinput.map.locationmarkerbutton": "Ustaw punkt orientacyjny na mapie" }, + vector_map: { } ) diff --git a/assets/voxygen/i18n/pl_PL/hud/bag.ron b/assets/voxygen/i18n/pl_PL/hud/bag.ron index 1ef6272b84..f822cdeaac 100644 --- a/assets/voxygen/i18n/pl_PL/hud/bag.ron +++ b/assets/voxygen/i18n/pl_PL/hud/bag.ron @@ -1,4 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { // Inventory @@ -22,15 +24,18 @@ "hud.bag.feet": "Stopy", "hud.bag.mainhand": "Ręka główna", "hud.bag.offhand": "Ręka poboczna", + "hud.bag.inactive_mainhand": "Nieaktywna ręka główna", + "hud.bag.inactive_offhand": "Nieaktywna ręka poboczna", + "hud.bag.swap_equipped_weapons_title": "Zamień założone bronie", + "hud.bag.swap_equipped_weapons_desc": "Wciśnij {key}", "hud.bag.bag": "Torba", "hud.bag.health": "Zdrowie", "hud.bag.energy": "Energia", - "hud.bag.combat_rating": "Combat Rating", + "hud.bag.combat_rating": "Combat Rating (CR)", "hud.bag.protection": "Ochrona", + "hud.bag.stun_res": "Odporność na ogłuszenie", "hud.bag.combat_rating_desc": "Liczone na postawie Twojego\nekwipunku i zdrowia.", "hud.bag.protection_desc": "Redukcja obrażeń dzięki pancerzowi", - - "hud.bag.stun_res": "Odporność na ogłuszenie", "hud.bag.stun_res_desc": "Odporność na ogłuszenie spowodowane przyjmowaniem wielu ciosów.\nRegeneruje się jak energia.", "hud.bag.sort_by_name": "Sortuj nazwami", "hud.bag.sort_by_quality": "Sortuj jakościami", diff --git a/assets/voxygen/i18n/pl_PL/hud/char_window.ron b/assets/voxygen/i18n/pl_PL/hud/char_window.ron index a5e2b44dd5..068e74811b 100644 --- a/assets/voxygen/i18n/pl_PL/hud/char_window.ron +++ b/assets/voxygen/i18n/pl_PL/hud/char_window.ron @@ -1,4 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { "character_window.character_name": "Imię postaci", diff --git a/assets/voxygen/i18n/pl_PL/hud/chat.ron b/assets/voxygen/i18n/pl_PL/hud/chat.ron index 066933145d..228a61359a 100644 --- a/assets/voxygen/i18n/pl_PL/hud/chat.ron +++ b/assets/voxygen/i18n/pl_PL/hud/chat.ron @@ -1,6 +1,18 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { + "hud.chat.all": "Wszystko", + "hud.chat.chat_tab_hover_tooltip": "Kliknij prawym aby otworzyć ustawienia", + + // Debuff outcomes + "hud.outcome.burning": "zmarł od podpalenia", + "hud.outcome.curse": "zmarł od klątwy", + "hud.outcome.bleeding": "zmarł przez wykrwawienie", + "hud.outcome.crippled": "zmarł od złamań", + "hud.outcome.frozen": "zmarł z zimna", + // Chat outputs "hud.chat.online_msg": "[{name}] jest online", "hud.chat.offline_msg": "[{name}] jest offline", @@ -10,15 +22,15 @@ "hud.chat.fall_kill_msg": "[{name}] spada z wysokości", "hud.chat.suicide_msg": "[{name}] umiera od własnych ran", - "hud.chat.pvp_buff_kill_msg": "[{victim}] umiera od {buff} - nałożone przez [{attacker}]", + "hud.chat.died_of_pvp_buff_msg": "[{victim}] {died_of_buff} nałożene przez [{attacker}]", "hud.chat.pvp_melee_kill_msg": "[{attacker}] zwycięża nad [{victim}]", "hud.chat.pvp_ranged_kill_msg": "[{attacker}] ustrzela [{victim}]", "hud.chat.pvp_explosion_kill_msg": "[{attacker}] wysadza [{victim}]", "hud.chat.pvp_energy_kill_msg": "[{attacker}] ubija [{victim}] magią", - "hud.chat.nonexistent_buff_kill_msg": "[{victim}] umiera od {buff}", + "hud.chat.died_of_buff_nonexistent_msg": "[{victim}] {died_of_buff}", - "hud.chat.npc_buff_kill_msg": "[{victim}] umiera od {buff} - nałożone przez {attacker}", + "hud.chat.died_of_npc_buff_msg": "[{victim}] {died_of_buff} nałożone przez {attacker}", "hud.chat.npc_melee_kill_msg": "{attacker} ubija [{victim}]", "hud.chat.npc_ranged_kill_msg": "{attacker} ustrzela [{victim}]", "hud.chat.npc_explosion_kill_msg": "{attacker} wysadza [{victim}]", diff --git a/assets/voxygen/i18n/pl_PL/hud/crafting.ron b/assets/voxygen/i18n/pl_PL/hud/crafting.ron index dc588ea204..2aa350d614 100644 --- a/assets/voxygen/i18n/pl_PL/hud/crafting.ron +++ b/assets/voxygen/i18n/pl_PL/hud/crafting.ron @@ -1,4 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { "hud.crafting": "Tworzenie", @@ -7,22 +9,31 @@ "hud.crafting.craft": "Stwórz", "hud.crafting.tool_cata": "Wymaga:", // Crafting Stations - "hud.crafting.req_crafting_station": "Wymaga użycia:", + "hud.crafting.req_crafting_station": "Wymaga:", "hud.crafting.anvil": "Kowadło", "hud.crafting.cauldron": "Kocioł", - "hud.crafting.cooking_pot": "Garnek", - "hud.crafting.crafting_bench": "Warsztat", + "hud.crafting.cooking_pot": "Gar", + "hud.crafting.crafting_bench": "Stół rzemieślniczy", + "hud.crafting.forge": "Piec", + "hud.crafting.loom": "Krosno", + "hud.crafting.spinning_wheel": "Kołowrotek", + "hud.crafting.tanning_rack": "Stojak do garbowania", + "hud.crafting.salvaging_station": "Stoisko odzyskiwania", + "hud.crafting.campfire": "Ognisko", // Tabs "hud.crafting.tabs.all": "Wszystko", "hud.crafting.tabs.armor": "Pancerz", - "hud.crafting.tabs.dismantle": "Recykling", + "hud.crafting.tabs.dismantle": "Zdemontuj", "hud.crafting.tabs.food": "Żywność", "hud.crafting.tabs.glider": "Lotnie", "hud.crafting.tabs.potion": "Mikstury", "hud.crafting.tabs.tool": "Narzędzia", "hud.crafting.tabs.utility": "Użytkowe", - "hud.crafting.tabs.weapon": "Broń", + "hud.crafting.tabs.weapon": "Bronie", "hud.crafting.tabs.bag": "Torby", + "hud.crafting.tabs.processed_material": "Materiały", + "hud.crafting.dismantle_title": "Demontowanie", + "hud.crafting.dismantle_explanation" : "Najedź na przedmioty w pleacaku aby\nzobaczyć co możesz odzyskać.\n\nKliknij podwójnie aby rozmontować.", }, diff --git a/assets/voxygen/i18n/pl_PL/hud/group.ron b/assets/voxygen/i18n/pl_PL/hud/group.ron index 653dfe2e3e..2899db7050 100644 --- a/assets/voxygen/i18n/pl_PL/hud/group.ron +++ b/assets/voxygen/i18n/pl_PL/hud/group.ron @@ -1,4 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { "hud.group": "Drużyna", diff --git a/assets/voxygen/i18n/pl_PL/hud/map.ron b/assets/voxygen/i18n/pl_PL/hud/map.ron index 85bdb6bbd4..e411f456a0 100644 --- a/assets/voxygen/i18n/pl_PL/hud/map.ron +++ b/assets/voxygen/i18n/pl_PL/hud/map.ron @@ -1,28 +1,41 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { // Map and Questlog "hud.map.map_title": "Mapa", "hud.map.qlog_title": "Zadania", + "hud.map.topo_map": "Widok topograficzny" "hud.map.difficulty": "Trudność", "hud.map.towns": "Miasta", "hud.map.castles": "Zamki", "hud.map.dungeons": "Lochy", "hud.map.caves": "Jaskinie", "hud.map.cave": "Jaskinia", - "hud.map.trees": "Gigan. drzewa", - "hud.map.tree": "Gigantyczne drzewo", + "hud.map.peaks": "Góry", + "hud.map.biomes": "Biomy", + "hud.map.voxel_map": "Mapa wokselowa", + "hud.map.trees": "Wielkie drzewa", + "hud.map.tree": "Wielkie drzewo", "hud.map.town": "Miasto", "hud.map.castle": "Zamek", "hud.map.dungeon": "Loch", "hud.map.difficulty_dungeon": "Loch\n\nTrudność: {difficulty}", "hud.map.drag": "Przewiń", "hud.map.zoom": "Przybliż", + "hud.map.mid_click": "Ustaw punkt orientacyjny", "hud.map.recenter": "Wycentruj", - "hud.map.topo_map": "Widok topograficzny" + "hud.map.marked_location": "Oznaczona lokacja", + "hud.map.marked_location_remove": "Kliknij aby usunąć", + "hud.map.change_map_mode": "Zmień typ mapy", + "hud.map.toggle_minimap_voxel": "Przełącz widok wokseli na minimapie", + "hud.map.zoom_minimap_explanation": "Przybliż minimapę aby zobaczyć\nteren dookoła ciebie z większą dokładnością", + "hud.map.gnarling": "Fortyfikacje Gnarlingów", + "hud.map.placed_by": "Umiejscowione poprzez {name}", }, vector_map: { } -) +) \ No newline at end of file diff --git a/assets/voxygen/i18n/pl_PL/hud/misc.ron b/assets/voxygen/i18n/pl_PL/hud/misc.ron index 9e8976ec63..5b7523a012 100644 --- a/assets/voxygen/i18n/pl_PL/hud/misc.ron +++ b/assets/voxygen/i18n/pl_PL/hud/misc.ron @@ -1,4 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { "hud.do_not_show_on_startup": "Nie pokazuj tego podczas startu", @@ -7,23 +9,24 @@ "hud.you_died": "Zginąłeś", "hud.waypoint_saved": "Punkt orientacyjny zachowany", "hud.sp_arrow_txt": "PR", /// punkty rozwoju + "hud.inventory_full": "Ekwipunek pełen", "hud.press_key_to_show_keybindings_fmt": "[{key}] przypisania klawiszy", "hud.press_key_to_toggle_lantern_fmt": "[{key}] latarnia", "hud.press_key_to_show_debug_info_fmt": "Naciśnij {key} by zobaczyć debug", "hud.press_key_to_toggle_keybindings_fmt": "Naciśnij {key} by przełączyć przypisania klawiszy", "hud.press_key_to_toggle_debug_info_fmt": "Naciśnij {key} by przełączyć debugowanie", - - // Respawn message + + // Respawn message "hud.press_key_to_respawn": r#"Naciśnij {key} by odrodzić się przy ostatnio odwiedzonym ognisku."#, - - // Tutorial Button + + // Tutorial Button "hud.tutorial_btn": r#"Samouczek"#, "hud.tutorial_click_here": r#"Naciśnij [ {key} ] by przełączyć tryb przechwytywania myszy i naciśnij ten przycisk!"#, "hud.tutorial_elements": r#"Tworzenie"#, -"hud.temp_quest_headline": r#"Witaj Przybyszu!"#, -"hud.temp_quest_text": r#"By zacząć swoją podróż zacznij od rozglądnięcia się i zebrania zapasów. + "hud.temp_quest_headline": r#"Witaj Przybyszu!"#, + "hud.temp_quest_text": r#"By zacząć swoją podróż zacznij od rozglądnięcia się i zebrania zapasów. Śmiało bierz cokolwiek będzie Ci potrzebne podczas Twojej wyprawy! @@ -31,7 +34,7 @@ Spójrz w prawy dolny róg ekranu by znaleźć różne rzeczy, takie jak Twoja t Menu tworzenia pozwala stworzyć pancerze, broń, żywność i wiele innych! -Dzikie zwierzęta dookoła miast są świetnym źródłem Skrawków Skóry (Leather Scraps) które możesz przetworzyć na ubrania zapewniające dobrą ochronę podczas podróżowania. +Dzikie zwierzęta dookoła miast są świetnym źródłem Skrawków Skóry które możesz przetworzyć na ubrania zapewniające dobrą ochronę podczas podróżowania. Kiedy poczujesz się gotów, spróbuj zdobyć lepszy ekwipunek z wielu wyzwań rozrzuconych po całej mapie! "#, @@ -42,7 +45,16 @@ Kiedy poczujesz się gotów, spróbuj zdobyć lepszy ekwipunek z wielu wyzwań r "hud.free_look_indicator": "Tryb rozglądania aktywny. Naciśnij {key} by wyłączyć.", "hud.camera_clamp_indicator": "Pionowa blokada kamery aktywna. Naciśnij {key} by wyłączyć.", - "hud.auto_walk_indicator": "Automatyczny lot/chód aktywny", + "hud.auto_walk_indicator": "Automatyczne chodzenie/pływanie aktywne", + "hud.collect": "Zbierz", + "hud.pick_up": "Podnieś", + "hud.open": "Otwórz", + "hud.use": "Użyj", + "hud.mine": "Wykop", + "hud.talk": "Rozmawiaj", + "hud.trade": "Handluj", + "hud.mount": "Dosiądź", + "hud.sit": "Usiądź", }, diff --git a/assets/voxygen/i18n/pl_PL/hud/sct.ron b/assets/voxygen/i18n/pl_PL/hud/sct.ron index 58d766e616..8837fc2069 100644 --- a/assets/voxygen/i18n/pl_PL/hud/sct.ron +++ b/assets/voxygen/i18n/pl_PL/hud/sct.ron @@ -1,4 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { // SCT outputs diff --git a/assets/voxygen/i18n/pl_PL/hud/settings.ron b/assets/voxygen/i18n/pl_PL/hud/settings.ron index 916aeba80c..dd65b35c98 100644 --- a/assets/voxygen/i18n/pl_PL/hud/settings.ron +++ b/assets/voxygen/i18n/pl_PL/hud/settings.ron @@ -1,4 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { // Settings @@ -7,7 +9,10 @@ "hud.settings.press_behavior.toggle": "Przełącz", "hud.settings.press_behavior.hold": "Przytrzymaj", "hud.settings.help_window": "Okno pomocy", - "hud.settings.debug_info": "Debug Info", + "hud.settings.debug_info": "Informacje debugowania", + "hud.settings.show_hitboxes": "Pokaż hitboxy", + "hud.settings.show_chat": "Pokaż czat", + "hud.settings.show_hotkey_hints": "Pokaż klawisze skrótu", "hud.settings.tips_on_startup": "Porady startowe", "hud.settings.ui_scale": "Skala interfejsu", "hud.settings.relative_scaling": "Relatywne skalowanie", @@ -25,9 +30,11 @@ "hud.settings.incoming_damage": "Otrzymywane obrażenia", "hud.settings.cumulated_incoming_damage": "Kalkulowane otrzymywane obrażenia", "hud.settings.speech_bubble": "Dymek rozmowy", + "hud.settings.speech_bubble_self": "Pokazuj swój dymek rozmowy", "hud.settings.speech_bubble_dark_mode": "Dymek rozmowy w trybie ciemnym", "hud.settings.speech_bubble_icon": "Ikona dymka rozmowy", "hud.settings.energybar_numbers": "Numery na pasku energii", + "hud.settings.always_show_bars": "Zawsze pokazuj paski zdrowia i energii", "hud.settings.values": "Wartości", "hud.settings.percentages": "Procenty", "hud.settings.chat": "Czat", @@ -46,6 +53,7 @@ "hud.settings.free_look_behavior": "Zachowanie trybu rozglądania", "hud.settings.auto_walk_behavior": "Zachowanie trybu automatycznego chodu", "hud.settings.camera_clamp_behavior": "Zachowanie kamery w zablokowanym trybie", + "hud.settings.player_physics_behavior": "Fizyka gracza (eksperymentalne)", "hud.settings.stop_auto_walk_on_input": "Przełącz automatyczny chód poruszaniem", "hud.settings.auto_camera": "Automatyczna kamera", "hud.settings.reset_gameplay": "Zresetuj ustawienia", @@ -54,7 +62,12 @@ "hud.settings.sprites_view_distance": "Odległość renderowania 2d", "hud.settings.figures_view_distance": "Odległość renderowania obiektów", "hud.settings.maximum_fps": "Ogranicz maksymalne klatki", - "hud.settings.fov": "Field of View (stopnie)", + "hud.settings.background_fps": "Ilość klatek w tle", + "hud.settings.present_mode": "Obecny tryb", + "hud.settings.present_mode.fifo": "FIFO", + "hud.settings.present_mode.mailbox": "MAILBOX", + "hud.settings.present_mode.immediate": "Natychmiastowy", + "hud.settings.fov": "Pole widzenia (stopnie)", "hud.settings.gamma": "Gamma", "hud.settings.exposure": "Ekspozycja", "hud.settings.ambiance": "Jasność atmosferyczna", @@ -73,6 +86,9 @@ "hud.settings.fullscreen_mode": "Tryb pełnego ekranu", "hud.settings.fullscreen_mode.exclusive": "Ekskluzywny (przejęcie)", "hud.settings.fullscreen_mode.borderless": "Okno bez ramek (łatwiejsze alt-tab'owanie)", + "hud.settings.gpu_profiler": "Włącz taktowanie GPU (Nie zawsze wspierane)", + "hud.settings.lossy_terrain_compression": "Słabsza kompresja terenu", + "hud.settings.weapon_trails": "Ścieżki broni (efekt ataku)", "hud.settings.particles": "Cząsteczki", "hud.settings.resolution": "Rozdzielczość", "hud.settings.bit_depth": "Głębia bitowa", @@ -86,9 +102,11 @@ "hud.settings.shadow_rendering_mode.cheap": "Lekki", "hud.settings.shadow_rendering_mode.map": "Mapa", "hud.settings.shadow_rendering_mode.map.resolution": "Rozdzielczość", - "hud.settings.lod_detail": "LoD Dystans", + "hud.settings.lod_detail": "Ilość szczegółów", "hud.settings.save_window_size": "Zapisz wymiary okna", "hud.settings.reset_graphics": "Zresetuj ustawienia", + "hud.settings.bloom": "Rozmycie", + "hud.settings.point_glow": "Poświata punktowa", "hud.settings.master_volume": "Głośność ogólna", "hud.settings.inactive_master_volume_perc": "Głośność ogólna (nieaktywne okno)", @@ -97,15 +115,31 @@ "hud.settings.audio_device": "Urządzenie dźwiękowe", "hud.settings.reset_sound": "Zresetuj ustawienia", - "hud.settings.awaitingkey": "Naciśnij klawisz...", + "hud.settings.english_fallback": "Wyświetl angielskie napisy dla brakujących tłumaczeń" + + "hud.settings.awaitingkey": "Naciśnij klawisz...", "hud.settings.unbound": "Brak", "hud.settings.reset_keybinds": "Zresetuj ustawienia", - "hud.settings.player_physics_behavior": "Fizyka gracza (eksperymentalne)", - "hud.settings.english_fallback": "Wyświetl angielskie napisy dla brakujących tłumaczeń" + "hud.settings.chat_tabs": "Chat Tabs", + "hud.settings.label": "Etykieta:", + "hud.settings.delete": "Usuń", + "hud.settings.show_all": "Pokaż wszystko", + "hud.settings.messages": "Wiadomości", + "hud.settings.activity": "Aktywność", + "hud.settings.death": "Śmierć", + "hud.settings.group": "Grupa", + "hud.settings.faction": "Segment", + "hud.settings.world": "Świat", + "hud.settings.region": "Region", + "hud.settings.say": "Powiedz", + "hud.settings.all": "Wszyscy", + "hud.settings.group_only": "Tylko dla grupy", + "hud.settings.reset_chat" : "Przywróć ustawienia podstawowe", }, vector_map: { } ) + diff --git a/assets/voxygen/i18n/pl_PL/hud/skills.ron b/assets/voxygen/i18n/pl_PL/hud/skills.ron index 0186674aab..dd60b65cf8 100644 --- a/assets/voxygen/i18n/pl_PL/hud/skills.ron +++ b/assets/voxygen/i18n/pl_PL/hud/skills.ron @@ -1,4 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { "hud.rank_up": "Nowy punkt rozwoju", @@ -58,6 +60,8 @@ "hud.skill.sc_heal_heal": "Zwiększa leczenie innych o {boost}%{SP}", "hud.skill.sc_heal_cost_title": "Koszt Wytrzymałości", "hud.skill.sc_heal_cost": "Leczenie innych kosztuje {boost}% mniej Wytrzymałości{SP}", + "hud.skill.sc_heal_duration_title": "Długość", + "hud.skill.sc_heal_duration": "Efekt aury leczącej trwa {boost}% dłużej{SP}", "hud.skill.sc_heal_range_title": "Zasięg", "hud.skill.sc_heal_range": "Promień dociera {boost}% dalej{SP}", "hud.skill.sc_wardaura_unlock_title": "Sfera obronna", @@ -165,7 +169,6 @@ "hud.skill.hmr_single_strike_damage" : "Zwiększa obrażenia za każde trafienie{SP}", "hud.skill.hmr_single_strike_knockback_title" : "Trafienie - odrzut", "hud.skill.hmr_single_strike_knockback" : "Zwiększa odrzut o {boost}%{SP}", - "hud.skill." : "", // Sword "hud.skill.sw_trip_str_title": "Potrójne cięcie", "hud.skill.sw_trip_str": "Trzy szybkie cięcia", @@ -236,9 +239,19 @@ "hud.skill.axe_leap_cost": "Zmniejsza koszt doskoku o {boost}%{SP}", "hud.skill.axe_leap_distance_title": "Doskok - dystans", "hud.skill.axe_leap_distance": "Zwiększa dystans doskoku o {boost}%{SP}", + // Mining + "hud.skill.mining_title": "Górnictwo", + "hud.skill.pick_strike_title": "Wykorzystanie kilofa", + "hud.skill.pick_strike": "Niszcz skały kilofem zby zdobywać rudy, kryształy i doświadczenie", + "hud.skill.pick_strike_speed_title": "Szybkość uderzania kilofem", + "hud.skill.pick_strike_speed": "Kop szybciej{SP}", + "hud.skill.pick_strike_oregain_title": "Wydajność kopania rud", + "hud.skill.pick_strike_oregain": "Szansa na zdobycie dodatkowej rudy ({boost}% per level){SP}", + "hud.skill.pick_strike_gemgain_title": "Wydajność kopania kryształów", + "hud.skill.pick_strike_gemgain": "Szansa na zdobycie dodadkowego kryształu ({boost}% per level){SP}", }, vector_map: { } -) +) \ No newline at end of file diff --git a/assets/voxygen/i18n/pl_PL/hud/social.ron b/assets/voxygen/i18n/pl_PL/hud/social.ron index 5e5330ca8f..cc3f362c0b 100644 --- a/assets/voxygen/i18n/pl_PL/hud/social.ron +++ b/assets/voxygen/i18n/pl_PL/hud/social.ron @@ -1,6 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM -/// Localization for "global" English +/// Lokalizacja na Polskie tłumaczenie ( string_map: { "hud.social": "Inni gracze", diff --git a/assets/voxygen/i18n/pl_PL/hud/trade.ron b/assets/voxygen/i18n/pl_PL/hud/trade.ron index caf4201730..724ed7b8d8 100644 --- a/assets/voxygen/i18n/pl_PL/hud/trade.ron +++ b/assets/voxygen/i18n/pl_PL/hud/trade.ron @@ -1,4 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { "hud.trade.trade_window": "Okno handlu", @@ -19,9 +21,12 @@ "hud.trade.coin": "monet(y)", "hud.trade.tooltip_hint_1": "", "hud.trade.tooltip_hint_2": "" + "hud.trade.your_offer": "Twoja oferta", + "hud.trade.their_offer": "Jego oferta", + "hud.trade.amount_input": "Wybierz przedmiot" }, + vector_map: { } -) - +) \ No newline at end of file diff --git a/assets/voxygen/i18n/pl_PL/main.ron b/assets/voxygen/i18n/pl_PL/main.ron index 4236e47f30..5623438ed5 100644 --- a/assets/voxygen/i18n/pl_PL/main.ron +++ b/assets/voxygen/i18n/pl_PL/main.ron @@ -1,4 +1,6 @@ /// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Lokalizacja na Polskie tłumaczenie ( string_map: { /// Start Main screen section @@ -8,6 +10,7 @@ "main.connecting": "Łączenie", "main.creating_world": "Tworzenie świata", "main.tip": "Porada:", + "main.unbound_key_tip": "Rozwiąż", // Welcome notice that appears the first time Veloren is started "main.notice": r#"Witaj w alfie Veloren! @@ -56,16 +59,34 @@ https://veloren.net/account/."#, "main.login.banned": "Konto zostało zbanowane z powodu:", "main.login.kicked": "Sesja została wyrzucona z powodu:", "main.login.select_language": "Wybierz język", - - "main.servers.select_server": "Wybierz serwer", + "main.login.client_version": "Wersja klienta", "main.login.server_version": "Wersja serwera", - "main.login.internal_error": "Błąd wewnętrzny klienta (najprawdopodobniej postać została usunięta)", - "main.login.client_version": "Wersja klienta" + "main.login.client_init_failed": "Błąd inicjalizacji klienta: {init_fail_reason}", + "main.login.username_bad_characters": "Nazwa posiada niedozwolone znaki! (Tylko znaki alfanumeryczne, '_' i '-' są dozwolone)", + "main.login.username_too_long": "Nazwa zbyt długa! Maksymalna długość wynosi: {max_len}", + "main.servers.select_server": "Wybierz serwer", + "main.servers.singleplayer_error": "Nie udało się połączyć z serwerem: {sp_error}", + "main.servers.network_error": "Błąd gniazda/połączenia z serwerem: {raw_error}", + "main.servers.participant_error": "Rozłączono klienta/błąd protokołu: {raw_error}", + "main.servers.stream_error": "Błąd (de)serializacji/połączenia z klientem: {raw_error}", + "main.servers.database_error": "Błąd bazy danych serwera: {raw_error}", + "main.servers.persistence_error": "Błąd wytrzymałości serwera (Prawdopodobnie powiązane z zasobami/danymi postaci): {raw_error}", + "main.servers.other_error": "Ogólny błąd serwera: {raw_error}", + + // Credits screen + "main.credits": "Twórcy", + "main.credits.created_by": "stworzone przez", + "main.credits.music": "Muzyka", + "main.credits.fonts": "Czcionki", + "main.credits.other_art": "Inne dzieła", + "main.credits.contributors": "Współtwórcy", + /// End Main screen section }, vector_map: { + /// The keybinding names can be found in voxygen/src/game_input.rs in the GameInput enum "loading.tips": [ "Naciśnij '{gameinput.togglelantern}' by zapalić latarnię.", "Naciśnij '{gameinput.help}' by zobaczyć podstawową klawiszologię.", @@ -86,6 +107,9 @@ https://veloren.net/account/."#, "Możesz przełączać typ paska zdrowia w opcjach.", "Usiądź obok ogniska (używając '{gameinput.sit}') by powoli wyleczyć się z obrażeń.", "Potrzebujesz więcej slotów w ekwipunku, albo nowego uzbrojenia? Wciśnij '{gameinput.crafting}' aby otworzyć menu tworzenia!", + "Wciśnij '{gameinput.roll}' aby się przeturlać. Turlanie może zostać użyte do szybszego poruszania się lub unikania wrogich ataków.", + "Zastanawiasz się do czego służy dany przedmiot? Wyszukaj 'input:' w polu wytwarzania aby zobaczyć w jakich recepturach jest on wykorzystywany.", + "Znalazłeś coś fajnego? Zrób temu zdjęcie wciskając '{gameinput.screenshot}'." ], } ) diff --git a/assets/voxygen/i18n/pl_PL/npc.ron b/assets/voxygen/i18n/pl_PL/npc.ron index d2213536c3..c19ed6ed04 100644 --- a/assets/voxygen/i18n/pl_PL/npc.ron +++ b/assets/voxygen/i18n/pl_PL/npc.ron @@ -1,4 +1,6 @@ -/// Localization for Polish / Tłumaczenia dla języka polskiego +/// Localization for Polish + +/// Tłumaczenia dla języka polskiego ( string_map: { }, @@ -171,5 +173,26 @@ "Poszczuję tarasqa (tarasque) na ciebie!", "Dlaczego ja?", ], + "npc.speech.villager_enemy_killed": [ + "Zniszczyłem swojego przeciwnika!", + "Nareszcie spokój!", + "... więc, co robiłem?", + ], + "npc.speech.menacing": [ + "Ostrzegam Cię!", + "Podejdź bliżej a zaatakuję!", + "Nie boję się Ciebie!", + "Lepiej szybko stąd uciekaj!", + "Krok w tył, jeśli Ci życie miłe!", + "Nie jesteś tu mile widziany!", + ], + "npc.speech.cultist_low_health_fleeing": [ + "Taktyczny odwrót!", + "Odwrót!", + "Przeklinam Cię!", + ///"I will curse you in the afterlife!", + "Muszę odpocząć!", + "Są zbyt potężni!", + ] }, ) From e194a2e3345ef915e494dab24df983ac1299d97c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Fri, 20 May 2022 12:20:57 +0200 Subject: [PATCH 006/229] export unterlying errors via network crate, to generate more detailed logs --- Cargo.lock | 2 +- network/protocol/Cargo.toml | 4 +- network/protocol/benches/protocols.rs | 39 ++++-- network/protocol/src/error.rs | 44 +++--- network/protocol/src/handshake.rs | 35 +++-- network/protocol/src/lib.rs | 22 ++- network/protocol/src/mpsc.rs | 35 +++-- network/protocol/src/quic.rs | 37 +++-- network/protocol/src/tcp.rs | 33 +++-- network/src/api.rs | 3 +- network/src/channel.rs | 195 +++++++++++++++++--------- network/src/participant.rs | 4 +- 12 files changed, 298 insertions(+), 155 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3de0c8fd88..1b0c53e7a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6690,7 +6690,7 @@ dependencies = [ [[package]] name = "veloren-network-protocol" -version = "0.6.0" +version = "0.6.1" dependencies = [ "async-channel", "async-trait", diff --git a/network/protocol/Cargo.toml b/network/protocol/Cargo.toml index c1814f893b..ebc9b87e5e 100644 --- a/network/protocol/Cargo.toml +++ b/network/protocol/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "veloren-network-protocol" description = "pure Protocol without any I/O itself" -version = "0.6.0" +version = "0.6.1" authors = ["Marcel Märtens "] edition = "2021" @@ -24,7 +24,7 @@ rand = { version = "0.8" } # async traits async-trait = "0.1.42" bytes = "^1" -hashbrown = { version = ">=0.9, <0.13" } +hashbrown = { version = ">=0.12, <0.13" } [dev-dependencies] async-channel = "1.5.1" diff --git a/network/protocol/benches/protocols.rs b/network/protocol/benches/protocols.rs index cb1dc02038..6cd709efe4 100644 --- a/network/protocol/benches/protocols.rs +++ b/network/protocol/benches/protocols.rs @@ -271,73 +271,88 @@ mod utils { #[async_trait] impl UnreliableDrain for ACDrain { + type CustomErr = (); type DataFormat = MpscMsg; - async fn send(&mut self, data: Self::DataFormat) -> Result<(), ProtocolError> { + async fn send( + &mut self, + data: Self::DataFormat, + ) -> Result<(), ProtocolError> { self.sender .send(data) .await - .map_err(|_| ProtocolError::Closed) + .map_err(|_| ProtocolError::Custom(())) } } #[async_trait] impl UnreliableSink for ACSink { + type CustomErr = (); type DataFormat = MpscMsg; - async fn recv(&mut self) -> Result { + async fn recv(&mut self) -> Result> { self.receiver .recv() .await - .map_err(|_| ProtocolError::Closed) + .map_err(|_| ProtocolError::Custom(())) } } #[async_trait] impl UnreliableDrain for TcpDrain { + type CustomErr = (); type DataFormat = BytesMut; - async fn send(&mut self, data: Self::DataFormat) -> Result<(), ProtocolError> { + async fn send( + &mut self, + data: Self::DataFormat, + ) -> Result<(), ProtocolError> { self.sender .send(data) .await - .map_err(|_| ProtocolError::Closed) + .map_err(|_| ProtocolError::Custom(())) } } #[async_trait] impl UnreliableSink for TcpSink { + type CustomErr = (); type DataFormat = BytesMut; - async fn recv(&mut self) -> Result { + async fn recv(&mut self) -> Result> { self.receiver .recv() .await - .map_err(|_| ProtocolError::Closed) + .map_err(|_| ProtocolError::Custom(())) } } #[async_trait] impl UnreliableDrain for QuicDrain { + type CustomErr = (); type DataFormat = QuicDataFormat; - async fn send(&mut self, data: Self::DataFormat) -> Result<(), ProtocolError> { + async fn send( + &mut self, + data: Self::DataFormat, + ) -> Result<(), ProtocolError> { self.sender .send(data) .await - .map_err(|_| ProtocolError::Closed) + .map_err(|_| ProtocolError::Custom(())) } } #[async_trait] impl UnreliableSink for QuicSink { + type CustomErr = (); type DataFormat = QuicDataFormat; - async fn recv(&mut self) -> Result { + async fn recv(&mut self) -> Result> { self.receiver .recv() .await - .map_err(|_| ProtocolError::Closed) + .map_err(|_| ProtocolError::Custom(())) } } } diff --git a/network/protocol/src/error.rs b/network/protocol/src/error.rs index 27199197d2..3c63a4907d 100644 --- a/network/protocol/src/error.rs +++ b/network/protocol/src/error.rs @@ -2,38 +2,50 @@ /// /// [`InitProtocol`]: crate::InitProtocol #[derive(Debug, PartialEq)] -pub enum InitProtocolError { - Closed, +pub enum InitProtocolError { + Custom(E), + /// expected Handshake, didn't get handshake + NotHandshake, + /// expected Id, didn't get id + NotId, WrongMagicNumber([u8; 7]), WrongVersion([u32; 3]), } /// When you return closed you must stay closed! #[derive(Debug, PartialEq)] -pub enum ProtocolError { - /// Closed indicates the underlying I/O got closed +pub enum ProtocolError { + /// Custom Error on the underlying I/O, /// e.g. the TCP, UDP or MPSC connection is dropped by the OS - Closed, + Custom(E), /// Violated indicates the veloren_network_protocol was violated /// the underlying I/O connection is still valid, but the remote side /// send WRONG (e.g. Invalid, or wrong order) data on the protocol layer. Violated, } -impl From for InitProtocolError { - fn from(err: ProtocolError) -> Self { +impl From> for InitProtocolError { + fn from(err: ProtocolError) -> Self { match err { - ProtocolError::Closed => InitProtocolError::Closed, - // not possible as the Init has raw access to the I/O - ProtocolError::Violated => InitProtocolError::Closed, + ProtocolError::Custom(e) => InitProtocolError::Custom(e), + ProtocolError::Violated => { + unreachable!("not possible as the Init has raw access to the I/O") + }, } } } -impl core::fmt::Display for InitProtocolError { +impl core::fmt::Display for InitProtocolError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - InitProtocolError::Closed => write!(f, "Channel closed"), + InitProtocolError::Custom(e) => write!(f, "custom: {:?}", e), + InitProtocolError::NotHandshake => write!( + f, + "Remote send something which couldn't be parsed as a handshake" + ), + InitProtocolError::NotId => { + write!(f, "Remote send something which couldn't be parsed as an id") + }, InitProtocolError::WrongMagicNumber(r) => write!( f, "Magic Number doesn't match, remote side send '{:?}' instead of '{:?}'", @@ -50,14 +62,14 @@ impl core::fmt::Display for InitProtocolError { } } -impl core::fmt::Display for ProtocolError { +impl core::fmt::Display for ProtocolError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - ProtocolError::Closed => write!(f, "Channel closed"), + ProtocolError::Custom(e) => write!(f, "Channel custom close: {:?}", e), ProtocolError::Violated => write!(f, "Channel protocol violated"), } } } -impl std::error::Error for InitProtocolError {} -impl std::error::Error for ProtocolError {} +impl std::error::Error for InitProtocolError {} +impl std::error::Error for ProtocolError {} diff --git a/network/protocol/src/handshake.rs b/network/protocol/src/handshake.rs index d02920e044..9f22b23312 100644 --- a/network/protocol/src/handshake.rs +++ b/network/protocol/src/handshake.rs @@ -21,7 +21,8 @@ use tracing::{debug, error, info, trace}; /// [`RecvProtocol`]: crate::RecvProtocol #[async_trait] pub trait ReliableDrain { - async fn send(&mut self, frame: InitFrame) -> Result<(), ProtocolError>; + type CustomErr: std::fmt::Debug + Send; + async fn send(&mut self, frame: InitFrame) -> Result<(), ProtocolError>; } /// Implement this for auto Handshake with [`ReliableDrain`]. See @@ -30,21 +31,25 @@ pub trait ReliableDrain { /// [`ReliableDrain`]: crate::ReliableDrain #[async_trait] pub trait ReliableSink { - async fn recv(&mut self) -> Result; + type CustomErr: std::fmt::Debug + Send; + async fn recv(&mut self) -> Result>; } #[async_trait] -impl InitProtocol for (D, S) +impl InitProtocol for (D, S) where - D: ReliableDrain + Send, - S: ReliableSink + Send, + D: ReliableDrain + Send, + S: ReliableSink + Send, + E: std::fmt::Debug + Send, { + type CustomErr = E; + async fn initialize( &mut self, initializer: bool, local_pid: Pid, local_secret: u128, - ) -> Result<(Pid, Sid, u128), InitProtocolError> { + ) -> Result<(Pid, Sid, u128), InitProtocolError> { #[cfg(debug_assertions)] const WRONG_NUMBER: &str = "Handshake does not contain the magic number required by \ veloren server.\nWe are not sure if you are a valid veloren \ @@ -122,11 +127,11 @@ where Ok(string) => error!(?string, ERR_S), _ => error!(?bytes, ERR_S), } - Err(InitProtocolError::Closed) + Err(InitProtocolError::NotHandshake) }, _ => { info!("Handshake failed"); - Err(InitProtocolError::Closed) + Err(InitProtocolError::NotHandshake) }, }?; @@ -152,11 +157,11 @@ where Ok(string) => error!(?string, ERR_S), _ => error!(?bytes, ERR_S), } - Err(InitProtocolError::Closed) + Err(InitProtocolError::NotId) }, _ => { info!("Handshake failed"); - Err(InitProtocolError::Closed) + Err(InitProtocolError::NotId) }, } } @@ -176,7 +181,7 @@ mod tests { let _ = p2; }); let (r1, _) = tokio::join!(r1, r2); - assert_eq!(r1.unwrap(), Err(InitProtocolError::Closed)); + assert_eq!(r1.unwrap(), Err(InitProtocolError::Custom(()))); } #[tokio::test] @@ -191,7 +196,7 @@ mod tests { }) .await?; let _ = p2.1.recv().await?; - Result::<(), InitProtocolError>::Ok(()) + Result::<(), InitProtocolError<()>>::Ok(()) }); let (r1, r2) = tokio::join!(r1, r2); assert_eq!( @@ -218,7 +223,7 @@ mod tests { }); let (r1, r2) = tokio::join!(r1, r2); assert_eq!(r1.unwrap(), Err(InitProtocolError::WrongVersion([0, 1, 2]))); - assert_eq!(r2.unwrap(), Err(InitProtocolError::Closed)); + assert_eq!(r2.unwrap(), Err(InitProtocolError::Custom(()))); } #[tokio::test] @@ -234,10 +239,10 @@ mod tests { .await?; let _ = p2.1.recv().await?; p2.0.send(InitFrame::Raw(b"Hello World".to_vec())).await?; - Result::<(), InitProtocolError>::Ok(()) + Result::<(), InitProtocolError<()>>::Ok(()) }); let (r1, r2) = tokio::join!(r1, r2); - assert_eq!(r1.unwrap(), Err(InitProtocolError::Closed)); + assert_eq!(r1.unwrap(), Err(InitProtocolError::NotId)); assert_eq!(r2.unwrap(), Ok(())); } } diff --git a/network/protocol/src/lib.rs b/network/protocol/src/lib.rs index 3c2eb70c75..5d6efdd45f 100644 --- a/network/protocol/src/lib.rs +++ b/network/protocol/src/lib.rs @@ -86,12 +86,14 @@ use async_trait::async_trait; /// Handshake: Used to connect 2 Channels. #[async_trait] pub trait InitProtocol { + type CustomErr: std::fmt::Debug + Send; + async fn initialize( &mut self, initializer: bool, local_pid: Pid, secret: u128, - ) -> Result<(Pid, Sid, u128), InitProtocolError>; + ) -> Result<(Pid, Sid, u128), InitProtocolError>; } /// Generic Network Send Protocol. @@ -101,18 +103,20 @@ pub trait InitProtocol { /// /// A `Stream` MUST be bound to a specific Channel. You MUST NOT switch the /// channel to send a stream mid air. We will provide takeover options for -/// Channel closure in the future to allow keeping a `Stream` over a broker +/// Channel closure in the future to allow keeping a `Stream` over a broken /// Channel. /// /// [`ProtocolEvent`]: crate::ProtocolEvent #[async_trait] pub trait SendProtocol { + type CustomErr: std::fmt::Debug + Send; + /// YOU MUST inform the `SendProtocol` by any Stream Open BEFORE using it in /// `send` and Stream Close AFTER using it in `send` via this fn. fn notify_from_recv(&mut self, event: ProtocolEvent); /// Send a Event via this Protocol. The `SendProtocol` MAY require `flush` /// to be called before actual data is send to the respective `Sink`. - async fn send(&mut self, event: ProtocolEvent) -> Result<(), ProtocolError>; + async fn send(&mut self, event: ProtocolEvent) -> Result<(), ProtocolError>; /// Flush all buffered messages according to their [`Prio`] and /// [`Bandwidth`]. provide the current bandwidth budget (per second) as /// well as the `dt` since last call. According to the budget the @@ -124,7 +128,7 @@ pub trait SendProtocol { &mut self, bandwidth: Bandwidth, dt: std::time::Duration, - ) -> Result; + ) -> Result>; } /// Generic Network Recv Protocol. See: [`SendProtocol`] @@ -132,9 +136,11 @@ pub trait SendProtocol { /// [`SendProtocol`]: crate::SendProtocol #[async_trait] pub trait RecvProtocol { + type CustomErr: std::fmt::Debug + Send; + /// Either recv an event or fail the Protocol, once the Recv side is closed /// it cannot recover from the error. - async fn recv(&mut self) -> Result; + async fn recv(&mut self) -> Result>; } /// This crate makes use of UnreliableDrains, they are expected to provide the @@ -147,8 +153,9 @@ pub trait RecvProtocol { /// [`async-channel`]: async-channel #[async_trait] pub trait UnreliableDrain: Send { + type CustomErr: std::fmt::Debug + Send; type DataFormat; - async fn send(&mut self, data: Self::DataFormat) -> Result<(), ProtocolError>; + async fn send(&mut self, data: Self::DataFormat) -> Result<(), ProtocolError>; } /// Sink counterpart of [`UnreliableDrain`] @@ -156,6 +163,7 @@ pub trait UnreliableDrain: Send { /// [`UnreliableDrain`]: crate::UnreliableDrain #[async_trait] pub trait UnreliableSink: Send { + type CustomErr: std::fmt::Debug + Send; type DataFormat; - async fn recv(&mut self) -> Result; + async fn recv(&mut self) -> Result>; } diff --git a/network/protocol/src/mpsc.rs b/network/protocol/src/mpsc.rs index ee497e5b4a..a9afd297c4 100644 --- a/network/protocol/src/mpsc.rs +++ b/network/protocol/src/mpsc.rs @@ -82,9 +82,11 @@ impl SendProtocol for MpscSendProtocol where D: UnreliableDrain, { + type CustomErr = D::CustomErr; + fn notify_from_recv(&mut self, _event: ProtocolEvent) {} - async fn send(&mut self, event: ProtocolEvent) -> Result<(), ProtocolError> { + async fn send(&mut self, event: ProtocolEvent) -> Result<(), ProtocolError> { #[cfg(feature = "trace_pedantic")] trace!(?event, "send"); match &event { @@ -113,7 +115,11 @@ where } } - async fn flush(&mut self, _: Bandwidth, _: Duration) -> Result { + async fn flush( + &mut self, + _: Bandwidth, + _: Duration, + ) -> Result> { Ok(0) } } @@ -123,7 +129,9 @@ impl RecvProtocol for MpscRecvProtocol where S: UnreliableSink, { - async fn recv(&mut self) -> Result { + type CustomErr = S::CustomErr; + + async fn recv(&mut self) -> Result> { let event = self.sink.recv().await?; #[cfg(feature = "trace_pedantic")] trace!(?event, "recv"); @@ -153,7 +161,9 @@ impl ReliableDrain for MpscSendProtocol where D: UnreliableDrain, { - async fn send(&mut self, frame: InitFrame) -> Result<(), ProtocolError> { + type CustomErr = D::CustomErr; + + async fn send(&mut self, frame: InitFrame) -> Result<(), ProtocolError> { self.drain.send(MpscMsg::InitFrame(frame)).await } } @@ -163,7 +173,9 @@ impl ReliableSink for MpscRecvProtocol where S: UnreliableSink, { - async fn recv(&mut self) -> Result { + type CustomErr = S::CustomErr; + + async fn recv(&mut self) -> Result> { match self.sink.recv().await? { MpscMsg::Event(_) => Err(ProtocolError::Violated), MpscMsg::InitFrame(f) => Ok(f), @@ -209,25 +221,30 @@ pub mod test_utils { #[async_trait] impl UnreliableDrain for ACDrain { + type CustomErr = (); type DataFormat = MpscMsg; - async fn send(&mut self, data: Self::DataFormat) -> Result<(), ProtocolError> { + async fn send( + &mut self, + data: Self::DataFormat, + ) -> Result<(), ProtocolError> { self.sender .send(data) .await - .map_err(|_| ProtocolError::Closed) + .map_err(|_| ProtocolError::Custom(())) } } #[async_trait] impl UnreliableSink for ACSink { + type CustomErr = (); type DataFormat = MpscMsg; - async fn recv(&mut self) -> Result { + async fn recv(&mut self) -> Result> { self.receiver .recv() .await - .map_err(|_| ProtocolError::Closed) + .map_err(|_| ProtocolError::Custom(())) } } } diff --git a/network/protocol/src/quic.rs b/network/protocol/src/quic.rs index fa905bdefd..c261a342f2 100644 --- a/network/protocol/src/quic.rs +++ b/network/protocol/src/quic.rs @@ -147,7 +147,9 @@ where } } - async fn recv_into_stream(&mut self) -> Result { + async fn recv_into_stream( + &mut self, + ) -> Result> { let chunk = self.sink.recv().await?; let buffer = match chunk.stream { QuicDataFormatStream::Main => &mut self.main_buffer, @@ -181,6 +183,8 @@ impl SendProtocol for QuicSendProtocol where D: UnreliableDrain, { + type CustomErr = D::CustomErr; + fn notify_from_recv(&mut self, event: ProtocolEvent) { match event { ProtocolEvent::OpenStream { @@ -206,7 +210,7 @@ where } } - async fn send(&mut self, event: ProtocolEvent) -> Result<(), ProtocolError> { + async fn send(&mut self, event: ProtocolEvent) -> Result<(), ProtocolError> { #[cfg(feature = "trace_pedantic")] trace!(?event, "send"); match event { @@ -268,7 +272,7 @@ where &mut self, bandwidth: Bandwidth, dt: Duration, - ) -> Result { + ) -> Result> { let (frames, _) = self.store.grab(bandwidth, dt); //Todo: optimize reserve let mut data_frames = 0; @@ -343,7 +347,9 @@ impl RecvProtocol for QuicRecvProtocol where S: UnreliableSink, { - async fn recv(&mut self) -> Result { + type CustomErr = S::CustomErr; + + async fn recv(&mut self) -> Result> { 'outer: loop { match ITFrame::read_frame(&mut self.main_buffer) { Ok(Some(frame)) => { @@ -484,7 +490,9 @@ impl ReliableDrain for QuicSendProtocol where D: UnreliableDrain, { - async fn send(&mut self, frame: InitFrame) -> Result<(), ProtocolError> { + type CustomErr = D::CustomErr; + + async fn send(&mut self, frame: InitFrame) -> Result<(), ProtocolError> { self.main_buffer.reserve(500); frame.write_bytes(&mut self.main_buffer); self.drain @@ -498,7 +506,9 @@ impl ReliableSink for QuicRecvProtocol where S: UnreliableSink, { - async fn recv(&mut self) -> Result { + type CustomErr = S::CustomErr; + + async fn recv(&mut self) -> Result> { while self.main_buffer.len() < 100 { if self.recv_into_stream().await? == QuicDataFormatStream::Main { if let Some(frame) = InitFrame::read_frame(&mut self.main_buffer) { @@ -564,9 +574,13 @@ mod test_utils { #[async_trait] impl UnreliableDrain for QuicDrain { + type CustomErr = (); type DataFormat = QuicDataFormat; - async fn send(&mut self, data: Self::DataFormat) -> Result<(), ProtocolError> { + async fn send( + &mut self, + data: Self::DataFormat, + ) -> Result<(), ProtocolError> { use rand::Rng; if matches!(data.stream, QuicDataFormatStream::Unreliable) && rand::thread_rng().gen::() < self.drop_ratio @@ -576,19 +590,20 @@ mod test_utils { self.sender .send(data) .await - .map_err(|_| ProtocolError::Closed) + .map_err(|_| ProtocolError::Custom(())) } } #[async_trait] impl UnreliableSink for QuicSink { + type CustomErr = (); type DataFormat = QuicDataFormat; - async fn recv(&mut self) -> Result { + async fn recv(&mut self) -> Result> { self.receiver .recv() .await - .map_err(|_| ProtocolError::Closed) + .map_err(|_| ProtocolError::Custom(())) } } } @@ -865,7 +880,7 @@ mod tests { drop(s); let e = e.await.unwrap(); - assert_eq!(e, Err(ProtocolError::Closed)); + assert_eq!(e, Err(ProtocolError::Custom(()))); } #[tokio::test] diff --git a/network/protocol/src/tcp.rs b/network/protocol/src/tcp.rs index bb8bc350d1..5529490e05 100644 --- a/network/protocol/src/tcp.rs +++ b/network/protocol/src/tcp.rs @@ -100,6 +100,8 @@ impl SendProtocol for TcpSendProtocol where D: UnreliableDrain, { + type CustomErr = D::CustomErr; + fn notify_from_recv(&mut self, event: ProtocolEvent) { match event { ProtocolEvent::OpenStream { @@ -122,7 +124,7 @@ where } } - async fn send(&mut self, event: ProtocolEvent) -> Result<(), ProtocolError> { + async fn send(&mut self, event: ProtocolEvent) -> Result<(), ProtocolError> { #[cfg(feature = "trace_pedantic")] trace!(?event, "send"); match event { @@ -170,7 +172,7 @@ where &mut self, bandwidth: Bandwidth, dt: Duration, - ) -> Result { + ) -> Result> { let (frames, total_bytes) = self.store.grab(bandwidth, dt); self.buffer.reserve(total_bytes as usize); let mut data_frames = 0; @@ -228,7 +230,9 @@ impl RecvProtocol for TcpRecvProtocol where S: UnreliableSink, { - async fn recv(&mut self) -> Result { + type CustomErr = S::CustomErr; + + async fn recv(&mut self) -> Result> { 'outer: loop { loop { match ITFrame::read_frame(&mut self.buffer) { @@ -307,7 +311,9 @@ impl ReliableDrain for TcpSendProtocol where D: UnreliableDrain, { - async fn send(&mut self, frame: InitFrame) -> Result<(), ProtocolError> { + type CustomErr = D::CustomErr; + + async fn send(&mut self, frame: InitFrame) -> Result<(), ProtocolError> { let mut buffer = BytesMut::with_capacity(500); frame.write_bytes(&mut buffer); self.drain.send(buffer).await @@ -319,7 +325,9 @@ impl ReliableSink for TcpRecvProtocol where S: UnreliableSink, { - async fn recv(&mut self) -> Result { + type CustomErr = S::CustomErr; + + async fn recv(&mut self) -> Result> { while self.buffer.len() < 100 { let chunk = self.sink.recv().await?; self.buffer.extend_from_slice(&chunk); @@ -371,25 +379,30 @@ mod test_utils { #[async_trait] impl UnreliableDrain for TcpDrain { + type CustomErr = (); type DataFormat = BytesMut; - async fn send(&mut self, data: Self::DataFormat) -> Result<(), ProtocolError> { + async fn send( + &mut self, + data: Self::DataFormat, + ) -> Result<(), ProtocolError> { self.sender .send(data) .await - .map_err(|_| ProtocolError::Closed) + .map_err(|_| ProtocolError::Custom(())) } } #[async_trait] impl UnreliableSink for TcpSink { + type CustomErr = (); type DataFormat = BytesMut; - async fn recv(&mut self) -> Result { + async fn recv(&mut self) -> Result> { self.receiver .recv() .await - .map_err(|_| ProtocolError::Closed) + .map_err(|_| ProtocolError::Custom(())) } } } @@ -659,7 +672,7 @@ mod tests { drop(s); let e = e.await.unwrap(); - assert_eq!(e, Err(ProtocolError::Closed)); + assert_eq!(e, Err(ProtocolError::Custom(()))); } #[tokio::test] diff --git a/network/src/api.rs b/network/src/api.rs index 19ac44d9b6..dc028dc797 100644 --- a/network/src/api.rs +++ b/network/src/api.rs @@ -1,4 +1,5 @@ use crate::{ + channel::ProtocolsError, message::{partial_eq_bincode, Message}, participant::{A2bStreamOpen, S2bShutdownBparticipant}, scheduler::{A2sConnect, Scheduler}, @@ -106,7 +107,7 @@ pub enum NetworkError { pub enum NetworkConnectError { /// Either a Pid UUID clash or you are trying to hijack a connection InvalidSecret, - Handshake(InitProtocolError), + Handshake(InitProtocolError), Io(std::io::Error), } diff --git a/network/src/channel.rs b/network/src/channel.rs index 7457fb0785..51a294bbee 100644 --- a/network/src/channel.rs +++ b/network/src/channel.rs @@ -193,7 +193,7 @@ impl Protocols { metrics: Arc, s2s_stop_listening_r: oneshot::Receiver<()>, c2s_protocol_s: mpsc::UnboundedSender<(Self, Cid)>, - ) -> std::io::Result<()> { + ) -> io::Result<()> { let (mpsc_s, mut mpsc_r) = mpsc::unbounded_channel(); MPSC_POOL.lock().await.insert(addr, mpsc_s); trace!(?addr, "Mpsc Listener bound"); @@ -255,26 +255,17 @@ impl Protocols { info!("Connecting Quic to: {}", &addr); let connecting = endpoint.connect_with(config, addr, &name).map_err(|e| { trace!(?e, "error setting up quic"); - NetworkConnectError::Io(std::io::Error::new( - std::io::ErrorKind::ConnectionAborted, - e, - )) + NetworkConnectError::Io(io::Error::new(io::ErrorKind::ConnectionAborted, e)) })?; let connection = connecting.await.map_err(|e| { trace!(?e, "error with quic connection"); - NetworkConnectError::Io(std::io::Error::new( - std::io::ErrorKind::ConnectionAborted, - e, - )) + NetworkConnectError::Io(io::Error::new(io::ErrorKind::ConnectionAborted, e)) })?; Self::new_quic(connection, false, metrics) .await .map_err(|e| { trace!(?e, "error with quic"); - NetworkConnectError::Io(std::io::Error::new( - std::io::ErrorKind::ConnectionAborted, - e, - )) + NetworkConnectError::Io(io::Error::new(io::ErrorKind::ConnectionAborted, e)) }) } @@ -286,7 +277,7 @@ impl Protocols { metrics: Arc, s2s_stop_listening_r: oneshot::Receiver<()>, c2s_protocol_s: mpsc::UnboundedSender<(Self, Cid)>, - ) -> std::io::Result<()> { + ) -> io::Result<()> { let (_endpoint, mut listener) = match quinn::Endpoint::server(server_config, addr) { Ok(v) => v, Err(e) => return Err(e), @@ -378,12 +369,14 @@ impl Protocols { #[async_trait] impl network_protocol::InitProtocol for Protocols { + type CustomErr = ProtocolsError; + async fn initialize( &mut self, initializer: bool, local_pid: Pid, secret: u128, - ) -> Result<(Pid, Sid, u128), InitProtocolError> { + ) -> Result<(Pid, Sid, u128), InitProtocolError> { match self { Protocols::Tcp(p) => p.initialize(initializer, local_pid, secret).await, Protocols::Mpsc(p) => p.initialize(initializer, local_pid, secret).await, @@ -395,6 +388,8 @@ impl network_protocol::InitProtocol for Protocols { #[async_trait] impl network_protocol::SendProtocol for SendProtocols { + type CustomErr = ProtocolsError; + fn notify_from_recv(&mut self, event: ProtocolEvent) { match self { SendProtocols::Tcp(s) => s.notify_from_recv(event), @@ -404,7 +399,7 @@ impl network_protocol::SendProtocol for SendProtocols { } } - async fn send(&mut self, event: ProtocolEvent) -> Result<(), ProtocolError> { + async fn send(&mut self, event: ProtocolEvent) -> Result<(), ProtocolError> { match self { SendProtocols::Tcp(s) => s.send(event).await, SendProtocols::Mpsc(s) => s.send(event).await, @@ -417,7 +412,7 @@ impl network_protocol::SendProtocol for SendProtocols { &mut self, bandwidth: Bandwidth, dt: Duration, - ) -> Result { + ) -> Result> { match self { SendProtocols::Tcp(s) => s.flush(bandwidth, dt).await, SendProtocols::Mpsc(s) => s.flush(bandwidth, dt).await, @@ -429,7 +424,9 @@ impl network_protocol::SendProtocol for SendProtocols { #[async_trait] impl network_protocol::RecvProtocol for RecvProtocols { - async fn recv(&mut self) -> Result { + type CustomErr = ProtocolsError; + + async fn recv(&mut self) -> Result> { match self { RecvProtocols::Tcp(r) => r.recv().await, RecvProtocols::Mpsc(r) => r.recv().await, @@ -439,6 +436,32 @@ impl network_protocol::RecvProtocol for RecvProtocols { } } +#[derive(Debug)] +pub enum MpscError { + Send(tokio::sync::mpsc::error::SendError), + Recv, +} + +#[cfg(feature = "quic")] +#[derive(Debug)] +pub enum QuicError { + Send(std::io::Error), + Connection(quinn::ConnectionError), + Write(quinn::WriteError), + Read(quinn::ReadError), + InternalMpsc, +} + +/// Error types for Protocols +#[derive(Debug)] +pub enum ProtocolsError { + Tcp(std::io::Error), + Udp(std::io::Error), + #[cfg(feature = "quic")] + Quic(QuicError), + Mpsc(MpscError), +} + /////////////////////////////////////// //// TCP #[derive(Debug)] @@ -454,26 +477,31 @@ pub struct TcpSink { #[async_trait] impl UnreliableDrain for TcpDrain { + type CustomErr = ProtocolsError; type DataFormat = BytesMut; - async fn send(&mut self, data: Self::DataFormat) -> Result<(), ProtocolError> { - match self.half.write_all(&data).await { - Ok(()) => Ok(()), - Err(_) => Err(ProtocolError::Closed), - } + async fn send(&mut self, data: Self::DataFormat) -> Result<(), ProtocolError> { + self.half + .write_all(&data) + .await + .map_err(|e| ProtocolError::Custom(ProtocolsError::Tcp(e))) } } #[async_trait] impl UnreliableSink for TcpSink { + type CustomErr = ProtocolsError; type DataFormat = BytesMut; - async fn recv(&mut self) -> Result { + async fn recv(&mut self) -> Result> { self.buffer.resize(1500, 0u8); match self.half.read(&mut self.buffer).await { - Ok(0) => Err(ProtocolError::Closed), + Ok(0) => Err(ProtocolError::Custom(ProtocolsError::Tcp(io::Error::new( + io::ErrorKind::BrokenPipe, + "read returned 0 bytes", + )))), Ok(n) => Ok(self.buffer.split_to(n)), - Err(_) => Err(ProtocolError::Closed), + Err(e) => Err(ProtocolError::Custom(ProtocolsError::Tcp(e))), } } } @@ -492,22 +520,27 @@ pub struct MpscSink { #[async_trait] impl UnreliableDrain for MpscDrain { + type CustomErr = ProtocolsError; type DataFormat = MpscMsg; - async fn send(&mut self, data: Self::DataFormat) -> Result<(), ProtocolError> { + async fn send(&mut self, data: Self::DataFormat) -> Result<(), ProtocolError> { self.sender .send(data) .await - .map_err(|_| ProtocolError::Closed) + .map_err(|e| ProtocolError::Custom(ProtocolsError::Mpsc(MpscError::Send(e)))) } } #[async_trait] impl UnreliableSink for MpscSink { + type CustomErr = ProtocolsError; type DataFormat = MpscMsg; - async fn recv(&mut self) -> Result { - self.receiver.recv().await.ok_or(ProtocolError::Closed) + async fn recv(&mut self) -> Result> { + self.receiver + .recv() + .await + .ok_or(ProtocolError::Custom(ProtocolsError::Mpsc(MpscError::Recv))) } } @@ -560,10 +593,11 @@ fn spawn_new( #[cfg(feature = "quic")] #[async_trait] impl UnreliableDrain for QuicDrain { + type CustomErr = ProtocolsError; type DataFormat = QuicDataFormat; - async fn send(&mut self, data: Self::DataFormat) -> Result<(), ProtocolError> { - match match data.stream { + async fn send(&mut self, data: Self::DataFormat) -> Result<(), ProtocolError> { + match data.stream { QuicDataFormatStream::Main => self.main.write_all(&data.data).await, QuicDataFormatStream::Unreliable => unimplemented!(), QuicDataFormatStream::Reliable(sid) => { @@ -575,41 +609,43 @@ impl UnreliableDrain for QuicDrain { // IF the buffer is empty this was created localy and WE are allowed to // open_bi(), if not, we NEED to block on sendstreams_r if data.data.is_empty() { - match self.con.open_bi().await { - Ok((mut sendstream, recvstream)) => { - // send SID as first msg - if sendstream.write_u64(sid.get_u64()).await.is_err() { - return Err(ProtocolError::Closed); - } - spawn_new(recvstream, Some(sid), &self.recvstreams_s); - vacant.insert(sendstream).write_all(&data.data).await - }, - Err(_) => return Err(ProtocolError::Closed), - } + let (mut sendstream, recvstream) = + self.con.open_bi().await.map_err(|e| { + ProtocolError::Custom(ProtocolsError::Quic( + QuicError::Connection(e), + )) + })?; + // send SID as first msg + sendstream.write_u64(sid.get_u64()).await.map_err(|e| { + ProtocolError::Custom(ProtocolsError::Quic(QuicError::Send(e))) + })?; + spawn_new(recvstream, Some(sid), &self.recvstreams_s); + vacant.insert(sendstream).write_all(&data.data).await } else { - let sendstream = self - .sendstreams_r - .recv() - .await - .ok_or(ProtocolError::Closed)?; + let sendstream = + self.sendstreams_r + .recv() + .await + .ok_or(ProtocolError::Custom(ProtocolsError::Quic( + QuicError::InternalMpsc, + )))?; vacant.insert(sendstream).write_all(&data.data).await } }, } }, - } { - Ok(()) => Ok(()), - Err(_) => Err(ProtocolError::Closed), } + .map_err(|e| ProtocolError::Custom(ProtocolsError::Quic(QuicError::Write(e)))) } } #[cfg(feature = "quic")] #[async_trait] impl UnreliableSink for QuicSink { + type CustomErr = ProtocolsError; type DataFormat = QuicDataFormat; - async fn recv(&mut self) -> Result { + async fn recv(&mut self) -> Result> { let (mut buffer, result, mut recvstream, id) = loop { use futures_util::FutureExt; // first handle all bi streams! @@ -620,20 +656,20 @@ impl UnreliableSink for QuicSink { }; if let Some(remote_stream) = a { - match remote_stream { - Ok((sendstream, mut recvstream)) => { - let sid = match recvstream.read_u64().await { - Ok(u64::MAX) => None, //unreliable - Ok(sid) => Some(Sid::new(sid)), - Err(_) => return Err(ProtocolError::Violated), - }; - if self.sendstreams_s.send(sendstream).is_err() { - return Err(ProtocolError::Closed); - } - spawn_new(recvstream, sid, &self.recvstreams_s); - }, - Err(_) => return Err(ProtocolError::Closed), + let (sendstream, mut recvstream) = remote_stream.map_err(|e| { + ProtocolError::Custom(ProtocolsError::Quic(QuicError::Connection(e))) + })?; + let sid = match recvstream.read_u64().await { + Ok(u64::MAX) => None, //unreliable + Ok(sid) => Some(Sid::new(sid)), + Err(_) => return Err(ProtocolError::Violated), + }; + if self.sendstreams_s.send(sendstream).is_err() { + return Err(ProtocolError::Custom(ProtocolsError::Quic( + QuicError::InternalMpsc, + ))); } + spawn_new(recvstream, sid, &self.recvstreams_s); } if let Some(data) = b { @@ -642,7 +678,12 @@ impl UnreliableSink for QuicSink { }; let r = match result { - Ok(Some(0)) => Err(ProtocolError::Closed), + Ok(Some(0)) => Err(ProtocolError::Custom(ProtocolsError::Quic( + QuicError::Send(io::Error::new( + io::ErrorKind::BrokenPipe, + "read returned 0 bytes", + )), + ))), Ok(Some(n)) => Ok(QuicDataFormat { stream: match id { Some(id) => QuicDataFormatStream::Reliable(id), @@ -650,8 +691,15 @@ impl UnreliableSink for QuicSink { }, data: buffer.split_to(n), }), - Ok(None) => Err(ProtocolError::Closed), - Err(_) => Err(ProtocolError::Closed), + Ok(None) => Err(ProtocolError::Custom(ProtocolsError::Quic( + QuicError::Send(io::Error::new( + io::ErrorKind::BrokenPipe, + "read returned None", + )), + ))), + Err(e) => Err(ProtocolError::Custom(ProtocolsError::Quic( + QuicError::Read(e), + ))), }?; let streams_s_clone = self.recvstreams_s.clone(); @@ -739,6 +787,15 @@ mod tests { drop(s); let e = e.await.unwrap(); assert!(e.is_err()); - assert_eq!(e.unwrap_err(), ProtocolError::Closed); + assert!(matches!(e, Err(..))); + let e = e.unwrap_err(); + assert!(matches!(e, ProtocolError::Custom(..))); + assert!(matches!(e, ProtocolError::Custom(ProtocolsError::Tcp(_)))); + match e { + ProtocolError::Custom(ProtocolsError::Tcp(e)) => { + assert_eq!(e.kind(), io::ErrorKind::BrokenPipe) + }, + _ => panic!("invalid error"), + } } } diff --git a/network/src/participant.rs b/network/src/participant.rs index 342759c1e2..2f8f38bca6 100644 --- a/network/src/participant.rs +++ b/network/src/participant.rs @@ -1,6 +1,6 @@ use crate::{ api::{ParticipantError, Stream}, - channel::{Protocols, RecvProtocols, SendProtocols}, + channel::{Protocols, ProtocolsError, RecvProtocols, SendProtocols}, metrics::NetworkMetrics, util::DeferredTracer, }; @@ -371,7 +371,7 @@ impl BParticipant { self.metrics .participant_bandwidth(&self.remote_pid_string, part_bandwidth); let _ = b2a_bandwidth_stats_s.send(part_bandwidth); - let r: Result<(), network_protocol::ProtocolError> = Ok(()); + let r: Result<(), network_protocol::ProtocolError> = Ok(()); r } .await; From fc735f509ebba4ce03481bb5e87b40c5d12649af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Mon, 23 May 2022 09:20:54 +0200 Subject: [PATCH 007/229] fix a unrelated clippy issue that came up suddenly --- voxygen/src/menu/main/client_init.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/voxygen/src/menu/main/client_init.rs b/voxygen/src/menu/main/client_init.rs index e2e173fb93..5cc0b5b791 100644 --- a/voxygen/src/menu/main/client_init.rs +++ b/voxygen/src/menu/main/client_init.rs @@ -16,6 +16,7 @@ use tracing::{trace, warn}; #[derive(Debug)] #[allow(clippy::enum_variant_names)] //TODO: evaluate ClientError ends with Enum name +#[allow(clippy::large_enum_variant)] // not a problem, its only send once pub enum Error { ClientError { error: ClientError, From 42af9b8e15d5598d85f0cb549c598fbc3e5de8a9 Mon Sep 17 00:00:00 2001 From: Corvella <10601026-Corvella@users.noreply.gitlab.com> Date: Mon, 23 May 2022 09:18:10 +0000 Subject: [PATCH 008/229] Hitbox improvements --- common/src/comp/body.rs | 56 +++++++++++++++++++++------------- common/src/comp/body/object.rs | 2 +- 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 184652993a..b245699f07 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -400,10 +400,10 @@ impl Body { }, Body::BipedSmall(body) => match body.species { biped_small::Species::Gnarling => Vec3::new(1.0, 0.75, 1.4), - biped_small::Species::Haniwa => Vec3::new(1.0, 0.75, 2.2), - biped_small::Species::Adlet => Vec3::new(1.0, 0.75, 2.0), - biped_small::Species::Sahagin => Vec3::new(1.0, 1.2, 1.7), - biped_small::Species::Myrmidon => Vec3::new(1.0, 0.75, 2.2), + biped_small::Species::Haniwa => Vec3::new(1.3, 1.0, 2.2), + biped_small::Species::Adlet => Vec3::new(1.3, 1.0, 2.0), + biped_small::Species::Sahagin => Vec3::new(1.3, 2.0, 1.7), + biped_small::Species::Myrmidon => Vec3::new(1.3, 1.0, 2.2), biped_small::Species::Husk => Vec3::new(1.7, 0.7, 2.7), _ => Vec3::new(1.0, 0.75, 1.4), @@ -415,7 +415,11 @@ impl Body { bird_medium::Species::Peacock => Vec3::new(1.3, 1.1, 1.4), _ => Vec3::new(2.0, 1.0, 1.5), }, - Body::BirdLarge(_) => Vec3::new(2.0, 6.0, 3.5), + Body::BirdLarge(body) => match body.species { + bird_large::Species::Cockatrice => Vec3::new(2.5, 5.5, 3.5), + bird_large::Species::Roc => Vec3::new(2.2, 7.5, 4.0), + _ => Vec3::new(2.0, 6.0, 3.5), + }, Body::Dragon(_) => Vec3::new(16.0, 10.0, 16.0), Body::FishMedium(_) => Vec3::new(0.5, 2.0, 0.8), Body::FishSmall(_) => Vec3::new(0.3, 1.2, 0.6), @@ -427,59 +431,67 @@ impl Body { Body::Object(object) => object.dimensions(), Body::ItemDrop(item_drop) => item_drop.dimensions(), Body::QuadrupedMedium(body) => match body.species { + quadruped_medium::Species::Akhlut => Vec3::new(2.5, 7.0, 3.0), quadruped_medium::Species::Barghest => Vec3::new(2.0, 4.4, 2.7), quadruped_medium::Species::Bear => Vec3::new(2.0, 3.8, 3.0), quadruped_medium::Species::Catoblepas => Vec3::new(2.0, 4.0, 2.9), quadruped_medium::Species::Cattle => Vec3::new(2.0, 3.6, 2.4), quadruped_medium::Species::Deer => Vec3::new(2.0, 3.0, 2.2), - quadruped_medium::Species::Dreadhorn => Vec3::new(2.0, 5.0, 4.0), + quadruped_medium::Species::Dreadhorn => Vec3::new(3.5, 6.0, 4.0), + quadruped_medium::Species::Frostfang => Vec3::new(1.5, 3.0, 1.5), quadruped_medium::Species::Grolgar => Vec3::new(2.0, 4.0, 2.0), quadruped_medium::Species::Highland => Vec3::new(2.0, 3.6, 2.4), quadruped_medium::Species::Horse => Vec3::new(2.0, 3.0, 2.4), quadruped_medium::Species::Lion => Vec3::new(2.0, 3.3, 2.0), quadruped_medium::Species::Moose => Vec3::new(2.0, 4.0, 2.5), + quadruped_medium::Species::Roshwalr => Vec3::new(2.0, 3.5, 2.2), quadruped_medium::Species::Saber => Vec3::new(2.0, 3.0, 2.0), quadruped_medium::Species::Tarasque => Vec3::new(2.0, 4.0, 2.6), quadruped_medium::Species::Yak => Vec3::new(2.0, 3.6, 3.0), - quadruped_medium::Species::Mammoth => Vec3::new(2.0, 7.0, 8.0), + quadruped_medium::Species::Mammoth => Vec3::new(7.5, 11.5, 8.0), quadruped_medium::Species::Ngoubou => Vec3::new(2.0, 3.2, 2.4), quadruped_medium::Species::Llama => Vec3::new(2.0, 2.5, 2.6), quadruped_medium::Species::Alpaca => Vec3::new(2.0, 2.0, 2.0), quadruped_medium::Species::Camel => Vec3::new(2.0, 4.0, 3.5), + quadruped_medium::Species::Wolf => Vec3::new(1.7, 3.0, 1.8), // FIXME: We really shouldn't be doing wildcards here _ => Vec3::new(2.0, 3.0, 2.0), }, Body::QuadrupedSmall(body) => match body.species { - quadruped_small::Species::Dodarock => Vec3::new(1.2, 1.8, 1.5), - quadruped_small::Species::Holladon => Vec3::new(1.2, 1.6, 1.5), + quadruped_small::Species::Batfox => Vec3::new(1.4, 1.7, 1.3), + quadruped_small::Species::Dodarock => Vec3::new(1.2, 1.9, 1.5), + quadruped_small::Species::Holladon => Vec3::new(1.3, 1.9, 1.5), + quadruped_small::Species::Hyena => Vec3::new(1.2, 1.4, 1.3), quadruped_small::Species::Truffler => Vec3::new(1.2, 1.8, 2.2), _ => Vec3::new(1.2, 1.2, 1.0), }, Body::QuadrupedLow(body) => match body.species { - quadruped_low::Species::Asp => Vec3::new(1.0, 3.0, 1.8), + quadruped_low::Species::Asp => Vec3::new(2.0, 3.0, 1.7), quadruped_low::Species::Crocodile => Vec3::new(1.0, 2.8, 1.3), - quadruped_low::Species::Deadwood => Vec3::new(1.0, 1.4, 1.3), - quadruped_low::Species::Lavadrake => Vec3::new(1.0, 3.0, 2.5), - quadruped_low::Species::Maneater => Vec3::new(1.0, 2.2, 4.0), - quadruped_low::Species::Monitor => Vec3::new(1.0, 2.3, 1.5), + quadruped_low::Species::Deadwood => Vec3::new(1.3, 1.3, 1.4), + quadruped_low::Species::Hakulaq => Vec3::new(1.8, 3.0, 2.0), + quadruped_low::Species::Icedrake => Vec3::new(2.0, 5.5, 2.5), + quadruped_low::Species::Lavadrake => Vec3::new(2.0, 4.7, 2.5), + quadruped_low::Species::Maneater => Vec3::new(2.5, 3.7, 4.0), + quadruped_low::Species::Monitor => Vec3::new(1.4, 3.2, 1.3), quadruped_low::Species::Pangolin => Vec3::new(1.0, 2.6, 1.1), - quadruped_low::Species::Rocksnapper => Vec3::new(1.0, 3.0, 2.9), - quadruped_low::Species::Sandshark => Vec3::new(1.1, 4.3, 1.7), - quadruped_low::Species::Basilisk => Vec3::new(1.8, 3.4, 2.9), - quadruped_low::Species::Salamander => Vec3::new(1.0, 2.4, 1.3), - quadruped_low::Species::Tortoise => Vec3::new(1.0, 1.8, 1.6), + quadruped_low::Species::Rocksnapper => Vec3::new(2.5, 3.5, 2.9), + quadruped_low::Species::Sandshark => Vec3::new(2.1, 4.3, 1.7), + quadruped_low::Species::Basilisk => Vec3::new(2.7, 6.0, 2.9), + quadruped_low::Species::Salamander => Vec3::new(1.7, 4.0, 1.3), + quadruped_low::Species::Tortoise => Vec3::new(1.7, 2.7, 1.5), _ => Vec3::new(1.0, 1.6, 1.3), }, Body::Ship(ship) => ship.dimensions(), Body::Theropod(body) => match body.species { theropod::Species::Archaeos => Vec3::new(4.0, 8.5, 8.0), - theropod::Species::Ntouka => Vec3::new(4.0, 7.0, 8.0), - theropod::Species::Odonto => Vec3::new(4.0, 7.0, 8.0), + theropod::Species::Ntouka => Vec3::new(4.0, 9.0, 6.6), + theropod::Species::Odonto => Vec3::new(4.0, 8.0, 6.6), theropod::Species::Sandraptor => Vec3::new(2.0, 3.0, 2.6), theropod::Species::Snowraptor => Vec3::new(2.0, 3.0, 2.6), theropod::Species::Sunlizard => Vec3::new(2.0, 3.6, 2.5), theropod::Species::Woodraptor => Vec3::new(2.0, 3.0, 2.6), - theropod::Species::Yale => Vec3::new(1.5, 3.2, 4.0), + theropod::Species::Yale => Vec3::new(2.0, 3.2, 4.0), }, Body::Arthropod(body) => match body.species { arthropod::Species::Tarantula => Vec3::new(4.0, 4.0, 1.8), diff --git a/common/src/comp/body/object.rs b/common/src/comp/body/object.rs index 638c12b6d4..a351c345e5 100644 --- a/common/src/comp/body/object.rs +++ b/common/src/comp/body/object.rs @@ -413,7 +413,7 @@ impl Body { Body::BoltFire => Vec3::new(0.1, 0.1, 0.1), Body::Crossbow => Vec3::new(3.0, 3.0, 1.5), Body::HaniwaSentry => Vec3::new(0.8, 0.8, 1.4), - Body::SeaLantern => Vec3::new(0.5, 0.5, 1.0), + Body::SeaLantern => Vec3::new(0.8, 0.8, 1.4), 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), From a9622fe28ef0e2aab1c09a513e8ff6895adfd6a6 Mon Sep 17 00:00:00 2001 From: Corvella <10601026-Corvella@users.noreply.gitlab.com> Date: Mon, 23 May 2022 23:09:47 +0000 Subject: [PATCH 009/229] Add a setting to toggle zooming in when charging bow --- CHANGELOG.md | 1 + assets/voxygen/i18n/en/hud/settings.ron | 1 + voxygen/src/hud/settings_window/gameplay.rs | 26 +++++++++++++++++++++ voxygen/src/session/mod.rs | 22 ++++++++++------- voxygen/src/session/settings_change.rs | 4 ++++ voxygen/src/settings/gameplay.rs | 2 ++ 6 files changed, 47 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46e0cc2882..319daaddc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Enable new giant trees, changed what entities spawn at them - Stealth is now shown as a percentage in Stats Diary UI - Stealth effects from sneaking and armor are evaluated independently. Armor now has effects even when not sneaking +- Zoom-in effect when aiming bow is now optional ### Removed diff --git a/assets/voxygen/i18n/en/hud/settings.ron b/assets/voxygen/i18n/en/hud/settings.ron index fc1369da8f..e7b2266b14 100644 --- a/assets/voxygen/i18n/en/hud/settings.ron +++ b/assets/voxygen/i18n/en/hud/settings.ron @@ -56,6 +56,7 @@ "hud.settings.player_physics_behavior": "Player physics (experimental)", "hud.settings.stop_auto_walk_on_input": "Stop auto walk on movement", "hud.settings.auto_camera": "Auto camera", + "hud.settings.bow_zoom": "Zoom in when charging bow", "hud.settings.reset_gameplay": "Reset to Defaults", "hud.settings.view_distance": "View Distance", diff --git a/voxygen/src/hud/settings_window/gameplay.rs b/voxygen/src/hud/settings_window/gameplay.rs index 010c71739b..68383732f7 100644 --- a/voxygen/src/hud/settings_window/gameplay.rs +++ b/voxygen/src/hud/settings_window/gameplay.rs @@ -50,6 +50,8 @@ widget_ids! { stop_auto_walk_on_input_label, auto_camera_button, auto_camera_label, + bow_zoom_button, + bow_zoom_label, } } @@ -523,6 +525,30 @@ impl<'a> Widget for Gameplay<'a> { .color(TEXT_COLOR) .set(state.ids.auto_camera_label, ui); + // Charging bow zoom toggle + let bow_zoom_toggle = ToggleButton::new( + self.global_state.settings.gameplay.bow_zoom, + self.imgs.checkbox, + self.imgs.checkbox_checked, + ) + .w_h(18.0, 18.0) + .down_from(state.ids.auto_camera_button, 8.0) + .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo) + .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked) + .set(state.ids.bow_zoom_button, ui); + + if self.global_state.settings.gameplay.bow_zoom != bow_zoom_toggle { + events.push(ChangeBowZoom(!self.global_state.settings.gameplay.bow_zoom)); + } + + Text::new(self.localized_strings.get("hud.settings.bow_zoom")) + .right_from(state.ids.bow_zoom_button, 10.0) + .font_size(self.fonts.cyri.scale(14)) + .font_id(self.fonts.cyri.conrod_id) + .graphics_for(state.ids.bow_zoom_button) + .color(TEXT_COLOR) + .set(state.ids.bow_zoom_label, ui); + // Reset the gameplay settings to the default settings if Button::image(self.imgs.button) .w_h(RESET_BUTTONS_WIDTH, RESET_BUTTONS_HEIGHT) diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 235a52cd23..fe14ed81b9 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -354,17 +354,21 @@ impl PlayState for SessionState { let client = self.client.borrow(); let player_entity = client.entity(); - let mut fov_scaling = 1.0; - if let Some(comp::CharacterState::ChargedRanged(cr)) = client - .state() - .read_storage::() - .get(player_entity) - { - if cr.charge_frac() > 0.5 { - fov_scaling -= 3.0 * cr.charge_frac() / 5.0; + if global_state.settings.gameplay.bow_zoom { + let mut fov_scaling = 1.0; + if let Some(comp::CharacterState::ChargedRanged(cr)) = client + .state() + .read_storage::() + .get(player_entity) + { + if cr.charge_frac() > 0.5 { + fov_scaling -= 3.0 * cr.charge_frac() / 5.0; + } } + camera.set_fixate(fov_scaling); + } else { + camera.set_fixate(1.0); } - camera.set_fixate(fov_scaling); // Compute camera data camera.compute_dependents(&*self.client.borrow().state().terrain()); diff --git a/voxygen/src/session/settings_change.rs b/voxygen/src/session/settings_change.rs index 0af724f2aa..46924ce0a0 100644 --- a/voxygen/src/session/settings_change.rs +++ b/voxygen/src/session/settings_change.rs @@ -63,6 +63,7 @@ pub enum Gameplay { ChangePlayerPhysicsBehavior { server_authoritative: bool }, ChangeStopAutoWalkOnInput(bool), ChangeAutoCamera(bool), + ChangeBowZoom(bool), ResetGameplaySettings, } @@ -318,6 +319,9 @@ impl SettingsChange { Gameplay::ChangeAutoCamera(state) => { settings.gameplay.auto_camera = state; }, + Gameplay::ChangeBowZoom(state) => { + settings.gameplay.bow_zoom = state; + }, Gameplay::ResetGameplaySettings => { // Reset Gameplay Settings settings.gameplay = GameplaySettings::default(); diff --git a/voxygen/src/settings/gameplay.rs b/voxygen/src/settings/gameplay.rs index 488c641f2e..e453f65c1a 100644 --- a/voxygen/src/settings/gameplay.rs +++ b/voxygen/src/settings/gameplay.rs @@ -17,6 +17,7 @@ pub struct GameplaySettings { pub player_physics_behavior: bool, pub stop_auto_walk_on_input: bool, pub auto_camera: bool, + pub bow_zoom: bool, } impl Default for GameplaySettings { @@ -34,6 +35,7 @@ impl Default for GameplaySettings { player_physics_behavior: false, stop_auto_walk_on_input: true, auto_camera: false, + bow_zoom: true, } } } From d84a26dfd821afdb5cdb5311cf1d4258d92a83a6 Mon Sep 17 00:00:00 2001 From: N A Date: Tue, 24 May 2022 02:09:45 +0000 Subject: [PATCH 010/229] Special case taming and mounting. --- common/src/comp/body/bird_medium.rs | 9 ++- common/src/comp/pet.rs | 62 +++++++++++++++++-- common/src/comp/phys.rs | 2 +- common/src/mounting.rs | 28 ++++++--- .../src/persistence/character/conversions.rs | 7 +++ server/src/persistence/json_models.rs | 1 + voxygen/src/hud/mod.rs | 27 +++----- 7 files changed, 100 insertions(+), 36 deletions(-) diff --git a/common/src/comp/body/bird_medium.rs b/common/src/comp/body/bird_medium.rs index 7754c4cce3..6b279cf536 100644 --- a/common/src/comp/body/bird_medium.rs +++ b/common/src/comp/body/bird_medium.rs @@ -1,6 +1,7 @@ use crate::{make_case_elim, make_proj_elim}; use rand::{seq::SliceRandom, thread_rng}; use serde::{Deserialize, Serialize}; +use strum::{Display, EnumString}; make_proj_elim!( body, @@ -31,7 +32,9 @@ impl From for super::Body { make_case_elim!( species, - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] + #[derive( + Copy, Clone, Debug, Display, EnumString, PartialEq, Eq, Hash, Serialize, Deserialize, + )] #[repr(u32)] pub enum Species { Duck = 0, @@ -98,7 +101,9 @@ impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies { make_case_elim!( body_type, - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] + #[derive( + Copy, Clone, Debug, Display, EnumString, PartialEq, Eq, Hash, Serialize, Deserialize, + )] #[repr(u32)] pub enum BodyType { Female = 0, diff --git a/common/src/comp/pet.rs b/common/src/comp/pet.rs index 78187c59cb..8f56628911 100644 --- a/common/src/comp/pet.rs +++ b/common/src/comp/pet.rs @@ -1,4 +1,4 @@ -use crate::comp::body::Body; +use crate::comp::{body::Body, phys::Mass, quadruped_low, quadruped_medium, quadruped_small}; use crossbeam_utils::atomic::AtomicCell; use serde::{Deserialize, Serialize}; use specs::Component; @@ -40,10 +40,62 @@ pub fn is_tameable(body: &Body) -> bool { // Currently only Quadruped animals can be tamed pending further work // on the pets feature (allowing larger animals to be tamed will // require balance issues to be addressed). - matches!( - body, - Body::QuadrupedLow(_) | Body::QuadrupedMedium(_) | Body::QuadrupedSmall(_) - ) + match body { + Body::QuadrupedMedium(quad_med) => + // NOTE: the reason we ban mammoth from being tameable even though they're + // agressive anyway, is that UncomfySilence is going to make them + // peaceful after this MR gets merged. Please, remove this note in your MR, + // UncomfySilence! + { + !matches!( + quad_med.species, + quadruped_medium::Species::Catoblepas + | quadruped_medium::Species::Mammoth + | quadruped_medium::Species::Hirdrasil + ) + }, + Body::QuadrupedLow(_) | Body::QuadrupedSmall(_) | Body::BirdMedium(_) => true, + _ => false, + } +} + +pub fn is_mountable(mount: &Body, rider: Option<&Body>) -> bool { + let is_light_enough = + |rider: Option<&Body>| -> bool { rider.map_or(false, |b| b.mass() <= Mass(500.0)) }; + + match mount { + Body::QuadrupedMedium(body) => match body.species { + quadruped_medium::Species::Alpaca + | quadruped_medium::Species::Antelope + | quadruped_medium::Species::Bear + | quadruped_medium::Species::Camel + | quadruped_medium::Species::Cattle + | quadruped_medium::Species::Deer + | quadruped_medium::Species::Donkey + | quadruped_medium::Species::Highland + | quadruped_medium::Species::Horse + | quadruped_medium::Species::Kelpie + | quadruped_medium::Species::Llama + | quadruped_medium::Species::Moose + | quadruped_medium::Species::Tuskram + | quadruped_medium::Species::Yak + | quadruped_medium::Species::Zebra => true, + quadruped_medium::Species::Mouflon => is_light_enough(rider), + _ => false, + }, + Body::QuadrupedSmall(body) => match body.species { + quadruped_small::Species::Truffler => true, + quadruped_small::Species::Boar | quadruped_small::Species::Holladon => { + is_light_enough(rider) + }, + _ => false, + }, + Body::QuadrupedLow(body) => matches!( + body.species, + quadruped_low::Species::Salamander | quadruped_low::Species::Tortoise + ), + _ => false, + } } impl Component for Pet { diff --git a/common/src/comp/phys.rs b/common/src/comp/phys.rs index e352326a76..423fbaf6a9 100644 --- a/common/src/comp/phys.rs +++ b/common/src/comp/phys.rs @@ -81,7 +81,7 @@ impl Component for Scale { } // Mass -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] pub struct Mass(pub f32); impl Default for Mass { diff --git a/common/src/mounting.rs b/common/src/mounting.rs index bfc0c6b185..96b586cf69 100644 --- a/common/src/mounting.rs +++ b/common/src/mounting.rs @@ -1,5 +1,6 @@ use crate::{ comp, + comp::{pet::is_mountable, Body}, link::{Is, Link, LinkHandle, Role}, terrain::TerrainGrid, uid::{Uid, UidAllocator}, @@ -38,6 +39,7 @@ impl Link for Mounting { Read<'a, UidAllocator>, WriteStorage<'a, Is>, WriteStorage<'a, Is>, + WriteStorage<'a, Body>, ); type DeleteData<'a> = ( Read<'a, UidAllocator>, @@ -58,7 +60,7 @@ impl Link for Mounting { fn create( this: &LinkHandle, - (uid_allocator, mut is_mounts, mut is_riders): Self::CreateData<'_>, + (uid_allocator, mut is_mounts, mut is_riders, body): Self::CreateData<'_>, ) -> Result<(), Self::Error> { let entity = |uid: Uid| uid_allocator.retrieve_entity_internal(uid.into()); @@ -66,15 +68,23 @@ impl Link for Mounting { // Forbid self-mounting Err(MountingError::NotMountable) } else if let Some((mount, rider)) = entity(this.mount).zip(entity(this.rider)) { - let can_mount_with = - |entity| is_mounts.get(entity).is_none() && is_riders.get(entity).is_none(); + if let Some(mount_body) = body.get(mount) { + if is_mountable(mount_body, body.get(rider)) { + let can_mount_with = + |entity| is_mounts.get(entity).is_none() && is_riders.get(entity).is_none(); - // Ensure that neither mount or rider are already part of a mounting - // relationship - if can_mount_with(mount) && can_mount_with(rider) { - let _ = is_mounts.insert(mount, this.make_role()); - let _ = is_riders.insert(rider, this.make_role()); - Ok(()) + // Ensure that neither mount or rider are already part of a mounting + // relationship + if can_mount_with(mount) && can_mount_with(rider) { + let _ = is_mounts.insert(mount, this.make_role()); + let _ = is_riders.insert(rider, this.make_role()); + Ok(()) + } else { + Err(MountingError::NotMountable) + } + } else { + Err(MountingError::NotMountable) + } } else { Err(MountingError::NotMountable) } diff --git a/server/src/persistence/character/conversions.rs b/server/src/persistence/character/conversions.rs index 9637a9ea75..21cdd22b82 100644 --- a/server/src/persistence/character/conversions.rs +++ b/server/src/persistence/character/conversions.rs @@ -209,6 +209,10 @@ pub fn convert_body_to_database_json( "quadruped_small", serde_json::to_string(&GenericBody::from(body))?, ), + common::comp::Body::BirdMedium(body) => ( + "bird_medium", + serde_json::to_string(&GenericBody::from(body))?, + ), _ => { return Err(PersistenceError::ConversionError(format!( "Unsupported body type for persistence: {:?}", @@ -577,6 +581,9 @@ pub fn convert_body_from_database( "quadruped_small" => { deserialize_body!(body_data, QuadrupedSmall, quadruped_small) }, + "bird_medium" => { + deserialize_body!(body_data, BirdMedium, bird_medium) + }, _ => { return Err(PersistenceError::ConversionError(format!( "{} is not a supported body type for deserialization", diff --git a/server/src/persistence/json_models.rs b/server/src/persistence/json_models.rs index 610ecccc7a..30003655f3 100644 --- a/server/src/persistence/json_models.rs +++ b/server/src/persistence/json_models.rs @@ -59,6 +59,7 @@ macro_rules! generic_body_from_impl { generic_body_from_impl!(comp::quadruped_low::Body); generic_body_from_impl!(comp::quadruped_medium::Body); generic_body_from_impl!(comp::quadruped_small::Body); +generic_body_from_impl!(comp::bird_medium::Body); #[derive(Serialize, Deserialize)] pub struct CharacterPosition { diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index c02dd10a1d..3803fb0ec6 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -82,6 +82,7 @@ use common::{ fluid_dynamics, inventory::{slot::InvSlotId, trade_pricing::TradePricing}, item::{tool::ToolKind, ItemDesc, MaterialStatManifest, Quality}, + pet::is_mountable, skillset::{skills::Skill, SkillGroupKind}, BuffData, BuffKind, Item, MapMarkerChange, }, @@ -1929,7 +1930,8 @@ impl Hud { _, health, _, - height_offset, + scale, + body, hpfl, in_group, dist_sqr, @@ -2034,23 +2036,10 @@ impl Hud { } else { None }; - (info.is_some() || bubble.is_some()).then(|| { ( - entity, - pos, - info, - bubble, - stats, - skill_set, - health, - buffs, - body.height() * scale.map_or(1.0, |s| s.0) + 0.5, - hpfl, - in_group, - dist_sqr, - alignment, - is_mount, + entity, pos, info, bubble, stats, skill_set, health, buffs, scale, + body, hpfl, in_group, dist_sqr, alignment, is_mount, ) }) }, @@ -2060,10 +2049,9 @@ impl Hud { &mut self.ids.overheads, &mut ui_widgets.widget_id_generator(), ); - let ingame_pos = pos + Vec3::unit_z() * height_offset; - // - // * height_offset + let height_offset = body.height() * scale.map_or(1.0, |s| s.0) + 0.5; + let ingame_pos = pos + Vec3::unit_z() * height_offset; // Speech bubble, name, level, and hp bars overhead::Overhead::new( @@ -2093,6 +2081,7 @@ impl Hud { if Some(*owner) == client.uid() && !client.is_riding() && is_mount.is_none() + && is_mountable(body, bodies.get(client.entity())) && dist_sqr < common::consts::MAX_MOUNT_RANGE.powi(2) => { vec![(GameInput::Mount, i18n.get("hud.mount").to_string())] From 2e6e864672f06968c81b6f796271b6eaa23aa4a7 Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Tue, 24 May 2022 23:31:20 +0200 Subject: [PATCH 011/229] fix missing comma at line ends --- assets/voxygen/i18n/pl_PL/hud/map.ron | 2 +- assets/voxygen/i18n/pl_PL/hud/settings.ron | 6 +++--- assets/voxygen/i18n/pl_PL/hud/trade.ron | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/voxygen/i18n/pl_PL/hud/map.ron b/assets/voxygen/i18n/pl_PL/hud/map.ron index e411f456a0..644264a0e6 100644 --- a/assets/voxygen/i18n/pl_PL/hud/map.ron +++ b/assets/voxygen/i18n/pl_PL/hud/map.ron @@ -6,7 +6,7 @@ // Map and Questlog "hud.map.map_title": "Mapa", "hud.map.qlog_title": "Zadania", - "hud.map.topo_map": "Widok topograficzny" + "hud.map.topo_map": "Widok topograficzny", "hud.map.difficulty": "Trudność", "hud.map.towns": "Miasta", "hud.map.castles": "Zamki", diff --git a/assets/voxygen/i18n/pl_PL/hud/settings.ron b/assets/voxygen/i18n/pl_PL/hud/settings.ron index dd65b35c98..e7fa4b7a28 100644 --- a/assets/voxygen/i18n/pl_PL/hud/settings.ron +++ b/assets/voxygen/i18n/pl_PL/hud/settings.ron @@ -34,7 +34,7 @@ "hud.settings.speech_bubble_dark_mode": "Dymek rozmowy w trybie ciemnym", "hud.settings.speech_bubble_icon": "Ikona dymka rozmowy", "hud.settings.energybar_numbers": "Numery na pasku energii", - "hud.settings.always_show_bars": "Zawsze pokazuj paski zdrowia i energii", + "hud.settings.always_show_bars": "Zawsze pokazuj paski zdrowia i energii", "hud.settings.values": "Wartości", "hud.settings.percentages": "Procenty", "hud.settings.chat": "Czat", @@ -115,9 +115,9 @@ "hud.settings.audio_device": "Urządzenie dźwiękowe", "hud.settings.reset_sound": "Zresetuj ustawienia", - "hud.settings.english_fallback": "Wyświetl angielskie napisy dla brakujących tłumaczeń" + "hud.settings.english_fallback": "Wyświetl angielskie napisy dla brakujących tłumaczeń", - "hud.settings.awaitingkey": "Naciśnij klawisz...", + "hud.settings.awaitingkey": "Naciśnij klawisz...", "hud.settings.unbound": "Brak", "hud.settings.reset_keybinds": "Zresetuj ustawienia", diff --git a/assets/voxygen/i18n/pl_PL/hud/trade.ron b/assets/voxygen/i18n/pl_PL/hud/trade.ron index 724ed7b8d8..97beddb038 100644 --- a/assets/voxygen/i18n/pl_PL/hud/trade.ron +++ b/assets/voxygen/i18n/pl_PL/hud/trade.ron @@ -20,10 +20,10 @@ "hud.trade.sell_price": "Cena sprzedaży", "hud.trade.coin": "monet(y)", "hud.trade.tooltip_hint_1": "", - "hud.trade.tooltip_hint_2": "" + "hud.trade.tooltip_hint_2": "", "hud.trade.your_offer": "Twoja oferta", "hud.trade.their_offer": "Jego oferta", - "hud.trade.amount_input": "Wybierz przedmiot" + "hud.trade.amount_input": "Wybierz przedmiot", }, From a366fc4512946c31b2bcfc420b5d3884dda83fcc Mon Sep 17 00:00:00 2001 From: Imbris Date: Tue, 10 May 2022 03:28:13 -0400 Subject: [PATCH 012/229] Update tracy --- Cargo.lock | 47 +++++++--- common/base/Cargo.toml | 2 +- common/base/src/lib.rs | 174 +++++++++++++++++-------------------- common/frontend/Cargo.toml | 2 +- common/src/slowjob.rs | 2 +- server-cli/src/main.rs | 5 +- voxygen/Cargo.toml | 2 +- voxygen/src/main.rs | 3 + voxygen/src/run.rs | 10 ++- 9 files changed, 132 insertions(+), 115 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76c15ad699..39efea9d81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2069,6 +2069,19 @@ dependencies = [ "byteorder", ] +[[package]] +name = "generator" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1d9279ca822891c1a4dae06d185612cf8fc6acfe5dff37781b41297811b12ee" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "winapi 0.3.9", +] + [[package]] name = "generic-array" version = "0.12.4" @@ -3152,6 +3165,19 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "loom" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc5c7d328e32cc4954e8e01193d7f0ef5ab257b5090b70a964e099a36034309" +dependencies = [ + "cfg-if 1.0.0", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + [[package]] name = "loupe" version = "0.1.3" @@ -4471,9 +4497,9 @@ dependencies = [ [[package]] name = "profiling" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9145ac0af1d93c638c98c40cf7d25665f427b2a44ad0a99b1dccf3e2f25bb987" +checksum = "2f61dcf0b917cd75d4521d7343d1ffff3d1583054133c9b5cbea3375c703c40d" dependencies = [ "profiling-procmacros", "tracy-client", @@ -4481,9 +4507,9 @@ dependencies = [ [[package]] name = "profiling-procmacros" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "151b4774158c69aae073abb06d0cf879c4657966e6f2d7535d9b0e94e85500af" +checksum = "98eee3c112f2a6f784b6713fe1d7fb7d6506e066121c0a49371fdb976f72bae5" dependencies = [ "quote 1.0.17", "syn 1.0.90", @@ -6242,9 +6268,9 @@ dependencies = [ [[package]] name = "tracing-tracy" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773057bb2b440e868776522a0587f732b1125116f12aca0eb37dea48d55ad2cd" +checksum = "23a42311a35ed976d72f359de43e9fe028ec9d9f1051c4c52bd05a4f66ff3cbf" dependencies = [ "tracing-core", "tracing-subscriber", @@ -6253,19 +6279,20 @@ dependencies = [ [[package]] name = "tracy-client" -version = "0.12.7" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffcb26a0c786a0e154afdf21284969ff23759f42f156bcfddddae1a3c2404f2" +checksum = "42ebfe7a24c18b5ba86d8920c124b41b942352f863fbe0c84d3d63428fa1860f" dependencies = [ + "loom", "once_cell", "tracy-client-sys", ] [[package]] name = "tracy-client-sys" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6226e4e77f0d46ce7ebb0a4b1daa82790035248b75bbf605b932a1d7b3b22b6d" +checksum = "9012b9dfeccaff16e93f5a8b02336125113a80a769902e679d334cbdd4d83f3b" dependencies = [ "cc", ] diff --git a/common/base/Cargo.toml b/common/base/Cargo.toml index 96b3aa3ae8..fc79ae9d20 100644 --- a/common/base/Cargo.toml +++ b/common/base/Cargo.toml @@ -13,4 +13,4 @@ tracing = { version = "0.1", default-features = false } directories-next = "2.0" # Tracy -tracy-client = { version = "0.12.0", optional = true } +tracy-client = { version = "0.13.1", optional = true } diff --git a/common/base/src/lib.rs b/common/base/src/lib.rs index 5c78484061..098d881849 100644 --- a/common/base/src/lib.rs +++ b/common/base/src/lib.rs @@ -4,30 +4,6 @@ pub mod userdata_dir; pub use userdata_dir::userdata_dir; -#[cfg(feature = "tracy")] pub use tracy_client; - -/// Allows downstream crates to conditionally do things based on whether tracy -/// is enabled without having to expose a cargo feature themselves. -pub const TRACY_ENABLED: bool = cfg!(feature = "tracy"); - -#[cfg(not(feature = "tracy"))] -#[macro_export] -macro_rules! plot { - ($name:expr, $value:expr) => { - // type check - let _: f64 = $value; - }; -} -#[cfg(feature = "tracy")] -#[macro_export] -macro_rules! plot { - ($name:expr, $value:expr) => {{ - use $crate::tracy_client::{create_plot, Plot}; - static PLOT: Plot = create_plot!($name); - PLOT.point($value); - }}; -} - // Panic in debug or tests, warn in release #[macro_export] macro_rules! dev_panic { @@ -49,6 +25,24 @@ macro_rules! dev_panic { }; } +#[cfg(feature = "tracy")] pub use tracy_client; + +/// Allows downstream crates to conditionally do things based on whether tracy +/// is enabled without having to expose a cargo feature themselves. +pub const TRACY_ENABLED: bool = cfg!(feature = "tracy"); + +#[cfg(not(feature = "tracy"))] +#[macro_export] +macro_rules! plot { + ($name:expr, $value:expr) => { + // type check + let _: f64 = $value; + }; +} + +#[cfg(feature = "tracy")] +pub use tracy_client::plot; + // https://discordapp.com/channels/676678179678715904/676685797524766720/723358438943621151 #[cfg(not(feature = "tracy"))] #[macro_export] @@ -83,52 +77,33 @@ macro_rules! span { }; ($guard_name:tt, $name:expr) => { // Directly use `tracy_client` to decrease overhead for better timing - let $guard_name = $crate::tracy_client::Span::new( - $name, - "", - module_path!(), - line!(), - // No callstack since this has significant overhead - 0, - ); + $crate::prof_span_alloc!($guard_name, $name); }; ($guard_name:tt, $no_tracy_name:expr, $tracy_name:expr) => { $crate::span!($guard_name, $tracy_name); }; } -#[cfg(feature = "tracy")] -pub struct ProfSpan(pub tracy_client::Span); #[cfg(not(feature = "tracy"))] pub struct ProfSpan; -/// Like the span macro but only used when profiling and not in regular tracing -/// operations -#[macro_export] +/// Just implemented so that we dont need to have +/// #[allow(clippy::drop_non_drop)] everywhere #[cfg(not(feature = "tracy"))] -macro_rules! prof_span { - ($guard_name:tt, $name:expr) => { - let $guard_name = $crate::ProfSpan; - }; - // Shorthand for when you want the guard to just be dropped at the end of the scope instead - // of controlling it manually - ($name:expr) => {}; +impl Drop for ProfSpan { + fn drop(&mut self) {} } +#[cfg(feature = "tracy")] +pub struct ProfSpan(pub tracy_client::Span); + /// Like the span macro but only used when profiling and not in regular tracing /// operations +#[cfg(not(feature = "tracy"))] #[macro_export] -#[cfg(feature = "tracy")] macro_rules! prof_span { ($guard_name:tt, $name:expr) => { - let $guard_name = $crate::ProfSpan($crate::tracy_client::Span::new( - $name, - "", - module_path!(), - line!(), - // No callstack since this has significant overhead - 0, - )); + let $guard_name = $crate::ProfSpan; }; // Shorthand for when you want the guard to just be dropped at the end of the scope instead // of controlling it manually @@ -137,51 +112,58 @@ macro_rules! prof_span { }; } -/// There's no guard, but really this is actually the guard -pub struct GuardlessSpan { - span: tracing::Span, - subscriber: tracing::Dispatch, -} - -impl GuardlessSpan { - pub fn new(span: tracing::Span) -> Self { - let subscriber = tracing::dispatcher::get_default(|d| d.clone()); - if let Some(id) = span.id() { - subscriber.enter(&id) - } - Self { span, subscriber } - } -} - -impl Drop for GuardlessSpan { - fn drop(&mut self) { - if let Some(id) = self.span.id() { - self.subscriber.exit(&id) - } - } -} - -/// Just implemented so that we dont need to have -/// #[allow(clippy::drop_non_drop)] everywhere -impl Drop for ProfSpan { - fn drop(&mut self) {} -} - +/// Like the span macro but only used when profiling and not in regular tracing +/// operations +#[cfg(feature = "tracy")] #[macro_export] -macro_rules! no_guard_span { - ($level:ident, $name:expr, $($fields:tt)*) => { - GuardlessSpan::new( - tracing::span!(tracing::Level::$level, $name, $($fields)*) - ) - }; - ($level:ident, $name:expr) => { - GuardlessSpan::new( - tracing::span!(tracing::Level::$level, $name) - ) +macro_rules! prof_span { + ($guard_name:tt, $name:expr) => { + let $guard_name = $crate::ProfSpan( + // No callstack since this has significant overhead + $crate::tracy_client::span!($name, 0), + ); }; + // Shorthand for when you want the guard to just be dropped at the end of the scope instead + // of controlling it manually ($name:expr) => { - GuardlessSpan::new( - tracing::span!(tracing::Level::TRACE, $name) - ) + $crate::prof_span!(_guard, $name); + }; +} + +/// Like the prof_span macro but this one allocates so it can use strings only +/// known at runtime. +#[cfg(not(feature = "tracy"))] +#[macro_export] +macro_rules! prof_span_alloc { + ($guard_name:tt, $name:expr) => { + let $guard_name = $crate::ProfSpan; + }; + // Shorthand for when you want the guard to just be dropped at the end of the scope instead + // of controlling it manually + ($name:expr) => { + $crate::prof_span!(_guard, $name); + }; +} + +/// Like the prof_span macro but this one allocates so it can use strings only +/// known at runtime. +#[cfg(feature = "tracy")] +#[macro_export] +macro_rules! prof_span_alloc { + ($guard_name:tt, $name:expr) => { + let $guard_name = $crate::ProfSpan({ + struct S; + let type_name = core::any::type_name::(); + let function_name = &type_name[..type_name.len() - 3]; + $crate::tracy_client::Client::running() + .expect("prof_span_alloc! without a running tracy_client::Client") + // No callstack since this has significant overhead + .span_alloc($name, function_name, file!(), line!(), 0) + }); + }; + // Shorthand for when you want the guard to just be dropped at the end of the scope instead + // of controlling it manually + ($name:expr) => { + $crate::prof_span!(_guard, $name); }; } diff --git a/common/frontend/Cargo.toml b/common/frontend/Cargo.toml index 32e5690f4a..e123a8ca7a 100644 --- a/common/frontend/Cargo.toml +++ b/common/frontend/Cargo.toml @@ -19,4 +19,4 @@ tracing-log = "0.1.1" tracing-subscriber = { version = "0.3.7", default-features = false, features = ["env-filter", "fmt", "time", "ansi", "smallvec", "tracing-log"]} # Tracy -tracing-tracy = { version = "0.8.0", optional = true } +tracing-tracy = { version = "0.9.0", optional = true } diff --git a/common/src/slowjob.rs b/common/src/slowjob.rs index a1f613b21e..414d4888f8 100644 --- a/common/src/slowjob.rs +++ b/common/src/slowjob.rs @@ -98,7 +98,7 @@ impl Queue { id, name: name.to_owned(), task: Box::new(move || { - common_base::prof_span!(_guard, &name_cloned); + common_base::prof_span_alloc!(_guard, &name_cloned); let execution_start = Instant::now(); f(); let execution_end = Instant::now(); diff --git a/server-cli/src/main.rs b/server-cli/src/main.rs index 8b03b7eb0b..8d1fb66349 100644 --- a/server-cli/src/main.rs +++ b/server-cli/src/main.rs @@ -32,6 +32,9 @@ lazy_static::lazy_static! { const TPS: u64 = 30; fn main() -> io::Result<()> { + #[cfg(feature = "tracy")] + common_base::tracy_client::Client::start(); + use clap::Parser; let app = ArgvApp::parse(); @@ -268,7 +271,7 @@ fn main() -> io::Result<()> { // Wait for the next tick. clock.tick(); #[cfg(feature = "tracy")] - common_base::tracy_client::finish_continuous_frame!(); + common_base::tracy_client::frame_mark(); } Ok(()) diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index a0915f4dbb..6e1e2882cd 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -127,7 +127,7 @@ itertools = "0.10.0" # Tracy tracing = "0.1" -profiling = { version = "1.0.1", default-features = false, optional = true } +profiling = { version = "1.0.6", default-features = false, optional = true } [target.'cfg(target_os = "macos")'.dependencies] dispatch = "0.1.4" diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index 1deb42e272..f7e57e9a9b 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -29,6 +29,9 @@ use tracing::{error, info, warn}; use veloren_voxygen::ui::egui::EguiState; fn main() { + #[cfg(feature = "tracy")] + common_base::tracy_client::Client::start(); + let userdata_dir = common_base::userdata_dir_workspace!(); // Determine where Voxygen's logs should go diff --git a/voxygen/src/run.rs b/voxygen/src/run.rs index ffdac0905a..a3d57ce4f4 100644 --- a/voxygen/src/run.rs +++ b/voxygen/src/run.rs @@ -5,7 +5,7 @@ use crate::{ window::{Event, EventLoop}, Direction, GlobalState, PlayState, PlayStateResult, }; -use common_base::{no_guard_span, span, GuardlessSpan}; +use common_base::{prof_span, span}; use std::{mem, time::Duration}; use tracing::debug; @@ -71,7 +71,8 @@ pub fn run(mut global_state: GlobalState, event_loop: EventLoop) { match event { winit::event::Event::NewEvents(_) => { - event_span = Some(no_guard_span!("Process Events")); + prof_span!(span, "Process Events"); + event_span = Some(span); }, winit::event::Event::MainEventsCleared => { event_span.take(); @@ -79,7 +80,8 @@ pub fn run(mut global_state: GlobalState, event_loop: EventLoop) { if polled_twice { handle_main_events_cleared(&mut states, control_flow, &mut global_state); } - poll_span = Some(no_guard_span!("Poll Winit")); + prof_span!(span, "Poll Winit"); + poll_span = Some(span); polled_twice = !polled_twice; }, winit::event::Event::WindowEvent { event, .. } => { @@ -252,7 +254,7 @@ fn handle_main_events_cleared( global_state.clock.tick(); drop(guard); #[cfg(feature = "tracy")] - common_base::tracy_client::finish_continuous_frame!(); + common_base::tracy_client::frame_mark(); // Maintain global state. global_state.maintain(global_state.clock.dt()); From 4eb781cdf7f9d406f04f7c24faa088dd2e4c85e2 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 26 May 2022 10:08:41 +0100 Subject: [PATCH 013/229] Fixed climbing --- common/src/states/wallrun.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/states/wallrun.rs b/common/src/states/wallrun.rs index a7a7594a3a..7c53447022 100644 --- a/common/src/states/wallrun.rs +++ b/common/src/states/wallrun.rs @@ -36,7 +36,7 @@ impl CharacterBehavior for Data { // this state if data.physics.on_wall.is_none() || data.physics.on_ground.is_some() - || data.physics.in_fluid.is_some() + || data.physics.in_liquid().is_some() { update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); } From 5c8c88b786998e35d89039292460b8ede202514a Mon Sep 17 00:00:00 2001 From: Makselord Date: Thu, 26 May 2022 17:08:39 -0400 Subject: [PATCH 014/229] fixed silver, gold, copper, tin ingots not showing correctly in crafting --- assets/common/items/mineral/ingot/copper.ron | 2 +- assets/common/items/mineral/ingot/gold.ron | 2 +- assets/common/items/mineral/ingot/silver.ron | 2 +- assets/common/items/mineral/ingot/tin.ron | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/common/items/mineral/ingot/copper.ron b/assets/common/items/mineral/ingot/copper.ron index 4446b33d37..2217a9a6ea 100644 --- a/assets/common/items/mineral/ingot/copper.ron +++ b/assets/common/items/mineral/ingot/copper.ron @@ -5,5 +5,5 @@ ItemDef( descriptor: "Copper", ), quality: Low, - tags: [], + tags: [MaterialKind(Metal)], ) diff --git a/assets/common/items/mineral/ingot/gold.ron b/assets/common/items/mineral/ingot/gold.ron index bdbaa29df5..e8f4be1470 100644 --- a/assets/common/items/mineral/ingot/gold.ron +++ b/assets/common/items/mineral/ingot/gold.ron @@ -5,5 +5,5 @@ ItemDef( descriptor: "Golden", ), quality: Epic, - tags: [], + tags: [MaterialKind(Metal)], ) \ No newline at end of file diff --git a/assets/common/items/mineral/ingot/silver.ron b/assets/common/items/mineral/ingot/silver.ron index a65b4739da..0fc2b14c30 100644 --- a/assets/common/items/mineral/ingot/silver.ron +++ b/assets/common/items/mineral/ingot/silver.ron @@ -5,5 +5,5 @@ ItemDef( descriptor: "Silver", ), quality: Epic, - tags: [], + tags: [MaterialKind(Metal)], ) \ No newline at end of file diff --git a/assets/common/items/mineral/ingot/tin.ron b/assets/common/items/mineral/ingot/tin.ron index 93ecf2c25e..69c5117144 100644 --- a/assets/common/items/mineral/ingot/tin.ron +++ b/assets/common/items/mineral/ingot/tin.ron @@ -5,5 +5,5 @@ ItemDef( descriptor: "Tin", ), quality: Common, - tags: [], + tags: [MaterialKind(Metal)], ) From 5cf899c4fe71715dda81481408246dcc004f36c8 Mon Sep 17 00:00:00 2001 From: Imbris Date: Thu, 26 May 2022 00:43:44 -0400 Subject: [PATCH 015/229] Plot fixes in client and dynamic name fix in voxygen (tracy update) --- client/src/lib.rs | 19 +++++-------------- .../src/render/renderer/pipeline_creation.rs | 4 ++-- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index e4769b5381..b1abccac49 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -47,6 +47,7 @@ use common::{ uid::{Uid, UidAllocator}, vol::RectVolSize, }; +#[cfg(feature = "tracy")] use common_base::plot; use common_base::{prof_span, span}; use common_net::{ msg::{ @@ -78,16 +79,6 @@ use tokio::runtime::Runtime; use tracing::{debug, error, trace, warn}; use vek::*; -#[cfg(feature = "tracy")] -mod tracy_plots { - use common_base::tracy_client::{create_plot, Plot}; - pub static TERRAIN_SENDS: Plot = create_plot!("terrain_sends"); - pub static TERRAIN_RECVS: Plot = create_plot!("terrain_recvs"); - pub static INGAME_SENDS: Plot = create_plot!("ingame_sends"); - pub static INGAME_RECVS: Plot = create_plot!("ingame_recvs"); -} -#[cfg(feature = "tracy")] use tracy_plots::*; - const PING_ROLLING_AVERAGE_SECS: usize = 10; #[derive(Debug)] @@ -783,8 +774,8 @@ impl Client { }; #[cfg(feature = "tracy")] { - INGAME_SENDS.point(ingame); - TERRAIN_SENDS.point(terrain); + plot!("ingame_sends", ingame); + plot!("terrain_sends", terrain); } stream.send(msg) }, @@ -2197,8 +2188,8 @@ impl Client { if cnt_start == cnt { #[cfg(feature = "tracy")] { - TERRAIN_RECVS.point(terrain_cnt as f64); - INGAME_RECVS.point(ingame_cnt as f64); + plot!("terrain_recvs", terrain_cnt as f64); + plot!("ingame_recvs", ingame_cnt as f64); } return Ok(cnt); } diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index a4e8e34126..9c4c047c19 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -10,7 +10,7 @@ use super::{ shaders::Shaders, ImmutableLayouts, Layouts, }; -use common_base::prof_span; +use common_base::{prof_span, prof_span_alloc}; use std::sync::Arc; /// All the pipelines @@ -984,7 +984,7 @@ impl<'a> Task<'a> { // _name only used when tracy feature is activated StartedTask { _span: { - prof_span!(guard, _name); + prof_span_alloc!(guard, _name); guard }, _task: self, From 3015b4a29dd12c5ffb79ae5302d60354b1eef1b0 Mon Sep 17 00:00:00 2001 From: StereoJunkie Date: Fri, 27 May 2022 16:57:53 +0000 Subject: [PATCH 016/229] Non-humanoid picking up consumables when hungry --- CHANGELOG.md | 1 + server/src/sys/agent.rs | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 319daaddc9..0aecb6f084 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Stealth is now shown as a percentage in Stats Diary UI - Stealth effects from sneaking and armor are evaluated independently. Armor now has effects even when not sneaking - Zoom-in effect when aiming bow is now optional +- Non-Humanoid NPCs now pick up consumables when less than full health and use them to heal up. ### Removed diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index 09e7bcad3b..094cffe8d8 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -37,6 +37,7 @@ use common::{ tool::{AbilitySpec, ToolKind}, ConsumableKind, Item, ItemDesc, ItemKind, }, + item_drop, projectile::ProjectileConstructor, Agent, Alignment, BehaviorState, Body, CharacterState, ControlAction, ControlEvent, Controller, Health, HealthChange, InputKind, InventoryAction, InventoryEvent, Pos, Scale, @@ -1601,7 +1602,24 @@ impl<'a> AgentData<'a> { } }; let is_valid_target = |entity: EcsEntity| match read_data.bodies.get(entity) { - Some(Body::ItemDrop(_)) => Some((entity, false)), + Some(Body::ItemDrop(item)) => { + //If statement that checks either if the self (agent) is a humanoid, + //or if the self is not a humanoid, it checks whether or not you are 'hungry' - + // meaning less than full health - and additionally checks if + // the target entity is a consumable item. If it qualifies for + // either being a humanoid or a hungry non-humanoid that likes consumables, + // it will choose the item as its target. + if matches!(self.body, Some(Body::Humanoid(_))) + || (self + .health + .map_or(false, |health| health.current() < health.maximum()) + && matches!(item, item_drop::Body::Consumable)) + { + Some((entity, false)) + } else { + None + } + }, _ => { if read_data.healths.get(entity).map_or(false, |health| { !health.is_dead && !is_invulnerable(entity, read_data) From 2bf8e1865f8bcabb131b8c7ed816a0de1003fd33 Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Fri, 27 May 2022 17:19:52 +0000 Subject: [PATCH 017/229] Skiing and ice skating --- CHANGELOG.md | 1 + .../common/items/armor/misc/foot/iceskate.ron | 15 +++ assets/common/items/armor/misc/foot/ski.ron | 16 +++ assets/voxygen/item_image_manifest.ron | 8 ++ .../voxel/armor/misc/foot/iceskate.vox | 3 + assets/voxygen/voxel/armor/misc/foot/ski.vox | 3 + .../voxel/humanoid_armor_foot_manifest.ron | 8 ++ common/src/comp/ability.rs | 1 + common/src/comp/character_state.rs | 43 +++++-- common/src/comp/inventory/item/armor.rs | 53 ++++++++ common/src/comp/phys.rs | 8 +- common/src/states/climb.rs | 4 +- common/src/states/dance.rs | 4 +- common/src/states/glide.rs | 4 +- common/src/states/glide_wield.rs | 4 +- common/src/states/idle.rs | 22 +++- common/src/states/mod.rs | 1 + common/src/states/roll.rs | 2 + common/src/states/sit.rs | 4 +- common/src/states/skate.rs | 118 ++++++++++++++++++ common/src/states/sprite_interact.rs | 3 +- common/src/states/stunned.rs | 4 +- common/src/states/talk.rs | 6 +- common/src/states/use_item.rs | 3 +- common/src/states/utils.rs | 40 +++++- common/src/states/wallrun.rs | 2 +- common/src/states/wielding.rs | 2 + common/systems/src/character_behavior.rs | 2 +- common/systems/src/phys.rs | 103 +++++++++++++-- common/systems/src/stats.rs | 1 + voxygen/egui/src/lib.rs | 3 +- .../audio/sfx/event_mapper/movement/tests.rs | 10 +- voxygen/src/scene/figure/mod.rs | 50 +++----- 33 files changed, 461 insertions(+), 90 deletions(-) create mode 100644 assets/common/items/armor/misc/foot/iceskate.ron create mode 100644 assets/common/items/armor/misc/foot/ski.ron create mode 100644 assets/voxygen/voxel/armor/misc/foot/iceskate.vox create mode 100644 assets/voxygen/voxel/armor/misc/foot/ski.vox create mode 100644 common/src/states/skate.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 319daaddc9..9b84829b91 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 - Water caves - Modular weapons - Added Thai translation +- Skiing and ice skating ### Changed diff --git a/assets/common/items/armor/misc/foot/iceskate.ron b/assets/common/items/armor/misc/foot/iceskate.ron new file mode 100644 index 0000000000..5dcbe4d806 --- /dev/null +++ b/assets/common/items/armor/misc/foot/iceskate.ron @@ -0,0 +1,15 @@ +ItemDef( + name: "Ice Skates", + description: "Best used on a frozen lake.", + kind: Armor(( + kind: Foot, + stats: ( + protection: Some(Normal(3.0)), + ground_contact: Skate, + ), + )), + quality: Moderate, + tags: [ + Material(Steel), + ], +) diff --git a/assets/common/items/armor/misc/foot/ski.ron b/assets/common/items/armor/misc/foot/ski.ron new file mode 100644 index 0000000000..4fea9c1388 --- /dev/null +++ b/assets/common/items/armor/misc/foot/ski.ron @@ -0,0 +1,16 @@ +ItemDef( + name: "Wooden skis", + description: "Best used downhill on snow.", + kind: Armor(( + kind: Foot, + stats: ( + protection: Some(Normal(3.0)), + ground_contact: Ski, + ), + )), + quality: Moderate, + tags: [ + Material(Wood), +// SalvageInto(Twigs), + ], +) diff --git a/assets/voxygen/item_image_manifest.ron b/assets/voxygen/item_image_manifest.ron index 1c7db9d146..d28341f06b 100644 --- a/assets/voxygen/item_image_manifest.ron +++ b/assets/voxygen/item_image_manifest.ron @@ -2699,6 +2699,14 @@ "voxel.armor.misc.pants.grayscale", (0.0, 1.0, 0.0), (-120.0, 210.0,15.0), 0.9, ), + Simple("common.items.armor.misc.foot.ski"): VoxTrans( + "voxel.armor.misc.foot.ski", + (0.0, 0.0, 0.0), (-120.0, 210.0,15.0), 0.9, + ), + Simple("common.items.armor.misc.foot.iceskate"): VoxTrans( + "voxel.armor.misc.foot.iceskate", + (0.0, 0.0, 0.0), (-120.0, 210.0,15.0), 0.9, + ), // Backs Simple("common.items.armor.misc.back.short_0"): VoxTrans( "voxel.armor.misc.back.short-0", diff --git a/assets/voxygen/voxel/armor/misc/foot/iceskate.vox b/assets/voxygen/voxel/armor/misc/foot/iceskate.vox new file mode 100644 index 0000000000..c7cdeaec4c --- /dev/null +++ b/assets/voxygen/voxel/armor/misc/foot/iceskate.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c09d41a50285049e51249219d3ecfb5a034913491d35d67948705c957d42c8f +size 1596 diff --git a/assets/voxygen/voxel/armor/misc/foot/ski.vox b/assets/voxygen/voxel/armor/misc/foot/ski.vox new file mode 100644 index 0000000000..cdbb40415c --- /dev/null +++ b/assets/voxygen/voxel/armor/misc/foot/ski.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16768cda33af1d245e2aee7aa92eea497f604227517b276a9b164cd6ab850320 +size 23322 diff --git a/assets/voxygen/voxel/humanoid_armor_foot_manifest.ron b/assets/voxygen/voxel/humanoid_armor_foot_manifest.ron index 5f42c91d7c..d4b95c17d3 100644 --- a/assets/voxygen/voxel/humanoid_armor_foot_manifest.ron +++ b/assets/voxygen/voxel/humanoid_armor_foot_manifest.ron @@ -164,5 +164,13 @@ vox_spec: ("armor.merchant.foot", (-2.5, -3.5, -2.0)), color: None ), + "common.items.armor.misc.foot.ski": ( + vox_spec: ("armor.misc.foot.ski", (-2.5, -15.5, -2.0)), + color: None + ), + "common.items.armor.misc.foot.iceskate": ( + vox_spec: ("armor.misc.foot.iceskate", (-2.5, -3.5, -2.0)), + color: None + ), }, )) diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 1c1daacf9b..95be90faeb 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -402,6 +402,7 @@ impl From<&CharacterState> for CharacterAbilityType { | CharacterState::SpriteSummon(_) | CharacterState::UseItem(_) | CharacterState::SpriteInteract(_) + | CharacterState::Skate(_) | CharacterState::Wallrun(_) => Self::Other, } } diff --git a/common/src/comp/character_state.rs b/common/src/comp/character_state.rs index 24acfec446..115fea7714 100644 --- a/common/src/comp/character_state.rs +++ b/common/src/comp/character_state.rs @@ -1,6 +1,7 @@ use crate::{ comp::{ - item::ConsumableKind, ControlAction, Density, Energy, InputAttr, InputKind, Ori, Pos, Vel, + inventory::item::armor::Friction, item::ConsumableKind, ControlAction, Density, Energy, + InputAttr, InputKind, Ori, Pos, Vel, }, event::{LocalEvent, ServerEvent}, states::{ @@ -123,6 +124,8 @@ pub enum CharacterState { SpriteInteract(sprite_interact::Data), /// Runs on the wall Wallrun(wallrun::Data), + /// Ice skating or skiing + Skate(skate::Data), } impl CharacterState { @@ -153,15 +156,16 @@ impl CharacterState { pub fn is_stealthy(&self) -> bool { matches!( self, - CharacterState::Idle(idle::Data { is_sneaking: true }) - | CharacterState::Wielding(wielding::Data { - is_sneaking: true, - .. - }) - | CharacterState::Roll(roll::Data { - is_sneaking: true, - .. - }) + CharacterState::Idle(idle::Data { + is_sneaking: true, + footwear: _ + }) | CharacterState::Wielding(wielding::Data { + is_sneaking: true, + .. + }) | CharacterState::Roll(roll::Data { + is_sneaking: true, + .. + }) ) } @@ -227,6 +231,8 @@ impl CharacterState { pub fn is_glide(&self) -> bool { matches!(self, CharacterState::Glide(_)) } + pub fn is_skate(&self) -> bool { matches!(self, CharacterState::Skate(_)) } + pub fn is_melee_dodge(&self) -> bool { matches!(self, CharacterState::Roll(d) if d.static_data.immune_melee) } @@ -329,6 +335,7 @@ impl CharacterState { CharacterState::SpriteSummon(data) => data.behavior(j, output_events), CharacterState::UseItem(data) => data.behavior(j, output_events), CharacterState::SpriteInteract(data) => data.behavior(j, output_events), + CharacterState::Skate(data) => data.behavior(j, output_events), } } @@ -375,12 +382,26 @@ impl CharacterState { CharacterState::SpriteSummon(data) => data.handle_event(j, output_events, action), CharacterState::UseItem(data) => data.handle_event(j, output_events, action), CharacterState::SpriteInteract(data) => data.handle_event(j, output_events, action), + CharacterState::Skate(data) => data.handle_event(j, output_events, action), + } + } + + pub fn footwear(&self) -> Option { + match &self { + CharacterState::Idle(data) => data.footwear, + CharacterState::Skate(data) => Some(data.footwear), + _ => None, } } } impl Default for CharacterState { - fn default() -> Self { Self::Idle(idle::Data { is_sneaking: false }) } + fn default() -> Self { + Self::Idle(idle::Data { + is_sneaking: false, + footwear: None, + }) + } } impl Component for CharacterState { diff --git a/common/src/comp/inventory/item/armor.rs b/common/src/comp/inventory/item/armor.rs index 4ae071fb94..ebdb2f8b61 100644 --- a/common/src/comp/inventory/item/armor.rs +++ b/common/src/comp/inventory/item/armor.rs @@ -1,3 +1,7 @@ +use crate::{ + comp::item::Rgb, + terrain::{Block, BlockKind}, +}; use serde::{Deserialize, Serialize}; use std::{cmp::Ordering, ops::Sub}; @@ -26,6 +30,45 @@ impl Armor { } } +/// longitudinal and lateral friction, only meaningful for footwear +#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] +pub enum Friction { + Normal, + Ski, + Skate, + // Snowshoe, + // Spikes, +} + +impl Default for Friction { + fn default() -> Self { Self::Normal } +} + +impl Friction { + pub fn can_skate_on(&self, b: BlockKind) -> bool { + match self { + Friction::Ski => matches!(b, BlockKind::Snow | BlockKind::Ice | BlockKind::Air), + Friction::Skate => b == BlockKind::Ice, + _ => false, + } + } + + /// longitudinal (forward) and lateral (side) friction + pub fn get_friction(&self, b: BlockKind) -> (f32, f32) { + match (self, b) { + (Friction::Ski, BlockKind::Snow) => (0.01, 0.95), + (Friction::Ski, BlockKind::Ice) => (0.001, 0.5), + (Friction::Ski, BlockKind::Water) => (0.1, 0.7), + (Friction::Ski, BlockKind::Air) => (0.0, 0.0), + (Friction::Skate, BlockKind::Ice) => (0.001, 0.99), + _ => { + let non_directional_friction = Block::new(b, Rgb::new(0, 0, 0)).get_friction(); + (non_directional_friction, non_directional_friction) + }, + } + } +} + #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] pub struct Stats { /// Protection is non-linearly transformed (following summation) to a damage @@ -46,6 +89,9 @@ pub struct Stats { /// Stealth is summed along with the base stealth bonus (2.0), and then /// the agent's perception distance is divided by this value stealth: Option, + /// Ground contact type, mostly for shoes + #[serde(default)] + ground_contact: Friction, } impl Stats { @@ -66,6 +112,7 @@ impl Stats { energy_reward, crit_power, stealth, + ground_contact: Friction::Normal, } } @@ -80,6 +127,8 @@ impl Stats { pub fn crit_power(&self) -> Option { self.crit_power } pub fn stealth(&self) -> Option { self.stealth } + + pub fn ground_contact(&self) -> Friction { self.ground_contact } } impl Sub for Stats { @@ -99,6 +148,7 @@ impl Sub for Stats { .map(|(a, b)| a - b), crit_power: self.crit_power.zip(other.crit_power).map(|(a, b)| a - b), stealth: self.stealth.zip(other.stealth).map(|(a, b)| a - b), + ground_contact: Friction::Normal, } } } @@ -159,6 +209,8 @@ impl Armor { pub fn stealth(&self) -> Option { self.stats.stealth } + pub fn ground_contact(&self) -> Friction { self.stats.ground_contact } + #[cfg(test)] pub fn test_armor( kind: ArmorKind, @@ -174,6 +226,7 @@ impl Armor { energy_reward: None, crit_power: None, stealth: None, + ground_contact: Friction::Normal, }, } } diff --git a/common/src/comp/phys.rs b/common/src/comp/phys.rs index 423fbaf6a9..d020d8e089 100644 --- a/common/src/comp/phys.rs +++ b/common/src/comp/phys.rs @@ -1,6 +1,9 @@ use super::{Fluid, Ori}; use crate::{ - comp::body::ship::figuredata::VoxelCollider, consts::WATER_DENSITY, terrain::Block, uid::Uid, + comp::{body::ship::figuredata::VoxelCollider, inventory::item::armor::Friction}, + consts::WATER_DENSITY, + terrain::Block, + uid::Uid, }; use hashbrown::HashSet; use serde::{Deserialize, Serialize}; @@ -182,6 +185,9 @@ pub struct PhysicsState { pub touch_entities: HashSet, pub in_fluid: Option, pub ground_vel: Vec3, + pub footwear: Friction, + pub skating_last_height: f32, + pub skating_active: bool, } impl PhysicsState { diff --git a/common/src/states/climb.rs b/common/src/states/climb.rs index 0f4bbbb4c4..68c2dd0be0 100644 --- a/common/src/states/climb.rs +++ b/common/src/states/climb.rs @@ -79,7 +79,7 @@ impl CharacterBehavior for Data { CLIMB_BOOST_JUMP_FACTOR * impulse / data.mass.0, )); }; - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); return update; }; // Move player @@ -103,7 +103,7 @@ impl CharacterBehavior for Data { .try_change_by(-energy_use * data.dt.0) .is_err() { - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); } // Set orientation direction based on wall direction diff --git a/common/src/states/dance.rs b/common/src/states/dance.rs index 0dc8653c3c..171e04bb39 100644 --- a/common/src/states/dance.rs +++ b/common/src/states/dance.rs @@ -20,7 +20,7 @@ impl CharacterBehavior for Data { // Try to Fall/Stand up/Move if data.physics.on_ground.is_none() || data.inputs.move_dir.magnitude_squared() > 0.0 { - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); } update @@ -52,7 +52,7 @@ impl CharacterBehavior for Data { fn stand(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); // Try to Fall/Stand up/Move - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); update } } diff --git a/common/src/states/glide.rs b/common/src/states/glide.rs index 35ecfd3ffd..81f437a198 100644 --- a/common/src/states/glide.rs +++ b/common/src/states/glide.rs @@ -89,7 +89,7 @@ impl CharacterBehavior for Data { .and_then(|inv| inv.equipped(EquipSlot::Glider)) .is_none() { - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); } else if !handle_climb(data, &mut update) { let air_flow = data .physics @@ -207,7 +207,7 @@ impl CharacterBehavior for Data { pos: data.pos.0, wielded: false, })); - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); update } } diff --git a/common/src/states/glide_wield.rs b/common/src/states/glide_wield.rs index 50261ecae5..f0d0e0b361 100644 --- a/common/src/states/glide_wield.rs +++ b/common/src/states/glide_wield.rs @@ -74,7 +74,7 @@ impl CharacterBehavior for Data { ..*self }) } else { - CharacterState::Idle(idle::Data { is_sneaking: false }) + CharacterState::Idle(idle::Data::default()) }; } @@ -98,7 +98,7 @@ impl CharacterBehavior for Data { pos: data.pos.0, wielded: false, })); - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); update } diff --git a/common/src/states/idle.rs b/common/src/states/idle.rs index 207f544264..4d46446694 100644 --- a/common/src/states/idle.rs +++ b/common/src/states/idle.rs @@ -1,19 +1,25 @@ use super::utils::*; use crate::{ - comp::{character_state::OutputEvents, CharacterState, InventoryAction, StateUpdate}, + comp::{ + character_state::OutputEvents, inventory::item::armor::Friction, CharacterState, + InventoryAction, StateUpdate, + }, states::behavior::{CharacterBehavior, JoinData}, }; use serde::{Deserialize, Serialize}; -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Default)] pub struct Data { pub is_sneaking: bool, + // None means unknown + pub(crate) footwear: Option, } impl CharacterBehavior for Data { fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); + handle_skating(data, &mut update); handle_orientation(data, &mut update, 1.0, None); handle_move(data, &mut update, if self.is_sneaking { 0.4 } else { 1.0 }); handle_jump(data, output_events, &mut update, 1.0); @@ -26,7 +32,10 @@ impl CharacterBehavior for Data { if self.is_sneaking && (data.physics.on_ground.is_none() || data.physics.in_liquid().is_some()) { - update.character = CharacterState::Idle(Data { is_sneaking: false }); + update.character = CharacterState::Idle(Data { + is_sneaking: false, + footwear: self.footwear, + }); } update @@ -75,13 +84,16 @@ impl CharacterBehavior for Data { fn sneak(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); - update.character = CharacterState::Idle(Data { is_sneaking: true }); + update.character = CharacterState::Idle(Data { + is_sneaking: true, + footwear: self.footwear, + }); update } fn stand(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); - update.character = CharacterState::Idle(Data { is_sneaking: false }); + update.character = CharacterState::Idle(Data::default()); update } diff --git a/common/src/states/mod.rs b/common/src/states/mod.rs index 10ec478c17..50920d6b11 100644 --- a/common/src/states/mod.rs +++ b/common/src/states/mod.rs @@ -23,6 +23,7 @@ pub mod roll; pub mod self_buff; pub mod shockwave; pub mod sit; +pub mod skate; pub mod spin_melee; pub mod sprite_interact; pub mod sprite_summon; diff --git a/common/src/states/roll.rs b/common/src/states/roll.rs index dbd96c527f..1d44e1428c 100644 --- a/common/src/states/roll.rs +++ b/common/src/states/roll.rs @@ -142,6 +142,7 @@ impl CharacterBehavior for Data { } else { CharacterState::Idle(idle::Data { is_sneaking: self.is_sneaking, + footwear: None, }) } } @@ -151,6 +152,7 @@ impl CharacterBehavior for Data { // If it somehow ends up in an incorrect stage section update.character = CharacterState::Idle(idle::Data { is_sneaking: self.is_sneaking, + footwear: None, }); }, } diff --git a/common/src/states/sit.rs b/common/src/states/sit.rs index a3f59648dd..3d19ae94f5 100644 --- a/common/src/states/sit.rs +++ b/common/src/states/sit.rs @@ -20,7 +20,7 @@ impl CharacterBehavior for Data { // Try to Fall/Stand up/Move if data.physics.on_ground.is_none() || data.inputs.move_dir.magnitude_squared() > 0.0 { - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); } update @@ -52,7 +52,7 @@ impl CharacterBehavior for Data { fn stand(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); // Try to Fall/Stand up/Move - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); update } } diff --git a/common/src/states/skate.rs b/common/src/states/skate.rs new file mode 100644 index 0000000000..c78e842de0 --- /dev/null +++ b/common/src/states/skate.rs @@ -0,0 +1,118 @@ +use super::utils::*; +use crate::{ + comp::{ + character_state::OutputEvents, item::armor::Friction, CharacterState, InventoryAction, + StateUpdate, + }, + states::{ + behavior::{CharacterBehavior, JoinData}, + idle, + }, +}; +use serde::{Deserialize, Serialize}; + +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Data { + pub(crate) footwear: Friction, + // hints for animation + pub turn: f32, // negative to left, positive to right, 1.0=45° + pub accelerate: f32, // negative to brake + pub sidewalk: f32, // negative to left +} + +impl Data { + pub fn new(_: &JoinData, footwear: Friction) -> Self { + Self { + footwear, + turn: Default::default(), + accelerate: Default::default(), + sidewalk: Default::default(), + } + } +} + +impl CharacterBehavior for Data { + fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { + let mut update = StateUpdate::from(data); + + handle_wield(data, &mut update); + handle_jump(data, output_events, &mut update, 1.0); + + if !data.physics.skating_active { + update.character = CharacterState::Idle(idle::Data { + is_sneaking: false, + footwear: Some(self.footwear), + }); + } else { + let plane_ori = data.inputs.look_dir.xy(); + let orthogonal = vek::Vec2::new(plane_ori.y, -plane_ori.x); + update.ori = vek::Vec3::new(plane_ori.x, plane_ori.y, 0.0).into(); + let current_planar_velocity = data.vel.0.xy().magnitude(); + let long_input = data.inputs.move_dir.dot(plane_ori); + let lat_input = data.inputs.move_dir.dot(orthogonal); + let acceleration = if long_input.abs() > lat_input.abs() { + if long_input > 0.0 { + if let CharacterState::Skate(data) = &mut update.character { + data.accelerate = 1.0; + data.sidewalk = 0.0; + } + // forward, max at 8u/s + (data.dt.0 * 3.0) + .min(8.0 - current_planar_velocity) + .max(0.0) + } else { + if let CharacterState::Skate(data) = &mut update.character { + data.accelerate = -1.0; + data.sidewalk = 0.0; + } + //brake up to 4u/s², but never backwards + (data.dt.0 * 4.0).min(current_planar_velocity) + } + } else { + if let CharacterState::Skate(data) = &mut update.character { + data.accelerate = 0.0; + data.sidewalk = lat_input; + } + // sideways: constant speed + (0.5 - current_planar_velocity).max(0.0) + }; + if let CharacterState::Skate(skate_data) = &mut update.character { + skate_data.turn = orthogonal.dot(data.vel.0.xy()); + } + let delta_vel = acceleration * data.inputs.move_dir; + update.vel.0 += vek::Vec3::new(delta_vel.x, delta_vel.y, 0.0); + } + + update + } + + fn manipulate_loadout( + &self, + data: &JoinData, + output_events: &mut OutputEvents, + inv_action: InventoryAction, + ) -> StateUpdate { + let mut update = StateUpdate::from(data); + handle_manipulate_loadout(data, output_events, &mut update, inv_action); + update + } + + fn wield(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { + let mut update = StateUpdate::from(data); + attempt_wield(data, &mut update); + update + } + + fn sit(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { + let mut update = StateUpdate::from(data); + attempt_sit(data, &mut update); + update + } + + fn stand(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { + let mut update = StateUpdate::from(data); + // Try to Fall/Stand up/Move + update.character = CharacterState::Idle(idle::Data::default()); + update + } +} diff --git a/common/src/states/sprite_interact.rs b/common/src/states/sprite_interact.rs index 68a556e8cd..8faa350d18 100644 --- a/common/src/states/sprite_interact.rs +++ b/common/src/states/sprite_interact.rs @@ -106,13 +106,14 @@ impl CharacterBehavior for Data { } else { CharacterState::Idle(idle::Data { is_sneaking: self.static_data.was_sneak, + footwear: None, }) } } }, _ => { // If it somehow ends up in an incorrect stage section - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); }, } diff --git a/common/src/states/stunned.rs b/common/src/states/stunned.rs index e899895145..0c694b71b3 100644 --- a/common/src/states/stunned.rs +++ b/common/src/states/stunned.rs @@ -72,7 +72,7 @@ impl CharacterBehavior for Data { update.character = CharacterState::Wielding(wielding::Data { is_sneaking: false }); } else { - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); } } }, @@ -82,7 +82,7 @@ impl CharacterBehavior for Data { update.character = CharacterState::Wielding(wielding::Data { is_sneaking: false }); } else { - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); } }, } diff --git a/common/src/states/talk.rs b/common/src/states/talk.rs index 25a43a1e6f..270166825c 100644 --- a/common/src/states/talk.rs +++ b/common/src/states/talk.rs @@ -42,14 +42,14 @@ impl CharacterBehavior for Data { fn sit(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); attempt_sit(data, &mut update); update } fn dance(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); attempt_dance(data, &mut update); update } @@ -57,7 +57,7 @@ impl CharacterBehavior for Data { fn stand(&self, data: &JoinData, _: &mut OutputEvents) -> StateUpdate { let mut update = StateUpdate::from(data); // Try to Fall/Stand up/Move - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); update } } diff --git a/common/src/states/use_item.rs b/common/src/states/use_item.rs index 6279bcebf6..5d6a2fac9c 100644 --- a/common/src/states/use_item.rs +++ b/common/src/states/use_item.rs @@ -132,13 +132,14 @@ impl CharacterBehavior for Data { } else { CharacterState::Idle(idle::Data { is_sneaking: self.static_data.was_sneak, + footwear: None, }) } } }, _ => { // If it somehow ends up in an incorrect stage section - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); }, } diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 4537a37e7a..45b3813e5c 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -4,8 +4,8 @@ use crate::{ comp::{ arthropod, biped_large, biped_small, character_state::OutputEvents, - inventory::slot::{EquipSlot, Slot}, - item::{Hands, ItemKind, ToolKind}, + inventory::slot::{ArmorSlot, EquipSlot, Slot}, + item::{armor::Friction, Hands, ItemKind, ToolKind}, quadruped_low, quadruped_medium, quadruped_small, skills::{Skill, SwimSkill, SKILL_MODIFIERS}, theropod, Body, CharacterAbility, CharacterState, Density, InputAttr, InputKind, @@ -14,7 +14,7 @@ use crate::{ consts::{FRIC_GROUND, GRAVITY, MAX_PICKUP_RANGE}, event::{LocalEvent, ServerEvent}, outcome::Outcome, - states::{behavior::JoinData, *}, + states::{behavior::JoinData, utils::CharacterState::Idle, *}, util::Dir, vol::ReadVol, }; @@ -301,6 +301,35 @@ impl Body { } } +/// set footwear in idle data and potential state change to Skate +pub fn handle_skating(data: &JoinData, update: &mut StateUpdate) { + if let Idle(crate::states::idle::Data { + is_sneaking, + mut footwear, + }) = data.character + { + if footwear.is_none() { + footwear = data.inventory.and_then(|inv| { + inv.equipped(EquipSlot::Armor(ArmorSlot::Feet)) + .map(|armor| match armor.kind().as_ref() { + ItemKind::Armor(a) => a.ground_contact(), + _ => crate::comp::inventory::item::armor::Friction::Normal, + }) + }); + update.character = Idle(crate::states::idle::Data { + is_sneaking: *is_sneaking, + footwear, + }); + } + if data.physics.skating_active { + update.character = CharacterState::Skate(crate::states::skate::Data::new( + data, + footwear.unwrap_or(Friction::Normal), + )); + } + } +} + /// Handles updating `Components` to move player based on state of `JoinData` pub fn handle_move(data: &JoinData<'_>, update: &mut StateUpdate, efficiency: f32) { let submersion = data @@ -635,7 +664,10 @@ pub fn attempt_talk(data: &JoinData<'_>, update: &mut StateUpdate) { pub fn attempt_sneak(data: &JoinData<'_>, update: &mut StateUpdate) { if data.physics.on_ground.is_some() && data.body.is_humanoid() { - update.character = CharacterState::Idle(idle::Data { is_sneaking: true }); + update.character = CharacterState::Idle(idle::Data { + is_sneaking: true, + footwear: data.character.footwear(), + }); } } diff --git a/common/src/states/wallrun.rs b/common/src/states/wallrun.rs index 7c53447022..adbba0adee 100644 --- a/common/src/states/wallrun.rs +++ b/common/src/states/wallrun.rs @@ -38,7 +38,7 @@ impl CharacterBehavior for Data { || data.physics.on_ground.is_some() || data.physics.in_liquid().is_some() { - update.character = CharacterState::Idle(idle::Data { is_sneaking: false }); + update.character = CharacterState::Idle(idle::Data::default()); } update diff --git a/common/src/states/wielding.rs b/common/src/states/wielding.rs index c750cfe42b..0cfea7f298 100644 --- a/common/src/states/wielding.rs +++ b/common/src/states/wielding.rs @@ -58,6 +58,7 @@ impl CharacterBehavior for Data { ) => { update.character = CharacterState::Idle(idle::Data { is_sneaking: self.is_sneaking, + footwear: None, }); }, _ => (), @@ -76,6 +77,7 @@ impl CharacterBehavior for Data { let mut update = StateUpdate::from(data); update.character = CharacterState::Idle(idle::Data { is_sneaking: self.is_sneaking, + footwear: None, }); update } diff --git a/common/systems/src/character_behavior.rs b/common/systems/src/character_behavior.rs index b82c849978..af268fb325 100644 --- a/common/systems/src/character_behavior.rs +++ b/common/systems/src/character_behavior.rs @@ -213,7 +213,7 @@ impl<'a> System<'a> for Sys { // If mounted, character state is controlled by mount if is_rider.is_some() && !join_struct.char_state.can_perform_mounted() { // TODO: A better way to swap between mount inputs and rider inputs - *join_struct.char_state = CharacterState::Idle(idle::Data { is_sneaking: false }); + *join_struct.char_state = CharacterState::Idle(idle::Data::default()); continue; } diff --git a/common/systems/src/phys.rs b/common/systems/src/phys.rs index 3343050c5f..86fb126403 100644 --- a/common/systems/src/phys.rs +++ b/common/systems/src/phys.rs @@ -2,6 +2,7 @@ use common::{ comp::{ body::ship::figuredata::{VoxelCollider, VOXEL_COLLIDER_MANIFEST}, fluid_dynamics::{Fluid, LiquidKind, Wings}, + inventory::item::armor::Friction, Body, CharacterState, Collider, Density, Immovable, Mass, Ori, PhysicsState, Pos, PosVelOriDefer, PreviousPhysCache, Projectile, Scale, Stats, Sticky, Vel, }, @@ -12,7 +13,7 @@ use common::{ outcome::Outcome, resources::DeltaTime, states, - terrain::{Block, TerrainGrid}, + terrain::{Block, BlockKind, TerrainGrid}, uid::Uid, util::{Projection, SpatialGrid}, vol::{BaseVol, ReadVol}, @@ -780,6 +781,13 @@ impl<'a> PhysicsData<'a> { 1.0 }; + if let Some(state) = character_state { + let footwear = state.footwear().unwrap_or(Friction::Normal); + if footwear != physics_state.footwear { + physics_state.footwear = footwear; + } + } + let in_loaded_chunk = read .terrain .get_key(read.terrain.pos_key(pos.0.map(|e| e.floor() as i32))) @@ -846,6 +854,7 @@ impl<'a> PhysicsData<'a> { climbing, |entity, vel| land_on_ground = Some((entity, vel)), read, + &ori, ); tgt_pos = cpos.0; }, @@ -878,6 +887,7 @@ impl<'a> PhysicsData<'a> { climbing, |entity, vel| land_on_ground = Some((entity, vel)), read, + &ori, ); // Sticky things shouldn't move when on a surface @@ -1142,6 +1152,7 @@ impl<'a> PhysicsData<'a> { Some((entity, Vel(ori_from.mul_direction(vel.0)))); }, read, + &ori, ); cpos.0 = transform_from.mul_point(cpos.0) + wpos; @@ -1339,6 +1350,7 @@ fn box_voxel_collision<'a, T: BaseVol + ReadVol>( climbing: bool, mut land_on_ground: impl FnMut(Entity, Vel), read: &PhysicsRead, + ori: &Ori, ) { // FIXME: Review these #![allow( @@ -1700,19 +1712,84 @@ fn box_voxel_collision<'a, T: BaseVol + ReadVol>( physics_state.on_wall = on_wall; let fric_mod = read.stats.get(entity).map_or(1.0, |s| s.friction_modifier); - let ground_fric = physics_state - .on_ground - .map(|b| b.get_friction()) - .unwrap_or(0.0); - let wall_fric = if physics_state.on_wall.is_some() && climbing { - FRIC_GROUND + // skating (ski) + if !vel.0.xy().is_approx_zero() + && physics_state + .on_ground + .map_or(false, |g| physics_state.footwear.can_skate_on(g.kind())) + { + const DT_SCALE: f32 = 1.0; // other areas use 60.0??? + const POTENTIAL_TO_KINETIC: f32 = 8.0; // * 2.0 * GRAVITY; + + let kind = physics_state.on_ground.map_or(BlockKind::Air, |g| g.kind()); + let (longitudinal_friction, lateral_friction) = physics_state.footwear.get_friction(kind); + // the amount of longitudinal speed preserved + let longitudinal_friction_factor_squared = + (1.0 - longitudinal_friction).powf(dt.0 * DT_SCALE * 2.0); + let lateral_friction_factor = (1.0 - lateral_friction).powf(dt.0 * DT_SCALE); + let groundplane_velocity = vel.0.xy(); + let mut longitudinal_dir = ori.look_vec().xy(); + if longitudinal_dir.is_approx_zero() { + // fall back to travelling dir (in case we look up) + longitudinal_dir = groundplane_velocity; + } + let longitudinal_dir = longitudinal_dir.normalized(); + let lateral_dir = Vec2::new(longitudinal_dir.y, -longitudinal_dir.x); + let squared_velocity = groundplane_velocity.magnitude_squared(); + // if we crossed an edge up or down accelerate in travelling direction, + // as potential energy is converted into kinetic energy we compare it with the + // square of velocity + let vertical_difference = physics_state.skating_last_height - pos.0.z; + // might become negative when skating slowly uphill + let height_factor_squared = if vertical_difference != 0.0 { + // E=½mv², we scale both energies by ½m + let kinetic = squared_velocity; + // positive accelerate, negative decelerate, ΔE=mgΔh + let delta_potential = vertical_difference.max(-1.0).min(2.0) * POTENTIAL_TO_KINETIC; + let new_energy = kinetic + delta_potential; + physics_state.skating_last_height = pos.0.z; + new_energy / kinetic + } else { + 1.0 + }; + + // we calculate these squared as we need to combined them Euclidianly anyway, + // skiing: separate speed into longitudinal and lateral component + let long_speed = groundplane_velocity.dot(longitudinal_dir); + let lat_speed = groundplane_velocity.dot(lateral_dir); + let long_speed_squared = long_speed.powi(2); + + // lateral speed is reduced by lateral_friction, + let new_lateral = lat_speed * lateral_friction_factor; + let lateral_speed_reduction = lat_speed - new_lateral; + // we convert this reduction partically (by the cosine of the angle) into + // longitudinal (elastic collision) and the remainder into heat + let cosine_squared_aoa = long_speed_squared / squared_velocity; + let converted_lateral_squared = cosine_squared_aoa * lateral_speed_reduction.powi(2); + let new_longitudinal_squared = longitudinal_friction_factor_squared + * (long_speed_squared + converted_lateral_squared) + * height_factor_squared; + let new_longitudinal = + new_longitudinal_squared.signum() * new_longitudinal_squared.abs().sqrt(); + let new_ground_speed = new_longitudinal * longitudinal_dir + new_lateral * lateral_dir; + physics_state.skating_active = true; + vel.0 = Vec3::new(new_ground_speed.x, new_ground_speed.y, 0.0); } else { - 0.0 - }; - let fric = ground_fric.max(wall_fric); - if fric > 0.0 { - vel.0 *= (1.0 - fric.min(1.0) * fric_mod).powf(dt.0 * 60.0); - physics_state.ground_vel = ground_vel; + let ground_fric = physics_state + .on_ground + .map(|b| b.get_friction()) + .unwrap_or(0.0); + let wall_fric = if physics_state.on_wall.is_some() && climbing { + FRIC_GROUND + } else { + 0.0 + }; + let fric = ground_fric.max(wall_fric); + if fric > 0.0 { + vel.0 *= (1.0 - fric.min(1.0) * fric_mod).powf(dt.0 * 60.0); + physics_state.ground_vel = ground_vel; + } + physics_state.skating_active = false; } physics_state.in_fluid = liquid diff --git a/common/systems/src/stats.rs b/common/systems/src/stats.rs index 77e29c3bf9..a6346ea2d1 100644 --- a/common/systems/src/stats.rs +++ b/common/systems/src/stats.rs @@ -147,6 +147,7 @@ impl<'a> System<'a> for Sys { | CharacterState::Sit { .. } | CharacterState::Dance { .. } | CharacterState::Glide { .. } + | CharacterState::Skate { .. } | CharacterState::GlideWield { .. } | CharacterState::Wielding { .. } | CharacterState::Equipping { .. } diff --git a/voxygen/egui/src/lib.rs b/voxygen/egui/src/lib.rs index c309887c80..b7aaf52d6e 100644 --- a/voxygen/egui/src/lib.rs +++ b/voxygen/egui/src/lib.rs @@ -11,7 +11,7 @@ mod widgets; use client::{Client, Join, World, WorldExt}; use common::{ comp, - comp::{Poise, PoiseState}, + comp::{inventory::item::armor::Friction, Poise, PoiseState}, }; use core::mem; use egui::{ @@ -708,6 +708,7 @@ fn selected_entity_window( Some(Fluid::Liquid { depth, kind, .. }) => format!("{:?} (Depth: {:.1})", kind, depth), _ => "None".to_owned() }); }); + two_col_row(ui, "Footwear", match physics_state.footwear{ Friction::Ski => "Ski", Friction::Skate => "Skate", /* Friction::Snowshoe => "Snowshoe", Friction::Spikes => "Spikes", */ Friction::Normal=>"Normal",}.to_string()); }); } }); diff --git a/voxygen/src/audio/sfx/event_mapper/movement/tests.rs b/voxygen/src/audio/sfx/event_mapper/movement/tests.rs index 1a393dcef0..efee782eb8 100644 --- a/voxygen/src/audio/sfx/event_mapper/movement/tests.rs +++ b/voxygen/src/audio/sfx/event_mapper/movement/tests.rs @@ -93,7 +93,7 @@ fn same_previous_event_elapsed_emits() { #[test] fn maps_idle() { let result = MovementEventMapper::map_movement_event( - &CharacterState::Idle(common::states::idle::Data { is_sneaking: false }), + &CharacterState::Idle(common::states::idle::Data::default()), &PhysicsState { on_ground: Some(Block::empty()), ..Default::default() @@ -115,7 +115,7 @@ fn maps_idle() { #[test] fn maps_run_with_sufficient_velocity() { let result = MovementEventMapper::map_movement_event( - &CharacterState::Idle(common::states::idle::Data { is_sneaking: false }), + &CharacterState::Idle(common::states::idle::Data::default()), &PhysicsState { on_ground: Some(Block::empty()), ..Default::default() @@ -137,7 +137,7 @@ fn maps_run_with_sufficient_velocity() { #[test] fn does_not_map_run_with_insufficient_velocity() { let result = MovementEventMapper::map_movement_event( - &CharacterState::Idle(common::states::idle::Data { is_sneaking: false }), + &CharacterState::Idle(common::states::idle::Data::default()), &PhysicsState { on_ground: Some(Block::empty()), ..Default::default() @@ -159,7 +159,7 @@ fn does_not_map_run_with_insufficient_velocity() { #[test] fn does_not_map_run_with_sufficient_velocity_but_not_on_ground() { let result = MovementEventMapper::map_movement_event( - &CharacterState::Idle(common::states::idle::Data { is_sneaking: false }), + &CharacterState::Idle(common::states::idle::Data::default()), &Default::default(), &PreviousEntityState { event: SfxEvent::Idle, @@ -214,7 +214,7 @@ fn maps_roll() { #[test] fn maps_land_on_ground_to_run() { let result = MovementEventMapper::map_movement_event( - &CharacterState::Idle(common::states::idle::Data { is_sneaking: false }), + &CharacterState::Idle(common::states::idle::Data::default()), &PhysicsState { on_ground: Some(Block::empty()), ..Default::default() diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 6ab216b478..42d2017765 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -976,9 +976,10 @@ impl FigureMgr { rel_vel.magnitude_squared() > 0.01, // Moving physics.in_liquid().is_some(), // In water is_rider.is_some(), + physics.skating_active, ) { - // Standing - (true, false, false, false) => { + // Standing or Skating + (true, false, false, false, _) | (_, _, false, false, true) => { anim::character::StandAnimation::update_skeleton( &CharacterSkeleton::new(holding_lantern), ( @@ -997,7 +998,7 @@ impl FigureMgr { ) }, // Running - (true, true, false, false) => { + (true, true, false, false, _) => { anim::character::RunAnimation::update_skeleton( &CharacterSkeleton::new(holding_lantern), ( @@ -1019,7 +1020,7 @@ impl FigureMgr { ) }, // In air - (false, _, false, false) => { + (false, _, false, false, _) => { anim::character::JumpAnimation::update_skeleton( &CharacterSkeleton::new(holding_lantern), ( @@ -1038,7 +1039,7 @@ impl FigureMgr { ) }, // Swim - (_, _, true, false) => anim::character::SwimAnimation::update_skeleton( + (_, _, true, false, _) => anim::character::SwimAnimation::update_skeleton( &CharacterSkeleton::new(holding_lantern), ( active_tool_kind, @@ -1056,7 +1057,7 @@ impl FigureMgr { skeleton_attr, ), // Mount - (_, _, _, true) => anim::character::MountAnimation::update_skeleton( + (_, _, _, true, _) => anim::character::MountAnimation::update_skeleton( &CharacterSkeleton::new(holding_lantern), ( active_tool_kind, @@ -1260,7 +1261,9 @@ impl FigureMgr { skeleton_attr, ) }, - CharacterState::Idle(idle::Data { is_sneaking: true }) => { + CharacterState::Idle(idle::Data { + is_sneaking: true, .. + }) => { anim::character::SneakAnimation::update_skeleton( &target_base, ( @@ -5257,16 +5260,11 @@ impl FigureMgr { // Average velocity relative to the current ground let _rel_avg_vel = state.avg_vel - physics.ground_vel; + let idlestate = CharacterState::Idle(common::states::idle::Data::default()); + let last = Last(idlestate.clone()); let (character, last_character) = match (character, last_character) { (Some(c), Some(l)) => (c, l), - _ => ( - &CharacterState::Idle(common::states::idle::Data { - is_sneaking: false, - }), - &Last(CharacterState::Idle(common::states::idle::Data { - is_sneaking: false, - })), - ), + _ => (&idlestate, &last), }; if !character.same_variant(&last_character.0) { @@ -5388,16 +5386,11 @@ impl FigureMgr { // Average velocity relative to the current ground let _rel_avg_vel = state.avg_vel - physics.ground_vel; + let idle_state = CharacterState::Idle(common::states::idle::Data::default()); + let last = Last(idle_state.clone()); let (character, last_character) = match (character, last_character) { (Some(c), Some(l)) => (c, l), - _ => ( - &CharacterState::Idle(common::states::idle::Data { - is_sneaking: false, - }), - &Last(CharacterState::Idle(common::states::idle::Data { - is_sneaking: false, - })), - ), + _ => (&idle_state, &last), }; if !character.same_variant(&last_character.0) { @@ -5486,16 +5479,11 @@ impl FigureMgr { // Average velocity relative to the current ground let _rel_avg_vel = state.avg_vel - physics.ground_vel; + let idlestate = CharacterState::Idle(common::states::idle::Data::default()); + let last = Last(idlestate.clone()); let (character, last_character) = match (character, last_character) { (Some(c), Some(l)) => (c, l), - _ => ( - &CharacterState::Idle(common::states::idle::Data { - is_sneaking: false, - }), - &Last(CharacterState::Idle(common::states::idle::Data { - is_sneaking: false, - })), - ), + _ => (&idlestate, &last), }; if !character.same_variant(&last_character.0) { From 34f580dfaa0e308f8cecbc1a95b2e19377555426 Mon Sep 17 00:00:00 2001 From: Ben Wallis Date: Sat, 28 May 2022 12:06:49 +0000 Subject: [PATCH 018/229] Introduced loot ownership rules to combat loot stealing by players * Added `LootOwner` component used to indicate that an `ItemDrop` entity is owned by another entity * A loot winner is now calculated after EXP allocation using the EXP per entity for weighted chance distribution * Used existing Inventory Full overitem text to show "Owned by {player} for {seconds}secs" when a pickup fails due to a loot ownership check * Updated agent code to take into account loot ownership when searching for `ItemDrop` targets to pick up * Added `loot` ECS system to clear expired loot ownerships --- CHANGELOG.md | 1 + assets/voxygen/i18n/en/hud/misc.ron | 2 + client/src/lib.rs | 4 +- common/net/src/sync/sync_ext.rs | 2 +- common/net/src/synced_components.rs | 5 ++ common/src/comp/inventory/mod.rs | 16 ++++- common/src/comp/loot_owner.rs | 63 +++++++++++++++++ common/src/comp/mod.rs | 4 +- common/state/src/state.rs | 1 + server/src/cmd.rs | 3 +- server/src/events/entity_manipulation.rs | 79 +++++++++++++++++---- server/src/events/interaction.rs | 3 +- server/src/events/inventory_manip.rs | 87 ++++++++++++++++++------ server/src/lib.rs | 9 +-- server/src/state_ext.rs | 7 +- server/src/sys/agent.rs | 39 ++++++----- server/src/sys/agent/data.rs | 4 +- server/src/sys/loot.rs | 42 ++++++++++++ server/src/sys/mod.rs | 1 + server/src/sys/msg/mod.rs | 6 +- voxygen/src/audio/sfx/mod.rs | 4 +- voxygen/src/hud/mod.rs | 76 ++++++++++++++++++--- voxygen/src/hud/overitem.rs | 30 ++++++-- voxygen/src/session/mod.rs | 28 ++++++-- 24 files changed, 424 insertions(+), 92 deletions(-) create mode 100644 common/src/comp/loot_owner.rs create mode 100644 server/src/sys/loot.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index b5d214bc69..cbebb7eae9 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 - Modular weapons - Added Thai translation - Skiing and ice skating +- Added loot ownership for NPC drops ### Changed diff --git a/assets/voxygen/i18n/en/hud/misc.ron b/assets/voxygen/i18n/en/hud/misc.ron index 1d54252a6a..ca4946ada8 100644 --- a/assets/voxygen/i18n/en/hud/misc.ron +++ b/assets/voxygen/i18n/en/hud/misc.ron @@ -10,6 +10,8 @@ "hud.waypoint_saved": "Waypoint Saved", "hud.sp_arrow_txt": "SP", "hud.inventory_full": "Inventory Full", + "hud.someone_else": "someone else", + "hud.owned_by_for_secs": "Owned by {name} for {secs} secs", "hud.press_key_to_show_keybindings_fmt": "[{key}] Keybindings", "hud.press_key_to_toggle_lantern_fmt": "[{key}] Lantern", diff --git a/client/src/lib.rs b/client/src/lib.rs index beb9326285..fe02b0031c 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -2133,8 +2133,8 @@ impl Client { }, ServerGeneral::InventoryUpdate(inventory, event) => { match event { - InventoryUpdateEvent::BlockCollectFailed(_) => {}, - InventoryUpdateEvent::EntityCollectFailed(_) => {}, + InventoryUpdateEvent::BlockCollectFailed { .. } => {}, + InventoryUpdateEvent::EntityCollectFailed { .. } => {}, _ => { // Push the updated inventory component to the client // FIXME: Figure out whether this error can happen under normal gameplay, diff --git a/common/net/src/sync/sync_ext.rs b/common/net/src/sync/sync_ext.rs index a84ea0bdd3..e6ba3dcd79 100644 --- a/common/net/src/sync/sync_ext.rs +++ b/common/net/src/sync/sync_ext.rs @@ -74,7 +74,7 @@ impl WorldSyncExt for specs::World { self.read_storage::().get(entity).copied() } - /// Get the UID of an entity + /// Get an entity from a UID fn entity_from_uid(&self, uid: u64) -> Option { self.read_resource::() .retrieve_entity_internal(uid) diff --git a/common/net/src/synced_components.rs b/common/net/src/synced_components.rs index 374931560c..2675eec32b 100644 --- a/common/net/src/synced_components.rs +++ b/common/net/src/synced_components.rs @@ -62,6 +62,7 @@ macro_rules! synced_components { combo: Combo, active_abilities: ActiveAbilities, can_build: CanBuild, + loot_owner: LootOwner, } }; } @@ -234,3 +235,7 @@ impl NetSync for ActiveAbilities { impl NetSync for CanBuild { const SYNC_FROM: SyncFrom = SyncFrom::ClientEntity; } + +impl NetSync for LootOwner { + const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity; +} diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index 616f25e5c9..37c4e33070 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -803,6 +803,12 @@ impl Component for Inventory { type Storage = DerefFlaggedStorage>; } +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] +pub enum CollectFailedReason { + InventoryFull, + LootOwned { owner_uid: Uid, expiry_secs: u64 }, +} + #[derive(Clone, Debug, Serialize, Deserialize)] pub enum InventoryUpdateEvent { Init, @@ -813,8 +819,14 @@ pub enum InventoryUpdateEvent { Swapped, Dropped, Collected(Item), - BlockCollectFailed(Vec3), - EntityCollectFailed(Uid), + BlockCollectFailed { + pos: Vec3, + reason: CollectFailedReason, + }, + EntityCollectFailed { + entity: Uid, + reason: CollectFailedReason, + }, Possession, Debug, Craft, diff --git a/common/src/comp/loot_owner.rs b/common/src/comp/loot_owner.rs new file mode 100644 index 0000000000..1f02a22ae0 --- /dev/null +++ b/common/src/comp/loot_owner.rs @@ -0,0 +1,63 @@ +use crate::{ + comp::{Alignment, Body, Player}, + uid::Uid, +}; +use serde::{Deserialize, Serialize}; +use specs::{Component, DerefFlaggedStorage}; +use specs_idvs::IdvStorage; +use std::{ + ops::Add, + time::{Duration, Instant}, +}; + +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] +pub struct LootOwner { + // TODO: Fix this if expiry is needed client-side, Instant is not serializable + #[serde(skip, default = "Instant::now")] + expiry: Instant, + owner_uid: Uid, +} + +// Loot becomes free-for-all after the initial ownership period +const OWNERSHIP_SECS: u64 = 45; + +impl LootOwner { + pub fn new(uid: Uid) -> Self { + Self { + expiry: Instant::now().add(Duration::from_secs(OWNERSHIP_SECS)), + owner_uid: uid, + } + } + + pub fn uid(&self) -> Uid { self.owner_uid } + + pub fn time_until_expiration(&self) -> Duration { self.expiry - Instant::now() } + + pub fn expired(&self) -> bool { self.expiry <= Instant::now() } + + pub fn default_instant() -> Instant { Instant::now() } + + pub fn can_pickup( + &self, + uid: Uid, + alignment: Option<&Alignment>, + body: Option<&Body>, + player: Option<&Player>, + ) -> bool { + let is_owned = matches!(alignment, Some(Alignment::Owned(_))); + let is_player = player.is_some(); + let is_pet = is_owned && !is_player; + + let owns_loot = self.uid().0 == uid.0; + let is_humanoid = matches!(body, Some(Body::Humanoid(_))); + + // Pet's can't pick up owned loot + // Humanoids must own the loot + // Non-humanoids ignore loot ownership + !is_pet && (owns_loot || !is_humanoid) + } +} + +impl Component for LootOwner { + type Storage = DerefFlaggedStorage>; +} diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index ba7d19c833..4da189e746 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -29,6 +29,7 @@ pub mod inventory; pub mod invite; #[cfg(not(target_arch = "wasm32"))] mod last; #[cfg(not(target_arch = "wasm32"))] mod location; +pub mod loot_owner; #[cfg(not(target_arch = "wasm32"))] pub mod melee; #[cfg(not(target_arch = "wasm32"))] mod misc; #[cfg(not(target_arch = "wasm32"))] pub mod ori; @@ -87,10 +88,11 @@ pub use self::{ tool::{self, AbilityItem}, Item, ItemConfig, ItemDrop, }, - slot, Inventory, InventoryUpdate, InventoryUpdateEvent, + slot, CollectFailedReason, Inventory, InventoryUpdate, InventoryUpdateEvent, }, last::Last, location::{MapMarker, MapMarkerChange, MapMarkerUpdate, Waypoint, WaypointArea}, + loot_owner::LootOwner, melee::{Melee, MeleeConstructor}, misc::Object, ori::Ori, diff --git a/common/state/src/state.rs b/common/state/src/state.rs index 3c5f13cb1b..6697f30394 100644 --- a/common/state/src/state.rs +++ b/common/state/src/state.rs @@ -157,6 +157,7 @@ impl State { ecs.register::(); ecs.register::(); ecs.register::(); + ecs.register::(); // Register components send from clients -> server ecs.register::(); diff --git a/server/src/cmd.rs b/server/src/cmd.rs index e4393c156d..eba2cc0870 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -500,13 +500,12 @@ fn handle_drop_all( server .state - .create_item_drop(Default::default(), &item) + .create_item_drop(Default::default(), item) .with(comp::Pos(Vec3::new( pos.0.x + rng.gen_range(5.0..10.0), pos.0.y + rng.gen_range(5.0..10.0), pos.0.z + 5.0, ))) - .with(item) .with(comp::Vel(vel)) .build(); } diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 29499abff7..d14a109ad4 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -3,6 +3,7 @@ use crate::{ comp::{ ability, agent::{Agent, AgentEvent, Sound, SoundKind}, + loot_owner::LootOwner, skillset::SkillGroupKind, BuffKind, BuffSource, PhysicsState, }, @@ -34,7 +35,8 @@ use common_net::{msg::ServerGeneral, sync::WorldSyncExt}; use common_state::BlockChange; use comp::chat::GenericChatMsg; use hashbrown::HashSet; -use rand::Rng; +use rand::{distributions::WeightedIndex, Rng}; +use rand_distr::Distribution; use specs::{ join::Join, saveload::MarkerAllocator, Builder, Entity as EcsEntity, Entity, WorldExt, }; @@ -203,6 +205,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, last_change: Healt } } + let mut exp_awards = Vec::<(Entity, f32)>::new(); // Award EXP to damage contributors // // NOTE: Debug logging is disabled by default for this module - to enable it add @@ -313,7 +316,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, last_change: Healt // Iterate through all contributors of damage for the killed entity, calculating // how much EXP each contributor should be awarded based on their // percentage of damage contribution - damage_contributors.iter().filter_map(|(damage_contributor, (_, damage_percent))| { + exp_awards = damage_contributors.iter().filter_map(|(damage_contributor, (_, damage_percent))| { let contributor_exp = exp_reward * damage_percent; match damage_contributor { DamageContrib::Solo(attacker) => { @@ -365,16 +368,23 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, last_change: Healt None } } - }).flatten().for_each(|(attacker, exp_reward)| { + }).flatten().collect::>(); + + exp_awards.iter().for_each(|(attacker, exp_reward)| { // Process the calculated EXP rewards - if let (Some(mut attacker_skill_set), Some(attacker_uid), Some(attacker_inventory), Some(pos)) = ( - skill_sets.get_mut(attacker), - uids.get(attacker), - inventories.get(attacker), - positions.get(attacker), + if let ( + Some(mut attacker_skill_set), + Some(attacker_uid), + Some(attacker_inventory), + Some(pos), + ) = ( + skill_sets.get_mut(*attacker), + uids.get(*attacker), + inventories.get(*attacker), + positions.get(*attacker), ) { handle_exp_gain( - exp_reward, + *exp_reward, attacker_inventory, &mut attacker_skill_set, attacker_uid, @@ -437,14 +447,53 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, last_change: Healt let pos = state.ecs().read_storage::().get(entity).cloned(); let vel = state.ecs().read_storage::().get(entity).cloned(); if let Some(pos) = pos { - // TODO: This should only be temporary as you'd eventually want to actually - // render the items on the ground, rather than changing the texture depending on - // the body type - let _ = state - .create_item_drop(comp::Pos(pos.0 + Vec3::unit_z() * 0.25), &item) + let winner_uid = if exp_awards.is_empty() { + None + } else { + // Use the awarded exp per entity as the weight distribution for drop chance + // Creating the WeightedIndex can only fail if there are weights <= 0 or no + // weights, which shouldn't ever happen + let dist = WeightedIndex::new(exp_awards.iter().map(|x| x.1)) + .expect("Failed to create WeightedIndex for loot drop chance"); + let mut rng = rand::thread_rng(); + let winner = exp_awards + .get(dist.sample(&mut rng)) + .expect("Loot distribution failed to find a winner") + .0; + + state + .ecs() + .read_storage::() + .get(winner) + .and_then(|body| { + // Only humanoids are awarded loot ownership - if the winner was a + // non-humanoid NPC the loot will be free-for-all + if matches!(body, Body::Humanoid(_)) { + Some(state.ecs().read_storage::().get(winner).cloned()) + } else { + None + } + }) + .flatten() + }; + + let item_drop_entity = state + .create_item_drop(comp::Pos(pos.0 + Vec3::unit_z() * 0.25), item) .maybe_with(vel) - .with(item) .build(); + + // If there was a loot winner, assign them as the owner of the loot. There will + // not be a loot winner when an entity dies to environment damage and such so + // the loot will be free-for-all. + if let Some(uid) = winner_uid { + debug!("Assigned UID {:?} as the winner for the loot drop", uid); + + state + .ecs() + .write_storage::() + .insert(item_drop_entity, LootOwner::new(uid)) + .unwrap(); + } } else { error!( ?entity, diff --git a/server/src/events/interaction.rs b/server/src/events/interaction.rs index 1ea2218dc7..c08cbca453 100644 --- a/server/src/events/interaction.rs +++ b/server/src/events/interaction.rs @@ -233,9 +233,8 @@ pub fn handle_mine_block( } } state - .create_item_drop(Default::default(), &item) + .create_item_drop(Default::default(), item) .with(comp::Pos(pos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0))) - .with(item) .build(); } diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index 1186bbbb6d..b9f5aa1437 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -24,7 +24,10 @@ use comp::LightEmitter; use crate::{client::Client, Server, StateExt}; use common::{ - comp::{pet::is_tameable, ChatType, Group}, + comp::{ + pet::is_tameable, Alignment, Body, ChatType, CollectFailedReason, Group, + InventoryUpdateEvent, Player, + }, event::{EventBus, ServerEvent}, }; use common_net::msg::ServerGeneral; @@ -109,27 +112,66 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv } match manip { - comp::InventoryManip::Pickup(uid) => { - let item_entity = if let Some(item_entity) = state.ecs().entity_from_uid(uid.into()) { - item_entity - } else { - // Item entity could not be found - most likely because the entity - // attempted to pick up the same item very quickly before its deletion of the - // world from the first pickup attempt was processed. - debug!("Failed to get entity for item Uid: {}", uid); - return; - }; + comp::InventoryManip::Pickup(pickup_uid) => { + let item_entity = + if let Some(item_entity) = state.ecs().entity_from_uid(pickup_uid.into()) { + item_entity + } else { + // Item entity could not be found - most likely because the entity + // attempted to pick up the same item very quickly before its deletion of the + // world from the first pickup attempt was processed. + debug!("Failed to get entity for item Uid: {}", pickup_uid); + return; + }; let entity_cylinder = get_cylinder(state, entity); // FIXME: Raycast so we can't pick up items through walls. if !within_pickup_range(entity_cylinder, || get_cylinder(state, item_entity)) { debug!( ?entity_cylinder, - "Failed to pick up item as not within range, Uid: {}", uid + "Failed to pick up item as not within range, Uid: {}", pickup_uid ); return; } + let loot_owner_storage = state.ecs().read_storage::(); + + // If there's a loot owner for the item being picked up, then + // determine whether the pickup should be rejected. + let ownership_check_passed = state + .ecs() + .read_storage::() + .get(item_entity) + .map_or(true, |loot_owner| { + let alignments = state.ecs().read_storage::(); + let bodies = state.ecs().read_storage::(); + let players = state.ecs().read_storage::(); + let can_pickup = loot_owner.can_pickup( + uid, + alignments.get(entity), + bodies.get(entity), + players.get(entity), + ); + if !can_pickup { + let event = + comp::InventoryUpdate::new(InventoryUpdateEvent::EntityCollectFailed { + entity: pickup_uid, + reason: CollectFailedReason::LootOwned { + owner_uid: loot_owner.uid(), + expiry_secs: loot_owner.time_until_expiration().as_secs(), + }, + }); + state.ecs().write_storage().insert(entity, event).unwrap(); + } + can_pickup + }); + + if !ownership_check_passed { + return; + } + + drop(loot_owner_storage); + // First, we remove the item, assuming picking it up will succeed (we do this to // avoid cloning the item, as we should not call Item::clone and it // may be removed!). @@ -140,7 +182,10 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv // Item component could not be found - most likely because the entity // attempted to pick up the same item very quickly before its deletion of the // world from the first pickup attempt was processed. - debug!("Failed to delete item component for entity, Uid: {}", uid); + debug!( + "Failed to delete item component for entity, Uid: {}", + pickup_uid + ); return; }; @@ -165,7 +210,10 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv ); drop(item_storage); drop(inventories); - comp::InventoryUpdate::new(comp::InventoryUpdateEvent::EntityCollectFailed(uid)) + comp::InventoryUpdate::new(comp::InventoryUpdateEvent::EntityCollectFailed { + entity: pickup_uid, + reason: comp::CollectFailedReason::InventoryFull, + }) }, Ok(_) => { // We succeeded in picking up the item, so we may now delete its old entity @@ -219,7 +267,10 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv Err(_) => { drop_item = Some(item_msg); comp::InventoryUpdate::new( - comp::InventoryUpdateEvent::BlockCollectFailed(pos), + comp::InventoryUpdateEvent::BlockCollectFailed { + pos, + reason: comp::CollectFailedReason::InventoryFull, + }, ) }, }; @@ -248,11 +299,10 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv drop(inventories); if let Some(item) = drop_item { state - .create_item_drop(Default::default(), &item) + .create_item_drop(Default::default(), item) .with(comp::Pos( Vec3::new(pos.x as f32, pos.y as f32, pos.z as f32) + Vec3::unit_z(), )) - .with(item) .with(comp::Vel(Vec3::zero())) .build(); } @@ -771,9 +821,8 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv }); state - .create_item_drop(Default::default(), &item) + .create_item_drop(Default::default(), item) .with(comp::Pos(pos.0 + *ori.look_dir() + Vec3::unit_z())) - .with(item) .with(comp::Vel(Vec3::zero())) .build(); } diff --git a/server/src/lib.rs b/server/src/lib.rs index 23a5739920..8a405e73eb 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -2,14 +2,15 @@ #![allow(clippy::option_map_unit_fn)] #![deny(clippy::clone_on_ref_ptr)] #![feature( - box_patterns, - label_break_value, bool_to_option, + box_patterns, drain_filter, + label_break_value, + let_chains, + let_else, never_type, option_zip, - unwrap_infallible, - let_else + unwrap_infallible )] #![cfg_attr(not(feature = "worldgen"), feature(const_panic))] diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs index ff999e8a2a..ef99603136 100644 --- a/server/src/state_ext.rs +++ b/server/src/state_ext.rs @@ -55,7 +55,7 @@ pub trait StateExt { ) -> EcsEntityBuilder; /// Build a static object entity fn create_object(&mut self, pos: comp::Pos, object: comp::object::Body) -> EcsEntityBuilder; - fn create_item_drop(&mut self, pos: comp::Pos, item: &Item) -> EcsEntityBuilder; + fn create_item_drop(&mut self, pos: comp::Pos, item: Item) -> EcsEntityBuilder; fn create_ship comp::Collider>( &mut self, pos: comp::Pos, @@ -271,11 +271,12 @@ impl StateExt for State { .with(body) } - fn create_item_drop(&mut self, pos: comp::Pos, item: &Item) -> EcsEntityBuilder { - let item_drop = comp::item_drop::Body::from(item); + fn create_item_drop(&mut self, pos: comp::Pos, item: Item) -> EcsEntityBuilder { + let item_drop = comp::item_drop::Body::from(&item); let body = comp::Body::ItemDrop(item_drop); self.ecs_mut() .create_entity_synced() + .with(item) .with(pos) .with(comp::Vel(Vec3::zero())) .with(item_drop.orientation(&mut thread_rng())) diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index 094cffe8d8..1315f593ea 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -1603,22 +1603,29 @@ impl<'a> AgentData<'a> { }; let is_valid_target = |entity: EcsEntity| match read_data.bodies.get(entity) { Some(Body::ItemDrop(item)) => { - //If statement that checks either if the self (agent) is a humanoid, - //or if the self is not a humanoid, it checks whether or not you are 'hungry' - - // meaning less than full health - and additionally checks if - // the target entity is a consumable item. If it qualifies for - // either being a humanoid or a hungry non-humanoid that likes consumables, - // it will choose the item as its target. - if matches!(self.body, Some(Body::Humanoid(_))) - || (self - .health - .map_or(false, |health| health.current() < health.maximum()) - && matches!(item, item_drop::Body::Consumable)) - { - Some((entity, false)) - } else { - None - } + // If there is no LootOwner then the ItemDrop is a valid target, otherwise check + // if the loot can be picked up + read_data + .loot_owners + .get(entity) + .map_or(Some((entity, false)), |loot_owner| { + // Agents want to pick up items if they are humanoid, or are hungry and the + // item is consumable + let hungry = self + .health + .map_or(false, |health| health.current() < health.maximum()); + let wants_pickup = matches!(self.body, Some(Body::Humanoid(_))) + || (hungry && matches!(item, item_drop::Body::Consumable)); + + let can_pickup = + loot_owner.can_pickup(*self.uid, self.alignment, self.body, None); + + if wants_pickup && can_pickup { + Some((entity, false)) + } else { + None + } + }) }, _ => { if read_data.healths.get(entity).map_or(false, |health| { diff --git a/server/src/sys/agent/data.rs b/server/src/sys/agent/data.rs index 67a68fd7b5..f89de2a7b7 100644 --- a/server/src/sys/agent/data.rs +++ b/server/src/sys/agent/data.rs @@ -2,7 +2,8 @@ use crate::rtsim::Entity as RtSimData; use common::{ comp::{ buff::Buffs, group, ActiveAbilities, Alignment, Body, CharacterState, Combo, Energy, - Health, Inventory, LightEmitter, Ori, PhysicsState, Pos, Scale, SkillSet, Stats, Vel, + Health, Inventory, LightEmitter, LootOwner, Ori, PhysicsState, Pos, Scale, SkillSet, Stats, + Vel, }, link::Is, mounting::Mount, @@ -152,6 +153,7 @@ pub struct ReadData<'a> { pub buffs: ReadStorage<'a, Buffs>, pub combos: ReadStorage<'a, Combo>, pub active_abilities: ReadStorage<'a, ActiveAbilities>, + pub loot_owners: ReadStorage<'a, LootOwner>, } pub enum Path { diff --git a/server/src/sys/loot.rs b/server/src/sys/loot.rs new file mode 100644 index 0000000000..6c991d64d2 --- /dev/null +++ b/server/src/sys/loot.rs @@ -0,0 +1,42 @@ +use common::{comp::LootOwner, uid::UidAllocator}; +use common_ecs::{Job, Origin, Phase, System}; +use specs::{saveload::MarkerAllocator, Entities, Entity, Join, Read, WriteStorage}; +use tracing::debug; + +// This system manages loot that exists in the world +#[derive(Default)] +pub struct Sys; +impl<'a> System<'a> for Sys { + type SystemData = ( + Entities<'a>, + WriteStorage<'a, LootOwner>, + Read<'a, UidAllocator>, + ); + + const NAME: &'static str = "loot"; + const ORIGIN: Origin = Origin::Server; + const PHASE: Phase = Phase::Create; + + fn run(_job: &mut Job, (entities, mut loot_owners, uid_allocator): Self::SystemData) { + // Find and remove expired loot ownership. Loot ownership is expired when either + // the expiry time has passed, or the owner entity no longer exists + let expired = (&entities, &loot_owners) + .join() + .filter(|(_, loot_owner)| { + loot_owner.expired() + || uid_allocator + .retrieve_entity_internal(loot_owner.uid().into()) + .map_or(true, |entity| !entities.is_alive(entity)) + }) + .map(|(entity, _)| entity) + .collect::>(); + + if !&expired.is_empty() { + debug!("Removing {} expired loot ownerships", expired.iter().len()); + } + + for entity in expired { + loot_owners.remove(entity); + } + } +} diff --git a/server/src/sys/mod.rs b/server/src/sys/mod.rs index 56ac301431..59e2b446f6 100644 --- a/server/src/sys/mod.rs +++ b/server/src/sys/mod.rs @@ -3,6 +3,7 @@ pub mod chunk_send; pub mod chunk_serialize; pub mod entity_sync; pub mod invite_timeout; +pub mod loot; pub mod metrics; pub mod msg; pub mod object; diff --git a/server/src/sys/msg/mod.rs b/server/src/sys/msg/mod.rs index 0edd89ecef..f69be4351a 100644 --- a/server/src/sys/msg/mod.rs +++ b/server/src/sys/msg/mod.rs @@ -5,7 +5,10 @@ pub mod ping; pub mod register; pub mod terrain; -use crate::{client::Client, sys::pets}; +use crate::{ + client::Client, + sys::{loot, pets}, +}; use common_ecs::{dispatch, System}; use serde::de::DeserializeOwned; use specs::DispatcherBuilder; @@ -20,6 +23,7 @@ pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) { dispatch::(dispatch_builder, &[]); dispatch::(dispatch_builder, &[]); dispatch::(dispatch_builder, &[]); + dispatch::(dispatch_builder, &[]); } /// handles all send msg and calls a handle fn diff --git a/voxygen/src/audio/sfx/mod.rs b/voxygen/src/audio/sfx/mod.rs index 9e359f9570..e0f7abb266 100644 --- a/voxygen/src/audio/sfx/mod.rs +++ b/voxygen/src/audio/sfx/mod.rs @@ -314,8 +314,8 @@ impl From<&InventoryUpdateEvent> for SfxEvent { _ => SfxEvent::Inventory(SfxInventoryEvent::Collected), } }, - InventoryUpdateEvent::BlockCollectFailed(_) - | InventoryUpdateEvent::EntityCollectFailed(_) => { + InventoryUpdateEvent::BlockCollectFailed { .. } + | InventoryUpdateEvent::EntityCollectFailed { .. } => { SfxEvent::Inventory(SfxInventoryEvent::CollectFailed) }, InventoryUpdateEvent::Consumed(consumable) => { diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 3803fb0ec6..3ac004bb85 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -80,7 +80,7 @@ use common::{ self, ability::AuxiliaryAbility, fluid_dynamics, - inventory::{slot::InvSlotId, trade_pricing::TradePricing}, + inventory::{slot::InvSlotId, trade_pricing::TradePricing, CollectFailedReason}, item::{tool::ToolKind, ItemDesc, MaterialStatManifest, Quality}, pet::is_mountable, skillset::{skills::Skill, SkillGroupKind}, @@ -997,6 +997,58 @@ pub struct Floaters { pub block_floaters: Vec, } +#[derive(Clone)] +pub enum HudLootOwner { + Name(String), + Unknown, +} + +#[derive(Clone)] +pub enum HudCollectFailedReason { + InventoryFull, + LootOwned { + owner: HudLootOwner, + expiry_secs: u64, + }, +} + +impl HudCollectFailedReason { + pub fn from_server_reason(reason: &CollectFailedReason, ecs: &specs::World) -> Self { + match reason { + CollectFailedReason::InventoryFull => HudCollectFailedReason::InventoryFull, + CollectFailedReason::LootOwned { + owner_uid, + expiry_secs, + } => { + let maybe_owner_name = + ecs.entity_from_uid((*owner_uid).into()).and_then(|entity| { + ecs.read_storage::() + .get(entity) + .map(|stats| stats.name.clone()) + }); + let owner = if let Some(name) = maybe_owner_name { + HudLootOwner::Name(name) + } else { + HudLootOwner::Unknown + }; + HudCollectFailedReason::LootOwned { + owner, + expiry_secs: *expiry_secs, + } + }, + } + } +} +#[derive(Clone)] +pub struct CollectFailedData { + pulse: f32, + reason: HudCollectFailedReason, +} + +impl CollectFailedData { + pub fn new(pulse: f32, reason: HudCollectFailedReason) -> Self { Self { pulse, reason } } +} + pub struct Hud { ui: Ui, ids: Ids, @@ -1005,8 +1057,8 @@ pub struct Hud { item_imgs: ItemImgs, fonts: Fonts, rot_imgs: ImgsRot, - failed_block_pickups: HashMap, f32>, - failed_entity_pickups: HashMap, + failed_block_pickups: HashMap, CollectFailedData>, + failed_entity_pickups: HashMap, new_loot_messages: VecDeque, new_messages: VecDeque, new_notifications: VecDeque, @@ -1772,9 +1824,9 @@ impl Hud { }; self.failed_block_pickups - .retain(|_, t| pulse - *t < overitem::PICKUP_FAILED_FADE_OUT_TIME); + .retain(|_, t| pulse - (*t).pulse < overitem::PICKUP_FAILED_FADE_OUT_TIME); self.failed_entity_pickups - .retain(|_, t| pulse - *t < overitem::PICKUP_FAILED_FADE_OUT_TIME); + .retain(|_, t| pulse - (*t).pulse < overitem::PICKUP_FAILED_FADE_OUT_TIME); // Render overitem: name, etc. for (entity, pos, item, distance) in (&entities, &pos, &items) @@ -1793,7 +1845,7 @@ impl Hud { distance, overitem::OveritemProperties { active: interactable.as_ref().and_then(|i| i.entity()) == Some(entity), - pickup_failed_pulse: self.failed_entity_pickups.get(&entity).copied(), + pickup_failed_pulse: self.failed_entity_pickups.get(&entity).cloned(), }, &self.fonts, vec![(GameInput::Interact, i18n.get("hud.pick_up").to_string())], @@ -1810,7 +1862,7 @@ impl Hud { let overitem_properties = overitem::OveritemProperties { active: true, - pickup_failed_pulse: self.failed_block_pickups.get(&pos).copied(), + pickup_failed_pulse: self.failed_block_pickups.get(&pos).cloned(), }; let pos = pos.map(|e| e as f32 + 0.5); let over_pos = pos + Vec3::unit_z() * 0.7; @@ -3938,12 +3990,14 @@ impl Hud { } } - pub fn add_failed_block_pickup(&mut self, pos: Vec3) { - self.failed_block_pickups.insert(pos, self.pulse); + pub fn add_failed_block_pickup(&mut self, pos: Vec3, reason: HudCollectFailedReason) { + self.failed_block_pickups + .insert(pos, CollectFailedData::new(self.pulse, reason)); } - pub fn add_failed_entity_pickup(&mut self, entity: EcsEntity) { - self.failed_entity_pickups.insert(entity, self.pulse); + pub fn add_failed_entity_pickup(&mut self, entity: EcsEntity, reason: HudCollectFailedReason) { + self.failed_entity_pickups + .insert(entity, CollectFailedData::new(self.pulse, reason)); } pub fn new_loot_message(&mut self, item: LootMessage) { diff --git a/voxygen/src/hud/overitem.rs b/voxygen/src/hud/overitem.rs index aaf6425f8f..16ca78a37e 100644 --- a/voxygen/src/hud/overitem.rs +++ b/voxygen/src/hud/overitem.rs @@ -11,6 +11,7 @@ use conrod_core::{ use i18n::Localization; use std::borrow::Cow; +use crate::hud::{CollectFailedData, HudCollectFailedReason, HudLootOwner}; use keyboard_keynames::key_layout::KeyLayout; pub const TEXT_COLOR: Color = Color::Rgba(0.61, 0.61, 0.89, 1.0); @@ -79,7 +80,7 @@ impl<'a> Overitem<'a> { pub struct OveritemProperties { pub active: bool, - pub pickup_failed_pulse: Option, + pub pickup_failed_pulse: Option, } pub struct State { @@ -215,9 +216,10 @@ impl<'a> Widget for Overitem<'a> { .parent(id) .set(state.ids.btn_bg, ui); } - if let Some(time) = self.properties.pickup_failed_pulse { + if let Some(collect_failed_data) = self.properties.pickup_failed_pulse { //should never exceed 1.0, but just in case - let age = ((self.pulse - time) / PICKUP_FAILED_FADE_OUT_TIME).clamp(0.0, 1.0); + let age = ((self.pulse - collect_failed_data.pulse) / PICKUP_FAILED_FADE_OUT_TIME) + .clamp(0.0, 1.0); let alpha = 1.0 - age.powi(4); let brightness = 1.0 / (age / 0.07 - 1.0).abs().clamp(0.01, 1.0); @@ -226,7 +228,25 @@ impl<'a> Widget for Overitem<'a> { color::hsla(hue, sat / brightness, lum * brightness.sqrt(), alp * alpha) }; - Text::new(self.localized_strings.get("hud.inventory_full")) + let text = match collect_failed_data.reason { + HudCollectFailedReason::InventoryFull => { + self.localized_strings.get("hud.inventory_full").to_string() + }, + HudCollectFailedReason::LootOwned { owner, expiry_secs } => { + let owner_name = match owner { + HudLootOwner::Name(name) => name, + HudLootOwner::Unknown => { + self.localized_strings.get("hud.someone_else").to_string() + }, + }; + self.localized_strings + .get("hud.owned_by_for_secs") + .replace("{name}", &owner_name) + .replace("{secs}", format!("{}", expiry_secs).as_str()) + }, + }; + + Text::new(&text) .font_id(self.fonts.cyri.conrod_id) .font_size(inv_full_font_size as u32) .color(shade_color(Color::Rgba(0.0, 0.0, 0.0, 1.0))) @@ -235,7 +255,7 @@ impl<'a> Widget for Overitem<'a> { .depth(self.distance_from_player_sqr + 6.0) .set(state.ids.inv_full_bg, ui); - Text::new(self.localized_strings.get("hud.inventory_full")) + Text::new(&text) .font_id(self.fonts.cyri.conrod_id) .font_size(inv_full_font_size as u32) .color(shade_color(Color::Rgba(1.0, 0.0, 0.0, 1.0))) diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index fe14ed81b9..d9af27e1b5 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -43,7 +43,10 @@ use crate::{ audio::sfx::SfxEvent, error::Error, game_input::GameInput, - hud::{DebugInfo, Event as HudEvent, Hud, HudInfo, LootMessage, PromptDialogSettings}, + hud::{ + DebugInfo, Event as HudEvent, Hud, HudCollectFailedReason, HudInfo, LootMessage, + PromptDialogSettings, + }, key_state::KeyState, menu::char_selection::CharSelectionState, render::{Drawer, GlobalsBindGroup}, @@ -244,12 +247,27 @@ impl SessionState { global_state.audio.emit_sfx_item(sfx_trigger_item); match inv_event { - InventoryUpdateEvent::BlockCollectFailed(pos) => { - self.hud.add_failed_block_pickup(pos); + InventoryUpdateEvent::BlockCollectFailed { pos, reason } => { + self.hud.add_failed_block_pickup( + pos, + HudCollectFailedReason::from_server_reason( + &reason, + client.state().ecs(), + ), + ); }, - InventoryUpdateEvent::EntityCollectFailed(uid) => { + InventoryUpdateEvent::EntityCollectFailed { + entity: uid, + reason, + } => { if let Some(entity) = client.state().ecs().entity_from_uid(uid.into()) { - self.hud.add_failed_entity_pickup(entity); + self.hud.add_failed_entity_pickup( + entity, + HudCollectFailedReason::from_server_reason( + &reason, + client.state().ecs(), + ), + ); } }, InventoryUpdateEvent::Collected(item) => { From c001de7409c6d830bdd6181c67419c0ec73e5770 Mon Sep 17 00:00:00 2001 From: Ben Wallis Date: Sat, 28 May 2022 16:28:26 +0100 Subject: [PATCH 019/229] Fixed pressing enter on character creation screen attempting to log in instead of create the character. Fixed deleting a character with no characters remaining resulting in the deleted character still being selected internally. --- voxygen/src/menu/char_selection/ui/mod.rs | 35 +++++++++++++++++------ 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/voxygen/src/menu/char_selection/ui/mod.rs b/voxygen/src/menu/char_selection/ui/mod.rs index 7dd69f485e..aa3d948f07 100644 --- a/voxygen/src/menu/char_selection/ui/mod.rs +++ b/voxygen/src/menu/char_selection/ui/mod.rs @@ -400,15 +400,29 @@ impl Controls { ref mut yes_button, ref mut no_button, } => { - // If no character is selected then select the first one - // Note: we don't need to persist this because it is the default - if self.selected.is_none() { - self.selected = client - .character_list() - .characters - .get(0) - .and_then(|i| i.character.id); + match self.selected { + Some(character_id) => { + // If the selected character no longer exists, deselect it. + if !client + .character_list() + .characters + .iter() + .any(|char| char.character.id.map_or(false, |id| id == character_id)) + { + self.selected = None; + } + }, + None => { + // If no character is selected then select the first one + // Note: we don't need to persist this because it is the default + self.selected = client + .character_list() + .characters + .get(0) + .and_then(|i| i.character.id); + }, } + // Get the index of the selected character let selected = self.selected.and_then(|id| { client @@ -1725,7 +1739,10 @@ impl CharSelectionUi { if self.enter_pressed { self.enter_pressed = false; - messages.push(Message::EnterWorld); + messages.push(match self.controls.mode { + Mode::Select { .. } => Message::EnterWorld, + Mode::CreateOrEdit { .. } => Message::CreateCharacter, + }); } if let Some(id) = self.select_character.take() { From 8488c7b25eaa063d950e280475d807b90dc8039a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Sat, 28 May 2022 23:17:28 +0200 Subject: [PATCH 020/229] Upgrade `assets_manager` to `0.8.0` and `image` to `0.24` This removes a significant number of duplicated dependencies --- Cargo.lock | 243 +++------------------ client/Cargo.toml | 2 +- common/assets/Cargo.toml | 4 +- common/assets/src/lib.rs | 6 +- common/net/Cargo.toml | 2 +- common/net/src/msg/compression.rs | 8 +- common/src/comp/body/ship.rs | 5 +- common/src/comp/inventory/item/mod.rs | 5 +- common/src/comp/inventory/item/tool.rs | 5 +- common/src/comp/inventory/trade_pricing.rs | 5 +- common/src/recipe.rs | 10 +- common/src/terrain/structure.rs | 10 +- voxygen/Cargo.toml | 4 +- voxygen/i18n/src/lib.rs | 17 +- voxygen/src/audio/music.rs | 5 +- voxygen/src/lib.rs | 3 +- voxygen/src/render/renderer/screenshot.rs | 48 ++-- voxygen/src/render/renderer/shaders.rs | 5 +- voxygen/src/render/texture.rs | 7 +- voxygen/src/scene/figure/load.rs | 2 +- world/Cargo.toml | 2 +- 21 files changed, 86 insertions(+), 312 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 45730db945..ce7c0e471a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -214,17 +214,17 @@ dependencies = [ [[package]] name = "assets_manager" -version = "0.7.2" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bec562a7c25c1aa60d4394cb96c914aa9236ae53dddf5e89ea8aac8a20d98c0" +checksum = "c53a8477ada5edbd6ba3b0698aabaa76b352454aedc8c8dca0c6328fc8313b7e" dependencies = [ "ab_glyph", "ahash 0.7.6", "bincode", "crossbeam-channel", "log", - "notify 4.0.17", - "parking_lot 0.11.2", + "notify", + "parking_lot 0.12.0", "ron 0.7.0", "serde", "serde_json", @@ -320,16 +320,16 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" +checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61" dependencies = [ "addr2line", "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide 0.4.4", - "object 0.27.1", + "miniz_oxide", + "object", "rustc-demangle", ] @@ -1461,16 +1461,6 @@ dependencies = [ "syn 1.0.90", ] -[[package]] -name = "deflate" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" -dependencies = [ - "adler32", - "byteorder", -] - [[package]] name = "deflate" version = "1.0.0" @@ -1870,14 +1860,12 @@ checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" [[package]] name = "flate2" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" dependencies = [ - "cfg-if 1.0.0", "crc32fast", - "libc", - "miniz_oxide 0.4.4", + "miniz_oxide", ] [[package]] @@ -1920,25 +1908,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fsevent" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" -dependencies = [ - "bitflags", - "fsevent-sys 2.0.1", -] - -[[package]] -name = "fsevent-sys" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" -dependencies = [ - "libc", -] - [[package]] name = "fsevent-sys" version = "4.1.0" @@ -1948,22 +1917,6 @@ dependencies = [ "libc", ] -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - [[package]] name = "funty" version = "1.2.0" @@ -2764,16 +2717,16 @@ dependencies = [ [[package]] name = "image" -version = "0.23.14" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" +checksum = "28edd9d7bc256be2502e325ac0628bde30b7001b9b52e0abe31a1a9dc2701212" dependencies = [ "bytemuck", "byteorder", "color_quant", "jpeg-decoder", "num-iter", - "num-rational 0.3.2", + "num-rational 0.4.0", "num-traits", "png", ] @@ -2799,17 +2752,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "inotify" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f" -dependencies = [ - "bitflags", - "inotify-sys", - "libc", -] - [[package]] name = "inotify" version = "0.9.6" @@ -2861,15 +2803,6 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9448015e586b611e5d322f6703812bbca2f1e709d5773ecd38ddb4e3bb649504" -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - [[package]] name = "itertools" version = "0.10.3" @@ -2922,9 +2855,9 @@ dependencies = [ [[package]] name = "jpeg-decoder" -version = "0.1.22" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" +checksum = "9478aa10f73e7528198d75109c8be5cd7d15fb530238040148d5f9a22d4c5b3b" [[package]] name = "js-sys" @@ -3363,40 +3296,11 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.3.7" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" -dependencies = [ - "adler32", -] - -[[package]] -name = "miniz_oxide" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" dependencies = [ "adler", - "autocfg", -] - -[[package]] -name = "mio" -version = "0.6.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" -dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log", - "miow 0.2.2", - "net2", - "slab", - "winapi 0.2.8", ] [[package]] @@ -3407,7 +3311,7 @@ checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" dependencies = [ "libc", "log", - "miow 0.3.7", + "miow", "ntapi", "winapi 0.3.9", ] @@ -3420,24 +3324,12 @@ checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" dependencies = [ "libc", "log", - "miow 0.3.7", + "miow", "ntapi", "wasi 0.11.0+wasi-snapshot-preview1", "winapi 0.3.9", ] -[[package]] -name = "mio-extras" -version = "2.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" -dependencies = [ - "lazycell", - "log", - "mio 0.6.23", - "slab", -] - [[package]] name = "mio-misc" version = "1.2.2" @@ -3450,18 +3342,6 @@ dependencies = [ "mio 0.7.14", ] -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - [[package]] name = "miow" version = "0.3.7" @@ -3632,17 +3512,6 @@ dependencies = [ "jni-sys", ] -[[package]] -name = "net2" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", -] - [[package]] name = "nibble_vec" version = "0.1.0" @@ -3744,33 +3613,15 @@ dependencies = [ [[package]] name = "notify" -version = "4.0.17" +version = "5.0.0-pre.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae03c8c853dba7bfd23e571ff0cff7bc9dceb40a4cd684cd1681824183f45257" -dependencies = [ - "bitflags", - "filetime", - "fsevent", - "fsevent-sys 2.0.1", - "inotify 0.7.1", - "libc", - "mio 0.6.23", - "mio-extras", - "walkdir 2.3.2", - "winapi 0.3.9", -] - -[[package]] -name = "notify" -version = "5.0.0-pre.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d13c22db70a63592e098fb51735bab36646821e6389a0ba171f3549facdf0b74" +checksum = "553f9844ad0b0824605c20fb55a661679782680410abfb1a8144c2e7e437e7a7" dependencies = [ "bitflags", "crossbeam-channel", "filetime", - "fsevent-sys 4.1.0", - "inotify 0.9.6", + "fsevent-sys", + "inotify", "kqueue", "libc", "mio 0.8.2", @@ -3900,17 +3751,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-rational" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-rational" version = "0.4.0" @@ -4012,15 +3852,6 @@ dependencies = [ "objc", ] -[[package]] -name = "object" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" -dependencies = [ - "memchr", -] - [[package]] name = "object" version = "0.28.3" @@ -4404,14 +4235,14 @@ dependencies = [ [[package]] name = "png" -version = "0.16.8" +version = "0.17.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" +checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba" dependencies = [ "bitflags", "crc32fast", - "deflate 0.8.6", - "miniz_oxide 0.3.7", + "deflate", + "miniz_oxide", ] [[package]] @@ -6933,7 +6764,7 @@ version = "0.1.0" dependencies = [ "find_folder", "libloading 0.7.3", - "notify 5.0.0-pre.14", + "notify", "tracing", ] @@ -6980,7 +6811,7 @@ dependencies = [ "clap 3.1.8", "criterion", "csv", - "deflate 1.0.0", + "deflate", "enum-iterator", "fallible-iterator", "flate2", @@ -7261,7 +7092,7 @@ dependencies = [ "leb128", "libloading 0.7.3", "loupe", - "object 0.28.3", + "object", "rkyv", "serde", "tempfile", @@ -7300,7 +7131,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24ce18ac2877050e59580d27ee1a88f3192d7a31e77fbba0852abc7888d6e0b5" dependencies = [ - "object 0.28.3", + "object", "thiserror", "wasmer-compiler", "wasmer-types", @@ -7855,16 +7686,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "wyz" version = "0.4.0" diff --git a/client/Cargo.toml b/client/Cargo.toml index 95de43833b..d5c55e870c 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -24,7 +24,7 @@ network = { package = "veloren-network", path = "../network", features = ["compr byteorder = "1.3.2" tokio = { version = "1.14", default-features = false, features = ["rt-multi-thread"] } quinn = "0.8" -image = { version = "0.23.12", default-features = false, features = ["png"] } +image = { version = "0.24", default-features = false, features = ["png"] } num = "0.4" tracing = { version = "0.1", default-features = false } rayon = "1.5" diff --git a/common/assets/Cargo.toml b/common/assets/Cargo.toml index dea2906e65..f27cc9b57f 100644 --- a/common/assets/Cargo.toml +++ b/common/assets/Cargo.toml @@ -7,11 +7,11 @@ version = "0.10.0" [dependencies] lazy_static = "1.4.0" -assets_manager = {version = "0.7", features = ["bincode", "ron", "json"]} +assets_manager = {version = "0.8.1", features = ["bincode", "ron", "json"]} ron = { version = "0.7", default-features = false } dot_vox = "4.0" wavefront = "0.2" # TODO: Use vertex-colors branch when we have models that have them -image = { version = "0.23.12", default-features = false, features = ["png"] } +image = { version = "0.24", default-features = false, features = ["png"] } tracing = "0.1" # asset tweak diff --git a/common/assets/src/lib.rs b/common/assets/src/lib.rs index 4784de231e..e5052b39d1 100644 --- a/common/assets/src/lib.rs +++ b/common/assets/src/lib.rs @@ -12,7 +12,7 @@ pub use assets_manager::{ self, BincodeLoader, BytesLoader, JsonLoader, LoadFrom, Loader, RonLoader, StringLoader, }, source::{self, Source}, - Asset, AssetCache, BoxedError, Compound, Error, SharedString, + AnyCache, Asset, AssetCache, BoxedError, Compound, Error, SharedString, }; mod fs; @@ -28,7 +28,7 @@ pub fn start_hot_reloading() { ASSETS.enhance_hot_reloading(); } pub type AssetHandle = assets_manager::Handle<'static, T>; pub type AssetGuard = assets_manager::AssetGuard<'static, T>; -pub type AssetDirHandle = assets_manager::DirHandle<'static, T, fs::FileSystem>; +pub type AssetDirHandle = assets_manager::DirHandle<'static, T>; pub type ReloadWatcher = assets_manager::ReloadWatcher<'static>; /// The Asset trait, which is implemented by all structures that have their data @@ -122,7 +122,7 @@ pub fn load_dir( /// 1) If can't load directory (filesystem errors) /// 2) If file can't be loaded (parsing problem) #[track_caller] -pub fn read_expect_dir( +pub fn read_expect_dir( specifier: &str, recursive: bool, ) -> impl Iterator> { diff --git a/common/net/Cargo.toml b/common/net/Cargo.toml index 012bc0622a..8df5f14dd6 100644 --- a/common/net/Cargo.toml +++ b/common/net/Cargo.toml @@ -15,7 +15,7 @@ common = {package = "veloren-common", path = "../../common"} bincode = "1.3.3" flate2 = "1.0.20" -image = { version = "0.23.12", default-features = false, features = ["png", "jpeg"] } +image = { version = "0.24", default-features = false, features = ["png", "jpeg"] } num-traits = "0.2" sum_type = "0.2.0" vek = { version = "0.15.8", features = ["serde"] } diff --git a/common/net/src/msg/compression.rs b/common/net/src/msg/compression.rs index f9f92de363..2985c63f53 100644 --- a/common/net/src/msg/compression.rs +++ b/common/net/src/msg/compression.rs @@ -4,7 +4,7 @@ use common::{ volumes::vol_grid_2d::VolGrid2d, }; use hashbrown::HashMap; -use image::{ImageBuffer, ImageDecoder, Pixel}; +use image::{ImageBuffer, ImageDecoder, ImageEncoder, Pixel}; use num_traits::cast::FromPrimitive; use serde::{Deserialize, Serialize}; use std::{ @@ -237,7 +237,7 @@ impl VoxelImageEncoding for QuadPngEncoding { CompressionType::Rle, FilterType::Up, ); - png.encode(&*x.as_raw(), x.width(), x.height(), image::ColorType::L8) + png.write_image(&*x.as_raw(), x.width(), x.height(), image::ColorType::L8) .ok()?; indices[i] = buf.len(); Some(()) @@ -252,7 +252,7 @@ impl VoxelImageEncoding for QuadPngEncoding { CompressionType::Rle, FilterType::Sub, ); - png.encode( + png.write_image( &*ws.3.as_raw(), ws.3.width(), ws.3.height(), @@ -513,7 +513,7 @@ impl VoxelImageEncoding for TriPngEncoding( - cache: &assets::AssetCache, - _: &str, - ) -> Result { + fn load(cache: assets::AnyCache, _: &str) -> Result { let manifest: AssetHandle> = AssetExt::load("common.manifests.ship_manifest")?; let mut colliders = HashMap::new(); diff --git a/common/src/comp/inventory/item/mod.rs b/common/src/comp/inventory/item/mod.rs index a487c153c8..57643ebec5 100644 --- a/common/src/comp/inventory/item/mod.rs +++ b/common/src/comp/inventory/item/mod.rs @@ -656,10 +656,7 @@ impl PartialEq for Item { } impl assets::Compound for ItemDef { - fn load( - cache: &assets::AssetCache, - specifier: &str, - ) -> Result { + fn load(cache: assets::AnyCache, specifier: &str) -> Result { if specifier.starts_with("veloren.core.") { return Err(format!( "Attempted to load an asset from a specifier reserved for core veloren functions. \ diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index 663b74aa01..f4891688aa 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -373,10 +373,7 @@ impl Asset for AbilityMap { } impl assets::Compound for AbilityMap { - fn load( - cache: &assets::AssetCache, - specifier: &str, - ) -> Result { + fn load(cache: assets::AnyCache, specifier: &str) -> Result { let manifest = cache.load::>(specifier)?.read(); Ok(AbilityMap( diff --git a/common/src/comp/inventory/trade_pricing.rs b/common/src/comp/inventory/trade_pricing.rs index 8ed04bf9f3..95d295d70a 100644 --- a/common/src/comp/inventory/trade_pricing.rs +++ b/common/src/comp/inventory/trade_pricing.rs @@ -299,10 +299,7 @@ impl EqualitySet { } impl assets::Compound for EqualitySet { - fn load( - cache: &assets::AssetCache, - id: &str, - ) -> Result { + fn load(cache: assets::AnyCache, id: &str) -> Result { #[derive(Debug, Deserialize)] enum EqualitySpec { LootTable(String), diff --git a/common/src/recipe.rs b/common/src/recipe.rs index f2feffa84e..6f2da5a81d 100644 --- a/common/src/recipe.rs +++ b/common/src/recipe.rs @@ -420,10 +420,7 @@ impl assets::Asset for ItemList { } impl assets::Compound for RecipeBook { - fn load( - cache: &assets::AssetCache, - specifier: &str, - ) -> Result { + fn load(cache: assets::AnyCache, specifier: &str) -> Result { #[inline] fn load_item_def(spec: &(String, u32)) -> Result<(Arc, u32), assets::Error> { let def = Arc::::load_cloned(&spec.0)?; @@ -748,10 +745,7 @@ enum RawComponentOutput { } impl assets::Compound for ComponentRecipeBook { - fn load( - cache: &assets::AssetCache, - specifier: &str, - ) -> Result { + fn load(cache: assets::AnyCache, specifier: &str) -> Result { #[inline] fn create_recipe_key(raw_recipe: &RawComponentRecipe) -> ComponentKey { match &raw_recipe.output { diff --git a/common/src/terrain/structure.rs b/common/src/terrain/structure.rs index 93e6592a7f..1465e8cb2d 100644 --- a/common/src/terrain/structure.rs +++ b/common/src/terrain/structure.rs @@ -68,10 +68,7 @@ impl std::ops::Deref for StructuresGroup { } impl assets::Compound for StructuresGroup { - fn load( - cache: &assets::AssetCache, - specifier: &str, - ) -> Result { + fn load(cache: assets::AnyCache, specifier: &str) -> Result { let specs = cache.load::(specifier)?.read(); Ok(StructuresGroup( @@ -139,10 +136,7 @@ impl ReadVol for Structure { } impl assets::Compound for BaseStructure { - fn load( - cache: &assets::AssetCache, - specifier: &str, - ) -> Result { + fn load(cache: assets::AnyCache, specifier: &str) -> Result { let dot_vox_data = cache.load::(specifier)?.read(); let dot_vox_data = &dot_vox_data.0; diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 6e1e2882cd..148ec677ea 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -90,7 +90,7 @@ gilrs = {version = "0.8.0", features = ["serde-serialize"]} server = { package = "veloren-server", path = "../server", optional = true, default-features = false, features = ["worldgen"] } # Utility -assets_manager = {version = "0.7", features = ["ab_glyph"]} +assets_manager = {version = "0.8", features = ["ab_glyph"]} backtrace = "0.3.40" bincode = "1.3.1" chrono = { version = "0.4.19", features = ["serde"] } @@ -105,7 +105,7 @@ dot_vox = "4.0" enum-iterator = "0.7" guillotiere = "0.6" hashbrown = {version = "0.11", features = ["rayon", "serde", "nightly"]} -image = {version = "0.23.12", default-features = false, features = ["ico", "png"]} +image = {version = "0.24", default-features = false, features = ["ico", "png"]} lazy_static = "1.4.0" native-dialog = { version = "0.6.3", optional = true } num = "0.4" diff --git a/voxygen/i18n/src/lib.rs b/voxygen/i18n/src/lib.rs index 428e867078..4c954d7f61 100644 --- a/voxygen/i18n/src/lib.rs +++ b/voxygen/i18n/src/lib.rs @@ -102,8 +102,8 @@ impl Language { } impl common_assets::Compound for Language { - fn load( - cache: &common_assets::AssetCache, + fn load( + cache: common_assets::AnyCache, asset_key: &str, ) -> Result { let manifest = cache @@ -282,15 +282,6 @@ impl LocalizationHandle { 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, @@ -315,8 +306,8 @@ impl common_assets::DirLoadable for FindManifests { struct LocalizationList(Vec); impl common_assets::Compound for LocalizationList { - fn load( - cache: &common_assets::AssetCache, + fn load( + cache: common_assets::AnyCache, specifier: &str, ) -> Result { // List language directories diff --git a/voxygen/src/audio/music.rs b/voxygen/src/audio/music.rs index 471f182aa0..d4c974b1bb 100644 --- a/voxygen/src/audio/music.rs +++ b/voxygen/src/audio/music.rs @@ -446,10 +446,7 @@ impl assets::Asset for SoundtrackCollection { } impl assets::Compound for SoundtrackCollection { - fn load( - _: &assets::AssetCache, - id: &str, - ) -> Result { + fn load(_: assets::AnyCache, id: &str) -> Result { let inner = || -> Result<_, assets::Error> { let manifest: AssetHandle> = AssetExt::load(id)?; diff --git a/voxygen/src/lib.rs b/voxygen/src/lib.rs index 4b51c032fb..d326b6c5c7 100644 --- a/voxygen/src/lib.rs +++ b/voxygen/src/lib.rs @@ -10,7 +10,8 @@ once_cell, trait_alias, option_get_or_insert_default, - map_try_insert + map_try_insert, + slice_as_chunks )] #![recursion_limit = "2048"] diff --git a/voxygen/src/render/renderer/screenshot.rs b/voxygen/src/render/renderer/screenshot.rs index 6a4220e07e..56f5636c86 100644 --- a/voxygen/src/render/renderer/screenshot.rs +++ b/voxygen/src/render/renderer/screenshot.rs @@ -147,7 +147,7 @@ impl TakeScreenshot { let buffer_map_future = buffer_slice.map_async(wgpu::MapMode::Read); // Wait on buffer mapping - let pixel_bytes = match singlethread_rt.block_on(buffer_map_future) { + let mut pixel_bytes = match singlethread_rt.block_on(buffer_map_future) { // Buffer is mapped and we can read it Ok(()) => { // Copy to a Vec @@ -174,38 +174,30 @@ impl TakeScreenshot { // Construct image let image = match self.tex_format { wgpu::TextureFormat::Bgra8UnormSrgb => { - let image = image::ImageBuffer::, Vec>::from_vec( - self.width, - self.height, - pixel_bytes, - ) - .expect( - "Failed to create ImageBuffer! Buffer was not large enough. This should not \ - occur", - ); - let image = image::DynamicImage::ImageBgra8(image); - - Ok(image) - }, - wgpu::TextureFormat::Rgba8UnormSrgb => { - let image = image::ImageBuffer::, Vec>::from_vec( - self.width, - self.height, - pixel_bytes, - ) - .expect( - "Failed to create ImageBuffer! Buffer was not large enough. This should not \ - occur", - ); - let image = image::DynamicImage::ImageRgba8(image); - - Ok(image) + let (pixels, rest) = pixel_bytes.as_chunks_mut(); + assert!(rest.is_empty()); + for [b, _g, r, _a] in pixels { + std::mem::swap(b, r); + } + Ok(pixel_bytes) }, + wgpu::TextureFormat::Rgba8UnormSrgb => Ok(pixel_bytes), format => Err(format!( "Unhandled format for screenshot texture: {:?}", format, )), - }; + } + .and_then(|pixel_bytes| { + let image = image::ImageBuffer::, Vec>::from_vec( + self.width, + self.height, + pixel_bytes, + ) + .expect( + "Failed to create ImageBuffer! Buffer was not large enough. This should not occur", + ); + Ok(image::DynamicImage::ImageRgba8(image)) + }); // Call supplied handler (self.screenshot_fn)(image); diff --git a/voxygen/src/render/renderer/shaders.rs b/voxygen/src/render/renderer/shaders.rs index 8bbf85ba75..8ee49843d8 100644 --- a/voxygen/src/render/renderer/shaders.rs +++ b/voxygen/src/render/renderer/shaders.rs @@ -24,10 +24,7 @@ pub struct Shaders { impl assets::Compound for Shaders { // TODO: Taking the specifier argument as a base for shaders specifiers // would allow to use several shaders groups easily - fn load( - _: &assets::AssetCache, - _: &str, - ) -> Result { + fn load(_: assets::AnyCache, _: &str) -> Result { let shaders = [ "include.constants", "include.globals", diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index e15911316e..e82eb2f6cb 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -1,6 +1,6 @@ use super::RenderError; use core::num::NonZeroU32; -use image::{DynamicImage, GenericImageView}; +use image::DynamicImage; use wgpu::Extent3d; /// Represents an image that has been uploaded to the GPU. @@ -21,17 +21,16 @@ impl Texture { filter_method: Option, address_mode: Option, ) -> Result { - let format = match &image { + let format = match image { DynamicImage::ImageLuma8(_) => wgpu::TextureFormat::R8Unorm, DynamicImage::ImageLumaA8(_) => panic!("ImageLuma8 unsupported"), DynamicImage::ImageRgb8(_) => panic!("ImageRgb8 unsupported"), DynamicImage::ImageRgba8(_) => wgpu::TextureFormat::Rgba8UnormSrgb, - DynamicImage::ImageBgr8(_) => panic!("ImageBgr8 unsupported"), - DynamicImage::ImageBgra8(_) => panic!("ImageBgra8 unsupported"), DynamicImage::ImageLuma16(_) => panic!("ImageLuma16 unsupported"), DynamicImage::ImageLumaA16(_) => panic!("ImageLumaA16 unsupported"), DynamicImage::ImageRgb16(_) => panic!("ImageRgb16 unsupported"), DynamicImage::ImageRgba16(_) => panic!("ImageRgba16 unsupported"), + _ => panic!("unsupported format"), }; // TODO: Actually handle images that aren't in rgba format properly. diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs index 4b8474131a..da1305a1a2 100644 --- a/voxygen/src/scene/figure/load.rs +++ b/voxygen/src/scene/figure/load.rs @@ -125,7 +125,7 @@ macro_rules! make_vox_spec { } impl assets::Compound for $Spec { - fn load(_: &assets::AssetCache, _: &str) -> Result { + fn load(_: assets::AnyCache, _: &str) -> Result { Ok($Spec { $( $field: AssetExt::load($asset_path)?, )* }) diff --git a/world/Cargo.toml b/world/Cargo.toml index f906bf1a09..86126f247c 100644 --- a/world/Cargo.toml +++ b/world/Cargo.toml @@ -19,7 +19,7 @@ bincode = "1.3.1" bitvec = "0.22" enum-iterator = "0.7" fxhash = "0.2.1" -image = { version = "0.23.12", default-features = false, features = ["png"] } +image = { version = "0.24", default-features = false, features = ["png"] } itertools = "0.10" vek = { version = "0.15.8", features = ["serde"] } noise = { version = "0.7", default-features = false } From ca2ef3e8135b33a1d169abc5f352e3fe3b1ec888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Sat, 28 May 2022 23:32:16 +0200 Subject: [PATCH 021/229] Add comments --- voxygen/src/render/renderer/screenshot.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/voxygen/src/render/renderer/screenshot.rs b/voxygen/src/render/renderer/screenshot.rs index 56f5636c86..659acd46c7 100644 --- a/voxygen/src/render/renderer/screenshot.rs +++ b/voxygen/src/render/renderer/screenshot.rs @@ -175,7 +175,10 @@ impl TakeScreenshot { let image = match self.tex_format { wgpu::TextureFormat::Bgra8UnormSrgb => { let (pixels, rest) = pixel_bytes.as_chunks_mut(); + // Always valid because each pixel should use four bytes. assert!(rest.is_empty()); + + // Swap blue and red components to get a RGBA texture. for [b, _g, r, _a] in pixels { std::mem::swap(b, r); } From f36e74e38365c5b9902b19ff3763b4af12b8632e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Sat, 28 May 2022 23:42:42 +0200 Subject: [PATCH 022/229] Fix deprecated function use --- voxygen/src/render/renderer/screenshot.rs | 7 ++++--- world/examples/chunk_compression_benchmarks.rs | 12 ++++++------ world/examples/heightmap_visualization.rs | 4 ++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/voxygen/src/render/renderer/screenshot.rs b/voxygen/src/render/renderer/screenshot.rs index 659acd46c7..83a5be9660 100644 --- a/voxygen/src/render/renderer/screenshot.rs +++ b/voxygen/src/render/renderer/screenshot.rs @@ -175,9 +175,10 @@ impl TakeScreenshot { let image = match self.tex_format { wgpu::TextureFormat::Bgra8UnormSrgb => { let (pixels, rest) = pixel_bytes.as_chunks_mut(); - // Always valid because each pixel should use four bytes. - assert!(rest.is_empty()); - + assert!( + rest.is_empty(), + "Always valid because each pixel uses four bytes" + ); // Swap blue and red components to get a RGBA texture. for [b, _g, r, _a] in pixels { std::mem::swap(b, r); diff --git a/world/examples/chunk_compression_benchmarks.rs b/world/examples/chunk_compression_benchmarks.rs index f4cb5fbf4e..3f493157c8 100644 --- a/world/examples/chunk_compression_benchmarks.rs +++ b/world/examples/chunk_compression_benchmarks.rs @@ -14,7 +14,7 @@ use common_net::msg::compression::{ WidePacking, }; use hashbrown::HashMap; -use image::ImageBuffer; +use image::{ImageBuffer, ImageEncoder}; use num_traits::cast::FromPrimitive; use rayon::ThreadPoolBuilder; use serde::{Deserialize, Serialize}; @@ -200,7 +200,7 @@ impl VoxelImageEncoding for PngEncoding { CompressionType::Rle, FilterType::Up, ); - png.encode( + png.write_image( &*ws.as_raw(), ws.width(), ws.height(), @@ -300,7 +300,7 @@ impl VoxelImageEncoding for MixedEncoding { CompressionType::Rle, FilterType::Up, ); - png.encode(&*x.as_raw(), x.width(), x.height(), image::ColorType::L8) + png.write_image(&*x.as_raw(), x.width(), x.height(), image::ColorType::L8) .ok()?; indices[i] = buf.len(); Some(()) @@ -406,7 +406,7 @@ impl VoxelImageEncoding for MixedEncodingSparseSprites { CompressionType::Fast, FilterType::Up, ); - png.encode( + png.write_image( &*ws.0.as_raw(), ws.0.width(), ws.0.height(), @@ -471,7 +471,7 @@ impl VoxelImageEncoding for MixedEncodingDenseSprites { CompressionType::Fast, FilterType::Up, ); - png.encode(&*x.as_raw(), x.width(), x.height(), image::ColorType::L8) + png.write_image(&*x.as_raw(), x.width(), x.height(), image::ColorType::L8) .ok()?; indices[i] = buf.len(); Some(()) @@ -637,7 +637,7 @@ impl<'a, NN: NearestNeighbor, const N: u32> VoxelImageEncoding for PaletteEncodi CompressionType::Rle, FilterType::Up, ); - png.encode(&*x.as_raw(), x.width(), x.height(), image::ColorType::L8) + png.write_image(&*x.as_raw(), x.width(), x.height(), image::ColorType::L8) .ok()?; indices[i] = buf.len(); Some(()) diff --git a/world/examples/heightmap_visualization.rs b/world/examples/heightmap_visualization.rs index 12403b3313..a192d9c192 100644 --- a/world/examples/heightmap_visualization.rs +++ b/world/examples/heightmap_visualization.rs @@ -1,6 +1,6 @@ use image::{ codecs::png::{CompressionType, FilterType, PngEncoder}, - ImageBuffer, + ImageBuffer, ImageEncoder, }; use rayon::ThreadPoolBuilder; use std::{fs::File, io::Write}; @@ -83,7 +83,7 @@ fn image_from_function [u8; 3]>( let mut heightmap_png = Vec::new(); let png = PngEncoder::new_with_quality(&mut heightmap_png, CompressionType::Best, FilterType::Paeth); - png.encode( + png.write_image( &*heightmap.as_raw(), heightmap.width(), heightmap.height(), From c92cd26ff1d90c1bc6e52f8acd22a23325e2b6ba Mon Sep 17 00:00:00 2001 From: Makselord Date: Fri, 27 May 2022 21:01:20 -0400 Subject: [PATCH 023/229] bamboo collectibles spawn near rivers --- world/src/layer/scatter.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/world/src/layer/scatter.rs b/world/src/layer/scatter.rs index 7bbacd644e..eb4a43662f 100644 --- a/world/src/layer/scatter.rs +++ b/world/src/layer/scatter.rs @@ -664,6 +664,17 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { * ((col.alt - CONFIG.sea_level) / 12.0).clamped(0.0, 1.0), Some((0.2, 128.0, 0.5)), ) + }), + (Bamboo, Ground, |_, col| { + ( + 0.35 * close(col.humidity, CONFIG.jungle_hum, 0.9) + * col + .water_dist + .map(|wd| Lerp::lerp(0.2, 0.0, (wd / 8.0).clamped(0.0, 1.0))) + .unwrap_or(0.0) + * ((col.alt - CONFIG.sea_level) / 12.0).clamped(0.0, 1.0), + Some((0.2, 128.0, 0.5)), + ) }), ]; From 6431c5567cfb5aefa7be9dfcea36a66fea040780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Sat, 28 May 2022 23:58:47 +0200 Subject: [PATCH 024/229] Fix clippy error --- voxygen/src/render/renderer/screenshot.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/voxygen/src/render/renderer/screenshot.rs b/voxygen/src/render/renderer/screenshot.rs index 83a5be9660..672c1056d8 100644 --- a/voxygen/src/render/renderer/screenshot.rs +++ b/voxygen/src/render/renderer/screenshot.rs @@ -191,7 +191,7 @@ impl TakeScreenshot { format, )), } - .and_then(|pixel_bytes| { + .map(|pixel_bytes| { let image = image::ImageBuffer::, Vec>::from_vec( self.width, self.height, @@ -200,7 +200,7 @@ impl TakeScreenshot { .expect( "Failed to create ImageBuffer! Buffer was not large enough. This should not occur", ); - Ok(image::DynamicImage::ImageRgba8(image)) + image::DynamicImage::ImageRgba8(image) }); // Call supplied handler From 60c2d7d96833b340f727867deb64ea5594d520e2 Mon Sep 17 00:00:00 2001 From: Makselord Date: Fri, 27 May 2022 21:20:28 -0400 Subject: [PATCH 025/229] updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cbebb7eae9..e0ee67ab93 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 - Added Thai translation - Skiing and ice skating - Added loot ownership for NPC drops +- Bamboo collectibles now spawn near rivers ### Changed From 69041137a0b2a12d6aab025c4e678f6309c22e9b Mon Sep 17 00:00:00 2001 From: Makselord Date: Sat, 28 May 2022 17:41:46 -0400 Subject: [PATCH 026/229] reduced bamboo spawn rates --- world/src/layer/scatter.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/world/src/layer/scatter.rs b/world/src/layer/scatter.rs index eb4a43662f..b758a270e1 100644 --- a/world/src/layer/scatter.rs +++ b/world/src/layer/scatter.rs @@ -665,9 +665,10 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { Some((0.2, 128.0, 0.5)), ) }), - (Bamboo, Ground, |_, col| { + (Bamboo, Ground, |_, col| { ( - 0.35 * close(col.humidity, CONFIG.jungle_hum, 0.9) + 0.014 + * close(col.humidity, CONFIG.jungle_hum, 0.9) * col .water_dist .map(|wd| Lerp::lerp(0.2, 0.0, (wd / 8.0).clamped(0.0, 1.0))) From b8c3d71fbeee61454e0182fd2d58adb9e511ebbd Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Sun, 29 May 2022 19:08:39 +0200 Subject: [PATCH 027/229] economy trace defaults to info --- common/frontend/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/common/frontend/src/lib.rs b/common/frontend/src/lib.rs index 504b359cfd..921f8c279b 100644 --- a/common/frontend/src/lib.rs +++ b/common/frontend/src/lib.rs @@ -56,6 +56,7 @@ where "veloren_common::trade=info", "veloren_world::sim=info", "veloren_world::civ=info", + "veloren_world::site::economy=info", "veloren_server::events::entity_manipulation=info", "hyper=info", "prometheus_hyper=info", From 3fc59d7e4d4e34f96ce321b6953a595efb5cfa47 Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Sun, 29 May 2022 19:09:52 +0200 Subject: [PATCH 028/229] lower trading output to trace (and raise one to warn) --- world/src/site/economy/mod.rs | 59 ++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/world/src/site/economy/mod.rs b/world/src/site/economy/mod.rs index d1cf20171e..e16808d6f7 100644 --- a/world/src/site/economy/mod.rs +++ b/world/src/site/economy/mod.rs @@ -10,7 +10,7 @@ use common::{ }; use lazy_static::lazy_static; use std::{cmp::Ordering::Less, convert::TryFrom}; -use tracing::{debug, info}; +use tracing::{debug, info, trace, warn}; use Good::*; mod map_types; @@ -383,14 +383,14 @@ impl Economy { .collect(); if site_id.id() == 1 { // cut down number of lines printed - debug!( + trace!( "Site {} #neighbors {} Transport capacity {}", site_id.id(), self.neighbors.len(), transportation_capacity, ); - debug!("missing {:#?} extra {:#?}", missing_goods, extra_goods,); - debug!("buy {:#?} pay {:#?}", good_price, good_payment); + trace!("missing {:#?} extra {:#?}", missing_goods, extra_goods,); + trace!("buy {:#?} pay {:#?}", good_price, good_payment); } // === the actual planning is here === for (g, (_, a)) in missing_goods.iter() { @@ -409,14 +409,16 @@ impl Economy { potential_balance += missing_trade * *price; buy_target = transportable_amount; // (buy_target - missing_trade).max(0.0); // avoid negative buy target caused by numeric inaccuracies missing_collect += collect - collect_capacity; - debug!( + trace!( "missing capacity {:?}/{:?} {:?}", - missing_trade, amount, potential_balance, + missing_trade, + amount, + potential_balance, ); amount = (amount - missing_trade).max(0.0); // you won't be able to transport it from elsewhere either, so don't count multiple times } let mut balance: f32 = *price * buy_target; - debug!( + trace!( "buy {:?} at {:?} amount {:?} balance {:?}", *g, s.id(), @@ -441,15 +443,17 @@ impl Economy { if acute_missing_dispatch == 0.0 { acute_missing_dispatch = missing_trade * effort2; } - debug!( + trace!( "can't carry payment {:?} {:?} {:?}", - g2, dispatch, dispatch_capacity + g2, + dispatch, + dispatch_capacity ); dispatch = dispatch_capacity; } extra_goods[*g2] -= amount2; - debug!("pay {:?} {:?} = {:?}", g2, amount2, balance); + trace!("pay {:?} {:?} = {:?}", g2, amount2, balance); balance -= amount2 * price2; neighbor_orders[*g2] -= amount2; dispatch_capacity = (dispatch_capacity - dispatch).max(0.0); @@ -465,9 +469,12 @@ impl Economy { collect_capacity = (collect_capacity - buy_target * effort).max(0.0); neighbor_orders[*g] += buy_target; amount -= buy_target; - debug!( + trace!( "deal amount {:?} end_balance {:?} price {:?} left {:?}", - buy_target, balance, *price, amount + buy_target, + balance, + *price, + amount ); } } @@ -492,7 +499,7 @@ impl Economy { if o.len() < 100 { o.push(to); } else { - debug!("overflow {:?}", o); + warn!("overflow {:?}", o); } } else { self.orders.insert(n.id, vec![to]); @@ -501,7 +508,7 @@ impl Economy { } // return missing transport capacity //missing_collect.max(missing_dispatch) - debug!( + trace!( "Tranportation {:?} {:?} {:?} {:?} {:?}", transportation_capacity, collect_capacity, @@ -513,7 +520,7 @@ impl Economy { - collect_capacity.min(dispatch_capacity) + missing_collect.max(missing_dispatch)); if site_id.id() == 1 { - debug!("Trade {:?}", result); + trace!("Trade {:?}", result); } result } @@ -557,7 +564,7 @@ impl Economy { .map(|(g, a, s)| (g, Some(total_orders[g] / (a - s)))), None, ); - debug!("trade {} {:?}", site_id.id(), order_stock_ratio); + trace!("trade {} {:?}", site_id.id(), order_stock_ratio); let prices = GoodMap::from_iter( self.values .iter() @@ -581,7 +588,7 @@ impl Economy { .map(|(g, a)| (g, *a, prices[g])) .collect(); sorted_buy.sort_by(|a, b| (b.2.partial_cmp(&a.2).unwrap_or(Less))); - debug!( + trace!( "with {} {:?} buy {:?}", o.customer.id(), sorted_sell, @@ -598,7 +605,7 @@ impl Economy { self.stocks[*g2] += amount2; balance = (balance - amount2 * *price2).max(0.0); *avail += amount2; // reduce (negative) brought stock - debug!("paid with {:?} {} {}", *g2, amount2, *price2); + trace!("paid with {:?} {} {}", *g2, amount2, *price2); if balance == 0.0 { break; } @@ -606,7 +613,7 @@ impl Economy { let mut paid_amount = (allocated_amount - balance / *price).min(self.stocks[*g]); if paid_amount / allocated_amount < 0.95 { - debug!( + trace!( "Client {} is broke on {:?} : {} {} severity {}", o.customer.id(), *g, @@ -615,7 +622,7 @@ impl Economy { order_stock_ratio, ); } else { - debug!("bought {:?} {} {}", *g, paid_amount, *price); + trace!("bought {:?} {} {}", *g, paid_amount, *price); } if self.stocks[*g] - paid_amount < 0.0 { info!( @@ -635,7 +642,7 @@ impl Economy { } for (g, amount, _) in sorted_buy.drain(..) { if amount < 0.0 { - debug!("shipping back unsold {} of {:?}", amount, g); + trace!("shipping back unsold {} of {:?}", amount, g); good_delivery[g] += -amount; } } @@ -652,7 +659,7 @@ impl Economy { ), amount: good_delivery, }; - debug!(?delivery); + trace!(?delivery); if let Some(deliveries) = deliveries.get_mut(&o.customer) { deliveries.push(delivery); } else { @@ -695,7 +702,7 @@ impl Economy { for (g, a) in d.amount.iter() { if *a < 0.0 { // likely rounding error, ignore - debug!("Unexpected delivery for {:?} {}", g, *a); + trace!("Unexpected delivery for {:?} {}", g, *a); } else { self.stocks[g] += *a; } @@ -896,7 +903,7 @@ impl Economy { }), 0.0, ); - debug!(?labor_ratios); + trace!(?labor_ratios); let labor_ratio_sum = labor_ratios.iter().map(|(_, r)| *r).sum::().max(0.01); let mut labor_context = vc.context("labor"); @@ -1002,7 +1009,7 @@ impl Economy { }) .sum(); let scale = reduced_amount / planned_amount.abs(); - debug!("re-plan {} {} {}", reduced_amount, planned_amount, scale); + trace!("re-plan {} {} {}", reduced_amount, planned_amount, scale); for k in self.orders.iter_mut() { for l in k.1.iter_mut().filter(|o| o.customer == site_id) { l.amount[g] *= scale; @@ -1021,7 +1028,7 @@ impl Economy { produced_goods[g] += *a; } } - debug!( + trace!( "merchant {} {}: {:?} {} {:?}", site_id.id(), self.pop, From f10b868dbfe76333179fce03d085936887983f42 Mon Sep 17 00:00:00 2001 From: Makselord Date: Sun, 29 May 2022 19:50:26 -0400 Subject: [PATCH 029/229] modular weapon modifier costs changed to 1, 5, 10, 15, 20, 30 --- CHANGELOG.md | 1 + assets/common/component_recipe_book.ron | 1008 +++++++++++------------ 2 files changed, 505 insertions(+), 504 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0ee67ab93..7608934693 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Stealth effects from sneaking and armor are evaluated independently. Armor now has effects even when not sneaking - Zoom-in effect when aiming bow is now optional - Non-Humanoid NPCs now pick up consumables when less than full health and use them to heal up. +- Changed module component modifier costs to the following scheme, based on base material: 1 -> 5 -> 10 -> 15 -> 20 -> 30 ### Removed diff --git a/assets/common/component_recipe_book.ron b/assets/common/component_recipe_book.ron index 8ac0446a32..fc5f4a5290 100644 --- a/assets/common/component_recipe_book.ron +++ b/assets/common/component_recipe_book.ron @@ -90,18 +90,6 @@ item: "common.items.modular.weapon.primary.hammer.spikedmace", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Hammer, - item: "common.items.modular.weapon.primary.hammer.spikedmace", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -113,13 +101,25 @@ toolkind: Hammer, item: "common.items.modular.weapon.primary.hammer.spikedmace", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Hammer, + item: "common.items.modular.weapon.primary.hammer.spikedmace", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Hammer, @@ -138,7 +138,7 @@ item: "common.items.modular.weapon.primary.hammer.spikedmace", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -162,18 +162,6 @@ item: "common.items.modular.weapon.primary.hammer.warhammer", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Hammer, - item: "common.items.modular.weapon.primary.hammer.warhammer", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -185,13 +173,25 @@ toolkind: Hammer, item: "common.items.modular.weapon.primary.hammer.warhammer", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Hammer, + item: "common.items.modular.weapon.primary.hammer.warhammer", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Hammer, @@ -210,7 +210,7 @@ item: "common.items.modular.weapon.primary.hammer.warhammer", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -234,18 +234,6 @@ item: "common.items.modular.weapon.primary.hammer.maul", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Hammer, - item: "common.items.modular.weapon.primary.hammer.maul", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -257,13 +245,25 @@ toolkind: Hammer, item: "common.items.modular.weapon.primary.hammer.maul", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Hammer, + item: "common.items.modular.weapon.primary.hammer.maul", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Hammer, @@ -282,7 +282,7 @@ item: "common.items.modular.weapon.primary.hammer.maul", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -306,18 +306,6 @@ item: "common.items.modular.weapon.primary.hammer.greatmace", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Hammer, - item: "common.items.modular.weapon.primary.hammer.greatmace", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -329,13 +317,25 @@ toolkind: Hammer, item: "common.items.modular.weapon.primary.hammer.greatmace", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Hammer, + item: "common.items.modular.weapon.primary.hammer.greatmace", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Hammer, @@ -354,7 +354,7 @@ item: "common.items.modular.weapon.primary.hammer.greatmace", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -378,18 +378,6 @@ item: "common.items.modular.weapon.primary.hammer.greathammer", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Hammer, - item: "common.items.modular.weapon.primary.hammer.greathammer", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -401,13 +389,25 @@ toolkind: Hammer, item: "common.items.modular.weapon.primary.hammer.greathammer", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Hammer, + item: "common.items.modular.weapon.primary.hammer.greathammer", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Hammer, @@ -426,7 +426,7 @@ item: "common.items.modular.weapon.primary.hammer.greathammer", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -450,18 +450,6 @@ item: "common.items.modular.weapon.primary.hammer.ornate", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Hammer, - item: "common.items.modular.weapon.primary.hammer.ornate", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -473,13 +461,25 @@ toolkind: Hammer, item: "common.items.modular.weapon.primary.hammer.ornate", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Hammer, + item: "common.items.modular.weapon.primary.hammer.ornate", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Hammer, @@ -498,7 +498,7 @@ item: "common.items.modular.weapon.primary.hammer.ornate", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -595,18 +595,6 @@ item: "common.items.modular.weapon.primary.sword.sawblade", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Sword, - item: "common.items.modular.weapon.primary.sword.sawblade", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -618,13 +606,25 @@ toolkind: Sword, item: "common.items.modular.weapon.primary.sword.sawblade", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Sword, + item: "common.items.modular.weapon.primary.sword.sawblade", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Sword, @@ -643,7 +643,7 @@ item: "common.items.modular.weapon.primary.sword.sawblade", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -667,18 +667,6 @@ item: "common.items.modular.weapon.primary.sword.katana", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Sword, - item: "common.items.modular.weapon.primary.sword.katana", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -690,13 +678,25 @@ toolkind: Sword, item: "common.items.modular.weapon.primary.sword.katana", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Sword, + item: "common.items.modular.weapon.primary.sword.katana", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Sword, @@ -715,7 +715,7 @@ item: "common.items.modular.weapon.primary.sword.katana", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -739,18 +739,6 @@ item: "common.items.modular.weapon.primary.sword.zweihander", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Sword, - item: "common.items.modular.weapon.primary.sword.zweihander", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -762,13 +750,25 @@ toolkind: Sword, item: "common.items.modular.weapon.primary.sword.zweihander", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Sword, + item: "common.items.modular.weapon.primary.sword.zweihander", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Sword, @@ -787,7 +787,7 @@ item: "common.items.modular.weapon.primary.sword.zweihander", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -811,18 +811,6 @@ item: "common.items.modular.weapon.primary.sword.sabre", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Sword, - item: "common.items.modular.weapon.primary.sword.sabre", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -834,13 +822,25 @@ toolkind: Sword, item: "common.items.modular.weapon.primary.sword.sabre", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Sword, + item: "common.items.modular.weapon.primary.sword.sabre", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Sword, @@ -859,7 +859,7 @@ item: "common.items.modular.weapon.primary.sword.sabre", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -883,18 +883,6 @@ item: "common.items.modular.weapon.primary.sword.greatsword", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Sword, - item: "common.items.modular.weapon.primary.sword.greatsword", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -906,13 +894,25 @@ toolkind: Sword, item: "common.items.modular.weapon.primary.sword.greatsword", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Sword, + item: "common.items.modular.weapon.primary.sword.greatsword", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Sword, @@ -931,7 +931,7 @@ item: "common.items.modular.weapon.primary.sword.greatsword", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -955,18 +955,6 @@ item: "common.items.modular.weapon.primary.sword.ornate", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Sword, - item: "common.items.modular.weapon.primary.sword.ornate", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -978,13 +966,25 @@ toolkind: Sword, item: "common.items.modular.weapon.primary.sword.ornate", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Sword, + item: "common.items.modular.weapon.primary.sword.ornate", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Sword, @@ -1003,7 +1003,7 @@ item: "common.items.modular.weapon.primary.sword.ornate", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1100,18 +1100,6 @@ item: "common.items.modular.weapon.primary.axe.jagged", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Axe, - item: "common.items.modular.weapon.primary.axe.jagged", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -1123,13 +1111,25 @@ toolkind: Axe, item: "common.items.modular.weapon.primary.axe.jagged", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Axe, + item: "common.items.modular.weapon.primary.axe.jagged", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Axe, @@ -1148,7 +1148,7 @@ item: "common.items.modular.weapon.primary.axe.jagged", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1172,18 +1172,6 @@ item: "common.items.modular.weapon.primary.axe.battleaxe", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Axe, - item: "common.items.modular.weapon.primary.axe.battleaxe", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -1195,13 +1183,25 @@ toolkind: Axe, item: "common.items.modular.weapon.primary.axe.battleaxe", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Axe, + item: "common.items.modular.weapon.primary.axe.battleaxe", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Axe, @@ -1220,7 +1220,7 @@ item: "common.items.modular.weapon.primary.axe.battleaxe", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1244,18 +1244,6 @@ item: "common.items.modular.weapon.primary.axe.poleaxe", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Axe, - item: "common.items.modular.weapon.primary.axe.poleaxe", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -1267,13 +1255,25 @@ toolkind: Axe, item: "common.items.modular.weapon.primary.axe.poleaxe", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Axe, + item: "common.items.modular.weapon.primary.axe.poleaxe", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Axe, @@ -1292,7 +1292,7 @@ item: "common.items.modular.weapon.primary.axe.poleaxe", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1316,18 +1316,6 @@ item: "common.items.modular.weapon.primary.axe.labrys", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Axe, - item: "common.items.modular.weapon.primary.axe.labrys", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -1339,13 +1327,25 @@ toolkind: Axe, item: "common.items.modular.weapon.primary.axe.labrys", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Axe, + item: "common.items.modular.weapon.primary.axe.labrys", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Axe, @@ -1364,7 +1364,7 @@ item: "common.items.modular.weapon.primary.axe.labrys", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1388,18 +1388,6 @@ item: "common.items.modular.weapon.primary.axe.greataxe", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Axe, - item: "common.items.modular.weapon.primary.axe.greataxe", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -1411,13 +1399,25 @@ toolkind: Axe, item: "common.items.modular.weapon.primary.axe.greataxe", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Axe, + item: "common.items.modular.weapon.primary.axe.greataxe", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Axe, @@ -1436,7 +1436,7 @@ item: "common.items.modular.weapon.primary.axe.greataxe", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1460,18 +1460,6 @@ item: "common.items.modular.weapon.primary.axe.ornate", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 2)), - additional_inputs: [ - (Item("common.items.tool.craftsman_hammer"), 0), - ], - craft_sprite: Some(Anvil), - ), - ( - output: ToolPrimaryComponent( - toolkind: Axe, - item: "common.items.modular.weapon.primary.axe.ornate", - ), - material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), @@ -1483,13 +1471,25 @@ toolkind: Axe, item: "common.items.modular.weapon.primary.axe.ornate", ), - material: ("common.items.mineral.ingot.cobalt", 5), + material: ("common.items.mineral.ingot.steel", 5), modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], craft_sprite: Some(Anvil), ), + ( + output: ToolPrimaryComponent( + toolkind: Axe, + item: "common.items.modular.weapon.primary.axe.ornate", + ), + material: ("common.items.mineral.ingot.cobalt", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), + additional_inputs: [ + (Item("common.items.tool.craftsman_hammer"), 0), + ], + craft_sprite: Some(Anvil), + ), ( output: ToolPrimaryComponent( toolkind: Axe, @@ -1508,7 +1508,7 @@ item: "common.items.modular.weapon.primary.axe.ornate", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 30)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1605,18 +1605,6 @@ item: "common.items.modular.weapon.primary.bow.composite", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.sticky_thread"), 3), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Bow, - item: "common.items.modular.weapon.primary.bow.composite", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), @@ -1628,13 +1616,25 @@ toolkind: Bow, item: "common.items.modular.weapon.primary.bow.composite", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Bow, + item: "common.items.modular.weapon.primary.bow.composite", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.sticky_thread"), 3), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Bow, @@ -1653,7 +1653,7 @@ item: "common.items.modular.weapon.primary.bow.composite", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 30)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1677,18 +1677,6 @@ item: "common.items.modular.weapon.primary.bow.greatbow", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.sticky_thread"), 3), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Bow, - item: "common.items.modular.weapon.primary.bow.greatbow", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), @@ -1700,13 +1688,25 @@ toolkind: Bow, item: "common.items.modular.weapon.primary.bow.greatbow", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Bow, + item: "common.items.modular.weapon.primary.bow.greatbow", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.sticky_thread"), 3), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Bow, @@ -1725,7 +1725,7 @@ item: "common.items.modular.weapon.primary.bow.greatbow", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 30)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1749,18 +1749,6 @@ item: "common.items.modular.weapon.primary.bow.longbow", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.sticky_thread"), 3), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Bow, - item: "common.items.modular.weapon.primary.bow.longbow", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), @@ -1772,13 +1760,25 @@ toolkind: Bow, item: "common.items.modular.weapon.primary.bow.longbow", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Bow, + item: "common.items.modular.weapon.primary.bow.longbow", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.sticky_thread"), 3), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Bow, @@ -1797,7 +1797,7 @@ item: "common.items.modular.weapon.primary.bow.longbow", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 30)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1821,18 +1821,6 @@ item: "common.items.modular.weapon.primary.bow.ornate", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.sticky_thread"), 3), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Bow, - item: "common.items.modular.weapon.primary.bow.ornate", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), @@ -1844,13 +1832,25 @@ toolkind: Bow, item: "common.items.modular.weapon.primary.bow.ornate", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Bow, + item: "common.items.modular.weapon.primary.bow.ornate", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.sticky_thread"), 3), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Bow, @@ -1869,7 +1869,7 @@ item: "common.items.modular.weapon.primary.bow.ornate", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 30)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1893,18 +1893,6 @@ item: "common.items.modular.weapon.primary.bow.shortbow", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.sticky_thread"), 3), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Bow, - item: "common.items.modular.weapon.primary.bow.shortbow", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), @@ -1916,13 +1904,25 @@ toolkind: Bow, item: "common.items.modular.weapon.primary.bow.shortbow", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Bow, + item: "common.items.modular.weapon.primary.bow.shortbow", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.sticky_thread"), 3), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Bow, @@ -1941,7 +1941,7 @@ item: "common.items.modular.weapon.primary.bow.shortbow", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 30)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1965,18 +1965,6 @@ item: "common.items.modular.weapon.primary.bow.warbow", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.sticky_thread"), 3), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Bow, - item: "common.items.modular.weapon.primary.bow.warbow", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), @@ -1988,13 +1976,25 @@ toolkind: Bow, item: "common.items.modular.weapon.primary.bow.warbow", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Bow, + item: "common.items.modular.weapon.primary.bow.warbow", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.sticky_thread"), 3), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Bow, @@ -2013,7 +2013,7 @@ item: "common.items.modular.weapon.primary.bow.warbow", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 30)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -2038,18 +2038,6 @@ item: "common.items.modular.weapon.primary.staff.brand", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.leather.leather_strips"), 2), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Staff, - item: "common.items.modular.weapon.primary.staff.brand", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), @@ -2061,13 +2049,25 @@ toolkind: Staff, item: "common.items.modular.weapon.primary.staff.brand", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Staff, + item: "common.items.modular.weapon.primary.staff.brand", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.leather.leather_strips"), 2), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Staff, @@ -2086,7 +2086,7 @@ item: "common.items.modular.weapon.primary.staff.brand", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 30)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2110,18 +2110,6 @@ item: "common.items.modular.weapon.primary.staff.grandstaff", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.leather.leather_strips"), 2), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Staff, - item: "common.items.modular.weapon.primary.staff.grandstaff", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), @@ -2133,13 +2121,25 @@ toolkind: Staff, item: "common.items.modular.weapon.primary.staff.grandstaff", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Staff, + item: "common.items.modular.weapon.primary.staff.grandstaff", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.leather.leather_strips"), 2), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Staff, @@ -2158,7 +2158,7 @@ item: "common.items.modular.weapon.primary.staff.grandstaff", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 30)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2182,18 +2182,6 @@ item: "common.items.modular.weapon.primary.staff.longpole", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.leather.leather_strips"), 2), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Staff, - item: "common.items.modular.weapon.primary.staff.longpole", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), @@ -2205,13 +2193,25 @@ toolkind: Staff, item: "common.items.modular.weapon.primary.staff.longpole", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Staff, + item: "common.items.modular.weapon.primary.staff.longpole", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.leather.leather_strips"), 2), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Staff, @@ -2230,7 +2230,7 @@ item: "common.items.modular.weapon.primary.staff.longpole", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 30)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2254,18 +2254,6 @@ item: "common.items.modular.weapon.primary.staff.ornate", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.leather.leather_strips"), 2), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Staff, - item: "common.items.modular.weapon.primary.staff.ornate", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), @@ -2277,13 +2265,25 @@ toolkind: Staff, item: "common.items.modular.weapon.primary.staff.ornate", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Staff, + item: "common.items.modular.weapon.primary.staff.ornate", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.leather.leather_strips"), 2), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Staff, @@ -2302,7 +2302,7 @@ item: "common.items.modular.weapon.primary.staff.ornate", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 30)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2326,18 +2326,6 @@ item: "common.items.modular.weapon.primary.staff.pole", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.leather.leather_strips"), 2), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Staff, - item: "common.items.modular.weapon.primary.staff.pole", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), @@ -2349,13 +2337,25 @@ toolkind: Staff, item: "common.items.modular.weapon.primary.staff.pole", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Staff, + item: "common.items.modular.weapon.primary.staff.pole", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.leather.leather_strips"), 2), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Staff, @@ -2374,7 +2374,7 @@ item: "common.items.modular.weapon.primary.staff.pole", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 30)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2398,18 +2398,6 @@ item: "common.items.modular.weapon.primary.staff.rod", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.leather.leather_strips"), 2), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Staff, - item: "common.items.modular.weapon.primary.staff.rod", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), @@ -2421,13 +2409,25 @@ toolkind: Staff, item: "common.items.modular.weapon.primary.staff.rod", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Staff, + item: "common.items.modular.weapon.primary.staff.rod", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.leather.leather_strips"), 2), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Staff, @@ -2446,7 +2446,7 @@ item: "common.items.modular.weapon.primary.staff.rod", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 30)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2543,18 +2543,6 @@ item: "common.items.modular.weapon.primary.sceptre.arbor", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.leather.leather_strips"), 2), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Sceptre, - item: "common.items.modular.weapon.primary.sceptre.arbor", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), @@ -2566,13 +2554,25 @@ toolkind: Sceptre, item: "common.items.modular.weapon.primary.sceptre.arbor", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Sceptre, + item: "common.items.modular.weapon.primary.sceptre.arbor", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.leather.leather_strips"), 2), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Sceptre, @@ -2591,7 +2591,7 @@ item: "common.items.modular.weapon.primary.sceptre.arbor", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 30)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2615,18 +2615,6 @@ item: "common.items.modular.weapon.primary.sceptre.cane", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.leather.leather_strips"), 2), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Sceptre, - item: "common.items.modular.weapon.primary.sceptre.cane", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), @@ -2638,13 +2626,25 @@ toolkind: Sceptre, item: "common.items.modular.weapon.primary.sceptre.cane", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Sceptre, + item: "common.items.modular.weapon.primary.sceptre.cane", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.leather.leather_strips"), 2), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Sceptre, @@ -2663,7 +2663,7 @@ item: "common.items.modular.weapon.primary.sceptre.cane", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 30)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2687,18 +2687,6 @@ item: "common.items.modular.weapon.primary.sceptre.crook", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.leather.leather_strips"), 2), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Sceptre, - item: "common.items.modular.weapon.primary.sceptre.crook", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), @@ -2710,13 +2698,25 @@ toolkind: Sceptre, item: "common.items.modular.weapon.primary.sceptre.crook", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Sceptre, + item: "common.items.modular.weapon.primary.sceptre.crook", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.leather.leather_strips"), 2), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Sceptre, @@ -2735,7 +2735,7 @@ item: "common.items.modular.weapon.primary.sceptre.crook", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 30)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2759,18 +2759,6 @@ item: "common.items.modular.weapon.primary.sceptre.crozier", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.leather.leather_strips"), 2), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Sceptre, - item: "common.items.modular.weapon.primary.sceptre.crozier", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), @@ -2782,13 +2770,25 @@ toolkind: Sceptre, item: "common.items.modular.weapon.primary.sceptre.crozier", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Sceptre, + item: "common.items.modular.weapon.primary.sceptre.crozier", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.leather.leather_strips"), 2), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Sceptre, @@ -2807,7 +2807,7 @@ item: "common.items.modular.weapon.primary.sceptre.crozier", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 30)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2831,18 +2831,6 @@ item: "common.items.modular.weapon.primary.sceptre.grandsceptre", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.leather.leather_strips"), 2), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Sceptre, - item: "common.items.modular.weapon.primary.sceptre.grandsceptre", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), @@ -2854,13 +2842,25 @@ toolkind: Sceptre, item: "common.items.modular.weapon.primary.sceptre.grandsceptre", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Sceptre, + item: "common.items.modular.weapon.primary.sceptre.grandsceptre", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.leather.leather_strips"), 2), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Sceptre, @@ -2879,7 +2879,7 @@ item: "common.items.modular.weapon.primary.sceptre.grandsceptre", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 30)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2903,18 +2903,6 @@ item: "common.items.modular.weapon.primary.sceptre.ornate", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 2)), - additional_inputs: [ - (Item("common.items.crafting_ing.leather.leather_strips"), 2), - ], - craft_sprite: Some(CraftingBench), - ), - ( - output: ToolPrimaryComponent( - toolkind: Sceptre, - item: "common.items.modular.weapon.primary.sceptre.ornate", - ), - material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), @@ -2926,13 +2914,25 @@ toolkind: Sceptre, item: "common.items.modular.weapon.primary.sceptre.ornate", ), - material: ("common.items.log.ironwood", 5), + material: ("common.items.log.hardwood", 5), modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], craft_sprite: Some(CraftingBench), ), + ( + output: ToolPrimaryComponent( + toolkind: Sceptre, + item: "common.items.modular.weapon.primary.sceptre.ornate", + ), + material: ("common.items.log.ironwood", 5), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), + additional_inputs: [ + (Item("common.items.crafting_ing.leather.leather_strips"), 2), + ], + craft_sprite: Some(CraftingBench), + ), ( output: ToolPrimaryComponent( toolkind: Sceptre, @@ -2951,7 +2951,7 @@ item: "common.items.modular.weapon.primary.sceptre.ornate", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 50)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 30)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], From c09f070241b047a2932d10682c358081c946a151 Mon Sep 17 00:00:00 2001 From: N A Date: Sun, 29 May 2022 23:53:00 +0000 Subject: [PATCH 030/229] Change animal species to have only one inventory slot --- common/src/comp/inventory/mod.rs | 23 +++++++++++-- common/src/comp/inventory/test.rs | 32 +++++++++---------- common/src/states/basic_summon.rs | 2 +- server/src/character_creator.rs | 2 +- server/src/cmd.rs | 4 +-- server/src/events/player.rs | 2 +- server/src/events/trade.rs | 4 +-- server/src/persistence/character.rs | 2 +- .../src/persistence/character/conversions.rs | 2 +- server/src/state_ext.rs | 4 +-- server/src/sys/terrain.rs | 2 +- .../audio/sfx/event_mapper/combat/tests.rs | 10 +++--- voxygen/src/menu/char_selection/ui/mod.rs | 2 +- 13 files changed, 55 insertions(+), 36 deletions(-) diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index 37c4e33070..e5cdaa2988 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -8,6 +8,7 @@ use vek::Vec3; use crate::{ comp::{ + body::Body, inventory::{ item::{tool::AbilityMap, ItemDef, ItemKind, MaterialStatManifest, TagExampleInfo}, loadout::Loadout, @@ -80,9 +81,19 @@ impl InventorySortOrder { /// that contains items etc) must first ensure items are unloaded from the item. /// This is handled in `inventory\slot.rs` impl Inventory { - pub fn new_empty() -> Inventory { Self::new_with_loadout(LoadoutBuilder::empty().build()) } + pub fn with_empty() -> Inventory { + Self::with_loadout_humanoid(LoadoutBuilder::empty().build()) + } - pub fn new_with_loadout(loadout: Loadout) -> Inventory { + pub fn with_loadout(loadout: Loadout, body: Body) -> Inventory { + if let Body::Humanoid(_) = body { + Self::with_loadout_humanoid(loadout) + } else { + Self::with_loadout_animal(loadout) + } + } + + pub fn with_loadout_humanoid(loadout: Loadout) -> Inventory { Inventory { next_sort_order: InventorySortOrder::Name, loadout, @@ -90,6 +101,14 @@ impl Inventory { } } + pub fn with_loadout_animal(loadout: Loadout) -> Inventory { + Inventory { + next_sort_order: InventorySortOrder::Name, + loadout, + slots: vec![None; 1], + } + } + /// Total number of slots in in the inventory. pub fn capacity(&self) -> usize { self.slots().count() } diff --git a/common/src/comp/inventory/test.rs b/common/src/comp/inventory/test.rs index e65d9748ec..c7d7e65b1e 100644 --- a/common/src/comp/inventory/test.rs +++ b/common/src/comp/inventory/test.rs @@ -124,7 +124,7 @@ fn push_all_unique_empty() { fn free_slots_minus_equipped_item_items_only_present_in_equipped_bag_slots() { let msm = &MaterialStatManifest::load().read(); let ability_map = &AbilityMap::load().read(); - let mut inv = Inventory::new_empty(); + let mut inv = Inventory::with_empty(); let bag = get_test_bag(18); let bag1_slot = EquipSlot::Armor(ArmorSlot::Bag1); @@ -144,7 +144,7 @@ fn free_slots_minus_equipped_item_items_only_present_in_equipped_bag_slots() { fn free_slots_minus_equipped_item() { let msm = &MaterialStatManifest::load().read(); let ability_map = &AbilityMap::load().read(); - let mut inv = Inventory::new_empty(); + let mut inv = Inventory::with_empty(); let bag = get_test_bag(18); let bag1_slot = EquipSlot::Armor(ArmorSlot::Bag1); @@ -166,7 +166,7 @@ fn free_slots_minus_equipped_item() { #[test] fn get_slot_range_for_equip_slot() { - let mut inv = Inventory::new_empty(); + let mut inv = Inventory::with_empty(); let bag = get_test_bag(18); let bag1_slot = EquipSlot::Armor(ArmorSlot::Bag1); inv.loadout.swap(bag1_slot, Some(bag)); @@ -196,7 +196,7 @@ fn can_swap_equipped_bag_into_empty_inv_slot( inv_slot_id: InvSlotId, expected_result: bool, ) { - let mut inv = Inventory::new_empty(); + let mut inv = Inventory::with_empty(); inv.replace_loadout_item(EquipSlot::Armor(ArmorSlot::Bag1), Some(get_test_bag(18))); @@ -209,7 +209,7 @@ fn can_swap_equipped_bag_into_empty_inv_slot( #[test] fn can_swap_equipped_bag_into_only_empty_slot_provided_by_itself_should_return_true() { - let mut inv = Inventory::new_empty(); + let mut inv = Inventory::with_empty(); inv.replace_loadout_item(EquipSlot::Armor(ArmorSlot::Bag1), Some(get_test_bag(18))); @@ -224,7 +224,7 @@ fn can_swap_equipped_bag_into_only_empty_slot_provided_by_itself_should_return_t fn unequip_items_both_hands() { let msm = &MaterialStatManifest::load().read(); let ability_map = &AbilityMap::load().read(); - let mut inv = Inventory::new_empty(); + let mut inv = Inventory::with_empty(); let sword = Item::new_from_asset_expect("common.items.weapons.sword.starter"); @@ -267,7 +267,7 @@ fn equip_replace_already_equipped_item() { "common.items.armor.misc.foot.sandals", )); - let mut inv = Inventory::new_empty(); + let mut inv = Inventory::with_empty(); inv.push(boots.duplicate(ability_map, msm)).unwrap(); inv.replace_loadout_item( EquipSlot::Armor(ArmorSlot::Feet), @@ -294,7 +294,7 @@ fn equip_replace_already_equipped_item() { /// after equipping it (because the equipped bag is larger) #[test] fn equip_equipping_smaller_bag_from_last_slot_of_big_bag() { - let mut inv = Inventory::new_empty(); + let mut inv = Inventory::with_empty(); const LARGE_BAG_ID: &str = "common.items.testing.test_bag_18_slot"; let small_bag = get_test_bag(9); @@ -322,7 +322,7 @@ fn equip_equipping_smaller_bag_from_last_slot_of_big_bag() { #[test] fn unequip_unequipping_bag_into_its_own_slot_with_no_other_free_slots_returns_one_item() { - let mut inv = Inventory::new_empty(); + let mut inv = Inventory::with_empty(); let bag = get_test_bag(9); assert!( @@ -350,7 +350,7 @@ fn unequip_unequipping_bag_into_its_own_slot_with_no_other_free_slots_returns_on fn equip_one_bag_equipped_equip_second_bag() { let msm = &MaterialStatManifest::load().read(); let ability_map = &AbilityMap::load().read(); - let mut inv = Inventory::new_empty(); + let mut inv = Inventory::with_empty(); let bag = get_test_bag(9); assert!( @@ -371,7 +371,7 @@ fn equip_one_bag_equipped_equip_second_bag() { #[test] fn free_after_swap_equipped_item_has_more_slots() { - let mut inv = Inventory::new_empty(); + let mut inv = Inventory::with_empty(); let bag = get_test_bag(18); assert!( @@ -394,7 +394,7 @@ fn free_after_swap_equipped_item_has_more_slots() { #[test] fn free_after_swap_equipped_item_has_less_slots() { - let mut inv = Inventory::new_empty(); + let mut inv = Inventory::with_empty(); let bag = get_test_bag(9); assert!( @@ -417,7 +417,7 @@ fn free_after_swap_equipped_item_has_less_slots() { #[test] fn free_after_swap_equipped_item_with_slots_swapped_with_empty_inv_slot() { - let mut inv = Inventory::new_empty(); + let mut inv = Inventory::with_empty(); let bag = get_test_bag(9); assert!( @@ -437,7 +437,7 @@ fn free_after_swap_equipped_item_with_slots_swapped_with_empty_inv_slot() { #[test] fn free_after_swap_inv_item_with_slots_swapped_with_empty_equip_slot() { - let mut inv = Inventory::new_empty(); + let mut inv = Inventory::with_empty(); inv.push(get_test_bag(9)).unwrap(); @@ -452,7 +452,7 @@ fn free_after_swap_inv_item_with_slots_swapped_with_empty_equip_slot() { #[test] fn free_after_swap_inv_item_without_slots_swapped_with_empty_equip_slot() { - let mut inv = Inventory::new_empty(); + let mut inv = Inventory::with_empty(); let boots = Item::new_from_asset_expect("common.items.testing.test_boots"); inv.push(boots).unwrap(); @@ -471,7 +471,7 @@ fn free_after_swap_inv_item_without_slots_swapped_with_empty_equip_slot() { // provide slots. #[test] fn backpack_crash() { - let mut inv = Inventory::new_empty(); + let mut inv = Inventory::with_empty(); let backpack = Item::new_from_asset_expect("common.items.armor.misc.back.backpack"); inv.loadout diff --git a/common/src/states/basic_summon.rs b/common/src/states/basic_summon.rs index 317e4b183f..ba77b32bd7 100644 --- a/common/src/states/basic_summon.rs +++ b/common/src/states/basic_summon.rs @@ -179,7 +179,7 @@ impl CharacterBehavior for Data { skill_set, health, poise: comp::Poise::new(body), - inventory: comp::Inventory::new_with_loadout(loadout), + inventory: comp::Inventory::with_loadout(loadout, body), body, agent: Some( comp::Agent::from_body(&body) diff --git a/server/src/character_creator.rs b/server/src/character_creator.rs index e1cfbf0541..96c3d5cbc2 100644 --- a/server/src/character_creator.rs +++ b/server/src/character_creator.rs @@ -50,7 +50,7 @@ pub fn create_character( .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 mut inventory = Inventory::with_loadout_humanoid(loadout); let stats = Stats::new(character_alias.to_string()); let skill_set = SkillSet::default(); // Default items for new characters diff --git a/server/src/cmd.rs b/server/src/cmd.rs index eba2cc0870..f631b728f6 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -1201,7 +1201,7 @@ fn handle_spawn( let body = body(); let loadout = LoadoutBuilder::from_default(&body).build(); - let inventory = Inventory::new_with_loadout(loadout); + let inventory = Inventory::with_loadout(loadout, body); let mut entity_base = server .state @@ -1293,7 +1293,7 @@ fn handle_spawn_training_dummy( skill_set, Some(health), poise, - Inventory::new_empty(), + Inventory::with_empty(), body, ) .with(comp::Vel(vel)) diff --git a/server/src/events/player.rs b/server/src/events/player.rs index 5fdc6616ae..0f63e53625 100644 --- a/server/src/events/player.rs +++ b/server/src/events/player.rs @@ -447,7 +447,7 @@ pub fn handle_possess(server: &mut Server, possessor_uid: Uid, possessee_uid: Ui let mut inventory = inventories .entry(possessee) .expect("Nobody has &mut World, so there's no way to delete an entity.") - .or_insert(Inventory::new_empty()); + .or_insert(Inventory::with_empty()); let debug_item = comp::Item::new_from_asset_expect("common.items.debug.admin_stick"); if let item::ItemKind::Tool(_) = &*debug_item.kind() { diff --git a/server/src/events/trade.rs b/server/src/events/trade.rs index e2bad21292..aa239aad24 100644 --- a/server/src/events/trade.rs +++ b/server/src/events/trade.rs @@ -428,12 +428,12 @@ mod tests { let player: EcsEntity = mockworld .create_entity() - .with(Inventory::new_empty()) + .with(Inventory::with_empty()) .build(); let merchant: EcsEntity = mockworld .create_entity() - .with(Inventory::new_empty()) + .with(Inventory::with_empty()) .build(); { diff --git a/server/src/persistence/character.rs b/server/src/persistence/character.rs index 943dabff96..5d79df0d5e 100644 --- a/server/src/persistence/character.rs +++ b/server/src/persistence/character.rs @@ -339,7 +339,7 @@ pub fn load_character_list(player_uuid_: &str, connection: &Connection) -> Chara Ok(CharacterItem { character: char, body: char_body, - inventory: Inventory::new_with_loadout(loadout), + inventory: Inventory::with_loadout_humanoid(loadout), }) }) .collect() diff --git a/server/src/persistence/character/conversions.rs b/server/src/persistence/character/conversions.rs index 21cdd22b82..23b6da224d 100644 --- a/server/src/persistence/character/conversions.rs +++ b/server/src/persistence/character/conversions.rs @@ -349,7 +349,7 @@ pub fn convert_inventory_from_database_items( // inventory at the correct position. // let loadout = convert_loadout_from_database_items(loadout_container_id, loadout_items)?; - let mut inventory = Inventory::new_with_loadout(loadout); + let mut inventory = Inventory::with_loadout_humanoid(loadout); let mut item_indices = HashMap::new(); // In order to items with components to properly load, it is important that this diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs index ef99603136..602b05855a 100644 --- a/server/src/state_ext.rs +++ b/server/src/state_ext.rs @@ -306,7 +306,7 @@ impl StateExt for State { .with(body) .with(comp::Scale(comp::ship::AIRSHIP_SCALE)) .with(comp::Controller::default()) - .with(comp::inventory::Inventory::new_empty()) + .with(comp::inventory::Inventory::with_empty()) .with(comp::CharacterState::default()) // TODO: some of these are required in order for the character_behavior system to // recognize a possesed airship; that system should be refactored to use `.maybe()` @@ -597,7 +597,7 @@ impl StateExt for State { comp::SkillSet::default(), Some(comp::Health::new(body, DEFAULT_PET_HEALTH_LEVEL)), Poise::new(body), - Inventory::new_empty(), + Inventory::with_empty(), body, ) .with(comp::Scale(1.0)) diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index 967c20c2e5..7dda1c5a52 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -389,7 +389,7 @@ impl NpcData { loadout_builder = loadout_builder.with_creator(make_loadout, economy.as_ref()); } let loadout = loadout_builder.build(); - let mut inventory = comp::inventory::Inventory::new_with_loadout(loadout); + let mut inventory = comp::inventory::Inventory::with_loadout(loadout, body); for (num, mut item) in items { if let Err(e) = item.set_amount(num) { tracing::warn!( diff --git a/voxygen/src/audio/sfx/event_mapper/combat/tests.rs b/voxygen/src/audio/sfx/event_mapper/combat/tests.rs index f4b4e89e38..b3b0b0eac8 100644 --- a/voxygen/src/audio/sfx/event_mapper/combat/tests.rs +++ b/voxygen/src/audio/sfx/event_mapper/combat/tests.rs @@ -17,7 +17,7 @@ fn maps_wield_while_equipping() { "common.items.weapons.axe.starter_axe", ))) .build(); - let inventory = Inventory::new_with_loadout(loadout); + let inventory = Inventory::with_loadout_humanoid(loadout); let result = CombatEventMapper::map_event( &CharacterState::Equipping(states::equipping::Data { @@ -45,7 +45,7 @@ fn maps_unwield() { "common.items.weapons.bow.starter", ))) .build(); - let inventory = Inventory::new_with_loadout(loadout); + let inventory = Inventory::with_loadout_humanoid(loadout); let result = CombatEventMapper::map_event( &CharacterState::default(), @@ -67,7 +67,7 @@ fn maps_basic_melee() { "common.items.weapons.axe.starter_axe", ))) .build(); - let inventory = Inventory::new_with_loadout(loadout); + let inventory = Inventory::with_loadout_humanoid(loadout); let result = CombatEventMapper::map_event( &CharacterState::BasicMelee(states::basic_melee::Data { @@ -118,7 +118,7 @@ fn matches_ability_stage() { "common.items.weapons.sword.starter", ))) .build(); - let inventory = Inventory::new_with_loadout(loadout); + let inventory = Inventory::with_loadout_humanoid(loadout); let result = CombatEventMapper::map_event( &CharacterState::ComboMelee(states::combo_melee::Data { @@ -180,7 +180,7 @@ fn ignores_different_ability_stage() { "common.items.weapons.axe.starter_axe", ))) .build(); - let inventory = Inventory::new_with_loadout(loadout); + let inventory = Inventory::with_loadout_humanoid(loadout); let result = CombatEventMapper::map_event( &CharacterState::ComboMelee(states::combo_melee::Data { diff --git a/voxygen/src/menu/char_selection/ui/mod.rs b/voxygen/src/menu/char_selection/ui/mod.rs index aa3d948f07..5108630834 100644 --- a/voxygen/src/menu/char_selection/ui/mod.rs +++ b/voxygen/src/menu/char_selection/ui/mod.rs @@ -202,7 +202,7 @@ impl Mode { .active_offhand(offhand.map(Item::new_from_asset_expect)) .build(); - let inventory = Box::new(Inventory::new_with_loadout(loadout)); + let inventory = Box::new(Inventory::with_loadout_humanoid(loadout)); Self::CreateOrEdit { name, From 4a2cdd08d4b9d2fb7cbbdf69b61cc19ab905daf8 Mon Sep 17 00:00:00 2001 From: Makselord Date: Mon, 30 May 2022 09:56:17 -0400 Subject: [PATCH 031/229] modular weapon modifier costs changed to 1, 2, 5, 10, 15, 25 --- assets/common/component_recipe_book.ron | 360 ++++++++++++------------ 1 file changed, 180 insertions(+), 180 deletions(-) diff --git a/assets/common/component_recipe_book.ron b/assets/common/component_recipe_book.ron index fc5f4a5290..08aa8992cc 100644 --- a/assets/common/component_recipe_book.ron +++ b/assets/common/component_recipe_book.ron @@ -90,7 +90,7 @@ item: "common.items.modular.weapon.primary.hammer.spikedmace", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -102,7 +102,7 @@ item: "common.items.modular.weapon.primary.hammer.spikedmace", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -114,7 +114,7 @@ item: "common.items.modular.weapon.primary.hammer.spikedmace", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -126,7 +126,7 @@ item: "common.items.modular.weapon.primary.hammer.spikedmace", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -138,7 +138,7 @@ item: "common.items.modular.weapon.primary.hammer.spikedmace", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -162,7 +162,7 @@ item: "common.items.modular.weapon.primary.hammer.warhammer", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -174,7 +174,7 @@ item: "common.items.modular.weapon.primary.hammer.warhammer", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -186,7 +186,7 @@ item: "common.items.modular.weapon.primary.hammer.warhammer", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -198,7 +198,7 @@ item: "common.items.modular.weapon.primary.hammer.warhammer", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -210,7 +210,7 @@ item: "common.items.modular.weapon.primary.hammer.warhammer", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -234,7 +234,7 @@ item: "common.items.modular.weapon.primary.hammer.maul", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -246,7 +246,7 @@ item: "common.items.modular.weapon.primary.hammer.maul", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -258,7 +258,7 @@ item: "common.items.modular.weapon.primary.hammer.maul", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -270,7 +270,7 @@ item: "common.items.modular.weapon.primary.hammer.maul", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -282,7 +282,7 @@ item: "common.items.modular.weapon.primary.hammer.maul", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -306,7 +306,7 @@ item: "common.items.modular.weapon.primary.hammer.greatmace", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -318,7 +318,7 @@ item: "common.items.modular.weapon.primary.hammer.greatmace", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -330,7 +330,7 @@ item: "common.items.modular.weapon.primary.hammer.greatmace", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -342,7 +342,7 @@ item: "common.items.modular.weapon.primary.hammer.greatmace", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -354,7 +354,7 @@ item: "common.items.modular.weapon.primary.hammer.greatmace", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -378,7 +378,7 @@ item: "common.items.modular.weapon.primary.hammer.greathammer", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -390,7 +390,7 @@ item: "common.items.modular.weapon.primary.hammer.greathammer", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -402,7 +402,7 @@ item: "common.items.modular.weapon.primary.hammer.greathammer", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -414,7 +414,7 @@ item: "common.items.modular.weapon.primary.hammer.greathammer", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -426,7 +426,7 @@ item: "common.items.modular.weapon.primary.hammer.greathammer", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -450,7 +450,7 @@ item: "common.items.modular.weapon.primary.hammer.ornate", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -462,7 +462,7 @@ item: "common.items.modular.weapon.primary.hammer.ornate", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -474,7 +474,7 @@ item: "common.items.modular.weapon.primary.hammer.ornate", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -486,7 +486,7 @@ item: "common.items.modular.weapon.primary.hammer.ornate", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -498,7 +498,7 @@ item: "common.items.modular.weapon.primary.hammer.ornate", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -595,7 +595,7 @@ item: "common.items.modular.weapon.primary.sword.sawblade", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -607,7 +607,7 @@ item: "common.items.modular.weapon.primary.sword.sawblade", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -619,7 +619,7 @@ item: "common.items.modular.weapon.primary.sword.sawblade", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -631,7 +631,7 @@ item: "common.items.modular.weapon.primary.sword.sawblade", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -643,7 +643,7 @@ item: "common.items.modular.weapon.primary.sword.sawblade", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -667,7 +667,7 @@ item: "common.items.modular.weapon.primary.sword.katana", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -679,7 +679,7 @@ item: "common.items.modular.weapon.primary.sword.katana", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -691,7 +691,7 @@ item: "common.items.modular.weapon.primary.sword.katana", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -703,7 +703,7 @@ item: "common.items.modular.weapon.primary.sword.katana", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -715,7 +715,7 @@ item: "common.items.modular.weapon.primary.sword.katana", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -739,7 +739,7 @@ item: "common.items.modular.weapon.primary.sword.zweihander", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -751,7 +751,7 @@ item: "common.items.modular.weapon.primary.sword.zweihander", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -763,7 +763,7 @@ item: "common.items.modular.weapon.primary.sword.zweihander", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -775,7 +775,7 @@ item: "common.items.modular.weapon.primary.sword.zweihander", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -787,7 +787,7 @@ item: "common.items.modular.weapon.primary.sword.zweihander", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -811,7 +811,7 @@ item: "common.items.modular.weapon.primary.sword.sabre", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -823,7 +823,7 @@ item: "common.items.modular.weapon.primary.sword.sabre", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -835,7 +835,7 @@ item: "common.items.modular.weapon.primary.sword.sabre", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -847,7 +847,7 @@ item: "common.items.modular.weapon.primary.sword.sabre", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -859,7 +859,7 @@ item: "common.items.modular.weapon.primary.sword.sabre", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -883,7 +883,7 @@ item: "common.items.modular.weapon.primary.sword.greatsword", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -895,7 +895,7 @@ item: "common.items.modular.weapon.primary.sword.greatsword", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -907,7 +907,7 @@ item: "common.items.modular.weapon.primary.sword.greatsword", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -919,7 +919,7 @@ item: "common.items.modular.weapon.primary.sword.greatsword", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -931,7 +931,7 @@ item: "common.items.modular.weapon.primary.sword.greatsword", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -955,7 +955,7 @@ item: "common.items.modular.weapon.primary.sword.ornate", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -967,7 +967,7 @@ item: "common.items.modular.weapon.primary.sword.ornate", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -979,7 +979,7 @@ item: "common.items.modular.weapon.primary.sword.ornate", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -991,7 +991,7 @@ item: "common.items.modular.weapon.primary.sword.ornate", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1003,7 +1003,7 @@ item: "common.items.modular.weapon.primary.sword.ornate", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1100,7 +1100,7 @@ item: "common.items.modular.weapon.primary.axe.jagged", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1112,7 +1112,7 @@ item: "common.items.modular.weapon.primary.axe.jagged", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1124,7 +1124,7 @@ item: "common.items.modular.weapon.primary.axe.jagged", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1136,7 +1136,7 @@ item: "common.items.modular.weapon.primary.axe.jagged", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1148,7 +1148,7 @@ item: "common.items.modular.weapon.primary.axe.jagged", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1172,7 +1172,7 @@ item: "common.items.modular.weapon.primary.axe.battleaxe", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1184,7 +1184,7 @@ item: "common.items.modular.weapon.primary.axe.battleaxe", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1196,7 +1196,7 @@ item: "common.items.modular.weapon.primary.axe.battleaxe", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1208,7 +1208,7 @@ item: "common.items.modular.weapon.primary.axe.battleaxe", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1220,7 +1220,7 @@ item: "common.items.modular.weapon.primary.axe.battleaxe", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1244,7 +1244,7 @@ item: "common.items.modular.weapon.primary.axe.poleaxe", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1256,7 +1256,7 @@ item: "common.items.modular.weapon.primary.axe.poleaxe", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1268,7 +1268,7 @@ item: "common.items.modular.weapon.primary.axe.poleaxe", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1280,7 +1280,7 @@ item: "common.items.modular.weapon.primary.axe.poleaxe", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1292,7 +1292,7 @@ item: "common.items.modular.weapon.primary.axe.poleaxe", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1316,7 +1316,7 @@ item: "common.items.modular.weapon.primary.axe.labrys", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1328,7 +1328,7 @@ item: "common.items.modular.weapon.primary.axe.labrys", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1340,7 +1340,7 @@ item: "common.items.modular.weapon.primary.axe.labrys", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1352,7 +1352,7 @@ item: "common.items.modular.weapon.primary.axe.labrys", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1364,7 +1364,7 @@ item: "common.items.modular.weapon.primary.axe.labrys", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1388,7 +1388,7 @@ item: "common.items.modular.weapon.primary.axe.greataxe", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1400,7 +1400,7 @@ item: "common.items.modular.weapon.primary.axe.greataxe", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1412,7 +1412,7 @@ item: "common.items.modular.weapon.primary.axe.greataxe", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1424,7 +1424,7 @@ item: "common.items.modular.weapon.primary.axe.greataxe", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1436,7 +1436,7 @@ item: "common.items.modular.weapon.primary.axe.greataxe", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1460,7 +1460,7 @@ item: "common.items.modular.weapon.primary.axe.ornate", ), material: ("common.items.mineral.ingot.iron", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 2)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1472,7 +1472,7 @@ item: "common.items.modular.weapon.primary.axe.ornate", ), material: ("common.items.mineral.ingot.steel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1484,7 +1484,7 @@ item: "common.items.modular.weapon.primary.axe.ornate", ), material: ("common.items.mineral.ingot.cobalt", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1496,7 +1496,7 @@ item: "common.items.modular.weapon.primary.axe.ornate", ), material: ("common.items.mineral.ingot.bloodsteel", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1508,7 +1508,7 @@ item: "common.items.modular.weapon.primary.axe.ornate", ), material: ("common.items.mineral.ingot.orichalcum", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 25)), additional_inputs: [ (Item("common.items.tool.craftsman_hammer"), 0), ], @@ -1605,7 +1605,7 @@ item: "common.items.modular.weapon.primary.bow.composite", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 2)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1617,7 +1617,7 @@ item: "common.items.modular.weapon.primary.bow.composite", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1629,7 +1629,7 @@ item: "common.items.modular.weapon.primary.bow.composite", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1641,7 +1641,7 @@ item: "common.items.modular.weapon.primary.bow.composite", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1653,7 +1653,7 @@ item: "common.items.modular.weapon.primary.bow.composite", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 25)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1677,7 +1677,7 @@ item: "common.items.modular.weapon.primary.bow.greatbow", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 2)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1689,7 +1689,7 @@ item: "common.items.modular.weapon.primary.bow.greatbow", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1701,7 +1701,7 @@ item: "common.items.modular.weapon.primary.bow.greatbow", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1713,7 +1713,7 @@ item: "common.items.modular.weapon.primary.bow.greatbow", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1725,7 +1725,7 @@ item: "common.items.modular.weapon.primary.bow.greatbow", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 25)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1749,7 +1749,7 @@ item: "common.items.modular.weapon.primary.bow.longbow", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 2)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1761,7 +1761,7 @@ item: "common.items.modular.weapon.primary.bow.longbow", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1773,7 +1773,7 @@ item: "common.items.modular.weapon.primary.bow.longbow", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1785,7 +1785,7 @@ item: "common.items.modular.weapon.primary.bow.longbow", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1797,7 +1797,7 @@ item: "common.items.modular.weapon.primary.bow.longbow", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 25)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1821,7 +1821,7 @@ item: "common.items.modular.weapon.primary.bow.ornate", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 2)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1833,7 +1833,7 @@ item: "common.items.modular.weapon.primary.bow.ornate", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1845,7 +1845,7 @@ item: "common.items.modular.weapon.primary.bow.ornate", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1857,7 +1857,7 @@ item: "common.items.modular.weapon.primary.bow.ornate", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1869,7 +1869,7 @@ item: "common.items.modular.weapon.primary.bow.ornate", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 25)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1893,7 +1893,7 @@ item: "common.items.modular.weapon.primary.bow.shortbow", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 2)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1905,7 +1905,7 @@ item: "common.items.modular.weapon.primary.bow.shortbow", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1917,7 +1917,7 @@ item: "common.items.modular.weapon.primary.bow.shortbow", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1929,7 +1929,7 @@ item: "common.items.modular.weapon.primary.bow.shortbow", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1941,7 +1941,7 @@ item: "common.items.modular.weapon.primary.bow.shortbow", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 25)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1965,7 +1965,7 @@ item: "common.items.modular.weapon.primary.bow.warbow", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 2)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1977,7 +1977,7 @@ item: "common.items.modular.weapon.primary.bow.warbow", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -1989,7 +1989,7 @@ item: "common.items.modular.weapon.primary.bow.warbow", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -2001,7 +2001,7 @@ item: "common.items.modular.weapon.primary.bow.warbow", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -2013,7 +2013,7 @@ item: "common.items.modular.weapon.primary.bow.warbow", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 25)), additional_inputs: [ (Item("common.items.crafting_ing.sticky_thread"), 3), ], @@ -2038,7 +2038,7 @@ item: "common.items.modular.weapon.primary.staff.brand", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 2)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2050,7 +2050,7 @@ item: "common.items.modular.weapon.primary.staff.brand", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2062,7 +2062,7 @@ item: "common.items.modular.weapon.primary.staff.brand", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2074,7 +2074,7 @@ item: "common.items.modular.weapon.primary.staff.brand", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2086,7 +2086,7 @@ item: "common.items.modular.weapon.primary.staff.brand", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 25)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2110,7 +2110,7 @@ item: "common.items.modular.weapon.primary.staff.grandstaff", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 2)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2122,7 +2122,7 @@ item: "common.items.modular.weapon.primary.staff.grandstaff", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2134,7 +2134,7 @@ item: "common.items.modular.weapon.primary.staff.grandstaff", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2146,7 +2146,7 @@ item: "common.items.modular.weapon.primary.staff.grandstaff", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2158,7 +2158,7 @@ item: "common.items.modular.weapon.primary.staff.grandstaff", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 25)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2182,7 +2182,7 @@ item: "common.items.modular.weapon.primary.staff.longpole", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 2)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2194,7 +2194,7 @@ item: "common.items.modular.weapon.primary.staff.longpole", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2206,7 +2206,7 @@ item: "common.items.modular.weapon.primary.staff.longpole", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2218,7 +2218,7 @@ item: "common.items.modular.weapon.primary.staff.longpole", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2230,7 +2230,7 @@ item: "common.items.modular.weapon.primary.staff.longpole", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 25)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2254,7 +2254,7 @@ item: "common.items.modular.weapon.primary.staff.ornate", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 2)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2266,7 +2266,7 @@ item: "common.items.modular.weapon.primary.staff.ornate", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2278,7 +2278,7 @@ item: "common.items.modular.weapon.primary.staff.ornate", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2290,7 +2290,7 @@ item: "common.items.modular.weapon.primary.staff.ornate", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2302,7 +2302,7 @@ item: "common.items.modular.weapon.primary.staff.ornate", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 25)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2326,7 +2326,7 @@ item: "common.items.modular.weapon.primary.staff.pole", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 2)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2338,7 +2338,7 @@ item: "common.items.modular.weapon.primary.staff.pole", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2350,7 +2350,7 @@ item: "common.items.modular.weapon.primary.staff.pole", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2362,7 +2362,7 @@ item: "common.items.modular.weapon.primary.staff.pole", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2374,7 +2374,7 @@ item: "common.items.modular.weapon.primary.staff.pole", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 25)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2398,7 +2398,7 @@ item: "common.items.modular.weapon.primary.staff.rod", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 2)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2410,7 +2410,7 @@ item: "common.items.modular.weapon.primary.staff.rod", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2422,7 +2422,7 @@ item: "common.items.modular.weapon.primary.staff.rod", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2434,7 +2434,7 @@ item: "common.items.modular.weapon.primary.staff.rod", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2446,7 +2446,7 @@ item: "common.items.modular.weapon.primary.staff.rod", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 25)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2543,7 +2543,7 @@ item: "common.items.modular.weapon.primary.sceptre.arbor", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 2)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2555,7 +2555,7 @@ item: "common.items.modular.weapon.primary.sceptre.arbor", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2567,7 +2567,7 @@ item: "common.items.modular.weapon.primary.sceptre.arbor", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2579,7 +2579,7 @@ item: "common.items.modular.weapon.primary.sceptre.arbor", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 15)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2591,7 +2591,7 @@ item: "common.items.modular.weapon.primary.sceptre.arbor", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.long_tusk", 25)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2615,7 +2615,7 @@ item: "common.items.modular.weapon.primary.sceptre.cane", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 2)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2627,7 +2627,7 @@ item: "common.items.modular.weapon.primary.sceptre.cane", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2639,7 +2639,7 @@ item: "common.items.modular.weapon.primary.sceptre.cane", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2651,7 +2651,7 @@ item: "common.items.modular.weapon.primary.sceptre.cane", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 15)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2663,7 +2663,7 @@ item: "common.items.modular.weapon.primary.sceptre.cane", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.strong_pincer", 25)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2687,7 +2687,7 @@ item: "common.items.modular.weapon.primary.sceptre.crook", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 2)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2699,7 +2699,7 @@ item: "common.items.modular.weapon.primary.sceptre.crook", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2711,7 +2711,7 @@ item: "common.items.modular.weapon.primary.sceptre.crook", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2723,7 +2723,7 @@ item: "common.items.modular.weapon.primary.sceptre.crook", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 15)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2735,7 +2735,7 @@ item: "common.items.modular.weapon.primary.sceptre.crook", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.sharp_fang", 25)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2759,7 +2759,7 @@ item: "common.items.modular.weapon.primary.sceptre.crozier", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 2)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2771,7 +2771,7 @@ item: "common.items.modular.weapon.primary.sceptre.crozier", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2783,7 +2783,7 @@ item: "common.items.modular.weapon.primary.sceptre.crozier", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2795,7 +2795,7 @@ item: "common.items.modular.weapon.primary.sceptre.crozier", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 15)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2807,7 +2807,7 @@ item: "common.items.modular.weapon.primary.sceptre.crozier", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.claw", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.claw", 25)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2831,7 +2831,7 @@ item: "common.items.modular.weapon.primary.sceptre.grandsceptre", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 2)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2843,7 +2843,7 @@ item: "common.items.modular.weapon.primary.sceptre.grandsceptre", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2855,7 +2855,7 @@ item: "common.items.modular.weapon.primary.sceptre.grandsceptre", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2867,7 +2867,7 @@ item: "common.items.modular.weapon.primary.sceptre.grandsceptre", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 15)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2879,7 +2879,7 @@ item: "common.items.modular.weapon.primary.sceptre.grandsceptre", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.large_horn", 25)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2903,7 +2903,7 @@ item: "common.items.modular.weapon.primary.sceptre.ornate", ), material: ("common.items.log.bamboo", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 2)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2915,7 +2915,7 @@ item: "common.items.modular.weapon.primary.sceptre.ornate", ), material: ("common.items.log.hardwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 5)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2927,7 +2927,7 @@ item: "common.items.modular.weapon.primary.sceptre.ornate", ), material: ("common.items.log.ironwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 10)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2939,7 +2939,7 @@ item: "common.items.modular.weapon.primary.sceptre.ornate", ), material: ("common.items.log.frostwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 20)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 15)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], @@ -2951,7 +2951,7 @@ item: "common.items.modular.weapon.primary.sceptre.ornate", ), material: ("common.items.log.eldwood", 5), - modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 30)), + modifier: Some(("common.items.crafting_ing.animal_misc.elegant_crest", 25)), additional_inputs: [ (Item("common.items.crafting_ing.leather.leather_strips"), 2), ], From 8df31180943f62b6c7ed8c75b18d9c44afcaa337 Mon Sep 17 00:00:00 2001 From: Makselord Date: Mon, 30 May 2022 10:08:22 -0400 Subject: [PATCH 032/229] updated changelog in accordance with 2nd change --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7608934693..37d3ecf330 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Stealth effects from sneaking and armor are evaluated independently. Armor now has effects even when not sneaking - Zoom-in effect when aiming bow is now optional - Non-Humanoid NPCs now pick up consumables when less than full health and use them to heal up. -- Changed module component modifier costs to the following scheme, based on base material: 1 -> 5 -> 10 -> 15 -> 20 -> 30 +- Changed module component modifier costs to the following scheme, based on base material: 1 -> 2 -> 5 -> 10 -> 15 -> 25 ### Removed From 99a992d985510667008c6c513911e80b83dc447d Mon Sep 17 00:00:00 2001 From: Ben Wallis Date: Mon, 30 May 2022 21:15:21 +0100 Subject: [PATCH 033/229] Added iproute2 and net-tools to docker image to facilitate diagnosing network issues --- server-cli/Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server-cli/Dockerfile b/server-cli/Dockerfile index 8bd818f1ac..e1ad116390 100644 --- a/server-cli/Dockerfile +++ b/server-cli/Dockerfile @@ -6,11 +6,14 @@ LABEL com.centurylinklabs.watchtower.stop-signal="SIGUSR1" ARG PROJECTNAME=server-cli # librust-backtrace+libbacktrace-dev = backtrace functionality +# iproute2 and net-tools for diagnostic purposes RUN apt-get update \ && export DEBIAN_FRONTEND=noninteractive \ && apt-get install -y --no-install-recommends --assume-yes \ ca-certificates \ librust-backtrace+libbacktrace-dev \ + iproute2 \ + net-tools \ && rm -rf /var/lib/apt/lists/*; COPY ./veloren-server-cli /opt/veloren-server-cli From 5e57eabd11515878d3d9a75110be391fe4a832f6 Mon Sep 17 00:00:00 2001 From: Sam Date: Sat, 28 May 2022 19:41:31 -0400 Subject: [PATCH 034/229] Code changes and msm --- .cargo/config | 1 + assets/common/material_stats_manifest.ron | 440 +++++++++++++++------ common/src/bin/csv_export/main.rs | 16 +- common/src/bin/csv_import/main.rs | 14 +- common/src/combat.rs | 61 +-- common/src/comp/inventory/item/armor.rs | 137 ++++--- common/src/comp/inventory/item/mod.rs | 4 +- common/src/comp/inventory/item/modular.rs | 32 +- common/src/comp/inventory/item/tool.rs | 15 - common/src/comp/inventory/loadout.rs | 2 +- common/src/comp/inventory/mod.rs | 2 +- common/src/comp/inventory/trade_pricing.rs | 6 +- common/src/comp/poise.rs | 17 +- common/src/states/utils.rs | 4 +- common/systems/src/buff.rs | 7 +- common/systems/src/stats.rs | 7 +- server/src/events/entity_manipulation.rs | 7 +- server/src/lib.rs | 2 +- server/src/state_ext.rs | 5 +- server/src/sys/agent.rs | 3 +- server/src/sys/agent/data.rs | 8 +- voxygen/src/hud/bag.rs | 17 +- voxygen/src/hud/diary.rs | 17 +- voxygen/src/hud/util.rs | 14 +- voxygen/src/session/mod.rs | 4 +- voxygen/src/ui/widgets/item_tooltip.rs | 174 ++++---- 26 files changed, 660 insertions(+), 356 deletions(-) diff --git a/.cargo/config b/.cargo/config index 041039b191..e9a85dd6aa 100644 --- a/.cargo/config +++ b/.cargo/config @@ -21,3 +21,4 @@ tracy-voxygen = "run --bin veloren-voxygen --no-default-features --features trac dbg-voxygen = "run --bin veloren-voxygen --profile debuginfo" # misc swarm = "run --bin swarm --features client/bin_bot,client/tick_network --" +ci-clippy = "clippy --all-targets --locked --features=bin_cmd_doc_gen,bin_compression,bin_csv,bin_graphviz,bin_bot,bin_asset_migrate,asset_tweak" \ No newline at end of file diff --git a/assets/common/material_stats_manifest.ron b/assets/common/material_stats_manifest.ron index 92b2c7b0d3..aaf8057352 100644 --- a/assets/common/material_stats_manifest.ron +++ b/assets/common/material_stats_manifest.ron @@ -1,125 +1,317 @@ // Keep in mind that material stats are multiplied by the form stats, not added (e.g. equip_time_secs is most sensitive to this) -({ - // Metals - "common.items.mineral.ingot.bronze": ( - equip_time_secs: 1.0, - power: 0.75, - effect_power: 1.0, - speed: 1.0, - crit_chance: 1.0, - range: 1.0, - energy_efficiency: 1.0, - buff_strength: 1.0, - ), - "common.items.mineral.ingot.iron": ( - equip_time_secs: 1.0, - power: 1.0, - effect_power: 1.0, - speed: 1.0, - crit_chance: 1.0, - range: 1.0, - energy_efficiency: 1.0, - buff_strength: 1.0, - ), - "common.items.mineral.ingot.steel": ( - equip_time_secs: 1.0, - power: 1.25, - effect_power: 1.0, - speed: 1.0, - crit_chance: 1.0, - range: 1.0, - energy_efficiency: 1.0, - buff_strength: 1.0, - ), - "common.items.mineral.ingot.cobalt": ( - equip_time_secs: 1.0, - power: 1.5, - effect_power: 1.0, - speed: 1.0, - crit_chance: 1.0, - range: 1.0, - energy_efficiency: 1.0, - buff_strength: 1.0, - ), - "common.items.mineral.ingot.bloodsteel": ( - equip_time_secs: 1.0, - power: 1.75, - effect_power: 1.0, - speed: 1.0, - crit_chance: 1.0, - range: 1.0, - energy_efficiency: 1.0, - buff_strength: 1.0, - ), - "common.items.mineral.ingot.orichalcum": ( - equip_time_secs: 1.0, - power: 2.0, - effect_power: 1.0, - speed: 1.0, - crit_chance: 1.0, - range: 1.0, - energy_efficiency: 1.0, - buff_strength: 1.0, - ), - // Woods - "common.items.log.wood": ( - equip_time_secs: 1.0, - power: 0.75, - effect_power: 1.0, - speed: 1.0, - crit_chance: 1.0, - range: 1.0, - energy_efficiency: 1.0, - buff_strength: 1.0, - ), - "common.items.log.bamboo": ( - equip_time_secs: 1.0, - power: 1.0, - effect_power: 1.0, - speed: 1.0, - crit_chance: 1.0, - range: 1.0, - energy_efficiency: 1.0, - buff_strength: 1.0, - ), - "common.items.log.hardwood": ( - equip_time_secs: 1.0, - power: 1.25, - effect_power: 1.0, - speed: 1.0, - crit_chance: 1.0, - range: 1.0, - energy_efficiency: 1.0, - buff_strength: 1.0, - ), - "common.items.log.ironwood": ( - equip_time_secs: 1.0, - power: 1.5, - effect_power: 1.0, - speed: 1.0, - crit_chance: 1.0, - range: 1.0, - energy_efficiency: 1.0, - buff_strength: 1.0, - ), - "common.items.log.frostwood": ( - equip_time_secs: 1.0, - power: 1.75, - effect_power: 1.0, - speed: 1.0, - crit_chance: 1.0, - range: 1.0, - energy_efficiency: 1.0, - buff_strength: 1.0, - ), - "common.items.log.eldwood": ( - equip_time_secs: 1.0, - power: 2.0, - effect_power: 1.0, - speed: 1.0, - crit_chance: 1.0, - range: 1.0, - energy_efficiency: 1.0, - buff_strength: 1.0, - ), -}) +( + tool_stats: { + // Metals + "common.items.mineral.ingot.bronze": ( + equip_time_secs: 1.0, + power: 0.75, + effect_power: 1.0, + speed: 1.0, + crit_chance: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + "common.items.mineral.ingot.iron": ( + equip_time_secs: 1.0, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + "common.items.mineral.ingot.steel": ( + equip_time_secs: 1.0, + power: 1.25, + effect_power: 1.0, + speed: 1.0, + crit_chance: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + "common.items.mineral.ingot.cobalt": ( + equip_time_secs: 1.0, + power: 1.5, + effect_power: 1.0, + speed: 1.0, + crit_chance: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + "common.items.mineral.ingot.bloodsteel": ( + equip_time_secs: 1.0, + power: 1.75, + effect_power: 1.0, + speed: 1.0, + crit_chance: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + "common.items.mineral.ingot.orichalcum": ( + equip_time_secs: 1.0, + power: 2.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + // Woods + "common.items.log.wood": ( + equip_time_secs: 1.0, + power: 0.75, + effect_power: 1.0, + speed: 1.0, + crit_chance: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + "common.items.log.bamboo": ( + equip_time_secs: 1.0, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + "common.items.log.hardwood": ( + equip_time_secs: 1.0, + power: 1.25, + effect_power: 1.0, + speed: 1.0, + crit_chance: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + "common.items.log.ironwood": ( + equip_time_secs: 1.0, + power: 1.5, + effect_power: 1.0, + speed: 1.0, + crit_chance: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + "common.items.log.frostwood": ( + equip_time_secs: 1.0, + power: 1.75, + effect_power: 1.0, + speed: 1.0, + crit_chance: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + "common.items.log.eldwood": ( + equip_time_secs: 1.0, + power: 2.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + }, + armor_stats: { + // Metals + "common.items.mineral.ingot.bronze": ( + protection: Some(Normal(40.0)), + poise_resilience: Some(Normal(10.0)), + ), + "common.items.mineral.ingot.iron": ( + protection: Some(Normal(80.0)), + poise_resilience: Some(Normal(20.0)), + ), + "common.items.mineral.ingot.steel": ( + protection: Some(Normal(120.0)), + poise_resilience: Some(Normal(30.0)), + ), + "common.items.mineral.ingot.cobalt": ( + protection: Some(Normal(160.0)), + poise_resilience: Some(Normal(40.0)), + ), + "common.items.mineral.ingot.bloodsteel": ( + protection: Some(Normal(200.0)), + poise_resilience: Some(Normal(50.0)), + ), + "common.items.mineral.ingot.orichalcum": ( + protection: Some(Normal(240.0)), + poise_resilience: Some(Normal(60.0)), + ), + // Hides + "common.items.crafting_ing.leather.simple_leather": ( + protection: Some(Normal(20.0)), + crit_power: Some(0.333), + stealth: Some(0.333), + ), + "common.items.crafting_ing.leather.thick_leather": ( + protection: Some(Normal(40.0)), + crit_power: Some(0.667), + stealth: Some(0.667), + ), + "common.items.crafting_ing.hide.scales": ( + protection: Some(Normal(60.0)), + crit_power: Some(1.0), + stealth: Some(1.0), + ), + "common.items.crafting_ing.hide.carapace": ( + protection: Some(Normal(80.0)), + crit_power: Some(1.33), + stealth: Some(1.33), + ), + "common.items.crafting_ing.hide.plate": ( + protection: Some(Normal(100.0)), + crit_power: Some(1.67), + stealth: Some(1.67), + ), + "common.items.crafting_ing.hide.dragon_scale": ( + protection: Some(Normal(120.0)), + crit_power: Some(2.0), + stealth: Some(2.0), + ), + // Cloths + "common.items.crafting_ing.cloth.linen": ( + protection: Some(Normal(15.0)), + energy_max: Some(16.7), + energy_reward: Some(0.167), + stealth: Some(0.167), + ), + "common.items.crafting_ing.cloth.wool": ( + protection: Some(Normal(30.0)), + energy_max: Some(33.3), + energy_reward: Some(0.333), + stealth: Some(0.333), + ), + "common.items.crafting_ing.cloth.silk": ( + protection: Some(Normal(45.0)), + energy_max: Some(50.0), + energy_reward: Some(0.5), + stealth: Some(0.5), + ), + "common.items.crafting_ing.cloth.lifecloth": ( + protection: Some(Normal(60.0)), + energy_max: Some(66.7), + energy_reward: Some(0.667), + stealth: Some(0.667), + ), + "common.items.crafting_ing.cloth.moonweave": ( + protection: Some(Normal(75.0)), + energy_max: Some(83.3), + energy_reward: Some(0.833), + stealth: Some(0.833), + ), + "common.items.crafting_ing.cloth.sunsilk": ( + protection: Some(Normal(90.0)), + energy_max: Some(100.0), + energy_reward: Some(1.0), + stealth: Some(1.0), + ), + // Pseudo materials + "common.items.modular.pseudo_material.alchemist": ( + protection: Some(Normal(160.0)), + poise_resilience: Some(Normal(20.0)), + energy_max: Some(45.0), + energy_reward: Some(0.5), + crit_power: Some(0.4), + ), + "common.items.modular.pseudo_material.assassin": ( + protection: Some(Normal(50.0)), + poise_resilience: Some(Normal(5.0)), + ), + "common.items.modular.pseudo_material.blacksmith": ( + protection: Some(Normal(160.0)), + poise_resilience: Some(Normal(20.0)), + energy_max: Some(45.0), + energy_reward: Some(0.5), + crit_power: Some(0.4), + ), + "common.items.modular.pseudo_material.bonerattler": ( + protection: Some(Normal(100.0)), + ), + "common.items.modular.pseudo_material.chef": ( + protection: Some(Normal(160.0)), + poise_resilience: Some(Normal(20.0)), + energy_max: Some(45.0), + energy_reward: Some(0.5), + crit_power: Some(0.4), + ), + "common.items.modular.pseudo_material.cloth_blue": ( + protection: Some(Normal(5.0)), + ), + "common.items.modular.pseudo_material.cloth_green": ( + protection: Some(Normal(5.0)), + ), + "common.items.modular.pseudo_material.cloth_purple": ( + protection: Some(Normal(5.0)), + ), + "common.items.modular.pseudo_material.cultist": ( + protection: Some(Normal(150.0)), + poise_resilience: Some(Normal(20.0)), + energy_max: Some(45.0), + energy_reward: Some(0.5), + crit_power: Some(0.4), + stealth: Some(0.4), + ), + "common.items.modular.pseudo_material.ferocious": ( + protection: Some(Normal(240.0)), + ), + "common.items.modular.pseudo_material.leather_plate": ( + protection: Some(Normal(160.0)), + poise_resilience: Some(Normal(40.0)), + ), + "common.items.modular.pseudo_material.merchant": ( + protection: Some(Normal(160.0)), + poise_resilience: Some(Normal(20.0)), + energy_max: Some(45.0), + energy_reward: Some(0.5), + crit_power: Some(0.4), + ), + "common.items.modular.pseudo_material.pirate": ( + protection: Some(Normal(160.0)), + poise_resilience: Some(Normal(20.0)), + energy_max: Some(45.0), + energy_reward: Some(0.5), + crit_power: Some(0.4), + ), + "common.items.modular.pseudo_material.rugged": ( + protection: Some(Normal(5.0)), + ), + "common.items.modular.pseudo_material.savage": ( + protection: Some(Normal(100.0)), + ), + "common.items.modular.pseudo_material.tarasque": ( + protection: Some(Normal(100.0)), + ), + "common.items.modular.pseudo_material.twigs": ( + protection: Some(Normal(60.0)), + ), + "common.items.modular.pseudo_material.twigsflowers": ( + protection: Some(Normal(60.0)), + ), + "common.items.modular.pseudo_material.twigsleaves": ( + protection: Some(Normal(60.0)), + ), + "common.items.modular.pseudo_material.velorite_mage": ( + protection: Some(Normal(115.0)), + ), + "common.items.modular.pseudo_material.witch": ( + protection: Some(Normal(160.0)), + poise_resilience: Some(Normal(20.0)), + energy_max: Some(45.0), + energy_reward: Some(0.5), + crit_power: Some(0.4), + ), + }, +) diff --git a/common/src/bin/csv_export/main.rs b/common/src/bin/csv_export/main.rs index edd19ad409..ab90b814b3 100644 --- a/common/src/bin/csv_export/main.rs +++ b/common/src/bin/csv_export/main.rs @@ -14,7 +14,7 @@ use veloren_common::{ item::{ armor::{ArmorKind, Protection}, tool::{Hands, Tool, ToolKind}, - Item, + Item, MaterialStatManifest, }, }, generation::{EntityConfig, EntityInfo}, @@ -56,20 +56,22 @@ fn armor_stats() -> Result<(), Box> { continue; } - let protection = match armor.protection() { + let msm = &MaterialStatManifest::load().read(); + + let protection = match armor.stats(msm).protection { Some(Protection::Invincible) => "Invincible".to_string(), Some(Protection::Normal(value)) => value.to_string(), None => "0.0".to_string(), }; - let poise_resilience = match armor.poise_resilience() { + let poise_resilience = match armor.stats(msm).poise_resilience { Some(Protection::Invincible) => "Invincible".to_string(), Some(Protection::Normal(value)) => value.to_string(), None => "0.0".to_string(), }; - let max_energy = armor.energy_max().unwrap_or(0.0).to_string(); - let energy_reward = armor.energy_reward().unwrap_or(0.0).to_string(); - let crit_power = armor.crit_power().unwrap_or(0.0).to_string(); - let stealth = armor.stealth().unwrap_or(0.0).to_string(); + let max_energy = armor.stats(msm).energy_max.unwrap_or(0.0).to_string(); + let energy_reward = armor.stats(msm).energy_reward.unwrap_or(0.0).to_string(); + let crit_power = armor.stats(msm).crit_power.unwrap_or(0.0).to_string(); + let stealth = armor.stats(msm).stealth.unwrap_or(0.0).to_string(); wtr.write_record(&[ item.item_definition_id() diff --git a/common/src/bin/csv_import/main.rs b/common/src/bin/csv_import/main.rs index 65f80d986c..f19ae44b37 100644 --- a/common/src/bin/csv_import/main.rs +++ b/common/src/bin/csv_import/main.rs @@ -12,7 +12,7 @@ use veloren_common::{ comp::{ self, item::{ - armor::{ArmorKind, Protection}, + armor::{ArmorKind, Protection, StatsSource}, tool::{AbilitySpec, Hands, Stats, ToolKind}, ItemDefinitionId, ItemKind, ItemTag, Material, Quality, }, @@ -124,7 +124,7 @@ fn armor_stats() -> Result<(), Box> { None }; - let max_energy = + let energy_max = if let Some(max_energy_raw) = record.get(headers["Max Energy"]) { let value = max_energy_raw.parse().unwrap(); if value == 0.0 { None } else { Some(value) } @@ -174,15 +174,19 @@ fn armor_stats() -> Result<(), Box> { }; let kind = armor.kind; - let armor_stats = comp::item::armor::Stats::new( + let armor_stats = comp::item::armor::Stats { protection, poise_resilience, - max_energy, + energy_max, energy_reward, crit_power, stealth, + ground_contact: Default::default(), + }; + let armor = comp::item::armor::Armor::new( + kind, + StatsSource::Direct(armor_stats), ); - let armor = comp::item::armor::Armor::new(kind, armor_stats); let quality = if let Some(quality_raw) = record.get(headers["Quality"]) { match quality_raw { diff --git a/common/src/combat.rs b/common/src/combat.rs index dfeae2e5cb..6a4ecf9aec 100644 --- a/common/src/combat.rs +++ b/common/src/combat.rs @@ -133,11 +133,12 @@ impl Attack { source: AttackSource, dir: Dir, damage: Damage, + msm: &MaterialStatManifest, mut emit: impl FnMut(ServerEvent), mut emit_outcome: impl FnMut(Outcome), ) -> f32 { let damage_reduction = - Damage::compute_damage_reduction(Some(damage), target.inventory, target.stats); + Damage::compute_damage_reduction(Some(damage), target.inventory, target.stats, msm); let block_reduction = match source { AttackSource::Melee => { if let (Some(CharacterState::BasicBlock(data)), Some(ori)) = @@ -186,6 +187,9 @@ impl Attack { mut emit: impl FnMut(ServerEvent), mut emit_outcome: impl FnMut(Outcome), ) -> bool { + // TODO: Maybe move this higher and pass it as argument into this function? + let msm = &MaterialStatManifest::load().read(); + let AttackOptions { target_dodging, may_harm, @@ -220,6 +224,7 @@ impl Attack { attack_source, dir, damage.damage, + msm, &mut emit, &mut emit_outcome, ); @@ -272,7 +277,7 @@ impl Attack { let reduced_damage = applied_damage * damage_reduction / (1.0 - damage_reduction); let poise = reduced_damage * CRUSHING_POISE_FRACTION; - let change = -Poise::apply_poise_reduction(poise, target.inventory); + let change = -Poise::apply_poise_reduction(poise, target.inventory, msm); let poise_change = PoiseChange { amount: change, impulse: *dir, @@ -307,7 +312,7 @@ impl Attack { emit(ServerEvent::EnergyChange { entity: attacker.entity, change: *ec - * compute_energy_reward_mod(attacker.inventory) + * compute_energy_reward_mod(attacker.inventory, msm) * strength_modifier, }); } @@ -342,7 +347,7 @@ impl Attack { } }, CombatEffect::Poise(p) => { - let change = -Poise::apply_poise_reduction(*p, target.inventory) + let change = -Poise::apply_poise_reduction(*p, target.inventory, msm) * strength_modifier; if change.abs() > Poise::POISE_EPSILON { let poise_change = PoiseChange { @@ -450,7 +455,7 @@ impl Attack { emit(ServerEvent::EnergyChange { entity: attacker.entity, change: ec - * compute_energy_reward_mod(attacker.inventory) + * compute_energy_reward_mod(attacker.inventory, msm) * strength_modifier, }); } @@ -485,8 +490,8 @@ impl Attack { } }, CombatEffect::Poise(p) => { - let change = - -Poise::apply_poise_reduction(p, target.inventory) * strength_modifier; + let change = -Poise::apply_poise_reduction(p, target.inventory, msm) + * strength_modifier; if change.abs() > Poise::POISE_EPSILON { let poise_change = PoiseChange { amount: change, @@ -755,8 +760,9 @@ impl Damage { damage: Option, inventory: Option<&Inventory>, stats: Option<&Stats>, + msm: &MaterialStatManifest, ) -> f32 { - let protection = compute_protection(inventory); + let protection = compute_protection(inventory, msm); let penetration = if let Some(damage) = damage { if let DamageKind::Piercing = damage.kind { @@ -1058,20 +1064,20 @@ pub fn combat_rating( // Normalized with a standard max health of 100 let health_rating = health.base_max() / 100.0 - / (1.0 - Damage::compute_damage_reduction(None, Some(inventory), None)).max(0.00001); + / (1.0 - Damage::compute_damage_reduction(None, Some(inventory), None, msm)).max(0.00001); // Normalized with a standard max energy of 100 and energy reward multiplier of // x1 - let energy_rating = (energy.base_max() + compute_max_energy_mod(Some(inventory))) / 100.0 - * compute_energy_reward_mod(Some(inventory)); + let energy_rating = (energy.base_max() + compute_max_energy_mod(Some(inventory), msm)) / 100.0 + * compute_energy_reward_mod(Some(inventory), msm); // Normalized with a standard max poise of 100 let poise_rating = poise.base_max() as f32 / 100.0 - / (1.0 - Poise::compute_poise_damage_reduction(inventory)).max(0.00001); + / (1.0 - Poise::compute_poise_damage_reduction(inventory, msm)).max(0.00001); // Normalized with a standard crit multiplier of 1.2 - let crit_rating = compute_crit_mult(Some(inventory)) / 1.2; + let crit_rating = compute_crit_mult(Some(inventory), msm) / 1.2; // Assumes a standard person has earned 20 skill points in the general skill // tree and 10 skill points for the weapon skill tree @@ -1100,14 +1106,14 @@ pub fn combat_rating( } #[cfg(not(target_arch = "wasm32"))] -pub fn compute_crit_mult(inventory: Option<&Inventory>) -> f32 { +pub fn compute_crit_mult(inventory: Option<&Inventory>, msm: &MaterialStatManifest) -> f32 { // Starts with a value of 1.25 when summing the stats from each armor piece, and // defaults to a value of 1.25 if no inventory is equipped inventory.map_or(1.25, |inv| { inv.equipped_items() .filter_map(|item| { if let ItemKind::Armor(armor) = &*item.kind() { - armor.crit_power() + armor.stats(msm).crit_power } else { None } @@ -1118,14 +1124,14 @@ pub fn compute_crit_mult(inventory: Option<&Inventory>) -> f32 { /// Computes the energy reward modifer from worn armor #[cfg(not(target_arch = "wasm32"))] -pub fn compute_energy_reward_mod(inventory: Option<&Inventory>) -> f32 { +pub fn compute_energy_reward_mod(inventory: Option<&Inventory>, msm: &MaterialStatManifest) -> f32 { // Starts with a value of 1.0 when summing the stats from each armor piece, and // defaults to a value of 1.0 if no inventory is present inventory.map_or(1.0, |inv| { inv.equipped_items() .filter_map(|item| { if let ItemKind::Armor(armor) = &*item.kind() { - armor.energy_reward() + armor.stats(msm).energy_reward } else { None } @@ -1137,13 +1143,13 @@ pub fn compute_energy_reward_mod(inventory: Option<&Inventory>) -> f32 { /// Computes the additive modifier that should be applied to max energy from the /// currently equipped items #[cfg(not(target_arch = "wasm32"))] -pub fn compute_max_energy_mod(inventory: Option<&Inventory>) -> f32 { +pub fn compute_max_energy_mod(inventory: Option<&Inventory>, msm: &MaterialStatManifest) -> f32 { // Defaults to a value of 0 if no inventory is present inventory.map_or(0.0, |inv| { inv.equipped_items() .filter_map(|item| { if let ItemKind::Armor(armor) = &*item.kind() { - armor.energy_max() + armor.stats(msm).energy_max } else { None } @@ -1158,10 +1164,11 @@ pub fn compute_max_energy_mod(inventory: Option<&Inventory>) -> f32 { pub fn perception_dist_multiplier_from_stealth( inventory: Option<&Inventory>, character_state: Option<&CharacterState>, + msm: &MaterialStatManifest, ) -> f32 { const SNEAK_MULTIPLIER: f32 = 0.7; - let item_stealth_multiplier = stealth_multiplier_from_items(inventory); + let item_stealth_multiplier = stealth_multiplier_from_items(inventory, msm); let is_sneaking = character_state.map_or(false, |state| state.is_stealthy()); let multiplier = item_stealth_multiplier * if is_sneaking { SNEAK_MULTIPLIER } else { 1.0 }; @@ -1170,12 +1177,15 @@ pub fn perception_dist_multiplier_from_stealth( } #[cfg(not(target_arch = "wasm32"))] -pub fn stealth_multiplier_from_items(inventory: Option<&Inventory>) -> f32 { +pub fn stealth_multiplier_from_items( + inventory: Option<&Inventory>, + msm: &MaterialStatManifest, +) -> f32 { let stealth_sum = inventory.map_or(0.0, |inv| { inv.equipped_items() .filter_map(|item| { if let ItemKind::Armor(armor) = &*item.kind() { - armor.stealth() + armor.stats(msm).stealth } else { None } @@ -1190,12 +1200,15 @@ pub fn stealth_multiplier_from_items(inventory: Option<&Inventory>) -> f32 { /// damage reduction applied to damage received by an entity None indicates that /// the armor equipped makes the entity invulnerable #[cfg(not(target_arch = "wasm32"))] -pub fn compute_protection(inventory: Option<&Inventory>) -> Option { +pub fn compute_protection( + inventory: Option<&Inventory>, + msm: &MaterialStatManifest, +) -> Option { inventory.map_or(Some(0.0), |inv| { inv.equipped_items() .filter_map(|item| { if let ItemKind::Armor(armor) = &*item.kind() { - armor.protection() + armor.stats(msm).protection } else { None } diff --git a/common/src/comp/inventory/item/armor.rs b/common/src/comp/inventory/item/armor.rs index ebdb2f8b61..26baf0152e 100644 --- a/common/src/comp/inventory/item/armor.rs +++ b/common/src/comp/inventory/item/armor.rs @@ -1,11 +1,15 @@ use crate::{ - comp::item::Rgb, + comp::item::{MaterialStatManifest, Rgb}, terrain::{Block, BlockKind}, }; use serde::{Deserialize, Serialize}; -use std::{cmp::Ordering, ops::Sub}; +use std::{ + cmp::Ordering, + ops::{Mul, Sub}, +}; +use strum::{EnumIter, IntoEnumIterator}; -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, EnumIter)] pub enum ArmorKind { Shoulder, Chest, @@ -69,66 +73,66 @@ impl Friction { } } -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Default)] pub struct Stats { /// Protection is non-linearly transformed (following summation) to a damage /// reduction using (prot / (60 + prot)) - protection: Option, + pub protection: Option, /// Poise protection is non-linearly transformed (following summation) to a /// poise damage reduction using (prot / (60 + prot)) - poise_resilience: Option, + pub poise_resilience: Option, /// Energy max is summed, and then applied directly to the max energy stat - energy_max: Option, + pub energy_max: Option, /// Energy recovery is summed, and then added to 1.0. When attacks reward /// energy, it is then multiplied by this value before the energy is /// rewarded. - energy_reward: Option, + pub energy_reward: Option, /// Crit power is summed, and then added to the default crit multiplier of /// 1.25. Damage is multiplied by this value when an attack crits. - crit_power: Option, + pub crit_power: Option, /// Stealth is summed along with the base stealth bonus (2.0), and then /// the agent's perception distance is divided by this value - stealth: Option, + pub stealth: Option, /// Ground contact type, mostly for shoes #[serde(default)] - ground_contact: Friction, + pub ground_contact: Friction, } impl Stats { - // DO NOT USE UNLESS YOU KNOW WHAT YOU ARE DOING - // Added for csv import of stats - pub fn new( - protection: Option, - poise_resilience: Option, - energy_max: Option, - energy_reward: Option, - crit_power: Option, - stealth: Option, - ) -> Self { - Self { - protection, - poise_resilience, - energy_max, - energy_reward, - crit_power, - stealth, + fn none() -> Self { + Stats { + protection: None, + poise_resilience: None, + energy_max: None, + energy_reward: None, + crit_power: None, + stealth: None, ground_contact: Friction::Normal, } } +} - pub fn protection(&self) -> Option { self.protection } +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub enum StatsSource { + Direct(Stats), + FromSet(String), +} - pub fn poise_resilience(&self) -> Option { self.poise_resilience } +impl Mul for Stats { + type Output = Self; - pub fn energy_max(&self) -> Option { self.energy_max } - - pub fn energy_reward(&self) -> Option { self.energy_reward } - - pub fn crit_power(&self) -> Option { self.crit_power } - - pub fn stealth(&self) -> Option { self.stealth } - - pub fn ground_contact(&self) -> Friction { self.ground_contact } + fn mul(self, val: f32) -> Self::Output { + Stats { + protection: self.protection.map(|a| a * val), + poise_resilience: self.poise_resilience.map(|a| a * val), + energy_max: self.energy_max.map(|a| a * val), + energy_reward: self.energy_reward.map(|a| a * val), + crit_power: self.crit_power.map(|a| a * val), + stealth: self.stealth.map(|a| a * val), + // There is nothing to multiply, it is just an enum + ground_contact: self.ground_contact, + } + } } impl Sub for Stats { @@ -177,6 +181,17 @@ impl Sub for Protection { } } +impl Mul for Protection { + type Output = Self; + + fn mul(self, val: f32) -> Self::Output { + match self { + Protection::Invincible => Protection::Invincible, + Protection::Normal(a) => Protection::Normal(a * val), + } + } +} + impl PartialOrd for Protection { fn partial_cmp(&self, other: &Self) -> Option { match (*self, *other) { @@ -191,25 +206,39 @@ impl PartialOrd for Protection { #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Armor { pub kind: ArmorKind, - pub stats: Stats, + stats: StatsSource, } impl Armor { - pub fn new(kind: ArmorKind, stats: Stats) -> Self { Self { kind, stats } } + pub fn new(kind: ArmorKind, stats: StatsSource) -> Self { Self { kind, stats } } - pub fn protection(&self) -> Option { self.stats.protection } + pub fn stats(&self, msm: &MaterialStatManifest) -> Stats { + match &self.stats { + StatsSource::Direct(stats) => *stats, + StatsSource::FromSet(set) => { + let set_stats = msm.armor_stats(set).unwrap_or_else(Stats::none); + let armor_kind_weight = |kind| match kind { + ArmorKind::Shoulder => 2.0, + ArmorKind::Chest => 3.0, + ArmorKind::Belt => 0.5, + ArmorKind::Hand => 1.0, + ArmorKind::Pants => 2.0, + ArmorKind::Foot => 1.0, + ArmorKind::Back => 0.5, + ArmorKind::Ring => 0.0, + ArmorKind::Neck => 0.0, + ArmorKind::Head => 0.0, + ArmorKind::Tabard => 0.0, + ArmorKind::Bag => 0.0, + }; - pub fn poise_resilience(&self) -> Option { self.stats.poise_resilience } + let armor_weights_sum: f32 = ArmorKind::iter().map(armor_kind_weight).sum(); + let multiplier = armor_kind_weight(self.kind) / armor_weights_sum; - pub fn energy_max(&self) -> Option { self.stats.energy_max } - - pub fn energy_reward(&self) -> Option { self.stats.energy_reward } - - pub fn crit_power(&self) -> Option { self.stats.crit_power } - - pub fn stealth(&self) -> Option { self.stats.stealth } - - pub fn ground_contact(&self) -> Friction { self.stats.ground_contact } + set_stats * multiplier + }, + } + } #[cfg(test)] pub fn test_armor( @@ -219,7 +248,7 @@ impl Armor { ) -> Armor { Armor { kind, - stats: Stats { + stats: StatsSource::Direct(Stats { protection: Some(protection), poise_resilience: Some(poise_resilience), energy_max: None, @@ -227,7 +256,7 @@ impl Armor { crit_power: None, stealth: None, ground_contact: Friction::Normal, - }, + }), } } } diff --git a/common/src/comp/inventory/item/mod.rs b/common/src/comp/inventory/item/mod.rs index 57643ebec5..450d556ea9 100644 --- a/common/src/comp/inventory/item/mod.rs +++ b/common/src/comp/inventory/item/mod.rs @@ -4,8 +4,8 @@ pub mod modular; pub mod tool; // Reexports -pub use modular::{ModularBase, ModularComponent}; -pub use tool::{AbilitySet, AbilitySpec, Hands, MaterialStatManifest, Tool, ToolKind}; +pub use modular::{MaterialStatManifest, ModularBase, ModularComponent}; +pub use tool::{AbilitySet, AbilitySpec, Hands, Tool, ToolKind}; use crate::{ assets::{self, AssetExt, BoxedError, Error}, diff --git a/common/src/comp/inventory/item/modular.rs b/common/src/comp/inventory/item/modular.rs index 84be27f07b..a984020c8c 100644 --- a/common/src/comp/inventory/item/modular.rs +++ b/common/src/comp/inventory/item/modular.rs @@ -1,8 +1,12 @@ use super::{ - tool::{self, AbilityMap, AbilitySpec, Hands, MaterialStatManifest}, + armor, + tool::{self, AbilityMap, AbilitySpec, Hands}, Item, ItemBase, ItemDef, ItemDesc, ItemKind, ItemTag, Material, Quality, ToolKind, }; -use crate::{assets::AssetExt, recipe}; +use crate::{ + assets::{self, Asset, AssetExt, AssetHandle}, + recipe, +}; use common_base::dev_panic; use hashbrown::HashMap; use lazy_static::lazy_static; @@ -20,6 +24,28 @@ macro_rules! modular_item_id_prefix { }; } +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct MaterialStatManifest { + tool_stats: HashMap, + armor_stats: HashMap, +} + +impl MaterialStatManifest { + pub fn load() -> AssetHandle { Self::load_expect("common.material_stats_manifest") } + + pub fn armor_stats(&self, key: &str) -> Option { + self.armor_stats.get(key).copied() + } +} + +// This could be a Compound that also loads the keys, but the RecipeBook +// Compound impl already does that, so checking for existence here is redundant. +impl Asset for MaterialStatManifest { + type Loader = assets::RonLoader; + + const EXTENSION: &'static str = "ron"; +} + #[derive(Clone, Debug, Serialize, Deserialize)] pub enum ModularBase { Tool, @@ -241,7 +267,7 @@ impl ModularComponent { .filter_map(|comp| { comp.item_definition_id() .itemdef_id() - .and_then(|id| msm.0.get(id)) + .and_then(|id| msm.tool_stats.get(id)) .copied() .zip(Some(1)) }) diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index f4891688aa..ed61131771 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -225,21 +225,6 @@ impl DivAssign for Stats { fn div_assign(&mut self, scalar: usize) { *self = *self / (scalar as f32); } } -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct MaterialStatManifest(pub HashMap); - -impl MaterialStatManifest { - pub fn load() -> AssetHandle { Self::load_expect("common.material_stats_manifest") } -} - -// This could be a Compound that also loads the keys, but the RecipeBook -// Compound impl already does that, so checking for existence here is redundant. -impl Asset for MaterialStatManifest { - type Loader = assets::RonLoader; - - const EXTENSION: &'static str = "ron"; -} - #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Tool { pub kind: ToolKind, diff --git a/common/src/comp/inventory/loadout.rs b/common/src/comp/inventory/loadout.rs index 7b3dfb1aab..dd2eee1bc8 100644 --- a/common/src/comp/inventory/loadout.rs +++ b/common/src/comp/inventory/loadout.rs @@ -408,7 +408,7 @@ impl Loadout { pub fn persistence_update_all_item_states( &mut self, ability_map: &item::tool::AbilityMap, - msm: &item::tool::MaterialStatManifest, + msm: &item::MaterialStatManifest, ) { self.slots.iter_mut().for_each(|slot| { if let Some(item) = &mut slot.slot { diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index e5cdaa2988..c62ac0f735 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -808,7 +808,7 @@ impl Inventory { pub fn persistence_update_all_item_states( &mut self, ability_map: &item::tool::AbilityMap, - msm: &item::tool::MaterialStatManifest, + msm: &item::MaterialStatManifest, ) { self.slots_mut().for_each(|slot| { if let Some(item) = slot { diff --git a/common/src/comp/inventory/trade_pricing.rs b/common/src/comp/inventory/trade_pricing.rs index 95d295d70a..e1f73c0ce6 100644 --- a/common/src/comp/inventory/trade_pricing.rs +++ b/common/src/comp/inventory/trade_pricing.rs @@ -686,14 +686,16 @@ impl TradePricing { #[cfg(test)] fn print_sorted(&self) { - use crate::comp::item::{armor, ItemKind}; + use crate::comp::item::{armor, ItemKind, MaterialStatManifest}; println!("Item, ForSale, Amount, Good, Quality, Deal, Unit,"); fn more_information(i: &Item, p: f32) -> (String, &'static str) { + let msm = &MaterialStatManifest::load().read(); + if let ItemKind::Armor(a) = &*i.kind() { ( - match a.protection() { + match a.stats(msm).protection { Some(armor::Protection::Invincible) => "Invincible".into(), Some(armor::Protection::Normal(x)) => format!("{:.4}", x * p), None => "0.0".into(), diff --git a/common/src/comp/poise.rs b/common/src/comp/poise.rs index dcc20e7416..fa36a0e452 100644 --- a/common/src/comp/poise.rs +++ b/common/src/comp/poise.rs @@ -2,7 +2,7 @@ use crate::{ combat::{DamageContributor, DamageSource}, comp::{ self, - inventory::item::{armor::Protection, ItemKind}, + inventory::item::{armor::Protection, ItemKind, MaterialStatManifest}, CharacterState, Inventory, }, resources::Time, @@ -226,12 +226,15 @@ impl Poise { } /// Returns the total poise damage reduction provided by all equipped items - pub fn compute_poise_damage_reduction(inventory: &Inventory) -> f32 { + pub fn compute_poise_damage_reduction( + inventory: &Inventory, + msm: &MaterialStatManifest, + ) -> f32 { let protection = inventory .equipped_items() .filter_map(|item| { if let ItemKind::Armor(armor) = &*item.kind() { - armor.poise_resilience() + armor.stats(msm).poise_resilience } else { None } @@ -249,9 +252,13 @@ impl Poise { /// Modifies a poise change when optionally given an inventory to aid in /// calculation of poise damage reduction - pub fn apply_poise_reduction(value: f32, inventory: Option<&Inventory>) -> f32 { + pub fn apply_poise_reduction( + value: f32, + inventory: Option<&Inventory>, + msm: &MaterialStatManifest, + ) -> f32 { inventory.map_or(value, |inv| { - value * (1.0 - Poise::compute_poise_damage_reduction(inv)) + value * (1.0 - Poise::compute_poise_damage_reduction(inv, msm)) }) } } diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 45b3813e5c..883740ee51 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -312,7 +312,7 @@ pub fn handle_skating(data: &JoinData, update: &mut StateUpdate) { footwear = data.inventory.and_then(|inv| { inv.equipped(EquipSlot::Armor(ArmorSlot::Feet)) .map(|armor| match armor.kind().as_ref() { - ItemKind::Armor(a) => a.ground_contact(), + ItemKind::Armor(a) => a.stats(data.msm).ground_contact, _ => crate::comp::inventory::item::armor::Friction::Normal, }) }); @@ -1084,7 +1084,7 @@ pub fn get_crit_data(data: &JoinData<'_>, ai: AbilityInfo) -> (f32, f32) { }) .unwrap_or(DEFAULT_CRIT_CHANCE); - let crit_mult = combat::compute_crit_mult(data.inventory); + let crit_mult = combat::compute_crit_mult(data.inventory, data.msm); (crit_chance, crit_mult) } diff --git a/common/systems/src/buff.rs b/common/systems/src/buff.rs index bd50c13496..e1d94d57c3 100644 --- a/common/systems/src/buff.rs +++ b/common/systems/src/buff.rs @@ -7,6 +7,7 @@ use common::{ Buffs, }, fluid_dynamics::{Fluid, LiquidKind}, + item::MaterialStatManifest, Energy, Group, Health, HealthChange, Inventory, LightEmitter, ModifierKind, PhysicsState, Stats, }, @@ -21,8 +22,8 @@ use common_ecs::{Job, Origin, ParMode, Phase, System}; use hashbrown::HashMap; use rayon::iter::ParallelIterator; use specs::{ - saveload::MarkerAllocator, shred::ResourceId, Entities, Join, ParJoin, Read, ReadStorage, - SystemData, World, WriteStorage, + saveload::MarkerAllocator, shred::ResourceId, Entities, Join, ParJoin, Read, ReadExpect, + ReadStorage, SystemData, World, WriteStorage, }; use std::time::Duration; @@ -38,6 +39,7 @@ pub struct ReadData<'a> { groups: ReadStorage<'a, Group>, uid_allocator: Read<'a, UidAllocator>, time: Read<'a, Time>, + msm: ReadExpect<'a, MaterialStatManifest>, } #[derive(Default)] @@ -207,6 +209,7 @@ impl<'a> System<'a> for Sys { None, read_data.inventories.get(entity), Some(&stat), + &read_data.msm, ); if (damage_reduction - 1.0).abs() < f32::EPSILON { for (id, buff) in buff_comp.buffs.iter() { diff --git a/common/systems/src/stats.rs b/common/systems/src/stats.rs index a6346ea2d1..1fb6761f51 100644 --- a/common/systems/src/stats.rs +++ b/common/systems/src/stats.rs @@ -2,6 +2,7 @@ use common::{ combat, comp::{ self, + item::MaterialStatManifest, skills::{GeneralSkill, Skill}, Body, CharacterState, Combo, Energy, Health, Inventory, Poise, PoiseChange, Pos, SkillSet, Stats, StatsModifier, @@ -11,7 +12,8 @@ use common::{ }; use common_ecs::{Job, Origin, Phase, System}; use specs::{ - shred::ResourceId, Entities, Join, Read, ReadStorage, SystemData, World, Write, WriteStorage, + shred::ResourceId, Entities, Join, Read, ReadExpect, ReadStorage, SystemData, World, Write, + WriteStorage, }; use vek::Vec3; @@ -28,6 +30,7 @@ pub struct ReadData<'a> { bodies: ReadStorage<'a, Body>, char_states: ReadStorage<'a, CharacterState>, inventories: ReadStorage<'a, Inventory>, + msm: ReadExpect<'a, MaterialStatManifest>, } /// This system kills players, levels them up, and regenerates energy. @@ -100,7 +103,7 @@ impl<'a> System<'a> for Sys { // Calculates energy scaling from stats and inventory let energy_mods = StatsModifier { add_mod: stat.max_energy_modifiers.add_mod - + combat::compute_max_energy_mod(inventory), + + combat::compute_max_energy_mod(inventory, &read_data.msm), mult_mod: stat.max_energy_modifiers.mult_mod, }; diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index d14a109ad4..3f84761385 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -558,7 +558,8 @@ pub fn handle_land_on_ground(server: &Server, entity: EcsEntity, vel: Vec3) let inventories = ecs.read_storage::(); let stats = ecs.read_storage::(); - let time = server.state.ecs().read_resource::