Merge branch 'master' of gitlab.com:veloren/veloren into sharp/small-fixes

This commit is contained in:
Joshua Yanovski 2020-08-07 06:47:10 +02:00
commit 77a8c7c267
84 changed files with 832 additions and 626 deletions

View File

@ -78,6 +78,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Updated windowing library (winit 0.19 -> 0.22)
- Bow M2 is now a charged attack that scales the longer it's held
- Fixed window resizing on Mac OS X.
- Dehardcoded many item variants
### Removed

22
Cargo.lock generated
View File

@ -3159,11 +3159,11 @@ dependencies = [
[[package]]
name = "proc-macro-error"
version = "1.0.3"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc175e9777c3116627248584e8f8b3e2987405cabe1c0adf7d1dd28f09dc7880"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr 1.0.3",
"proc-macro-error-attr 1.0.4",
"proc-macro2 1.0.18",
"quote 1.0.7",
"syn 1.0.33",
@ -3185,14 +3185,12 @@ dependencies = [
[[package]]
name = "proc-macro-error-attr"
version = "1.0.3"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cc9795ca17eb581285ec44936da7fc2335a3f34f2ddd13118b6f4d515435c50"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2 1.0.18",
"quote 1.0.7",
"syn 1.0.33",
"syn-mid",
"version_check 0.9.2",
]
@ -4035,9 +4033,9 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
[[package]]
name = "structopt"
version = "0.3.15"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de2f5e239ee807089b62adce73e48c625e0ed80df02c7ab3f068f5db5281065c"
checksum = "de5472fb24d7e80ae84a7801b7978f95a19ec32cb1876faea59ab711eb901976"
dependencies = [
"clap",
"lazy_static",
@ -4046,12 +4044,12 @@ dependencies = [
[[package]]
name = "structopt-derive"
version = "0.4.8"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "510413f9de616762a4fbeab62509bf15c729603b72d7cd71280fbca431b1c118"
checksum = "1e0eb37335aeeebe51be42e2dc07f031163fbabfa6ac67d7ea68b5c2f68d5f99"
dependencies = [
"heck",
"proc-macro-error 1.0.3",
"proc-macro-error 1.0.4",
"proc-macro2 1.0.18",
"quote 1.0.7",
"syn 1.0.33",

View File

@ -3,7 +3,7 @@ Item(
description: "Used by city guards.",
kind: Lantern(
(
kind: Black0,
kind: "Black0",
color: (r: 255, g: 190, b: 75),
strength_thousandths: 3000,
flicker_thousandths: 300,

View File

@ -2,7 +2,7 @@ Item(
name: "Flask of Velorite Dusk",
description: "Increases Exp by 250\n\nTake with plenty of water\n\n<Right-Click to use>",
kind: Consumable(
kind: PotionExp,
kind: "PotionExp",
effect: Xp(250),
),
)

View File

@ -3,7 +3,7 @@ Item(
description: "Illuminates even the darkest dungeon\nA great monster was slain for this item",
kind: Lantern(
(
kind: Blue0,
kind: "Blue0",
color: (r: 220, g: 220, b: 255),
strength_thousandths: 6500,
flicker_thousandths: 300,

View File

@ -2,7 +2,7 @@ Item(
name: "Potent Potion",
description: "A potent healing potion.\n\nRestores 100 health on use.\n\n<Right-Click to use>",
kind: Consumable(
kind: Potion,
kind: "Potion",
effect: Health((
amount: 1000,
cause: Item,

View File

@ -2,7 +2,7 @@ Item(
name: "Potion of Skill",
description: "Provides 250 XP to the drinker\n\n<Right-Click to use>",
kind: Consumable(
kind: Potion,
kind: "Potion",
effect: Xp(250),
),
)

View File

@ -2,7 +2,7 @@ Item(
name: "Large Potion",
description: "Restores 100 Health\n\n<Right-Click to use>",
kind: Consumable(
kind: PotionLarge,
kind: "PotionLarge",
effect: Health((
amount: 1000,
cause: Item,

View File

@ -2,7 +2,7 @@ Item(
name: "Medium Potion",
description: "Restores 70 Health\n\n<Right-Click to use>",
kind: Consumable(
kind: PotionMed,
kind: "PotionMed",
effect: Health((
amount: 700,
cause: Item,

View File

@ -2,7 +2,7 @@ Item(
name: "Minor Potion",
description: "Restores 50 Health\n\n<Right-Click to use>",
kind: Consumable(
kind: PotionMinor,
kind: "PotionMinor",
effect: Health((
amount: 500,
cause: Item,

View File

@ -2,6 +2,6 @@ Item(
name: "Empty Vial",
description: "Can be filled with fluids.",
kind: Ingredient(
kind: EmptyVial,
kind: "EmptyVial",
)
)

View File

@ -2,6 +2,6 @@ Item(
name: "Leather Scraps",
description: "Used to craft various items.",
kind: Ingredient(
kind: LeatherScraps,
kind: "LeatherScraps",
)
)

View File

@ -2,6 +2,6 @@ Item(
name: "Shiny Gem",
description: "It's so shiny!",
kind: Ingredient(
kind: ShinyGem,
kind: "ShinyGem",
)
)

View File

@ -2,6 +2,6 @@ Item(
name: "Stones",
description: "Pebbles from the ground.",
kind: Ingredient(
kind: Stones,
kind: "Stones",
)
)

View File

@ -2,6 +2,6 @@ Item(
name: "Twigs",
description: "Dry.",
kind: Ingredient(
kind: Twigs,
kind: "Twigs",
)
)

View File

@ -2,6 +2,6 @@ Item(
name: "Craftsman Hammer",
description: "Used to craft various items.",
kind: Ingredient(
kind: CraftsmanHammer,
kind: "CraftsmanHammer",
)
)

View File

@ -2,6 +2,6 @@ Item(
name: "Mortar and Pestle",
description: "Crushes and grinds things into\na fine powder or paste.\nUsed to craft various items.",
kind: Ingredient(
kind: MortarPestle,
kind: "MortarPestle",
)
)

View File

@ -2,6 +2,6 @@ Item(
name: "Blue Flower",
description: "Matches the color of the sky.",
kind: Ingredient(
kind: Flower,
kind: "Flower",
)
)

View File

@ -2,6 +2,6 @@ Item(
name: "Pink Flower",
description: "Looks like a lollipop.",
kind: Ingredient(
kind: Flower,
kind: "Flower",
)
)

View File

@ -2,6 +2,6 @@ Item(
name: "Red Flower",
description: "Roses are red...",
kind: Ingredient(
kind: Flower,
kind: "Flower",
)
)

View File

@ -2,6 +2,6 @@ Item(
name: "Sunflower",
description: "Smells like summer.",
kind: Ingredient(
kind: Flower,
kind: "Flower",
)
)

View File

@ -2,6 +2,6 @@ Item(
name: "White flower",
description: "Pure and precious.",
kind: Ingredient(
kind: Flower,
kind: "Flower",
)
)

View File

@ -2,6 +2,6 @@ Item(
name: "Yellow Flower",
description: "Glows like the sun.",
kind: Ingredient(
kind: Flower,
kind: "Flower",
)
)

View File

@ -2,7 +2,7 @@ Item(
name: "Apple",
description: "Restores 20 Health\n\nRed and juicy\n\n<Right-Click to use>",
kind: Consumable(
kind: Apple,
kind: "Apple",
effect: Health((
amount: 200,
cause: Item,

View File

@ -2,7 +2,7 @@ Item(
name: "Mushroom Curry",
description: "Restores 120 Health\n\nWho could say no to that?\n\n<Right-Click to use>",
kind: Consumable(
kind: AppleShroomCurry,
kind: "AppleShroomCurry",
effect: Health((
amount: 1200,
cause: Item,

View File

@ -2,7 +2,7 @@ Item(
name: "Apple Stick",
description: "Restores 60 Health\n\n<Right-Click to use>",
kind: Consumable(
kind: AppleStick,
kind: "AppleStick",
effect: Health((
amount: 600,
cause: Item,

View File

@ -2,7 +2,7 @@ Item(
name: "Dwarven Cheese",
description: "Restores 15 Health\n\nAromatic and nutritious\n\n<Right-Click to use>",
kind: Consumable(
kind: Cheese,
kind: "Cheese",
effect: Health((
amount: 150,
cause: Item,

View File

@ -2,7 +2,7 @@ Item(
name: "Coconut",
description: "Restores 30 health\n\nReliable source of water and fat\n\n<Right-Click to use>",
kind: Consumable(
kind: Coconut,
kind: "Coconut",
effect: Health((
amount: 300,
cause: Item,

View File

@ -2,7 +2,7 @@ Item(
name: "Mushroom",
description: "Restores 10 Health\n\nHopefully this one is not poisonous\n\n<Right-Click to use>",
kind: Consumable(
kind: Mushroom,
kind: "Mushroom",
effect: Health((
amount: 100,
cause: Item,

View File

@ -2,7 +2,7 @@ Item(
name: "Mushroom Stick",
description: "Restores 50 Health\n\n<Right-Click to use>",
kind: Consumable(
kind: MushroomStick,
kind: "MushroomStick",
effect: Health((
amount: 500,
cause: Item,

View File

@ -2,6 +2,6 @@ Item(
name: "Long Grass",
description: "Greener than an orc's snout.",
kind: Ingredient(
kind: Grass,
kind: "Grass",
)
)

View File

@ -2,6 +2,6 @@ Item(
name: "Medium Grass",
description: "Greener than an orc's snout.",
kind: Ingredient(
kind: Grass,
kind: "Grass",
)
)

View File

@ -2,6 +2,6 @@ Item(
name: "Short Grass",
description: "Greener than an orc's snout.",
kind: Ingredient(
kind: Grass,
kind: "Grass",
)
)

View File

@ -3,7 +3,7 @@ Item(
description: "Used by city guards.",
kind: Lantern(
(
kind: Black0,
kind: "Black0",
color: (r: 255, g: 190, b: 75),
strength_thousandths: 3000,
flicker_thousandths: 300,

View File

@ -3,7 +3,7 @@ Item(
description: "This lantern is surprisingly cold when lit.",
kind: Lantern(
(
kind: Blue0,
kind: "Blue0",
color: (r: 64, g: 127, b: 153),
strength_thousandths: 4000,
flicker_thousandths: 250,

View File

@ -3,7 +3,7 @@ Item(
description: "It has an opening that could fit a ring...",
kind: Lantern(
(
kind: Green0,
kind: "Green0",
color: (r: 192, g: 255, b: 76),
strength_thousandths: 4000,
flicker_thousandths: 500,

View File

@ -3,7 +3,7 @@ Item(
description: "Caution: contents hot",
kind: Lantern(
(
kind: Red0,
kind: "Red0",
color: (r: 255, g: 127, b: 51),
strength_thousandths: 3500,
flicker_thousandths: 1000,

View File

@ -2,7 +2,7 @@ Item(
name: "Velorite",
description: "Increases Exp by 20\n\nJust a slight touch makes you feel the knowledge of ancient times\n\n<Right-Click to use>",
kind: Consumable(
kind: Velorite,
kind: "Velorite",
effect: Xp(20),
),
)

View File

@ -2,7 +2,7 @@ Item(
name: "Velorite Fragment",
description: "Increases Exp by 10\n\nSmall runes sparkle on its surface\n\n<Right-Click to use>",
kind: Consumable(
kind: VeloriteFrag,
kind: "VeloriteFrag",
effect: Xp(10),
),
)

View File

@ -529,6 +529,10 @@
"troll": {
"keyword": "troll",
"generic": "Troll"
},
"dullahan": {
"keyword": "dullahan",
"generic": "Dullahan"
}
}
},

View File

@ -77,31 +77,31 @@
],
threshold: 0.3,
),
Inventory(Consumed(Potion)): (
Inventory(Consumed("Potion")): (
files: [
"voxygen.audio.sfx.inventory.consumable.liquid",
],
threshold: 0.3,
),
Inventory(Consumed(PotionMinor)): (
Inventory(Consumed("PotionMinor")): (
files: [
"voxygen.audio.sfx.inventory.consumable.liquid",
],
threshold: 0.3,
),
Inventory(Consumed(Apple)): (
Inventory(Consumed("Apple")): (
files: [
"voxygen.audio.sfx.inventory.consumable.apple",
],
threshold: 0.3,
),
Inventory(Consumed(Mushroom)): (
Inventory(Consumed("Mushroom")): (
files: [
"voxygen.audio.sfx.inventory.consumable.food",
],
threshold: 0.3,
),
Inventory(Consumed(Cheese)): (
Inventory(Consumed("Cheese")): (
files: [
"voxygen.audio.sfx.inventory.consumable.food",
],

View File

@ -1,25 +1,25 @@
/// Translation document instructions
///
/// In order to keep localization documents readable please follow the following
///
/// In order to keep localization documents readible please follow the following
/// rules:
/// - separate the string map sections using a commentary describing the purpose
/// of the next section
/// - prepend multi-line strings with a commentary
/// - append one blank lines after a multi-line strings and two after sections
///
/// To add a new language in Veloren, just write an additional `.ron` file in
/// To add a new language in Veloren, just write an additional `.ron` file in
/// `assets/voxygen/i18n` and that's it!
///
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// WARNING: Localization files shall be saved in UTF-8 format without BOM
/// Localization for "global" Español Latino
/// Localization for "latinoamericano" Latin-American
VoxygenLocalization(
metadata: (
language_name: "Español Latino",
language_identifier: "es_la",
),
convert_utf8_to_ascii: false,
fonts: {
fonts: {
"opensans": Font (
asset_key: "voxygen.font.OpenSans-Regular",
scale_ratio: 1.0,
@ -40,17 +40,17 @@ VoxygenLocalization(
asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended",
scale_ratio: 1.0,
),
},
},
string_map: {
/// Start Common section
// Texts used in multiple locations with the same formatting
"common.username": "usuario",
"common.username": "Usuario",
"common.singleplayer": "Un Jugador",
"common.multiplayer": "Multijugador",
"common.servers": "Servidores",
"common.quit": "Salir",
"common.settings": "Configuracion",
"common.languages": "Lenguajes",
"common.settings": "Configuración",
"common.languages": "Idiomas",
"common.interface": "Interfaz",
"common.gameplay": "Jugabilidad",
"common.controls": "Controles",
@ -72,17 +72,17 @@ VoxygenLocalization(
"common.fatal_error": "Error Fatal",
// Message when connection to the server is lost
"common.connection_lost": r#"Conexion perdida!
Se reinicio el servidor?
El cliente esta actualizado?"#,
"common.connection_lost": r#"Conexión perdida!
Se reinició el servidor?
El cliente está actualizado?"#,
"common.races.orc": "Orco",
"common.races.human": "Humano",
"common.races.dwarf": "Enano",
"common.races.elf": "Elfo",
"common.races.undead": "No-Muerto",
"common.races.danari": "Danari",
"common.species.orc": "Orco",
"common.species.human": "Humano",
"common.species.dwarf": "Enano",
"common.species.elf": "Elfo",
"common.species.undead": "No-Muerto",
"common.species.danari": "Danari",
"common.weapons.axe": "Hacha",
"common.weapons.sword": "Espada",
@ -95,18 +95,19 @@ El cliente esta actualizado?"#,
/// Start Main screen section
"main.connecting": "Conectando",
"main.creating_world": "Creando Mundo",
"main.tip": "Consejo:",
// Welcome notice that appears the first time Veloren is started
"main.notice": r#"Bienvenido a la version alfa de Veloren!
Antes de que te diviertas, por favor ten en cuenta lo siguiente:
- Esta es una alfa muy temprana, espera fallos, jugabilidad extremadamente incompleta, mecánicas sin pulir y características faltantes.
- Esta es una alfa muy temprana, espera fallos, jugabilidad extremadamente incompleta, mecánicas sin pulir y características faltantes.
- Si tienes críticas constructivas o reportes de fallos, puedes contactarnos por reddit, GitLab, o por el server de Discord de nuestra comunidad.
- Veloren esta licenciado bajo la licencia GPL 3 open-source (código abierto).
Eso significa que tienes la libertad de jugar, modificar, y redistribuir el juego como desees (siempre y cuando dicho trabajo también este licenciado como GPL 3).
- Veloren esta licenciado bajo la licencia GPL 3 open-source (código abierto). Eso significa que tienes la libertad de jugar, modificar, y redistribuir el Juego como
desees (siempre y cuando dicho trabajo también este licenciado como GPL 3).
- Veloren es un proyecto en comunidad sin ánimo de lucro, y todos los que trabajan en el son voluntarios.
Si te gusta lo que ves, eres bienvenido a unirte a los equipos de desarrollo o de arte!
@ -115,18 +116,16 @@ Gracias por tomarte el tiempo de leer este mensaje, esperamos que disfrutes el j
~ Los Desarrolladores de Veloren"#,
/// Login process description
// Login process description
"main.login_process": r#"Información sobre el proceso para Iniciar Sesión:
Si estas teniendo problemas iniciando sesión:
Por favor ten en cuenta que ahora necesitas una cuenta
para jugar en servidores con autenticación activada.
Puedes crearte una cuenta en
https://account.veloren.net."#,
"main.login.server_not_found": "No se encontró el servidor",
"main.login.server_not_found": "No se encontró el servidor",
"main.login.authentication_error": "Error de autenticación en el servidor",
"main.login.server_full": "El servidor esta lleno",
"main.login.untrusted_auth_server": "El servidor de autenticación no es confiable",
@ -138,7 +137,7 @@ https://account.veloren.net."#,
"main.login.failed_sending_request": "El pedido al servidor de autenticacion fallo",
"main.login.invalid_character": "El personaje seleccionado no es válido",
"main.login.client_crashed": "El cliente crasheó",
"main.login.not_on_whitelist": "No estas en la lista blanca. Contacta al Dueño del Servidor si quieres unirte.",
"main.login.not_on_whitelist": "No estas en la lista blanca. Contacta al Dueño del Servidor si quieres unirte.",
/// End Main screen section
@ -148,8 +147,8 @@ https://account.veloren.net."#,
"hud.show_tips": "Mostrar Consejos",
"hud.quests": "Misiones",
"hud.you_died": "Moriste",
"hud.waypoint_saved": "Marcador Guardado",
"hud.waypoint_saved": "Marcador Guardado",
"hud.press_key_to_show_keybindings_fmt": "Presiona {key} para mostrar los controles del teclado",
"hud.press_key_to_show_debug_info_fmt": "Presiona {key} para mostrar información de depuración",
"hud.press_key_to_toggle_keybindings_fmt": "Presiona {key} para alternar los controles del teclado",
@ -167,11 +166,11 @@ https://account.veloren.net."#,
"hud.sct.experience": "{amount} Exp",
"hud.sct.block": "BLOQUEADO",
/// Respawn message
// Respawn message
"hud.press_key_to_respawn": r#"Presiona {key} para reaparecer en la ultima fogata que visitaste."#,
/// Welcome message
"hud.welcome": r#"Bienvenido a la alfa de Veloren!,
// Welcome message
"hud.welcome": r#"Bienvenido a la alfa de Veloren!
Algunos consejos antes de que empieces:
@ -204,11 +203,11 @@ Quieres liberar tu cursor para cerrar esta ventana? Presiona TAB!
Disfruta tu estadía en el Mundo de Veloren."#,
"hud.temp_quest_headline": r#"Porfavor, ayudanos Viajero!"#,
"hud.temp_quest_text": r#"Calabozos llenos de cultistas malvados
han emergido alrededor de nuestros pacíficos pueblos!
"hud.temp_quest_text": r#"Calabozos llenos de cultistas malvados
han emergido alrededor de nuestros pacíficos pueblos!
Consigue alguien que te acompañe, re-abastecete con comida
Consigue alguien que te acompañe, re-abastecete con comida
y derrota sus viles lideres y acólitos.
@ -217,7 +216,7 @@ objetos infundidos con magia?"#,
// Inventory
// Inventory
"hud.bag.inventory": "Inventario de {playername}",
"hud.bag.stats_title": "Estadísticas de {playername}",
"hud.bag.exp": "Exp",
@ -229,24 +228,24 @@ objetos infundidos con magia?"#,
"hud.bag.shoulders": "Hombros",
"hud.bag.chest": "Torso",
"hud.bag.hands": "Manos",
"hud.bag.lantern": "Farol",
"hud.bag.belt": "Cinturon",
"hud.bag.lantern": "Linterna",
"hud.bag.belt": "Cinturón",
"hud.bag.ring": "Anillo",
"hud.bag.back": "Espalda",
"hud.bag.legs": "Piernas",
"hud.bag.feet": "Pies",
"hud.bag.mainhand": "Mano Principal",
"hud.bag.offhand": "Mano Secundaria",
"hud.bag.offhand": "Mano Secundaria",
// Map and Questlog
"hud.map.map_title": "Mapa",
"hud.map.qlog_title": "Misiones",
// Settings
// Settings
"hud.settings.general": "General",
"hud.settings.none": "Ninguno",
"hud.settings.press_behavior.toggle": "Alternar",
"hud.settings.none": "Ninguno",
"hud.settings.press_behavior.toggle": "Alternar",
"hud.settings.press_behavior.hold": "Mantener",
"hud.settings.help_window": "Ventana de Ayuda",
"hud.settings.debug_info": "Info de Depuración",
@ -257,7 +256,7 @@ objetos infundidos con magia?"#,
"hud.settings.crosshair": "Mira",
"hud.settings.transparency": "Transparencia",
"hud.settings.hotbar": "Inventario Rápido",
"hud.settings.toggle_shortcuts": "Alternar Atajos",
"hud.settings.toggle_shortcuts": "Alternar Atajos",
"hud.settings.toggle_bar_experience": "Alternar Barra de Experiencia",
"hud.settings.scrolling_combat_text": "Texto de Combate con Desplazamiento",
"hud.settings.single_damage_number": "Números de Daño Singular",
@ -266,13 +265,14 @@ objetos infundidos con magia?"#,
"hud.settings.cumulated_incoming_damage": "Daño Recibido Acumulado",
"hud.settings.speech_bubble": "Burbuja de Diálogo",
"hud.settings.speech_bubble_dark_mode": "Burbuja de Diálogo en Modo Oscuro",
"hud.settings.speech_bubble_icon": "Icono de Burbuja de Diálogo",
"hud.settings.speech_bubble_icon": "Burbuja de Diálogo en Modo Oscuro",
"hud.settings.energybar_numbers": "Números de la Barra de Energia",
"hud.settings.values": "Valores",
"hud.settings.percentages": "Porcentajes",
"hud.settings.chat": "Chat",
"hud.settings.background_transparency": "Transparencia del Fondo",
"hud.settings.chat_character_name": "Nombres de Personajes en el chat",
"hud.settings.loading_tips": "Consejos en Pantalla de Carga",
"hud.settings.pan_sensitivity": "Sensibilidad de Desplazamiento de la Cámara",
"hud.settings.zoom_sensitivity": "Sensibilidad del Zoom",
@ -280,7 +280,7 @@ objetos infundidos con magia?"#,
"hud.settings.invert_mouse_y_axis": "Invertir eje Y del Ratón",
"hud.settings.enable_mouse_smoothing": "Suavizado de la Cámara",
"hud.settings.free_look_behavior": "Comportamiento de vista libre",
"hud.settings.auto_walk_behavior": "Comportamiento al caminar automaticamente",
"hud.settings.auto_walk_behavior": "Comportamiento al caminar automaticamente",
"hud.settings.stop_auto_walk_on_input": "Frenar caminata automática",
"hud.settings.view_distance": "Distancia de Visión",
@ -288,7 +288,7 @@ objetos infundidos con magia?"#,
"hud.settings.figures_view_distance": "Distancia de Visión de Entidades",
"hud.settings.maximum_fps": "FPS Máximos",
"hud.settings.fov": "Campo de Visión (grados)",
"hud.settings.gamma": "Gama",
"hud.settings.gamma": "Gama",
"hud.settings.antialiasing_mode": "Modo Anti-Aliasing",
"hud.settings.cloud_rendering_mode": "Modo de Renderizado de Nubes",
"hud.settings.fluid_rendering_mode": "Modo de Renderizado de Fluidos",
@ -301,22 +301,28 @@ objetos infundidos con magia?"#,
"hud.settings.music_volume": "Volumen de Musica",
"hud.settings.sound_effect_volume": "Volumen de Efectos de Sonido",
"hud.settings.audio_device": "Dispositivo de Audio",
"hud.settings.awaitingkey": "Presiona una tecla...",
"hud.settings.awaitingkey": "Presiona una tecla...",
"hud.settings.unbound": "Ninguno",
"hud.settings.reset_keybinds": "Reestablecer a los valores predeterminados",
"hud.social": "Social",
"hud.social.online": "En Linea",
"hud.social.online": "En Línea",
"hud.social.friends": "Amigos",
"hud.social.not_yet_available": "Aún no esta disponible",
"hud.social.faction": "Facción",
"hud.social.play_online_fmt": "{nb_player} jugador(es) en linea",
"hud.social.play_online_fmt": "{nb_player} jugador(es) en línea",
"hud.spell": "Hechizos",
"hud.crafting": "Crafteo",
"hud.crafting.recipes": "Recetas",
"hud.crafting.ingredients": "Ingredientes:",
"hud.crafting.craft": "Fabricar",
"hud.crafting.tool_cata": "Requisitos:",
"hud.free_look_indicator": "Vista libre activa",
"hud.auto_walk_indicator": "Caminata automática activa",
"hud.spell": "Hechizos",
"hud.free_look_indicator": "Vista libre activa",
"hud.auto_walk_indicator": "Caminata automática activa",
/// End HUD section
@ -325,7 +331,7 @@ objetos infundidos con magia?"#,
"gameinput.primary": "Ataque Básico",
"gameinput.secondary": "Ataque Secundario/Bloquear/Apuntar",
"gameinput.slot1": "Ranura de Inventario Rápido 1",
"gameinput.slot1": "Ranura de Inventario Rápido 1",
"gameinput.slot2": "Ranura de Inventario Rápido 2",
"gameinput.slot3": "Ranura de Inventario Rápido 3",
"gameinput.slot4": "Ranura de Inventario Rápido 4",
@ -357,21 +363,21 @@ objetos infundidos con magia?"#,
"gameinput.mount": "Montar",
"gameinput.enter": "Entrar",
"gameinput.command": "Comando",
"gameinput.escape": "Escape",
"gameinput.escape": "Escapar",
"gameinput.map": "Mapa",
"gameinput.bag": "Bolsa",
"gameinput.social": "Social",
"gameinput.sit": "Sentarse",
"gameinput.spellbook": "Hechizos",
"gameinput.settings": "Configuración",
"gameinput.respawn": "Re-aparecer",
"gameinput.respawn": "Reaparecer",
"gameinput.charge": "Cargar",
"gameinput.togglewield": "Alternar empuñadura",
"gameinput.interact": "Interactuar",
"gameinput.freelook": "Vista Libre",
"gameinput.autowalk": "Caminata Automática",
"gameinput.autowalk": "Caminata Automática",
"gameinput.dance": "Bailar",
/// End GameInput section
@ -393,23 +399,25 @@ objetos infundidos con magia?"#,
"char_selection.beard": "Barba",
"char_selection.hair_style": "Estilo de Pelo",
"char_selection.hair_color": "Color de Pelo",
"char_selection.chest_color": "Color del Torso",
"char_selection.eye_color": "Color de Ojos",
"char_selection.skin": "Piel",
"char_selection.eyebrows": "Cejas",
"char_selection.eyeshape": "Detalles de los Ojos",
"char_selection.accessories": "Accesorios",
"char_selection.create_info_name": "Tu Personaje necesita un nombre!",
/// End chracter selection section
/// Start character window section
"character_window.character_name": "Nombre de Personaje",
// Charater stats
// Character stats
"character_window.character_stats": r#"Resistencia
Estado Físico
Fuerza de Voluntad
Protección
"#,
/// End character window section
@ -417,10 +425,30 @@ Fuerza de Voluntad
/// Start Escape Menu Section
"esc_menu.logout": "Cerrar Sesión",
"esc_menu.quit_game": "Salir del Juego",
/// End Escape Menu Section
}
vector_map: {
/// End Escape Menu Section
},
vector_map: {
"loading.tips": [
"Presiona 'G' para encender tu linterna.",
"Presiona 'F1' para ver los controles predeterminados.",
"Puedes escribir /say o /s para chatear solo con jugadores alrededor tuyo.",
"Puedes escribr /region o /r para chatear solo con jugadores que están a unos cien bloques alrededor tuyo.",
"Para enviar mensajes privados escribe /tell segudi de el nombre de un jugador y luego tu mensaje.",
"NPCs con el mismo nivel pueden tener una dificultad diferente.",
"Observa el terreno en búsqueda de comida, cofres y botines!",
"¿Inventario lleno de comida? Intenta craftear mejor comida con ella!",
"¿Te preguntas dónde debes hacerlo? Los Dungeons están marcados con puntos marrones en el mapa!",
"No te olvides de ajustar los gráficos de tu pc. Presiona 'N' para abrir la configuración.",
"Jugar con otros es divertido! Presiona 'O' para ver quien esta conectado.",
"Un NPC con una craneo debajo de su barra de vida es bastante más poderoso comparado contigo.",
"Presiona 'J' para bailar. Fiesta!",
"Presiona 'Shift-Izquierdo' para abrir tu planeador y conquistar los cielos.",
"Veloren está aún en Alfa temprana. Hacemos lo mejor para mejorar día a día!",
"Si te quieres unir al equipo de desarrolladores o solo chatear con nosotros, únete a nuestro servidor en Discord.",
],
"npc.speech.villager_under_attack": [
"Ayuda, ¡Me están atacando!",
"¡Ayuda! ¡Me están atacando!",
@ -457,7 +485,50 @@ Fuerza de Voluntad
"¡Vienen por mi!",
"¡Ayuda! ¡Ayuda! Estoy siendo oprimido",
"Ah, se nota que la violencia es parte del sistema.",
"¡Esto no es más que un rasguño!"
],
"¡Esto no es más que un rasguño!",
"Para con eso!",
"¿Qué te hice para merecer esto?",
"Por favor, para de atacarme!",
"Hey! Mira hacia adonde apuntas esa cosa",
"Desgraciado, vete de aqui!",
"Para ya! Vete!",
"Ahora me estas enfureciendo!",
"Hey!¿Quién te piensas que eres?",
"Te arrancaré la cabeza por eso!",
"Detente, por favor! No llevo nada de valor!",
"Te voy a mandar a mi hermano, el es más grande que yo!",
"Nooo, le contaré a mi madre!",
"Maldito seas!",
"Por favor no lo hagas.",
"Eso no fue agradable!",
"Tu arma sirve, ahora aléjala!",
"Si claro...",
"Por favor, tengo familia!",
"Soy demasiado jóven para morir!",
"¿Podemos hablar sobre esto?",
"La violencia no es el medio!",
"Este día se esta convirtiendo en uno muy feo...",
"Hey, eso dolió!",
"Ayy!",
"Qué violento!",
"Detente, te lo suplico!",
"Ojala te enfermes!",
"Esto no es divertido.",
"¡¿Cómo te atreves?!",
"Vas a pagar por eso!",
"Sigue con eso y lo lamentarás!",
"No hagas que te lastime!",
"Tiene que haber algun tipo de malentendido!",
"No necesitas hacer esto!",
"Vete, demonio!",
"Eso dolió realmente!",
"¿Por qué harias eso?",
"Por los espíritus, para!",
"Me habrás confudido con alguien más!",
"No me merezco esto!",
"Por favor, no lo hagas de nuevo",
"Guardias, tiren este monstruo al lago",
"Invocaré mis demonios en ti!",
],
}
)

View File

@ -461,11 +461,11 @@
(2.0, -1.0, 0.0), (-135.0, 90.0, 0.0), 1.1,
),
Tool(Hammer("CobaltHammer0")): VoxTrans(
"voxel.weapon.hammer.2hhammer_Cobalt-0",
"voxel.weapon.hammer.2hhammer_cobalt-0",
(2.0, -1.0, 0.0), (-135.0, 90.0, 0.0), 1.1,
),
Tool(Hammer("CobaltHammer1")): VoxTrans(
"voxel.weapon.hammer.2hhammer_Cobalt-1",
"voxel.weapon.hammer.2hhammer_cobalt-1",
(2.0, -1.0, 0.0), (-135.0, 90.0, 0.0), 1.1,
),
Tool(Hammer("RunicHammer")): VoxTrans(
@ -508,16 +508,16 @@
(0.0, 0.0, 0.0), (-90.0, 90.0, 0.0), 2.4,
),
// Lanterns
Lantern(Black0): Png(
Lantern("Black0"): Png(
"element.icons.lantern_black-0",
),
Lantern(Green0): Png(
Lantern("Green0"): Png(
"element.icons.lantern_green-0",
),
Lantern(Blue0): Png(
Lantern("Blue0"): Png(
"element.icons.lantern_blue-0",
),
Lantern(Red0): Png(
Lantern("Red0"): Png(
"element.icons.lantern_red-0",
),
// Farming Equipment
@ -621,7 +621,7 @@
"voxel.armor.shoulder.cultist_right",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
),
// Druid Set
// Druid Set
Armor(Chest("Druid")): VoxTrans(
"voxel.armor.chest.druid",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
@ -762,7 +762,7 @@
"voxel.armor.hand.steel_right-0",
(0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0,
),
Armor(Shoulder("Steel0")): VoxTrans(
Armor(Shoulder("Steel0")): VoxTrans(
"voxel.armor.shoulder.steel_right-0",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
@ -787,7 +787,7 @@
"voxel.armor.hand.leather_right-0",
(0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0,
),
Armor(Shoulder("Leather0")): VoxTrans(
Armor(Shoulder("Leather0")): VoxTrans(
"voxel.armor.shoulder.leather_right-0",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
@ -817,7 +817,7 @@
"voxel.armor.hand.leather_right-2",
(0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0,
),
Armor(Shoulder("Leather2")): VoxTrans(
Armor(Shoulder("Leather2")): VoxTrans(
"voxel.armor.shoulder.leather_right-2",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
@ -871,7 +871,7 @@
"voxel.armor.shoulder.cloth_green_right-0",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
Armor(Shoulder("ClothGreen0")): VoxTrans(
Armor(Shoulder("ClothGreen0")): VoxTrans(
"voxel.armor.shoulder.cloth_green_right-0",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
@ -900,19 +900,19 @@
"voxel.armor.shoulder.cloth_purple_right-0",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
Armor(Shoulder("ClothBlue1")): VoxTrans(
Armor(Shoulder("ClothBlue1")): VoxTrans(
"voxel.armor.shoulder.cloth_blue_right-1",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
Armor(Shoulder("IronSpikes")): VoxTrans(
Armor(Shoulder("IronSpikes")): VoxTrans(
"voxel.armor.shoulder.iron_spikes_right",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
Armor(Shoulder("IronLeather3")): VoxTrans(
Armor(Shoulder("IronLeather3")): VoxTrans(
"voxel.armor.shoulder.leather_iron_right-3",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
Armor(Shoulder("IronLeather2")): VoxTrans(
Armor(Shoulder("IronLeather2")): VoxTrans(
"voxel.armor.shoulder.leather_iron_right-2",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
@ -978,7 +978,7 @@
"voxel.armor.hand.twigsleaves_glove_right",
(0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0,
),
Armor(Shoulder("LeafyShoulder")): VoxTrans(
Armor(Shoulder("LeafyShoulder")): VoxTrans(
"voxel.armor.shoulder.twigsleaves_shoulder_right",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
@ -1003,7 +1003,7 @@
"voxel.armor.hand.twigsflowers_glove_right",
(0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0,
),
Armor(Shoulder("FlowerShoulder")): VoxTrans(
Armor(Shoulder("FlowerShoulder")): VoxTrans(
"voxel.armor.shoulder.twigsflowers_shoulder_right",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
@ -1047,55 +1047,54 @@
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.0,
),
// Consumables
Consumable(Apple):
Png(
Consumable("Apple"): Png(
"element.icons.item_apple",
),
Consumable(Coconut): Png(
Consumable("Coconut"): Png(
"element.icons.item_coconut",
),
Consumable(PotionMed): VoxTrans(
Consumable("PotionMed"): VoxTrans(
"voxel.object.potion_red",
(0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.7,
),
Consumable(PotionMinor): VoxTrans(
Consumable("PotionMinor"): VoxTrans(
"voxel.object.potion_red",
(0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.5,
),
Consumable(PotionLarge): VoxTrans(
Consumable("PotionLarge"): VoxTrans(
"voxel.object.potion_red",
(0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.9,
),
Consumable(PotionExp): VoxTrans(
Consumable("PotionExp"): VoxTrans(
"voxel.object.potion_turq",
(0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.8,
),
Consumable(Cheese): Png(
Consumable("Cheese"): Png(
"element.icons.item_cheese",
),
Consumable(Potion): VoxTrans(
Consumable("Potion"): VoxTrans(
"voxel.object.potion_red",
(0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 1.0,
),
Consumable(Mushroom): VoxTrans(
Consumable("Mushroom"): VoxTrans(
"voxel.sprite.mushrooms.mushroom-10",
(0.0, 0.0, 0.0), (-50.0, 70.0, 40.0), 1.0,
),
Consumable(Velorite): VoxTrans(
Consumable("Velorite"): VoxTrans(
"voxel.sprite.velorite.velorite_ore",
(0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8,
),
Consumable(VeloriteFrag): VoxTrans(
Consumable("VeloriteFrag"): VoxTrans(
"voxel.sprite.velorite.velorite_1",
(0.0, 0.0, 0.0), (-50.0, 40.0, 20.0), 0.8,
),
Consumable(AppleShroomCurry): Png(
Consumable("AppleShroomCurry"): Png(
"element.icons.item_apple_curry",
),
Consumable(AppleStick): Png(
Consumable("AppleStick"): Png(
"element.icons.item_apple_stick",
),
Consumable(MushroomStick): Png(
Consumable("MushroomStick"): Png(
"element.icons.item_shroom_stick",
),
@ -1109,36 +1108,36 @@
(0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8,
),
// Ingredients
Ingredient(CraftsmanHammer): VoxTrans( //TODO This should be a 1h hammer!
Ingredient("CraftsmanHammer"): VoxTrans( //TODO This should be a 1h hammer!
"voxel.weapon.hammer.craftsman",
(1.0, 1.0, 0.0), (-135.0, 90.0, 0.0), 1.0,
),
Ingredient(Flower): VoxTrans(
Ingredient("Flower"): VoxTrans(
"voxel.sprite.flowers.flower_red_2",
(0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8,
),
Ingredient(Grass): VoxTrans(
Ingredient("Grass"): VoxTrans(
"voxel.sprite.grass.grass_long_5",
(0.0, 0.0, 0.0), (-90.0, 50.0, 0.0), 1.0,
),
Ingredient(Stones): VoxTrans(
Ingredient("Stones"): VoxTrans(
"voxel.sprite.rocks.rock-0",
(0.0, 0.0, 0.0), (-50.0, 40.0, 20.0), 0.8,
),
Ingredient(Twigs): VoxTrans(
Ingredient("Twigs"): VoxTrans(
"voxel.sprite.twigs.twigs-0",
(0.0, 0.0, 0.0), (-20.0, 10.0, 20.0), 0.9,
),
Ingredient(LeatherScraps): Png(
Ingredient("LeatherScraps"): Png(
"element.icons.item_leather0",
),
Ingredient(ShinyGem): Png(
Ingredient("ShinyGem"): Png(
"element.icons.gem",
),
Ingredient(MortarPestle): Png(
Ingredient("MortarPestle"): Png(
"element.icons.item_mortarpestlecoco",
),
Ingredient(EmptyVial): VoxTrans(
Ingredient("EmptyVial"): VoxTrans(
"voxel.object.potion_empty",
(0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.8,
),

View File

@ -143,4 +143,43 @@
center: ("armor.empty"),
)
),
(Dullahan, Male): (
head: (
offset: (-8.0, -5.0, -6.0),
center: ("armor.empty"),
),
torso_upper: (
offset: (-9.0, -7.5, -7.0),
center: ("npc.dullahan.male.torso_upper"),
),
torso_lower: (
offset: (-8.0, -6.0, -9.0),
center: ("npc.dullahan.male.torso_lower"),
),
main: (
offset: (-1.5, -9.0, -10.0),
center: ("npc.dullahan.male.sword"),
)
),
(Dullahan, Female): (
head: (
offset: (-8.0, -5.0, -6.0),
center: ("armor.empty"),
),
torso_upper: (
offset: (-9.0, -7.5, -7.0),
center: ("npc.dullahan.male.torso_upper"),
),
torso_lower: (
offset: (-8.0, -6.0, -9.0),
center: ("npc.dullahan.male.torso_lower"),
),
main: (
offset: (-1.5, -9.0, -10.0),
center: ("npc.dullahan.male.sword"),
)
),
})

View File

@ -1,274 +1,342 @@
({
(Ogre, Male): (
shoulder_l: (
offset: (-4.0, -5.5, -4.0),
lateral: ("armor.empty"),
),
shoulder_r: (
offset: (-4.0, -5.5, -4.0),
lateral: ("npc.ogre.male.shoulder_r"),
),
hand_l: (
offset: (-2.5, -2.5, -11.0),
lateral: ("npc.ogre.male.hand_l"),
),
hand_r: (
offset: (-2.5, -2.5, -11.0),
lateral: ("npc.ogre.male.hand_r"),
),
leg_l: (
offset: (-6.0, -3.5, -7.0),
lateral: ("npc.ogre.male.leg_l"),
),
leg_r: (
offset: (0.0, -3.5, -7.0),
lateral: ("npc.ogre.male.leg_r"),
),
foot_l: (
offset: (-3.0, -5.0, -2.5),
lateral: ("npc.ogre.male.foot_l"),
),
foot_r: (
offset: (-3.0, -5.0, -2.5),
lateral: ("npc.ogre.male.foot_r"),
)
),
(Ogre, Female): (
shoulder_l: (
offset: (-4.0, -5.5, -4.0),
lateral: ("armor.empty"),
),
shoulder_r: (
offset: (-4.0, -5.5, -4.0),
lateral: ("npc.ogre.male.shoulder_r"),
),
hand_l: (
offset: (-2.5, -2.5, -11.0),
lateral: ("npc.ogre.male.hand_l"),
),
hand_r: (
offset: (-2.5, -2.5, -11.0),
lateral: ("npc.ogre.male.hand_r"),
),
leg_l: (
offset: (-6.0, -3.5, -7.0),
lateral: ("npc.ogre.male.leg_l"),
),
leg_r: (
offset: (0.0, -3.5, -7.0),
lateral: ("npc.ogre.male.leg_r"),
),
foot_l: (
offset: (-3.0, -5.0, -2.5),
lateral: ("npc.ogre.male.foot_l"),
),
foot_r: (
offset: (-3.0, -5.0, -2.5),
lateral: ("npc.ogre.male.foot_r"),
)
),
(Cyclops, Male): (
shoulder_l: (
offset: (-3.0, -4.0, -5.0),
lateral: ("npc.cyclops.male.shoulder_l"),
),
shoulder_r: (
offset: (-3.0, -4.0, -5.0),
lateral: ("npc.cyclops.male.shoulder_r"),
),
hand_l: (
offset: (-3.5, -3.5, -14.0),
lateral: ("npc.cyclops.male.hand_l"),
),
hand_r: (
offset: (-3.5, -3.5, -14.0),
lateral: ("npc.cyclops.male.hand_r"),
),
leg_l: (
offset: (-6.0, -3.5, -7.0),
lateral: ("npc.cyclops.male.leg_l"),
),
leg_r: (
offset: (0.0, -3.5, -7.0),
lateral: ("npc.cyclops.male.leg_r"),
),
foot_l: (
offset: (-3.0, -5.0, -5.0),
lateral: ("npc.cyclops.male.foot_l"),
),
foot_r: (
offset: (-3.0, -5.0, -5.0),
lateral: ("npc.cyclops.male.foot_r"),
)
),
(Cyclops, Female): (
shoulder_l: (
offset: (-3.0, -4.0, -5.0),
lateral: ("npc.cyclops.male.shoulder_l"),
),
shoulder_r: (
offset: (-3.0, -4.0, -5.0),
lateral: ("npc.cyclops.male.shoulder_r"),
),
hand_l: (
offset: (-3.5, -3.5, -14.0),
lateral: ("npc.cyclops.male.hand_l"),
),
hand_r: (
offset: (-3.5, -3.5, -14.0),
lateral: ("npc.cyclops.male.hand_r"),
),
leg_l: (
offset: (-6.0, -3.5, -7.0),
lateral: ("npc.cyclops.male.leg_l"),
),
leg_r: (
offset: (0.0, -3.5, -7.0),
lateral: ("npc.cyclops.male.leg_r"),
),
foot_l: (
offset: (-3.0, -5.0, -5.0),
lateral: ("npc.cyclops.male.foot_l"),
),
foot_r: (
offset: (-3.0, -5.0, -5.0),
lateral: ("npc.cyclops.male.foot_r"),
)
),
(Wendigo, Male): (
shoulder_l: (
offset: (-3.0, -4.0, -5.0),
lateral: ("npc.wendigo.male.shoulder_l"),
),
shoulder_r: (
offset: (-3.0, -4.0, -5.0),
lateral: ("npc.wendigo.male.shoulder_r"),
),
hand_l: (
offset: (-4.0, -3.5, -18.0),
lateral: ("npc.wendigo.male.hand_l"),
),
hand_r: (
offset: (-4.0, -3.5, -18.0),
lateral: ("npc.wendigo.male.hand_r"),
),
leg_l: (
offset: (-4.0, -2.5, -9.0),
lateral: ("npc.wendigo.male.leg_l"),
),
leg_r: (
offset: (0.0, -2.5, -9.0),
lateral: ("npc.wendigo.male.leg_r"),
),
foot_l: (
offset: (-4.0, -5.0, -5.5),
lateral: ("npc.wendigo.male.foot_l"),
),
foot_r: (
offset: (-4.0, -5.0, -5.5),
lateral: ("npc.wendigo.male.foot_r"),
)
),
(Wendigo, Female): (
shoulder_l: (
offset: (-3.0, -4.0, -5.0),
lateral: ("npc.wendigo.male.shoulder_l"),
),
shoulder_r: (
offset: (-3.0, -4.0, -5.0),
lateral: ("npc.wendigo.male.shoulder_r"),
),
hand_l: (
offset: (-4.0, -3.5, -18.0),
lateral: ("npc.wendigo.male.hand_l"),
),
hand_r: (
offset: (-4.0, -3.5, -18.0),
lateral: ("npc.wendigo.male.hand_r"),
),
leg_l: (
offset: (-4.0, -2.5, -9.0),
lateral: ("npc.wendigo.male.leg_l"),
),
leg_r: (
offset: (0.0, -2.5, -9.0),
lateral: ("npc.wendigo.male.leg_r"),
),
foot_l: (
offset: (-4.0, -5.0, -5.5),
lateral: ("npc.wendigo.male.foot_l"),
),
foot_r: (
offset: (-4.0, -5.0, -5.5),
lateral: ("npc.wendigo.male.foot_r"),
)
),
(Troll, Male): (
shoulder_l: (
offset: (-5.0, -4.5, -7.0),
lateral: ("npc.troll.male.shoulder_l"),
),
shoulder_r: (
offset: (-5.0, -4.5, -7.0),
lateral: ("npc.troll.male.shoulder_r"),
),
hand_l: (
offset: (-3.5, -4.0, -15.0),
lateral: ("npc.troll.male.hand_l"),
),
hand_r: (
offset: (-3.5, -4.0, -15.0),
lateral: ("npc.troll.male.hand_r"),
),
leg_l: (
offset: (-3.0, -2.5, -4.5),
lateral: ("npc.troll.male.leg_l"),
),
leg_r: (
offset: (-3.0, -2.5, -4.5),
lateral: ("npc.troll.male.leg_r"),
),
foot_l: (
offset: (-3.0, -5.0, -2.5),
lateral: ("npc.troll.male.foot_l"),
),
foot_r: (
offset: (-3.0, -5.0, -2.5),
lateral: ("npc.troll.male.foot_r"),
)
),
(Troll, Female): (
shoulder_l: (
offset: (-5.0, -4.5, -7.0),
lateral: ("npc.troll.male.shoulder_l"),
),
shoulder_r: (
offset: (-5.0, -4.5, -7.0),
lateral: ("npc.troll.male.shoulder_r"),
),
hand_l: (
offset: (-3.5, -4.0, -15.0),
lateral: ("npc.troll.male.hand_l"),
),
hand_r: (
offset: (-3.5, -4.0, -15.0),
lateral: ("npc.troll.male.hand_r"),
),
leg_l: (
offset: (-3.0, -2.5, -4.5),
lateral: ("npc.troll.male.leg_l"),
),
leg_r: (
offset: (-3.0, -2.5, -4.5),
lateral: ("npc.troll.male.leg_r"),
),
foot_l: (
offset: (-3.0, -5.0, -2.5),
lateral: ("npc.troll.male.foot_l"),
),
foot_r: (
offset: (-3.0, -5.0, -2.5),
lateral: ("npc.troll.male.foot_r"),
)
),
})
({
(Ogre, Male): (
shoulder_l: (
offset: (-4.0, -5.5, -4.0),
lateral: ("armor.empty"),
),
shoulder_r: (
offset: (-4.0, -5.5, -4.0),
lateral: ("npc.ogre.male.shoulder_r"),
),
hand_l: (
offset: (-2.5, -2.5, -11.0),
lateral: ("npc.ogre.male.hand_l"),
),
hand_r: (
offset: (-2.5, -2.5, -11.0),
lateral: ("npc.ogre.male.hand_r"),
),
leg_l: (
offset: (-6.0, -3.5, -7.0),
lateral: ("npc.ogre.male.leg_l"),
),
leg_r: (
offset: (0.0, -3.5, -7.0),
lateral: ("npc.ogre.male.leg_r"),
),
foot_l: (
offset: (-3.0, -5.0, -2.5),
lateral: ("npc.ogre.male.foot_l"),
),
foot_r: (
offset: (-3.0, -5.0, -2.5),
lateral: ("npc.ogre.male.foot_r"),
),
),
(Ogre, Female): (
shoulder_l: (
offset: (-4.0, -5.5, -4.0),
lateral: ("armor.empty"),
),
shoulder_r: (
offset: (-4.0, -5.5, -4.0),
lateral: ("npc.ogre.male.shoulder_r"),
),
hand_l: (
offset: (-2.5, -2.5, -11.0),
lateral: ("npc.ogre.male.hand_l"),
),
hand_r: (
offset: (-2.5, -2.5, -11.0),
lateral: ("npc.ogre.male.hand_r"),
),
leg_l: (
offset: (-6.0, -3.5, -7.0),
lateral: ("npc.ogre.male.leg_l"),
),
leg_r: (
offset: (0.0, -3.5, -7.0),
lateral: ("npc.ogre.male.leg_r"),
),
foot_l: (
offset: (-3.0, -5.0, -2.5),
lateral: ("npc.ogre.male.foot_l"),
),
foot_r: (
offset: (-3.0, -5.0, -2.5),
lateral: ("npc.ogre.male.foot_r"),
),
),
(Cyclops, Male): (
shoulder_l: (
offset: (-3.0, -4.0, -5.0),
lateral: ("npc.cyclops.male.shoulder_l"),
),
shoulder_r: (
offset: (-3.0, -4.0, -5.0),
lateral: ("npc.cyclops.male.shoulder_r"),
),
hand_l: (
offset: (-3.5, -3.5, -14.0),
lateral: ("npc.cyclops.male.hand_l"),
),
hand_r: (
offset: (-3.5, -3.5, -14.0),
lateral: ("npc.cyclops.male.hand_r"),
),
leg_l: (
offset: (-6.0, -3.5, -7.0),
lateral: ("npc.cyclops.male.leg_l"),
),
leg_r: (
offset: (0.0, -3.5, -7.0),
lateral: ("npc.cyclops.male.leg_r"),
),
foot_l: (
offset: (-3.0, -5.0, -5.0),
lateral: ("npc.cyclops.male.foot_l"),
),
foot_r: (
offset: (-3.0, -5.0, -5.0),
lateral: ("npc.cyclops.male.foot_r"),
),
),
(Cyclops, Female): (
shoulder_l: (
offset: (-3.0, -4.0, -5.0),
lateral: ("npc.cyclops.male.shoulder_l"),
),
shoulder_r: (
offset: (-3.0, -4.0, -5.0),
lateral: ("npc.cyclops.male.shoulder_r"),
),
hand_l: (
offset: (-3.5, -3.5, -14.0),
lateral: ("npc.cyclops.male.hand_l"),
),
hand_r: (
offset: (-3.5, -3.5, -14.0),
lateral: ("npc.cyclops.male.hand_r"),
),
leg_l: (
offset: (-6.0, -3.5, -7.0),
lateral: ("npc.cyclops.male.leg_l"),
),
leg_r: (
offset: (0.0, -3.5, -7.0),
lateral: ("npc.cyclops.male.leg_r"),
),
foot_l: (
offset: (-3.0, -5.0, -5.0),
lateral: ("npc.cyclops.male.foot_l"),
),
foot_r: (
offset: (-3.0, -5.0, -5.0),
lateral: ("npc.cyclops.male.foot_r"),
),
),
(Wendigo, Male): (
shoulder_l: (
offset: (-3.0, -4.0, -5.0),
lateral: ("npc.wendigo.male.shoulder_l"),
),
shoulder_r: (
offset: (-3.0, -4.0, -5.0),
lateral: ("npc.wendigo.male.shoulder_r"),
),
hand_l: (
offset: (-4.0, -3.5, -18.0),
lateral: ("npc.wendigo.male.hand_l"),
),
hand_r: (
offset: (-4.0, -3.5, -18.0),
lateral: ("npc.wendigo.male.hand_r"),
),
leg_l: (
offset: (-4.0, -2.5, -9.0),
lateral: ("npc.wendigo.male.leg_l"),
),
leg_r: (
offset: (0.0, -2.5, -9.0),
lateral: ("npc.wendigo.male.leg_r"),
),
foot_l: (
offset: (-4.0, -5.0, -5.5),
lateral: ("npc.wendigo.male.foot_l"),
),
foot_r: (
offset: (-4.0, -5.0, -5.5),
lateral: ("npc.wendigo.male.foot_r"),
),
),
(Wendigo, Female): (
shoulder_l: (
offset: (-3.0, -4.0, -5.0),
lateral: ("npc.wendigo.male.shoulder_l"),
),
shoulder_r: (
offset: (-3.0, -4.0, -5.0),
lateral: ("npc.wendigo.male.shoulder_r"),
),
hand_l: (
offset: (-4.0, -3.5, -18.0),
lateral: ("npc.wendigo.male.hand_l"),
),
hand_r: (
offset: (-4.0, -3.5, -18.0),
lateral: ("npc.wendigo.male.hand_r"),
),
leg_l: (
offset: (-4.0, -2.5, -9.0),
lateral: ("npc.wendigo.male.leg_l"),
),
leg_r: (
offset: (0.0, -2.5, -9.0),
lateral: ("npc.wendigo.male.leg_r"),
),
foot_l: (
offset: (-4.0, -5.0, -5.5),
lateral: ("npc.wendigo.male.foot_l"),
),
foot_r: (
offset: (-4.0, -5.0, -5.5),
lateral: ("npc.wendigo.male.foot_r"),
),
),
(Troll, Male): (
shoulder_l: (
offset: (-5.0, -4.5, -7.0),
lateral: ("npc.troll.male.shoulder_l"),
),
shoulder_r: (
offset: (-5.0, -4.5, -7.0),
lateral: ("npc.troll.male.shoulder_r"),
),
hand_l: (
offset: (-3.5, -4.0, -15.0),
lateral: ("npc.troll.male.hand_l"),
),
hand_r: (
offset: (-3.5, -4.0, -15.0),
lateral: ("npc.troll.male.hand_r"),
),
leg_l: (
offset: (-3.0, -2.5, -4.5),
lateral: ("npc.troll.male.leg_l"),
),
leg_r: (
offset: (-3.0, -2.5, -4.5),
lateral: ("npc.troll.male.leg_r"),
),
foot_l: (
offset: (-3.0, -5.0, -2.5),
lateral: ("npc.troll.male.foot_l"),
),
foot_r: (
offset: (-3.0, -5.0, -2.5),
lateral: ("npc.troll.male.foot_r"),
),
),
(Troll, Female): (
shoulder_l: (
offset: (-5.0, -4.5, -7.0),
lateral: ("npc.troll.male.shoulder_l"),
),
shoulder_r: (
offset: (-5.0, -4.5, -7.0),
lateral: ("npc.troll.male.shoulder_r"),
),
hand_l: (
offset: (-3.5, -4.0, -15.0),
lateral: ("npc.troll.male.hand_l"),
),
hand_r: (
offset: (-3.5, -4.0, -15.0),
lateral: ("npc.troll.male.hand_r"),
),
leg_l: (
offset: (-3.0, -2.5, -4.5),
lateral: ("npc.troll.male.leg_l"),
),
leg_r: (
offset: (-3.0, -2.5, -4.5),
lateral: ("npc.troll.male.leg_r"),
),
foot_l: (
offset: (-3.0, -5.0, -2.5),
lateral: ("npc.troll.male.foot_l"),
),
foot_r: (
offset: (-3.0, -5.0, -2.5),
lateral: ("npc.troll.male.foot_r"),
),
),
(Dullahan, Male): (
shoulder_l: (
offset: (-7.5, -5.5, -6.0),
lateral: ("npc.dullahan.male.shoulder_l"),
),
shoulder_r: (
offset: (-7.5, -5.5, -6.0),
lateral: ("npc.dullahan.male.shoulder_r"),
),
hand_l: (
offset: (-4.5, -4.5, -15.0),
lateral: ("npc.dullahan.male.hand_l"),
),
hand_r: (
offset: (-4.5, -4.5, -15.0),
lateral: ("npc.dullahan.male.hand_r"),
),
leg_l: (
offset: (-6.0, -3.0, -7.0),
lateral: ("npc.dullahan.male.leg_l"),
),
leg_r: (
offset: (0.0, -3.0, -7.0),
lateral: ("npc.dullahan.male.leg_r"),
),
foot_l: (
offset: (-3.0, -5.0, -8.0),
lateral: ("npc.dullahan.male.foot_l"),
),
foot_r: (
offset: (-3.0, -5.0, -8.0),
lateral: ("npc.dullahan.male.foot_r"),
),
),
(Dullahan, Female): (
shoulder_l: (
offset: (-7.5, -5.5, -6.0),
lateral: ("npc.dullahan.male.shoulder_l"),
),
shoulder_r: (
offset: (-7.5, -5.5, -6.0),
lateral: ("npc.dullahan.male.shoulder_r"),
),
hand_l: (
offset: (-4.5, -4.5, -15.0),
lateral: ("npc.dullahan.male.hand_l"),
),
hand_r: (
offset: (-4.5, -4.5, -15.0),
lateral: ("npc.dullahan.male.hand_r"),
),
leg_l: (
offset: (-6.0, -3.0, -7.0),
lateral: ("npc.dullahan.male.leg_l"),
),
leg_r: (
offset: (0.0, -3.0, -7.0),
lateral: ("npc.dullahan.male.leg_r"),
),
foot_l: (
offset: (-3.0, -5.0, -8.0),
lateral: ("npc.dullahan.male.foot_l"),
),
foot_r: (
offset: (-3.0, -5.0, -8.0),
lateral: ("npc.dullahan.male.foot_r"),
),
),
})

View File

@ -4,19 +4,19 @@
color: None
),
map: {
Green0: (
"Green0": (
vox_spec: ("armor.lantern.green-0", (-2.0, -2.0, -7.0)),
color: None
),
Black0: (
"Black0": (
vox_spec: ("armor.lantern.black-0", (-2.0, -2.0, -7.0)),
color: None
),
Red0: (
"Red0": (
vox_spec: ("armor.lantern.red-0", (-2.0, -2.0, -7.0)),
color: None
),
Blue0: (
"Blue0": (
vox_spec: ("armor.lantern.blue-0", (-2.0, -2.0, -7.0)),
color: None
),

BIN
assets/voxygen/voxel/npc/dullahan/male/foot_l.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/dullahan/male/foot_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/dullahan/male/hand_l.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/dullahan/male/hand_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/dullahan/male/leg_l.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/dullahan/male/leg_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/dullahan/male/shoulder_l.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/dullahan/male/shoulder_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/dullahan/male/sword.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/dullahan/male/torso_lower.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/dullahan/male/torso_upper.vox (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -213,7 +213,7 @@ impl Body {
pub fn radius(&self) -> f32 {
// TODO: Improve these values (some might be reliant on more info in inner type)
match self {
Body::Humanoid(_) => 0.5,
Body::Humanoid(_) => 0.2,
Body::QuadrupedSmall(_) => 0.3,
Body::QuadrupedMedium(_) => 0.9,
Body::Critter(_) => 0.2,
@ -229,8 +229,29 @@ impl Body {
}
}
// Note: currently assumes sphericality
pub fn height(&self) -> f32 { self.radius() * 2.0 }
pub fn height(&self) -> f32 {
match self {
Body::Humanoid(humanoid) => match humanoid.species {
humanoid::Species::Danari => 0.8,
humanoid::Species::Dwarf => 0.9,
humanoid::Species::Orc => 1.14,
humanoid::Species::Undead => 0.95,
_ => 1.0,
},
Body::QuadrupedSmall(_) => 0.6,
Body::QuadrupedMedium(_) => 0.5,
Body::Critter(_) => 0.4,
Body::BirdMedium(_) => 1.2,
Body::FishMedium(_) => 1.0,
Body::Dragon(_) => 5.0,
Body::BirdSmall(_) => 0.4,
Body::FishSmall(_) => 0.4,
Body::BipedLarge(_) => 4.0,
Body::Golem(_) => 5.0,
Body::QuadrupedLow(_) => 0.5,
Body::Object(_) => 0.6,
}
}
pub fn base_health(&self) -> u32 {
match self {

View File

@ -32,6 +32,7 @@ pub enum Species {
Cyclops = 1,
Wendigo = 2,
Troll = 3,
Dullahan = 4,
}
/// Data representing per-species generic data.
@ -43,6 +44,7 @@ pub struct AllSpecies<SpeciesMeta> {
pub cyclops: SpeciesMeta,
pub wendigo: SpeciesMeta,
pub troll: SpeciesMeta,
pub dullahan: SpeciesMeta,
}
impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies<SpeciesMeta> {
@ -55,15 +57,17 @@ impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies<SpeciesMeta>
Species::Cyclops => &self.cyclops,
Species::Wendigo => &self.wendigo,
Species::Troll => &self.troll,
Species::Dullahan => &self.dullahan,
}
}
}
pub const ALL_SPECIES: [Species; 4] = [
pub const ALL_SPECIES: [Species; 5] = [
Species::Ogre,
Species::Cyclops,
Species::Wendigo,
Species::Troll,
Species::Dullahan,
];
impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {

View File

@ -16,24 +16,6 @@ use specs_idvs::IdvStorage;
use std::{fs::File, io::BufReader};
use vek::Rgb;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Consumable {
Coconut,
Apple,
Cheese,
Potion,
Mushroom,
Velorite,
VeloriteFrag,
PotionMinor,
PotionMed,
PotionLarge,
PotionExp,
AppleShroomCurry,
AppleStick,
MushroomStick,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Throwable {
Bomb,
@ -45,43 +27,14 @@ pub enum Utility {
Collar,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Ingredient {
Flower,
Grass,
EmptyVial,
LeatherScraps,
ShinyGem,
Stones,
Twigs,
MortarPestle,
CraftsmanHammer,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum LanternKind {
Black0 = 1,
Green0 = 2,
Red0 = 3,
Blue0 = 4,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Lantern {
pub kind: LanternKind,
pub kind: String,
color: Rgb<u32>,
strength_thousandths: u32,
flicker_thousandths: u32,
}
pub const ALL_LANTERNS: [LanternKind; 4] = [
LanternKind::Black0,
LanternKind::Green0,
LanternKind::Red0,
LanternKind::Blue0,
];
impl Lantern {
pub fn strength(&self) -> f32 { self.strength_thousandths as f32 / 1000_f32 }
@ -97,7 +50,7 @@ pub enum ItemKind {
Lantern(Lantern),
Armor(armor::Armor),
Consumable {
kind: Consumable,
kind: String,
effect: Effect,
#[serde(default = "default_amount")]
amount: u32,
@ -113,7 +66,7 @@ pub enum ItemKind {
amount: u32,
},
Ingredient {
kind: Ingredient,
kind: String,
#[serde(default = "default_amount")]
amount: u32,
},

View File

@ -142,7 +142,7 @@ impl Tool {
recover_duration: Duration::from_millis(300),
base_healthchange: (-120.0 * self.base_power()) as i32,
range: 3.5,
max_angle: 60.0,
max_angle: 20.0,
},
LeapMelee {
energy_cost: 800,
@ -157,8 +157,8 @@ impl Tool {
buildup_duration: Duration::from_millis(700),
recover_duration: Duration::from_millis(150),
base_healthchange: (-50.0 * self.base_power()) as i32,
range: 3.0,
max_angle: 60.0,
range: 3.5,
max_angle: 20.0,
}],
Bow(_) => vec![
BasicRanged {
@ -171,7 +171,7 @@ impl Tool {
hit_entity: vec![
projectile::Effect::Damage((-40.0 * self.base_power()) as i32),
projectile::Effect::Knockback(10.0),
projectile::Effect::RewardEnergy(100),
projectile::Effect::RewardEnergy(50),
projectile::Effect::Vanish,
],
time_left: Duration::from_secs(15),
@ -202,7 +202,7 @@ impl Tool {
recover_duration: Duration::from_millis(400),
base_healthchange: (-50.0 * self.base_power()) as i32,
range: 3.5,
max_angle: 60.0,
max_angle: 20.0,
},
DashMelee {
energy_cost: 700,
@ -219,8 +219,8 @@ impl Tool {
buildup_duration: Duration::from_millis(0),
recover_duration: Duration::from_millis(300),
base_healthchange: (-10.0 * self.base_power()) as i32,
range: 10.0,
max_angle: 45.0,
range: 5.0,
max_angle: 20.0,
},
BasicMelee {
energy_cost: 350,
@ -238,8 +238,8 @@ impl Tool {
buildup_duration: Duration::from_millis(100),
recover_duration: Duration::from_millis(300),
base_healthchange: (-40.0 * self.base_power()) as i32,
range: 10.0,
max_angle: 45.0,
range: 3.5,
max_angle: 20.0,
},
BasicRanged {
energy_cost: 0,
@ -261,7 +261,6 @@ impl Tool {
col: (0.85, 0.5, 0.11).into(),
..Default::default()
}),
projectile_gravity: None,
},
BasicRanged {
@ -349,8 +348,8 @@ impl Tool {
buildup_duration: Duration::from_millis(0),
recover_duration: Duration::from_millis(1000),
base_healthchange: -20,
range: 5.0,
max_angle: 60.0,
range: 3.5,
max_angle: 15.0,
}],
}
}

View File

@ -2,7 +2,7 @@ pub mod item;
pub mod slot;
use crate::{assets, recipe::Recipe};
use item::{Consumable, Item, ItemKind};
use item::{Item, ItemKind};
use serde::{Deserialize, Serialize};
use specs::{Component, FlaggedStorage, HashMapStorage};
use specs_idvs::IdvStorage;
@ -38,7 +38,7 @@ impl Inventory {
/// Adds a new item to the first fitting group of the inventory or starts a
/// new group. Returns the item again if no space was found.
pub fn push(&mut self, item: Item) -> Option<Item> {
let item = match item.kind {
let item = match &item.kind {
ItemKind::Tool(_) | ItemKind::Armor { .. } | ItemKind::Lantern(_) => {
self.add_to_first_empty(item)
},
@ -61,7 +61,7 @@ impl Inventory {
..
}) = slot
{
if item_kind == *kind {
if *item_kind == *kind {
*amount += new_amount;
self.recount_items();
return None;
@ -92,7 +92,7 @@ impl Inventory {
..
}) = slot
{
if item_kind == *kind {
if *item_kind == *kind {
*amount += new_amount;
self.recount_items();
return None;
@ -123,7 +123,7 @@ impl Inventory {
..
}) = slot
{
if item_kind == *kind {
if *item_kind == *kind {
*amount += new_amount;
self.recount_items();
return None;
@ -153,7 +153,7 @@ impl Inventory {
..
}) = slot
{
if item_kind == *kind {
if *item_kind == *kind {
*amount += new_amount;
self.recount_items();
return None;
@ -424,7 +424,7 @@ impl Inventory {
} else {
*amount -= 1;
return_item.kind = ItemKind::Consumable {
kind: *kind,
kind: kind.clone(),
effect: *effect,
amount: 1,
};
@ -451,7 +451,7 @@ impl Inventory {
} else {
*amount -= 1;
return_item.kind = ItemKind::Ingredient {
kind: *kind,
kind: kind.clone(),
amount: 1,
};
self.recount_items();
@ -531,7 +531,7 @@ impl Component for Inventory {
pub enum InventoryUpdateEvent {
Init,
Used,
Consumed(Consumable),
Consumed(String),
Gave,
Given,
Swapped,

View File

@ -73,7 +73,7 @@ impl LoadoutBuilder {
recover_duration: Duration::from_millis(100),
base_healthchange: -(body.base_dmg() as i32),
range: body.base_range(),
max_angle: 80.0,
max_angle: 20.0,
}),
ability2: None,
ability3: None,

View File

@ -85,7 +85,7 @@ impl CharacterBehavior for Data {
if let Some(attack) = data.attacking {
if attack.applied && attack.hit_count > 0 {
data.updater.remove::<Attacking>(data.entity);
update.energy.change_by(100, EnergySource::HitEnemy);
update.energy.change_by(50, EnergySource::HitEnemy);
}
}

View File

@ -1,5 +1,5 @@
use crate::{
comp::{Attacking, CharacterState, EnergySource, StateUpdate},
comp::{Attacking, CharacterState, StateUpdate},
states::utils::*,
sys::character_behavior::*,
};
@ -57,7 +57,7 @@ impl CharacterBehavior for Data {
data.updater.insert(data.entity, Attacking {
base_healthchange: -(self.base_damage as i32),
range: 3.5,
max_angle: 180_f32.to_radians(),
max_angle: 45_f32.to_radians(),
applied: false,
hit_count: 0,
knockback: 0.0,
@ -90,14 +90,6 @@ impl CharacterBehavior for Data {
data.updater.remove::<Attacking>(data.entity);
}
// Grant energy on successful hit
if let Some(attack) = data.attacking {
if attack.applied && attack.hit_count > 0 {
data.updater.remove::<Attacking>(data.entity);
update.energy.change_by(100, EnergySource::HitEnemy);
}
}
update
}
}

View File

@ -1,5 +1,5 @@
use crate::{
comp::{Attacking, CharacterState, EnergySource, StateUpdate},
comp::{Attacking, CharacterState, StateUpdate},
states::utils::*,
sys::character_behavior::*,
};
@ -110,14 +110,6 @@ impl CharacterBehavior for Data {
data.updater.remove::<Attacking>(data.entity);
}
// Grant energy on successful hit
if let Some(attack) = data.attacking {
if attack.applied && attack.hit_count > 0 {
data.updater.remove::<Attacking>(data.entity);
update.energy.change_by(100, EnergySource::HitEnemy);
}
}
update
}
}

View File

@ -133,14 +133,6 @@ impl CharacterBehavior for Data {
data.updater.remove::<Attacking>(data.entity);
}
// Grant energy on successful hit
if let Some(attack) = data.attacking {
if attack.applied && attack.hit_count > 0 {
data.updater.remove::<Attacking>(data.entity);
update.energy.change_by(10, EnergySource::HitEnemy);
}
}
update
}
}

View File

@ -70,6 +70,8 @@ impl CharacterBehavior for Data {
fn behavior(&self, data: &JoinData) -> StateUpdate {
let mut update = StateUpdate::from(data);
handle_move(data, &mut update, 0.3);
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
let stage_time_active = self
.stage_time_active
@ -109,16 +111,6 @@ impl CharacterBehavior for Data {
},
};
// Handle hit applied
if let Some(attack) = data.attacking {
if attack.applied && attack.hit_count > 0 {
// Take energy on successful hit
update.energy.change_by(100, EnergySource::HitEnemy);
// Always remove component
data.updater.remove::<Attacking>(data.entity);
}
}
// Handling movement
if stage_time_active < Duration::from_millis(STAGE_DURATION / 3) {
let adjusted_accel = match (self.stage, data.physics.touch_entity.is_none()) {
@ -130,12 +122,7 @@ impl CharacterBehavior for Data {
// Move player forward while in first third of each stage
if update.vel.0.magnitude_squared() < BASE_SPEED.powf(2.0) {
update.vel.0 += data.dt.0
* (if data.physics.on_ground {
Vec3::new(0.0, 0.0, 500.0) // Jump upwards if on ground
} else {
Vec3::one()
} + adjusted_accel * Vec3::from(data.ori.0.xy()));
update.vel.0 += data.dt.0 * (adjusted_accel * Vec3::from(data.ori.0.xy()));
let mag2 = update.vel.0.magnitude_squared();
if mag2 > BASE_SPEED.powf(2.0) {
update.vel.0 = update.vel.0.normalized() * BASE_SPEED;
@ -155,14 +142,16 @@ impl CharacterBehavior for Data {
Stage::Third => (self.base_damage as f32 * 1.5) as u32,
};
update.vel.0 = Vec3::new(data.inputs.move_dir.x, data.inputs.move_dir.y, 0.0) * 5.0;
// Try to deal damage in second half of stage
data.updater.insert(data.entity, Attacking {
base_healthchange: -(dmg as i32),
range: 3.5,
max_angle: 180_f32.to_radians(),
max_angle: 45_f32.to_radians(),
applied: false,
hit_count: 0,
knockback: 16.0,
knockback: 10.0,
});
CharacterState::TripleStrike(Data {
@ -187,6 +176,8 @@ impl CharacterBehavior for Data {
// Player messed up inputs, don't transition
else { None };
update.vel.0 = Vec3::new(data.inputs.move_dir.x, data.inputs.move_dir.y, 0.0) * 5.0;
if let Some(stage) = next_stage {
CharacterState::TripleStrike(Data {
base_damage: self.base_damage,
@ -220,7 +211,7 @@ impl CharacterBehavior for Data {
if let Some(attack) = data.attacking {
if attack.applied && attack.hit_count > 0 {
data.updater.remove::<Attacking>(data.entity);
update.energy.change_by(100, EnergySource::HitEnemy);
update.energy.change_by(50, EnergySource::HitEnemy);
}
}

View File

@ -471,7 +471,7 @@ impl<'a> System<'a> for Sys {
let diff = Vec2::<f32>::from(pos.0 - pos_other.0);
let collision_dist = 0.95 * (scale + scale_other);
let collision_dist = 0.55 * (scale + scale_other);
if diff.magnitude_squared() > 0.0
&& diff.magnitude_squared() < collision_dist.powf(2.0)

View File

@ -24,12 +24,12 @@ pub fn handle_lantern(server: &mut Server, entity: EcsEntity) {
.write_storage::<comp::LightEmitter>()
.remove(entity);
} else {
let lantern_opt = ecs
.read_storage::<comp::Loadout>()
let loadout_storage = ecs.read_storage::<comp::Loadout>();
let lantern_opt = loadout_storage
.get(entity)
.and_then(|loadout| loadout.lantern.as_ref())
.and_then(|item| {
if let comp::item::ItemKind::Lantern(l) = item.kind {
if let comp::item::ItemKind::Lantern(l) = &item.kind {
Some(l)
} else {
None

View File

@ -157,7 +157,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
match &item.kind {
ItemKind::Consumable { kind, effect, .. } => {
maybe_effect = Some(*effect);
Some(comp::InventoryUpdateEvent::Consumed(*kind))
Some(comp::InventoryUpdateEvent::Consumed(kind.clone()))
},
ItemKind::Throwable { kind, .. } => {
if let Some(pos) =

View File

@ -0,0 +1 @@
-- This file should undo anything in `up.sql`

View File

@ -0,0 +1,17 @@
-- Delete invalid data caused by inconsistent enforcement of foreign key constraints.
DELETE FROM stats
WHERE NOT EXISTS (SELECT 1 FROM character WHERE character.id = stats.character_id);
DELETE FROM body
WHERE NOT EXISTS (SELECT 1 FROM character WHERE character.id = body.character_id);
DELETE FROM inventory
WHERE NOT EXISTS (SELECT 1 FROM character WHERE character.id = inventory.character_id);
DELETE FROM loadout
WHERE NOT EXISTS (SELECT 1 FROM character WHERE character.id = loadout.character_id);
-- Fix up incorrect skill data.
UPDATE stats
SET skills = json('{"skill_groups":[],"skills":[]}')
WHERE skills = json('""');

View File

@ -234,7 +234,7 @@ impl Drop for CharacterLoader {
/// After first logging in, and after a character is selected, we fetch this
/// data for the purpose of inserting their persisted data for the entity.
fn load_character_data(player_uuid: &str, character_id: i32, db_dir: &str) -> CharacterDataResult {
let connection = establish_connection(db_dir);
let connection = establish_connection(db_dir)?;
let result = schema::character::dsl::character
.filter(schema::character::id.eq(character_id))
@ -281,7 +281,7 @@ fn load_character_list(player_uuid: &str, db_dir: &str) -> CharacterListResult {
.inner_join(schema::body::table)
.inner_join(schema::stats::table)
.inner_join(schema::loadout::table)
.load::<(Character, Body, Stats, Loadout)>(&establish_connection(db_dir));
.load::<(Character, Body, Stats, Loadout)>(&establish_connection(db_dir)?);
match result {
Ok(data) => Ok(data
@ -322,7 +322,7 @@ fn create_character(
) -> CharacterListResult {
check_character_limit(uuid, db_dir)?;
let connection = establish_connection(db_dir);
let connection = establish_connection(db_dir)?;
connection.transaction::<_, diesel::result::Error, _>(|| {
use schema::{body, character, character::dsl::*, inventory, loadout, stats};
@ -413,12 +413,20 @@ fn create_character(
fn delete_character(uuid: &str, character_id: i32, db_dir: &str) -> CharacterListResult {
use schema::character::dsl::*;
diesel::delete(
character
.filter(id.eq(character_id))
.filter(player_uuid.eq(uuid)),
)
.execute(&establish_connection(db_dir))?;
let connection = establish_connection(db_dir)?;
if let Err(e) = connection.transaction::<_, diesel::result::Error, _>(|| {
diesel::delete(
character
.filter(id.eq(character_id))
.filter(player_uuid.eq(uuid)),
)
.execute(&connection)?;
Ok(())
}) {
error!(?e, "Error during stats batch update transaction");
}
load_character_list(uuid, db_dir)
}
@ -432,7 +440,7 @@ fn check_character_limit(uuid: &str, db_dir: &str) -> Result<(), Error> {
let character_count = character
.select(count_star())
.filter(player_uuid.eq(uuid))
.load::<i64>(&establish_connection(db_dir))?;
.load::<i64>(&establish_connection(db_dir)?)?;
match character_count.first() {
Some(count) => {
@ -511,25 +519,28 @@ impl CharacterUpdater {
fn batch_update(updates: impl Iterator<Item = (i32, CharacterUpdateData)>, db_dir: &str) {
let connection = establish_connection(db_dir);
if let Err(e) = connection.transaction::<_, diesel::result::Error, _>(|| {
updates.for_each(
|(character_id, (stats_update, inventory_update, loadout_update))| {
update(
character_id,
&stats_update,
&inventory_update,
&loadout_update,
&connection,
)
},
);
if let Err(e) = connection.and_then(|connection| {
connection.transaction::<_, diesel::result::Error, _>(|| {
updates.for_each(
|(character_id, (stats_update, inventory_update, loadout_update))| {
update(
character_id,
&stats_update,
&inventory_update,
&loadout_update,
&connection,
)
},
);
Ok(())
Ok(())
})
}) {
error!(?e, "Error during stats batch update transaction");
}
}
/// NOTE: Only call while a transaction is held!
fn update(
character_id: i32,
stats: &StatsUpdate,

View File

@ -31,10 +31,16 @@ embed_migrations!();
pub fn run_migrations(db_dir: &str) -> Result<(), diesel_migrations::RunMigrationsError> {
let db_dir = &apply_saves_dir_override(db_dir);
let _ = fs::create_dir(format!("{}/", db_dir));
embedded_migrations::run_with_output(&establish_connection(db_dir), &mut std::io::stdout())
embedded_migrations::run_with_output(
&establish_connection(db_dir).expect(
"If we cannot execute migrations, we should not be allowed to launch the server, so \
we don't populate it with bad data.",
),
&mut std::io::stdout(),
)
}
fn establish_connection(db_dir: &str) -> SqliteConnection {
fn establish_connection(db_dir: &str) -> QueryResult<SqliteConnection> {
let db_dir = &apply_saves_dir_override(db_dir);
let database_url = format!("{}/db.sqlite", db_dir);
@ -45,18 +51,21 @@ fn establish_connection(db_dir: &str) -> SqliteConnection {
// Set a busy timeout (in ms): https://sqlite.org/c3ref/busy_timeout.html
if let Err(e) = connection.batch_execute(
"
PRAGMA foreign_keys = ON;
PRAGMA journal_mode = WAL;
PRAGMA busy_timeout = 250;
",
) {
warn!(
?e,
"Failed adding PRAGMA statements while establishing sqlite connection, this will \
result in a higher likelihood of locking errors"
"Failed adding PRAGMA statements while establishing sqlite connection, including \
enabling foreign key constraints. We will not allow connecting to the server under \
these conditions."
);
return Err(e);
}
connection
Ok(connection)
}
fn apply_saves_dir_override(db_dir: &str) -> String {

View File

@ -137,9 +137,9 @@ impl<'a> System<'a> for Sys {
energy_cost: 0,
buildup_duration: Duration::from_millis(0),
recover_duration: Duration::from_millis(400),
base_healthchange: -60,
range: 5.0,
max_angle: 80.0,
base_healthchange: -40,
range: 3.5,
max_angle: 15.0,
}),
ability2: None,
ability3: None,

View File

@ -111,42 +111,49 @@ impl<'a> From<&'a comp::biped_large::Body> for SkeletonAttr {
(Cyclops, _) => (4.5, 7.5),
(Wendigo, _) => (3.0, 13.5),
(Troll, _) => (6.0, 10.0),
(Dullahan, _) => (3.0, 6.0),
},
upper_torso: match (body.species, body.body_type) {
(Ogre, _) => (0.0, 19.0),
(Cyclops, _) => (-2.0, 27.0),
(Wendigo, _) => (-1.0, 29.0),
(Troll, _) => (-1.0, 27.5),
(Dullahan, _) => (0.0, 29.0),
},
lower_torso: match (body.species, body.body_type) {
(Ogre, _) => (1.0, -5.5),
(Cyclops, _) => (1.0, -4.5),
(Wendigo, _) => (-1.5, -6.0),
(Troll, _) => (1.0, -10.5),
(Dullahan, _) => (0.0, -6.5),
},
shoulder: match (body.species, body.body_type) {
(Ogre, _) => (6.1, 0.5, 2.5),
(Cyclops, _) => (9.5, 2.5, 2.5),
(Wendigo, _) => (9.0, 0.5, -0.5),
(Troll, _) => (11.0, 0.5, -2.5),
(Dullahan, _) => (14.0, 0.5, 4.5),
},
hand: match (body.species, body.body_type) {
(Ogre, _) => (10.5, -1.0, -0.5),
(Cyclops, _) => (10.0, 2.0, -0.5),
(Wendigo, _) => (12.0, 0.0, -0.5),
(Troll, _) => (11.5, 0.0, -1.5),
(Dullahan, _) => (14.5, 0.0, -2.5),
},
leg: match (body.species, body.body_type) {
(Ogre, _) => (0.0, 0.0, 0.0),
(Cyclops, _) => (0.0, 0.0, -5.0),
(Wendigo, _) => (2.0, 2.0, -2.5),
(Troll, _) => (5.0, 0.0, -6.0),
(Dullahan, _) => (0.0, 0.0, -5.0),
},
foot: match (body.species, body.body_type) {
(Ogre, _) => (4.0, 2.5, 2.5),
(Cyclops, _) => (4.0, 0.5, 5.0),
(Wendigo, _) => (5.0, 0.5, 6.0),
(Troll, _) => (6.0, 0.5, 4.0),
(Dullahan, _) => (4.0, 2.5, 8.0),
},
}
}

View File

@ -21,6 +21,8 @@ impl Animation for JumpAnimation {
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let wave = (_anim_time as f32 * 1.0).sin();
next.head.position = Vec3::new(0.0, skeleton_attr.head.0, skeleton_attr.head.1);
next.head.orientation = Quaternion::rotation_z(0.8) * Quaternion::rotation_x(0.5);
next.head.scale = Vec3::one();
@ -30,11 +32,11 @@ impl Animation for JumpAnimation {
next.chest.scale = Vec3::one() / 18.0;
next.feet_f.position = Vec3::new(0.0, skeleton_attr.feet_f.0, skeleton_attr.feet_f.1);
next.feet_f.orientation = Quaternion::rotation_z(0.0);
next.feet_f.orientation = Quaternion::rotation_x(wave * 0.4);
next.feet_f.scale = Vec3::one();
next.feet_b.position = Vec3::new(0.0, skeleton_attr.feet_b.0, skeleton_attr.feet_b.1);
next.feet_b.orientation = Quaternion::rotation_x(0.0);
next.feet_b.orientation = Quaternion::rotation_x(wave * 0.4);
next.feet_b.scale = Vec3::one();
next.tail.position = Vec3::new(0.0, skeleton_attr.tail.0, skeleton_attr.tail.1);

View File

@ -22,8 +22,8 @@ impl Animation for RunAnimation {
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let wave = (anim_time as f32 * 13.0).sin();
let wave_cos = (anim_time as f32 * 13.0).sin();
let wave = (anim_time as f32 * 8.0).sin();
let wavealt = (anim_time as f32 * 8.0 + PI / 2.0).sin();
let wave_slow = (anim_time as f32 * 6.5 + PI).sin();
next.head.position = Vec3::new(0.0, skeleton_attr.head.0, skeleton_attr.head.1);
@ -36,15 +36,17 @@ impl Animation for RunAnimation {
skeleton_attr.chest.0 + wave * 1.0,
skeleton_attr.chest.1,
) / 18.0;
next.chest.orientation = Quaternion::rotation_y(0.0);
next.chest.orientation = Quaternion::rotation_x(wave * 0.1);
next.chest.scale = Vec3::one() / 18.0;
next.feet_f.position = Vec3::new(0.0, skeleton_attr.feet_f.0, skeleton_attr.feet_f.1);
next.feet_f.orientation = Quaternion::rotation_x(wave * 1.0);
next.feet_f.orientation =
Quaternion::rotation_x(wave * 0.8) * Quaternion::rotation_z(wavealt / 6.0);
next.feet_f.scale = Vec3::one();
next.feet_b.position = Vec3::new(0.0, skeleton_attr.feet_b.0, skeleton_attr.feet_b.1);
next.feet_b.orientation = Quaternion::rotation_x(wave_cos * 1.0);
next.feet_b.orientation =
Quaternion::rotation_x(wavealt * 0.8) * Quaternion::rotation_z(wavealt / 6.0);
next.feet_b.scale = Vec3::one();
next.tail.position =

View File

@ -88,7 +88,7 @@ use crate::audio::AudioFrontend;
use common::{
assets,
comp::{
item::{Consumable, ItemKind, ToolCategory},
item::{ItemKind, ToolCategory},
CharacterAbilityType, InventoryUpdateEvent, Ori, Pos,
},
event::EventBus,
@ -153,7 +153,7 @@ pub enum SfxInventoryEvent {
Collected,
CollectedTool(ToolCategory),
CollectFailed,
Consumed(Consumable),
Consumed(String),
Debug,
Dropped,
Given,
@ -177,7 +177,7 @@ impl From<&InventoryUpdateEvent> for SfxEvent {
SfxEvent::Inventory(SfxInventoryEvent::CollectFailed)
},
InventoryUpdateEvent::Consumed(consumable) => {
SfxEvent::Inventory(SfxInventoryEvent::Consumed(*consumable))
SfxEvent::Inventory(SfxInventoryEvent::Consumed(consumable.clone()))
},
InventoryUpdateEvent::Debug => SfxEvent::Inventory(SfxInventoryEvent::Debug),
InventoryUpdateEvent::Dropped => SfxEvent::Inventory(SfxInventoryEvent::Dropped),

View File

@ -77,8 +77,8 @@ impl State {
.filter(|kind| {
use common::comp::item::{tool::ToolKind, ItemKind};
if let ItemKind::Tool(kind) = kind {
if let ToolKind::Staff(_) = &kind.kind {
true
if let ToolKind::Staff(kind) = &kind.kind {
kind != "Sceptre"
} else if let ToolKind::Debug(kind) = &kind.kind {
kind == "Boost"
} else {

View File

@ -4,7 +4,7 @@ use common::{
comp::item::{
armor::{Armor, ArmorKind},
tool::{Tool, ToolKind},
Consumable, Ingredient, Item, ItemKind, Lantern, LanternKind, Throwable, Utility,
Item, ItemKind, Lantern, Throwable, Utility,
},
figure::Segment,
};
@ -20,24 +20,24 @@ use vek::*;
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum ItemKey {
Tool(ToolKind),
Lantern(LanternKind),
Lantern(String),
Armor(ArmorKind),
Utility(Utility),
Consumable(Consumable),
Consumable(String),
Throwable(Throwable),
Ingredient(Ingredient),
Ingredient(String),
Empty,
}
impl From<&Item> for ItemKey {
fn from(item: &Item) -> Self {
match &item.kind {
ItemKind::Tool(Tool { kind, .. }) => ItemKey::Tool(kind.clone()),
ItemKind::Lantern(Lantern { kind, .. }) => ItemKey::Lantern(*kind),
ItemKind::Lantern(Lantern { kind, .. }) => ItemKey::Lantern(kind.clone()),
ItemKind::Armor(Armor { kind, .. }) => ItemKey::Armor(kind.clone()),
ItemKind::Utility { kind, .. } => ItemKey::Utility(*kind),
ItemKind::Consumable { kind, .. } => ItemKey::Consumable(*kind),
ItemKind::Consumable { kind, .. } => ItemKey::Consumable(kind.clone()),
ItemKind::Throwable { kind, .. } => ItemKey::Throwable(*kind),
ItemKind::Ingredient { kind, .. } => ItemKey::Ingredient(*kind),
ItemKind::Ingredient { kind, .. } => ItemKey::Ingredient(kind.clone()),
}
}
}

View File

@ -8,7 +8,7 @@ use anim::Skeleton;
use common::{
assets::watch::ReloadIndicator,
comp::{
item::{armor::ArmorKind, tool::ToolKind, ItemKind, LanternKind},
item::{armor::ArmorKind, tool::ToolKind, ItemKind},
Body, CharacterState, Loadout,
},
figure::Segment,
@ -39,7 +39,7 @@ struct CharacterCacheKey {
chest: Option<ArmorKind>,
belt: Option<ArmorKind>,
back: Option<ArmorKind>,
lantern: Option<LanternKind>,
lantern: Option<String>,
hand: Option<ArmorKind>,
pants: Option<ArmorKind>,
foot: Option<ArmorKind>,
@ -88,7 +88,7 @@ impl CharacterCacheKey {
lantern: if let Some(ItemKind::Lantern(lantern)) =
loadout.lantern.as_ref().map(|i| &i.kind)
{
Some(lantern.kind)
Some(lantern.kind.clone())
} else {
None
},

View File

@ -13,7 +13,7 @@ use common::{
item::{
armor::{Armor, ArmorKind},
tool::{Tool, ToolKind},
ItemKind, Lantern, LanternKind,
ItemKind, Lantern,
},
object,
quadruped_low::{BodyType as QLBodyType, Species as QLSpecies},
@ -268,7 +268,7 @@ pub struct HumArmorFootSpec(ArmorVoxSpecMap<String, ArmorVoxSpec>);
#[derive(Serialize, Deserialize)]
pub struct HumMainWeaponSpec(HashMap<ToolKind, ArmorVoxSpec>);
#[derive(Serialize, Deserialize)]
pub struct HumArmorLanternSpec(ArmorVoxSpecMap<LanternKind, ArmorVoxSpec>);
pub struct HumArmorLanternSpec(ArmorVoxSpecMap<String, ArmorVoxSpec>);
#[derive(Serialize, Deserialize)]
pub struct HumArmorHeadSpec(ArmorVoxSpecMap<String, ArmorVoxSpec>);
#[derive(Serialize, Deserialize)]
@ -841,7 +841,7 @@ impl HumArmorLanternSpec {
let spec = if let Some(ItemKind::Lantern(Lantern { kind, .. })) =
loadout.lantern.as_ref().map(|i| &i.kind)
{
match self.0.map.get(&kind) {
match self.0.map.get(kind) {
Some(spec) => spec,
None => {
error!(?kind, "No lantern specification exists");