External Mod Holdable Support - samfundev/KtaneTwitchPlays GitHub Wiki

The main branch contains functionality to allow mod holdables to provide command response directly from within their own code, without having to write a command response class in TP:KTaNE. There are currently two implementation options available for providing the interaction: a simple way and a more complex way. You must also declare string TwitchHelpMessage.

Easy/Simple Implementation

This option is useful for issuing a simple sequence of KMSelectable object interactions, like in Keypad. The method should have the exact signature declared below (can be either public or non-public, but must be non-static):

KMSelectable[] ProcessTwitchCommand(string command)
{
}

Depending on the value of the command, return back either:

  • an array of KMSelectable objects to interact with, in the order they should be interacted with
  • null, to indicate that nothing should happen (i.e. ignore the command)

If at any point a KMSelectable interaction will cause a strike, TP:KTaNE will stop execution of the given KMSelectable objects mid-way automatically; you don't have to worry about this in your implementation.

Do not implement this option if:

  • You have to hold down on an interaction (like in The Button)
  • Buttons have to be pressed in a time-critical manner (like Light Cycle, Crazy Talk, Color Flash)
  • The holdable has a delay between the KMSelectable interaction and a strike/solve being awarded (like Two Bits, Cheap Checkout, Simon Screams)

Advanced Implementation

This option allows for full flexibility of interaction, by asking you to implement a coroutine-like method. If you don't know how to write coroutines in Unity, I recommend reading up on the Unity documentation to better understand how coroutines work. The method should have the exact signature declared below (can be either public or non-public, but must be non-static):

IEnumerator ProcessTwitchCommand(string command)
{
}

This implementation option will allow you to do the following:

  • yield break; without yield return-ing something, to denote that nothing should happen (i.e. ignore the command)
  • Wait for seconds using yield return new WaitForSeconds(__);
  • Wait for the next frame using yield return null;
  • A IEnumerator object. This acts like a sub-routine call, and will be processed before the current routine resumes execution.
  • A KMSelectable object to interact with; Twitch Plays will hold down the interaction of this object until the same KMSelectable object is yielded again, either by this command or a subsequent command
  • A KMSelectable [] array. This causes ALL of the buttons to be pressed unless one of the ones pressed causes a strike, in which case, the remainder of the sequence is aborted.
  • A string to denote special cases like the following:
    • "strike" indicates that this command will cause a strike at some later point; all this does is tell Twitch Plays to attribute the strike to the author of this command
    • "trycancel" indicates that this command is allowed to be cancelled at the given time of the yield. Just know that you won't be able to clean up if you do your cancel this way, and there is a pending !cancel or !stop.
    • "cancelled" indicates that you have stopped processing the command in response to the TwitchShouldCancelCommand bool being set to true.
    • "sendtochat {message}" Send a message directly to twitch chat.
    • "sendtochaterror {message}" Sends a message to the chat about why a users command was invalid.
    • "waiting music" can be used to play the waiting music if a command will take long to finish.
  • A Quaternion object to change the orientation of the holdable; Only really required if your holdable has more than just the front and back side.
  • A Dictionary<string, bool> object to define custom true/false settings that can be checked for at a later time.
  • A string[] object can be used to detonate the bomb if the first string is detonate or explode. The next string can optionally be a reason why and you can also add a third string to override the name.
  • A object[] containing a string, object, object in that order. This allows for asking if the user that submitted the command has permission to perform that command.
    • For the string, these are the permission asking types.
      • "streamer-only"
      • "streamer"
      • "superuser-only"
      • "superuser"
      • "admin-only"
      • "admin"
      • "mod-only"
      • "mod"
      • "defuser-only"
      • "defuser"
      • Any mod defined string specified in a previously yielded Dictionary <string,bool> object.
    • The second object is only used when the command sender does have permission to perform the command. It can be of the following types.
      • Action - Action to be performed if permission is granted.
      • IEnumerator - where execution is to resume if permission is granted.
    • The third object is used only when the command sender doesn't have permission to perform the command. It can be of the following types.
      • string containing sendtochat message or sendtochaterror message or parseerror
      • Action - Action to be performed if permission is denied.
      • IEnumerator - where execution is to resume if permission is denied.

You could also interact directly with your own KMSelectable objects without passing them through to TP:KTaNE.

Be aware that the coroutine should yield return something if the command given is valid and should interact with the holdable in some way; doing nothing may cause TP:KTaNE to misinterpret the response as an ignore command response. You can yield return anything you want to achieve this.

Also, be aware that TP:KTaNE plays the commands out in a single-queue and doesn't dispatch the actions simultaneously. To this fact, ensure that your command response doesn't halt the coroutine excessively, unless the holdable's design explicitly infers this style of behaviour (like releasing a button on a specific condition).

If at any point, the holdable causes a strike as a result of the command, the IEnumerator will stop being processed, unless you have yield returned "multiple strikes"

Additional Implementation Tasks

All of the tasks mentioned below are purely optional, but allow for a richer user-to-holdable interaction. Again, these can be public or non-public as before, but must still be non-static.

bool TwitchShouldCancelCommand;

Declaring this field is a way for the Advanced Implementation to be notified that it should cancel command processing. If you define this and see in the code that the value of the field is set to true, then stop processing the command, clean up, then do a yield return "cancelled" to acknowledge the cancel.

string TwitchHelpMessage;

This field allows you to specify the help message displaying examples of how to input the command, when !{id} help is entered into chat. Use the {0} string token to denote where the holdable's ID should be inserted into the help text. Declaring this field is mandatory.