> For the complete documentation index, see [llms.txt](https://feliperoddd.gitbook.io/gasify/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://feliperoddd.gitbook.io/gasify/cookbook.md).

# Cookbook 🥣

Here we describe the recipes for some common mechanics. We can see how simple it is to implement them with GASify.

## Dash&#x20;

Create a duration **GE** with a multiply modifier to MovementSpeed **attribute**.\
Hook the MovementSpeed **attribute** to your movementSpeed variable on the controller.\
Drag the **GE** to an ability (**GA**) and activate it.&#x20;

```csharp
public class PlayerController : MonoBehaviour {
        public AbilitySystemComponent asc;
        public AttributeName movementSpeedAttributeName;
        public float moveSpeed = 10f;

        private void Awake() {
            asc = GetComponent<AbilitySystemComponent>();
            asc.OnAttributeChanged += (attributeName, oldValue, newValue, ge) => { if (attributeName == movementSpeedAttributeName) moveSpeed = newValue; };
        }
}
```

## Constant Health regeneration

Create a **GE** with **infinite** duration.\
Add a period value, and a BasicModifier that targets Health. Set it to Add and put a value.\
Attach it to a **passive ability** the ASC is initialized with OR Apply the **GE** on start manually.

## Constant Health regeneration based on a HealthRegen attribute

Create a **GE** with **infinite** duration.\
Add a period value, and an AttributeBasedModifier that targets Health and uses your HealthRegen  attribute.\
Attach it to a **passive ability** the ASC is initialized with OR Apply the **GE** on start manually.

## Stun

Add a **GameplayTag** named "Stun" to the stunning **GE**. \
Make a listener for ASC.**OnTagsChanged** event on your player controller. \
If the Stun tag is present when the event is triggered, disable the control, else enable it.

```csharp
public GameplayTag stunTag;

private void Awake() {
    asc.OnTagsChanged += (tags, source, target, applicationGuid) => {
        if (tags.Contains(stunTag)) DisableController();
        else EnableController();
    };
}
```

## Custom Damage Formulas

Extend the Calculation base class and make a DamageCalculation that implements your custom formula.

<pre class="language-csharp"><code class="lang-csharp">    public class DamageCalculation : GameplayEffectCalculation {
        public string name = "DamageCalculation"; //this is just to have it display on inspector
        
        public override List&#x3C;Modifier> Execute(GameplayEffect ge) { //Example of default mechanic using Calculations
            minDmg = ge.source.GetAttributeValue("DamageMin");
            maxDmg = ge.source.GetAttributeValue("DamageMax");
<strong>            damage = UnityEngine.Random.Range(minDmg, maxDmg);
</strong><strong>            
</strong><strong>            var damageModifier = new BasicModifier() { attributeName = AttributeNameLibrary.Instance.GetByName("Health"), modifierOperator = ModifierOperator.Add, value = -damage };
</strong>            return new List&#x3C;Modifier>(){damageModifier};
        }
    }
</code></pre>

Create a ScriptableObject class that holds it.

{% code fullWidth="false" %}

```csharp
[Serializable][CreateAssetMenu(menuName = "GAS/GameplayEffectCalculationSO_DamageCalculation", fileName = "GameplayEffectCalculationSO_DamageCalculation")]
public class GameplayEffectCalculationSO_DamageCalculation : GameplayEffectCalculationSO {
    public GameplayEffectCalculationSO_DamageCalculation() {
        calc = new DamageCalculation();
    }
}
```

{% endcode %}

&#x20;Create a SO instance of the Calculation (**GEC**) via the assetMenu, and attach it to the damage GE. &#x20;

## OnDamageHit VFX/SFX (Cues)

Select the **GE** ScriptableObject that contains your Damage calculation or modifier.\
Add a **GameplayTag** "OnDamageHit" to its **CueTags**\
Go to your CuesLibrary, register a prefab (VFX/SFX) and assign its tag to the **GameplayTag** (OnDamageHit) you just added on the **GE CueTags**.

## Inventory item consumption on ability activation

(e.g. Ammo consumption when using a Shoot Ability)

Create a new class that inheritis from any GameplayAbility class. \
On the new class, override **CheckCost** and **Activate**, respectively, to include a **check for the cost** on your inventory and **pay the cost** when activated.&#x20;

## Bonus Damage depending on Weapon Type

Create a **tag** for you weapon type e.g. "Weapon.Type.Ranged.Bow".&#x20;

Whenever you equip/unequip the weapon, apply/remove an **infinite** durationType **GE 1** with "Weapon.Type.Ranged.Bow" on **GrantedTags**

Create an **GE 2** with Multiply **Modifier** (with the bonus value) for MinDamage and MaxDamage attributes.

Add "Weapon.Type.Ranged.Bow" to the **GE 2's ApplicationTagRequirementsRequired**

When the **GE 2** is applied, the modifiers will only be applied if the target has "Weapon.Type.Ranged.Bow" on its tags.

## Global Cooldown

Create a tag for it "Ability.Cooldown.Global"\
Assign it to the **SourceTagsForbidden** of every ability that shares the global cooldown, OR extend **GameplayAbility's CanActivate()** method to always check for that specific tag for all abilities.\
Add it to the cooldown effect on the abilities that should trigger it, OR extend **GameplayAbility's Activate()** to always apply the tag for X seconds when the ability is activated.

## Hit Position&#x20;

If you are doing a shooter game and/or require exact hit positions to trigger cues:\
1 - Add a position vector to your GE.

```csharp
public class GameplayEffect {
	public Vector3 positionalData;
}
```

2 - Pass the GE on the GameplayCue and move it to the desired position:

```csharp
AddCue(... , GameplayEffect ge) {
    ...
    instance.position = ge.positionalData;
}
```

## More?

Hit me up at **<feliperoddd@gmail.com>** and tell me what you want, and I'll give you a recipe for it ;)
