Armas de Proyectil
Objetivo
Agregar ataques de proyectil a la Espada de Cristal del tutorial Crear un Banco de Crafteo. Crearás un elemento de daño personalizado, munición crafteable y dos ataques de proyectil: un rayo cargado que consume munición al embestir, y un orbe especial que se dispara cuando la SignatureEnergy está llena.

Lo que Aprenderás
- Cómo las definiciones de
Projectiley los archivosProjectileConfigtrabajan juntos - Cómo las interacciones
Type: "Projectile"disparan proyectiles desde armas - Cómo
Type: "Charging"crea ataques de mantener-para-cargar con una barra de progreso - Cómo
Type: "ModifyInventory"consume munición con un respaldo en caso de fallo - Cómo
EntityStatsOnHitgenera SignatureEnergy a partir de impactos de proyectil - Cómo
InteractionVarssobrescribe el comportamiento vanilla de la espada sin reemplazar la cadena completa
Requisitos Previos
- El mod del Yunque de Cristal de Crear un Banco de Crafteo
- El mod del bloque Brillo de Cristal de Crear un Bloque Personalizado
- El mod del Árbol Encantado de Árboles y Semillas Personalizados
Repositorio del mod complementario: hytale-mods-custom-projectile (v2.0.0)
Descripción General del Sistema de Proyectiles
El sistema de proyectiles de Hytale tiene tres capas:
| Capa | Ubicación | Propósito |
|---|---|---|
| Definición de Proyectil | Server/Projectiles/ | La entidad del proyectil: apariencia, física, hitbox, daño base |
| Config de Proyectil | Server/ProjectileConfigs/ | Configuración de lanzamiento: fuerza, desplazamiento de aparición, sonidos y cadenas de interacción de impacto/fallo |
| Interacción del Arma | Server/Item/Interactions/ | Type: "Projectile" con una referencia Config que dispara el proyectil |
El flujo es:
Jugador mantiene ataque → Interacción de carga (1s) → ModifyInventory (consumir munición) → Éxito: Animación de embestida + Proyectil se dispara desde la punta de la espada → Fallo (sin munición): Ataque de embestida normalPaso 1: Crear un Elemento de Daño Personalizado
Crea un nuevo tipo de daño para que los proyectiles de cristal inflijan su propio elemento de daño con un color distintivo.
Server/Entity/Damage/Crystal_Light.json{ "Parent": "Elemental", "Inherits": "Elemental", "DamageTextColor": "#88ccff"}Los campos Parent e Inherits hacen que Crystal Light se comporte como otros daños elementales (afectado por resistencia elemental). El DamageTextColor controla el color del número de daño flotante — azul claro para coincidir con el tema de cristal.
Los elementos de daño vanilla como Fire, Ice y Nature siguen el mismo patrón. Puedes referenciar tu elemento personalizado por nombre ("Crystal_Light") en cualquier objeto BaseDamage.
Paso 2: Crear Definiciones de Proyectil
Las definiciones de proyectil describen la entidad física que viaja por el mundo. Crea dos: un rayo rápido para el ataque cargado y un orbe grande para el ataque especial.
Rayo de Luz de Cristal
Server/Projectiles/Crystal_Light_Bolt.json{ "Appearance": "Ice_Bolt", "Radius": 0.2, "Height": 0.2, "HorizontalCenterShot": 0.2, "VerticalCenterShot": 0.1, "DepthShot": 1.5, "PitchAdjustShot": true, "SticksVertically": false, "MuzzleVelocity": 55, "TerminalVelocity": 60, "Gravity": 2, "ImpactSlowdown": 0, "TimeToLive": 10, "Damage": 18, "DeadTimeMiss": 0, "DeathEffectsOnHit": true, "HitParticles": { "SystemId": "Impact_Ice" }, "DeathParticles": { "SystemId": "Impact_Ice" }, "HitSoundEventId": "SFX_Ice_Break", "DeathSoundEventId": "SFX_Ice_Break"}Orbe de Luz de Cristal
Server/Projectiles/Crystal_Light_Orb.json{ "Appearance": "Ice_Ball", "Radius": 2.5, "Height": 0.3, "HorizontalCenterShot": 0.2, "DepthShot": 1, "PitchAdjustShot": false, "SticksVertically": false, "MuzzleVelocity": 35, "TerminalVelocity": 45, "Gravity": 3, "Damage": 36, "DeathEffectsOnHit": true, "TimeToLive": 5, "DeadTimeMiss": 0, "ImpactSlowdown": 0, "VerticalCenterShot": 0, "HitParticles": { "SystemId": "Impact_Ice" }, "DeathParticles": { "SystemId": "IceBall_Explosion" }, "MissParticles": { "SystemId": "IceBall_Explosion" }, "DeathSoundEventId": "SFX_Ice_Ball_Death"}Diferencias Clave
| Propiedad | Rayo | Orbe |
|---|---|---|
Appearance | Ice_Bolt (pequeño, tipo flecha) | Ice_Ball (esfera grande) |
MuzzleVelocity | 55 (rápido) | 35 (más lento) |
Gravity | 2 (trayectoria plana) | 3 (arco leve) |
Radius | 0.2 (estrecho) | 2.5 (amplio con salpicadura) |
Damage | 18 | 36 (doble) |
Paso 3: Crear Configs de Proyectil
Los Configs de Proyectil conectan la interacción del arma con el proyectil. Definen la fuerza de lanzamiento, posición de aparición, sonidos y qué sucede al impactar o fallar.
Config del Rayo
Server/ProjectileConfigs/HytaleModdingManual/Projectile_Config_Crystal_Light_Bolt.json{ "Parent": "Projectile_Config_Arrow_Base", "Model": "Ice_Bolt", "Physics": { "Type": "Standard", "Gravity": 2, "TerminalVelocityAir": 60, "TerminalVelocityWater": 15, "RotationMode": "VelocityDamped", "Bounciness": 0.0, "SticksVertically": false }, "LaunchForce": 55, "SpawnOffset": { "X": 0.3, "Y": -0.3, "Z": 1.5 }, "LaunchLocalSoundEventId": "SFX_Ice_Break", "LaunchWorldSoundEventId": "SFX_Ice_Break", "Interactions": { "ProjectileHit": { "Interactions": [ "Crystal_Light_Bolt_Damage", "Common_Projectile_Despawn" ] }, "ProjectileMiss": { "Interactions": [ "Common_Projectile_Miss", "Common_Projectile_Despawn" ] } }}El SpawnOffset controla dónde aparece el proyectil relativo al jugador. Z: 1.5 lo empuja hacia adelante hasta la punta de la espada. Y: -0.3 lo baja desde la altura de la cabeza.
Parent: "Projectile_Config_Arrow_Base" hereda la física y rotación de aparición predeterminadas de flechas. Sobrescribimos Physics, LaunchForce y SpawnOffset para el comportamiento de nuestro rayo de cristal.
Config del Orbe
Server/ProjectileConfigs/HytaleModdingManual/Projectile_Config_Crystal_Light_Orb.json{ "Parent": "Projectile_Config_Arrow_Base", "Model": "Ice_Ball", "Physics": { "Type": "Standard", "Gravity": 3, "TerminalVelocityAir": 45, "TerminalVelocityWater": 10, "RotationMode": "VelocityDamped", "Bounciness": 0.0, "SticksVertically": false }, "LaunchForce": 35, "LaunchLocalSoundEventId": "SFX_Ice_Ball_Death", "LaunchWorldSoundEventId": "SFX_Ice_Ball_Death", "Interactions": { "ProjectileHit": { "Interactions": [ "Crystal_Light_Orb_Damage", "Common_Projectile_Despawn" ] }, "ProjectileMiss": { "Interactions": [ "Common_Projectile_Miss", "Common_Projectile_Despawn" ] } }}Paso 4: Crear Interacciones de Daño
Las interacciones de daño definen qué sucede cuando un proyectil impacta una entidad. Especifican cantidades de daño, retroceso, partículas, sonidos y generación de estadísticas.
Daño del Rayo
Server/Item/Interactions/HytaleModdingManual/Crystal_Light_Bolt_Damage.json{ "Parent": "DamageEntityParent", "DamageCalculator": { "BaseDamage": { "Crystal_Light": 18 } }, "DamageEffects": { "Knockback": { "Type": "Force", "VelocityConfig": { "AirResistance": 0.97, "AirResistanceMax": 0.96, "GroundResistance": 0.94, "GroundResistanceMax": 0.3, "Threshold": 3.0, "Style": "Exp" }, "Direction": { "X": 0.0, "Y": 1, "Z": -3 }, "Force": 8, "VelocityType": "Add" }, "WorldParticles": [ { "SystemId": "Impact_Ice", "Scale": 1 } ], "WorldSoundEventId": "SFX_Ice_Break", "EntityStatsOnHit": [ { "EntityStatId": "SignatureEnergy", "Amount": 5 } ] }}Daño del Orbe
Server/Item/Interactions/HytaleModdingManual/Crystal_Light_Orb_Damage.json{ "Parent": "DamageEntityParent", "DamageCalculator": { "BaseDamage": { "Crystal_Light": 36 } }, "DamageEffects": { "Knockback": { "Type": "Force", "VelocityConfig": { "AirResistance": 0.97, "AirResistanceMax": 0.96, "GroundResistance": 0.94, "GroundResistanceMax": 0.3, "Threshold": 3.0, "Style": "Exp" }, "Direction": { "X": 0.0, "Y": 3, "Z": -1 }, "Force": 20, "VelocityType": "Set" }, "WorldParticles": [ { "SystemId": "Impact_Ice", "Scale": 1 }, { "SystemId": "IceBall_Explosion", "Scale": 1 } ], "WorldSoundEventId": "SFX_Ice_Ball_Death", "EntityStatsOnHit": [ { "EntityStatId": "SignatureEnergy", "Amount": 10 } ] }}Generación de SignatureEnergy
El array EntityStatsOnHit es clave para el ciclo de progresión de la espada. Cada impacto de rayo otorga +5 de SignatureEnergy, y cada impacto de orbe otorga +10. Cuando la SignatureEnergy alcanza el 100%, el ataque especial queda disponible. Esto crea un ciclo de juego: usa ataques cargados para acumular energía, y luego desata el poderoso orbe.
Paso 5: Crear el Objeto de Munición
Las Cargas de Luz son la munición consumida por el ataque cargado. Se craftean en el Yunque de Cristal en lotes de 50.
Server/Item/Items/HytaleModdingManual/Weapon_Arrow_Crystal_Glow.json{ "TranslationProperties": { "Name": "server.items.Weapon_Arrow_Crystal_Glow.name", "Description": "server.items.Weapon_Arrow_Crystal_Glow.description" }, "Categories": [ "Items.Weapons" ], "Quality": "Uncommon", "ItemLevel": 25, "PlayerAnimationsId": "Dagger", "Recipe": { "TimeSeconds": 5.0, "KnowledgeRequired": false, "Input": [ { "ItemId": "Plant_Fruit_Enchanted", "Quantity": 1 }, { "ItemId": "Ore_Crystal_Glow", "Quantity": 1 }, { "ItemId": "Weapon_Arrow_Crude", "Quantity": 10 } ], "OutputQuantity": 50, "BenchRequirement": [ { "Type": "Crafting", "Categories": [ "Crystal_Glow" ], "Id": "Armory_Crystal_Glow" } ] }, "Model": "Items/Weapons/Arrow/Arrow.blockymodel", "Texture": "Items/Weapons/Arrow/Crude_Texture.png", "Icon": "Icons/ItemsGenerated/Weapon_Arrow_Crude.png", "MaxStack": 100, "Tags": { "Type": [ "Weapon" ], "Family": [ "Arrow" ] }, "Weapon": {}, "Light": { "Radius": 1, "Color": "#88ccff" }, "ItemSoundSetId": "ISS_Weapons_Arrows"}
Puntos clave:
OutputQuantity: 50produce 50 cargas por crafteo — importante para objetos de munición que se consumen rápidamente- Sin
InteractionsniInteractionVars— este objeto es solo munición, no un arma que puedas blandir - El objeto vacío
Weapon: {}es necesario para que el objeto aparezca en las categorías de armas MaxStack: 100permite llevar una cantidad razonable
Paso 6: Crear las Interacciones de Disparo
Estas son interacciones simples de Type: "Projectile" que disparan cada proyectil. Deben ser archivos nombrados, no en línea — Hytale valida las interacciones por ID de asset y las interacciones de proyectil en línea pueden fallar la validación.
Disparo del Rayo
Server/Item/Interactions/HytaleModdingManual/Crystal_Sword_Shoot_Bolt.json{ "Type": "Projectile", "Config": "Projectile_Config_Crystal_Light_Bolt", "Next": { "Type": "Simple", "RunTime": 0.2 }}Disparo del Orbe
Server/Item/Interactions/HytaleModdingManual/Crystal_Sword_Shoot_Orb.json{ "Type": "Projectile", "Config": "Projectile_Config_Crystal_Light_Orb", "Next": { "Type": "Simple", "RunTime": 0.2 }}El campo Config referencia el ProjectileConfig por nombre de archivo (sin .json). El bloque Next agrega un breve tiempo de espera después de disparar.
Paso 7: Crear la Interacción de Carga
La interacción de carga requiere que el jugador mantenga presionado el botón de ataque durante 1 segundo antes de que se active el ataque cargado.
Server/Item/Interactions/HytaleModdingManual/Crystal_Sword_Charge.json{ "Type": "Charging", "AllowIndefiniteHold": false, "DisplayProgress": true, "HorizontalSpeedMultiplier": 0.5, "Next": { "0": "Weapon_Sword_Primary_Thrust", "1.0": "Crystal_Sword_Charged_Entry" }}| Campo | Propósito |
|---|---|
AllowIndefiniteHold | false significa que se dispara automáticamente cuando se alcanza el umbral más alto |
DisplayProgress | Muestra la barra de carga sobre la barra de acceso rápido |
HorizontalSpeedMultiplier | Reduce la velocidad de movimiento mientras se carga (0.5 = mitad de velocidad) |
Next | Mapea umbrales de carga (en segundos) a interacciones |
Los umbrales funcionan como “el más alto alcanzado”:
- Soltar antes de 1.0s → ejecuta
"0"→ embestida vanilla normal (no se consume munición) - Mantener por 1.0s → se dispara automáticamente
"1.0"→ entrada cargada con proyectil
Paso 8: Crear la Entrada Cargada
Este es el núcleo del ataque cargado. Verifica la munición, la consume, reproduce la animación de embestida y dispara el rayo.
Server/Item/Interactions/HytaleModdingManual/Crystal_Sword_Charged_Entry.json{ "Type": "ModifyInventory", "ItemToRemove": { "Id": "Weapon_Arrow_Crystal_Glow", "Quantity": 1 }, "AdjustHeldItemDurability": -0.3, "Next": { "Type": "Parallel", "Interactions": [ { "Interactions": [ "Weapon_Sword_Primary_Thrust" ] }, { "Interactions": [ { "Type": "Simple", "RunTime": 0.6 }, "Crystal_Sword_Shoot_Bolt" ] } ] }, "Failed": "Weapon_Sword_Primary_Thrust"}Cómo funciona
ModifyInventoryverifica si el jugador tiene 1Weapon_Arrow_Crystal_Glowen el inventario- Si tiene (
Next): remueve la munición, reduce la durabilidad en 0.3, luego ejecuta unParallel:- Rama 1: Reproduce la animación de embestida vanilla (
Weapon_Sword_Primary_Thrust) - Rama 2: Espera 0.6 segundos (sincronizando el proyectil con el final de la animación de embestida), luego dispara el rayo
- Rama 1: Reproduce la animación de embestida vanilla (
- Si no tiene munición (
Failed): realiza una embestida normal sin proyectil
El Parallel es esencial para la sincronización — permite que el proyectil se dispare en el momento exacto en que la animación de embestida alcanza la extensión completa (0.6s), en lugar de esperar a que toda la animación termine.
Paso 9: Crear el Ataque Especial
El ataque especial dispara un poderoso Orbe de Luz de Cristal cuando la SignatureEnergy alcanza el 100%.
Interacción Raíz
Server/Item/RootInteractions/HytaleModdingManual/Crystal_Sword_Special.json{ "Interactions": [ "Crystal_Sword_Special" ]}Interacción Especial
Server/Item/Interactions/HytaleModdingManual/Crystal_Sword_Special.json{ "Type": "StatsCondition", "Costs": { "SignatureEnergy": 100 }, "ValueType": "Percent", "Next": { "Type": "Serial", "Interactions": [ { "Type": "Parallel", "Interactions": [ { "Interactions": [ { "Type": "Simple", "RunTime": 0.4, "Effects": { "ItemPlayerAnimationsId": "Sword", "ItemAnimationId": "Thrust", "ClearAnimationOnFinish": true, "Particles": [ { "SystemId": "IceBall", "TargetNodeName": "Handle", "PositionOffset": { "X": 1.0, "Y": 0, "Z": 0 } } ] } } ] }, { "Interactions": [ "Crystal_Sword_Shoot_Orb" ] } ] }, { "Type": "ChangeStat", "StatModifiers": { "SignatureEnergy": -100 }, "ValueType": "Percent" } ] }}El flujo:
StatsConditionverifica si la SignatureEnergy está al 100% — si no, no pasa nadaParallelejecuta la animación de embestida (con partículas de IceBall en la hoja) junto con el proyectil del orbeChangeStatdrena toda la SignatureEnergy después del ataque
Paso 10: Conectar Todo a la Espada
Actualiza Weapon_Sword_Crystal_Glow.json para conectar todos los nuevos sistemas. Los cambios clave están en Interactions, InteractionVars y Weapon:
{ "Parent": "Template_Weapon_Sword", "Interactions": { "Primary": "Root_Weapon_Sword_Primary", "Secondary": "Root_Weapon_Sword_Secondary_Guard", "Ability1": "Crystal_Sword_Special" }, "InteractionVars": { "Thrust_Damage": { "Interactions": [ { "Parent": "Weapon_Sword_Primary_Thrust_Damage", "DamageCalculator": { "BaseDamage": { "Physical": 20, "Crystal_Light": 12 } } } ] }, "Thrust_Stamina": { "Interactions": [ "Crystal_Sword_Charge" ] } }, "Weapon": { "EntityStatsToClear": [ "SignatureEnergy" ], "StatModifiers": { "SignatureEnergy": [ { "Amount": 20, "CalculationType": "Additive" } ] } }, "ItemAppearanceConditions": { "SignatureEnergy": [ { "Condition": [100, 100], "ConditionValueType": "Percent", "Particles": [ { "SystemId": "Sword_Signature_Ready", "TargetNodeName": "Handle", "PositionOffset": { "X": 0.8 }, "TargetEntityPart": "PrimaryItem" } ] } ] }}Qué hace cada sección
Interactions — Vincula los botones de ataque a cadenas de interacción:
Primaryusa el ataque primario vanilla de espada (Root_Weapon_Sword_Primary) — esto preserva el combo completo de golpesAbility1se vincula a nuestro ataque especial personalizado
InteractionVars — Sobrescribe partes específicas de la cadena vanilla sin reemplazarla:
Thrust_Damageagrega daño Crystal_Light a la embestidaThrust_Staminareemplaza la verificación de estamina con nuestra interacción de carga — así es como el ataque de proyectil cargado se integra en el combo existente de la espada
Weapon — Configura la SignatureEnergy:
StatModifiersagrega 20 de SignatureEnergy máxima cuando está equipadaEntityStatsToClearreinicia la energía cuando se desequipa el arma
ItemAppearanceConditions — Muestra partículas brillantes en la espada cuando la SignatureEnergy alcanza el 100%, señalando que el ataque especial está listo.
Paso 11: Probar en el Juego
-
Copia la carpeta
CreateACraftingBench/a%APPDATA%/Hytale/UserData/Mods/ -
Asegúrate de que los mods CreateACustomBlock y CustomTreesAndSaplings también estén instalados (dependencias requeridas)
-
Inicia Hytale y craftea Cargas de Luz en el Yunque de Cristal
-
Prueba el ataque cargado:
- Equipa la Espada de Cristal con Cargas de Luz en tu inventario
- Mantén presionado el ataque primario — la barra de carga debería aparecer
- Suelta antes de 1s → embestida normal (no se consume munición)
- Mantén por 1s → animación de embestida + rayo de cristal se dispara desde la punta de la espada
-
Prueba el ataque especial:
- Golpea enemigos con rayos cargados para acumular SignatureEnergy (+5 por impacto de rayo)
- Cuando la espada brille (100% de energía), presiona Habilidad1
- Un gran Orbe de Luz de Cristal debería dispararse con un efecto de explosión
Errores comunes y soluciones:
| Error | Causa | Solución |
|---|---|---|
Failed to validate asset | Interacción Type: "Projectile" en línea | Extraer a un archivo nombrado |
| El proyectil sale de la cabeza | SpawnOffset no configurado | Agregar SpawnOffset con Z: 1.5 para moverlo hacia adelante |
| Munición consumida sin proyectil | RunTime en un Type: "Projectile" | Usar Next: { "Type": "Simple", "RunTime": 0.2 } en su lugar |
| Disparo rápido infinito | Replace Var apuntando a su propia sobrescritura | Referenciar interacciones directamente, nunca auto-referenciar |
| Barra de carga no visible | DisplayProgress faltante | Establecer "DisplayProgress": true en la interacción Charging |
| El especial nunca se activa | Sin EntityStatsOnHit en el daño | Agregar EntityStatsOnHit con cantidad de SignatureEnergy a las interacciones de daño |
Resumen de Estructura de Archivos
CreateACraftingBench/ Server/ Entity/Damage/ Crystal_Light.json Projectiles/ Crystal_Light_Bolt.json Crystal_Light_Orb.json ProjectileConfigs/HytaleModdingManual/ Projectile_Config_Crystal_Light_Bolt.json Projectile_Config_Crystal_Light_Orb.json Item/ Interactions/HytaleModdingManual/ Crystal_Light_Bolt_Damage.json Crystal_Light_Orb_Damage.json Crystal_Sword_Charge.json Crystal_Sword_Charged_Entry.json Crystal_Sword_Shoot_Bolt.json Crystal_Sword_Shoot_Orb.json Crystal_Sword_Special.json RootInteractions/HytaleModdingManual/ Crystal_Sword_Special.json Items/HytaleModdingManual/ Weapon_Arrow_Crystal_Glow.json Weapon_Sword_Crystal_Glow.json (actualizado)Próximos Pasos
- Tiendas de NPC y Comercio — vende Cargas de Luz en una tienda de mercader
- Tablas de Botín Personalizadas — haz que los enemigos suelten Cargas de Luz
- Referencia de Config de Proyectil — referencia completa del esquema para todos los campos de config de proyectil