---
title: "Sequencer"
---
<style>
html, body, .ui-content {
background-color: #333;
color: #ddd;
}
.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
color: #ddd;
}
.markdown-body h1,
.markdown-body h2 {
border-bottom-color: #ffffff69;
}
.markdown-body h1 .octicon-link,
.markdown-body h2 .octicon-link,
.markdown-body h3 .octicon-link,
.markdown-body h4 .octicon-link,
.markdown-body h5 .octicon-link,
.markdown-body h6 .octicon-link {
color: #fff;
}
.markdown-body img {
background-color: transparent;
}
.ui-toc-dropdown .nav>.active:focus>a, .ui-toc-dropdown .nav>.active:hover>a, .ui-toc-dropdown .nav>.active>a {
color: white;
border-left: 2px solid white;
}
.expand-toggle:hover,
.expand-toggle:focus,
.back-to-top:hover,
.back-to-top:focus,
.go-to-bottom:hover,
.go-to-bottom:focus {
color: white;
}
.ui-toc-dropdown {
background-color: #333;
}
.ui-toc-label.btn {
background-color: #191919;
color: white;
}
.ui-toc-dropdown .nav>li>a:focus,
.ui-toc-dropdown .nav>li>a:hover {
color: white;
border-left: 1px solid white;
}
.markdown-body blockquote {
color: #bcbcbc;
}
.markdown-body table tr {
background-color: #5f5f5f;
}
.markdown-body table tr:nth-child(2n) {
background-color: #4f4f4f;
}
.markdown-body code,
.markdown-body tt {
color: #eee;
background-color: rgba(230, 230, 230, 0.36);
}
a,
.open-files-container li.selected a {
color: #5EB7E0;
}
</style>
# Sequencer
[TOC]
#### Links
> Blade & Sorcery Discord server: https://discord.gg/bladeandsorcery
> Discord Forum: https://discord.com/channels/327809947272478720/1196482135398293575
> GitHub Repo: https://github.com/ksmto/Sequencer
> Download: https://github.com/ksmto/Sequencer/releases/tag/sequencer
> Documentation: https://hackmd.io/@ksmto/kseqencer
To get the DLL file, go the the GitHub repository or the Discord forum to retrieve it.
## How to Use
(Note: this is an example using an item behaviour component!)
In your class make a field of the type "Sequencer" like this:
```csharp
public class SequencerExample : MonoBehaviour
{
private Item _item;
// Initialize and start our sequencer
private readonly Sequencer _sequencer = Sequencer.Start();
// When our item is spawned
private void Start()
{
_item = GetComponent<Item>();
}
}
```
Now in a Update method, use the "_sequencer.Update()" function. This will ensure the Sequencer is continuously checking for new sequences.
```csharp
public class SequencerExample : MonoBehaviour
{
private Item _item;
// Initialize and start our sequencer
private readonly Sequencer _sequencer = Sequencer.Start();
// When our item is spawned
private void Start()
{
_item = GetComponent<Item>();
}
// Runs every frame of the game, while the item is spawned
private void Update()
{
// Update the sequencer
_sequencer.Update();
}
}
```
Finally, in a Start method you can check conditions, like this:
```csharp
public class SequencerExample : MonoBehaviour
{
private Item _item;
// Initialize and start our sequencer
private readonly Sequencer _sequencer = Sequencer.Start();
// When our item is spawned
private void Start()
{
_item = GetComponent<Item>();
if (_item != null && _item.mainHandler != null)
{
// Use the sequencer to check if we pressed the alternate use button while holding it, if so, despawn the item
_sequencer?.If(() => _item.mainHandler.playerHand.controlHand.alternateUsePressed).Do(_item.Despawn);
}
}
// Runs every frame of the game, while the item is spawned
private void Update()
{
// Update the sequencer
_sequencer.Update();
}
}
```
## Functions & Conditions
There are a few functions when using the Sequencer, so lets jump right in.
### Start
First, we have Start. Start initializes and starts the sequencer. Use this when creating the field for your Sequencer, like this:
```csharp=
public class SequencerExample
{
private Sequencer _sequencer = Sequencer.Start();
}
```
### Update
Next we have Update, Update makes the Sequencer run and check conditions continuosly, you need to put it inside of an Update method to ensure the Sequencer is continuously checking for new sequences! Here's an example in MonoBehaviour:
```csharp=
public class SequencerExample : MonoBehaviour
{
// Initialize and start our sequencer
private Sequencer _sequencer = Sequencer.Start();
private void Update()
{
// Update the sequencer
_sequencer.Update();
}
}
```
### Do
The Do method is used to do something, it can also be used alone, use it in Start like this:
```csharp=
public class SequencerExample : MonoBehaviour
{
// Initialize and start our sequencer
private Sequencer _sequencer = Sequencer.Start();
private void Start()
{
// Alone
_sequencer.Do(() => DO_SOMETHING);
// Chained
_sequencer.If(() => CONDITION).Do(() => DO_SOMETHING);
}
private void Update()
{
// Update the sequencer
_sequencer.Update();
}
}
```
Now we're getting into the condition checkers, these will be used to execute functions and check if something happened.
:::danger
NOTE: The statment methods (If and While) are MEANT to be used in Start!!
:::
### If
The If method checks if a condition was met, use it in Start like this:
```csharp=
public class SequencerExample : MonoBehaviour
{
// Initialize and start our sequencer
private Sequencer _sequencer = Sequencer.Start();
private void Start()
{
_sequencer.If(() => CONDITION).Do(() => DO_SOMETHING);
}
private void Update()
{
// Update the sequencer
_sequencer.Update();
}
}
```
### While
The While method is used with the Do method to do something while a condition is met, use it in Start like this:
```csharp=
public class SequencerExample : MonoBehaviour
{
// Initialize and start our sequencer
private Sequencer _sequencer = Sequencer.Start();
private void Start()
{
_sequencer.While(() => CONDITION).Do(() => DO_SOMETHING);
}
private void Update()
{
// Update the sequencer
_sequencer.Update();
}
}
```
## Examples
### ThunderScript Example
```csharp
using System.Collections;
using ThunderRoad;
using UnityEngine;
namespace kSequencer.Examples;
public class SequencerThunderScript : ThunderScript
{
// Initialize and start our sequencer
private readonly Sequencer _sequencer = Sequencer.Start();
// When our script is enabled in the game
public override void ScriptEnable()
{
base.ScriptEnable();
_sequencer.If(() => Player.currentCreature != null).Do(() => GameManager.local.StartCoroutine(SpawnItemPerSecond()));
}
// Spawns an item in the position of the players left hand magic position, per second the player is active
private IEnumerator SpawnItemPerSecond()
{
while (Player.currentCreature != null)
{
// Spawn an item
var itemData = Catalog.GetData<ItemData>("DaggerCommon");
itemData?.SpawnAsync(null, Player.currentCreature.handLeft.caster.magicSource.position, Quaternion.identity);
// Wait 1 second
yield return new WaitForSeconds(1.0f);
}
}
// Runs every frame, while our script is active
public override void ScriptUpdate()
{
base.ScriptUpdate();
// Update the sequencer
_sequencer.Update();
}
}
```
### Item Example
```csharp
using ThunderRoad;
using UnityEngine;
namespace kSequencer.Examples;
public class SequencerItemModule : ItemModule
{
// When the item is loaded
public override void OnItemLoaded(Item item)
{
base.OnItemLoaded(item);
// Add our behaviour component
item.gameObject.TryGetOrAddComponent(out MonoBehaviour behaviour);
}
}
public class SequencerItemBehaviour : MonoBehaviour
{
private Item _item;
// Initialize and start our sequencer
private readonly Sequencer _sequencer = Sequencer.Start();
// When our item is spawned
private void Start()
{
_item = GetComponent<Item>();
if (_item != null && _item.mainHandler != null)
{
// Use the sequencer to check if we pressed the alternate use button while holding it, if so, despawn the item
_sequencer?.If(() => _item.mainHandler.playerHand.controlHand.alternateUsePressed).Do(_item.Despawn);
}
}
// Runs every frame of the game, while the item is spawned
private void Update()
{
// Update the sequencer
_sequencer.Update();
}
}
```
### Spell Example
```csharp
using ThunderRoad;
using UnityEngine;
namespace kSequencer.Examples;
public class SequencerSpell : SpellCastCharge
{
// Initialize and start our sequencer
private Sequencer _sequencer = Sequencer.Start();
public override void Load(SpellCaster spellCaster, Level level)
{
base.Load(spellCaster, level);
// Uses the Sequencer to check if we pressed the grip while we are casting the spell, then spawn an item into the players hand
_sequencer.If(() => spellCaster.ragdollHand.playerHand.controlHand.gripPressed).While(() => spellCaster.isFiring).Do(SpawnItemInHand);
}
// Spawns an item into the players hand
private void SpawnItemInHand()
{
// Spawn an item
var itemData = Catalog.GetData<ItemData>("DaggerCommon");
itemData?.SpawnAsync(item =>
{
// Grab the item
spellCaster.ragdollHand.Grab(item.GetMainHandle(spellCaster.ragdollHand.side));
}, spellCaster.magicSource.position, Quaternion.identity);
// End the spell's cast
spellCaster.Fire(false);
}
// Runs every frame, while the spell is active (casting or not)
public override void UpdateCaster()
{
base.UpdateCaster();
// Update the sequencer
_sequencer.Update();
}
}
```