damage

Daños y resistencias

En Sticks & Stones hemos optado por un sistema de daños y resistencias, lo que significa que un arma que puede ser poderosa contra un enemigo pero débil contra otro. Lo mismo ocurre con los enemigos, que pueden ser vulnerables o resistentes a los diferentes tipos de daño.

Tipos de daño

Los objetos que causan daño, como las armas, definen uno o varios tipos de daño.

  • Perforante
  • Aplastante
  • Cortante
  • Hendidor
  • Fuego
  • Disparo
  • Virtual

En nuestro código, utilizamos un enum para catalogarlos.

public enum DamageType
{
    Piercing,
    Crushing,
    Slashing,
    Cleaving,
    Fire,
    Shoot,
    Virtual
}

Un arma podría combinar varios tipos de daño, por ejemplo un garrote con pinchos combinaría daño aplastante y perforante. Además para cada tipo de daño se define la cantidad de daño, pero eso lo veremos más adelante.

Armas

Las armas tienen varias propiedades en común. En nuestro código las agrupamos con 3 interfaces: IInventariable, IEquippable y IDamageDealer.

public abstract class Weapon : Wearable,
    IInventariable,
    IEquippable,
    IDamageDealer
{
    ...
}

Inventariable: indica que las armas pueden colocarse en un inventario, como por ejemplo la mochila.

public interface IInventariable
{
    InventariableType InventariableType { get; }
 
    float Weight { get; }
 
    bool Stackable { get; }
 
    short InventoryValue { get; }
}

Equipable: indica que las armas pueden equiparse en el cuerpo de un personaje.

public interface IEquippable
{
    List<BodyPart> AllowedEquippableAreas { get; }
 
    bool TwoHandsUse { get; }
}

Dañino: cualquier objeto que puede causar daños.

/// <summary>
/// Cualquier cosa susceptible de causar daño.
/// </summary>
public interface IDamageDealer
{
    /// <summary>
    /// Objeto con la configuración e información sobre el daño.
    /// </summary>
    DamageSource DamageSource { get; }
 
    /// <summary>
    /// Indica si puede ser lanzado o arrojado.
    /// </summary>
    bool CanBeHurled { get; }
}

La parte más interesante es IDamageDealer que es la interface que indica que un objeto puede causar daño mediante la propiedad DamageSource, que habla de la cantidad y tipos de daño.

DamageSource básicamente contiene un diccionario donde la clave es el tipo de daño y el valor es un entero que indica la cantidad de daño.

public class DamageSource
{
    public readonly Dictionary<DamageTypeint> DamageByType;
 
    #region Constructor
    public DamageSource(Dictionary<DamageTypeint> types)
    {
        DamageByType = types;
    }
    #endregion
}

Inicialmente DamageSource tenía propiedades adicionales relacionadas con efectos negativos (debuff) que se aplicaban al atacar. Pero es una mecánica que por ahora vamos a omitir del videojuego.

Estos son ejemplos de objetos dañinos (armas principalmente) que tenemos configurados en Sticks & Stones.

stone-axe-icon  Hacha de piedra
Hendidor = 13
wooden-bow-icon  Arco de madera
Disparo = 5
wooden-club-icon  Mazo de madera
Aplastante = 25
bone-knife  Cuchillo de hueso
Perforante = 4
Cortante = 2
*Daño potencial = 6
wooden-arrows  Flecha de madera
Perforante = 8

En el caso de las armas de proyectil, cómo los arcos, el daño que acaban causando depende también del proyectil que lanzan. Simplificando, se puede decir que un arma de proyectil causa un daño equivalente al suyo más el del proyectil que lanza. Según los ejemplos anteriores, un arco de madera que lanza flechas de madera, tendría un daño potencial de 13 (5 de disparo y 8 de perforante).

Resistencia y vulnerabilidad al daño

La resistencia o vulnerabilidad al daño es una propiedad que se configura en los personajes, pero también afecta al entorno, como por ejemplo un árbol.

Similar a cómo ocurre en las armas, en el código utilizamos una interface que indica si un objeto puede recibir daño.

Esta interface se llama IVulnerable.

public interface IVulnerable
    {
        uint BaseHitPoints { get; }
 
        int CurrentHitPoints { getset; }
 
        Dictionary<DamageTypeint> ResistencesByDamageType { get; }
 
        DamageInfo GettingDamage(
            CharacterBase owner,
            IDamageDealer damageDealer,
            ProjectileWeapon projectileWeapon,
            float damageMultiplier,
            AttackProperties attackProperties);
    }

La propiedad interesante es ResistencesByDamageType, que consiste en un diccionario donde la clave es el tipo de daño y el valor es el porcentaje de resistencia o vulnerabilidad a ese tipo de daño. Un valor negativo indica que es vulnerable y un valor positivo que es resistente. La omisión de un tipo de daño indica que no le afectará ni positivamente ni negativamente, es decir, un objeto que no tiene configuradas resistencias o vulnerabilidades recibirá el daño potencial del arma (13 siguiendo el ejemplo del arco y flecha u 6 del cuchillo de hueso).

Como dije, no solo los personajes son vulnerables al daño, hay objetos del entorno que también lo son, como por ejemplo los árboles.

forest-tree
Hendidor = -50%
Aplastante = 99%
Perforante = 80%
Disparo = 90%
Cortante = 80%
Fuego = -80%

Se puede observar que los árboles son especialmente vulnerables al daño hendidor (el que producen las hachas) y al fuego, y muy resistentes al resto de daños.

Los principales enemigos de Sticks & Stones, la míticas Holo-Balls, configuran sus propias resistencias y vulnerabilidades. La finalidad es crear estrategias y elecciones de armas específicas para cada enfrentamiento. No queremos que exista una sola arma poderosa, queremos que cualquier arma pueda ser útil.

En definitiva, en Sticks & Stones hay que experimentar para conocer y aprender sobre los enemigos y las armas.

¿Crees que este nivel de profundidad en el sistema de daños le sienta bien al videojuego?

One thought on “Daños y resistencias”

  1. Creo que es un sistema muy acertado para lo que plantea el juego y le da bastante profundidad a la hora de preparar los combates. Nice work!

Leave a Reply to Reven4nt Cancel reply

Your email address will not be published. Required fields are marked *