↩️ Back
↩️ Back
The mod is based on .NET Standard 2.1 (Framework), and so should be your extension!
Creating an extension is literally the same process as if you were creating a solution (.sln) for a BepInEx mod
Visual Studio 2022:
File ➜ New ➜ Project ➜ Class Library (C#, .NET Standard) ➜ Framework: .NET Standard 2.1
Setting up an actual BepInEx mod for Baldi's Basics Plus is optional
(can be used to patch code for certain custom vote options)
1. The main part of writing your own extension is to define an extension enty point!
using StreamerIntegrationPlus;
namespace THE_NAME_OF_THE_ASSEMBLY
{
public static class SIPExtensionEntryPoint
{
private static void Extend()
{
ChatVotingManager.AddCustomVoteOptionsUnderNamespace("THE_NAME_OF_THE_ASSEMBLY.VoteOptions");
StreamerIntegrationBasePlugin.RegisterPlatform<MyOwnIntegration>(); // Registers a custom platform
}
}
}
2. Defining a custom vote option is not that hard too!
using StreamerIntegrationPlus;
namespace THE_NAME_OF_THE_ASSEMBLY.VoteOptions
{
// This is an example vote option that just enables light flickering for 10 to 20 seconds!
internal sealed class MyOwnVoteOption : VoteOption
{
// Keep it short, because it's going to be displayed on the card
public override string NameKey => "Example\nVote Option!";
public override float MinTime => 10f;
public override float MaxTime => 20f;
// Is that vote option bad, neutral or good for a host?
public override VoteOptionKindness Kindness => VoteOptionKindness.Good;
public override bool AllowOnCurrentVote()
{
// Can be selected as a candidate if no lights are flickering
return BaseGameManager.Instance?.Ec?.lightsToFlicker.Count > 0;
}
public override void OnElected()
{
// This is being called once the winner card is decided. Refer to XML for more information
}
public override void OnTimerStart()
{
BaseGameManager.Instance?.Ec?.FlickerLights(true);
}
public override void OnTimerTick()
{
// This is being called on each timer tick. Refer to XML for more information
}
public override void OnTimerEnd()
{
BaseGameManager.Instance?.Ec?.FlickerLights(false);
}
public override float ChanceAsCandidate => 0.5f; // 50%
public override bool EnsureSafeTimerTick => true; // Ensures that OnTimerTick is only being executed if // AllowOnCurrentVote is true.
// I do reccomend to set it to false if AllowOnCurrentVote has some expensive calculations, such as
// reflections to gain access to non-public parts of the game's code!
public override void Reset() // Absolutely optional, you can use OnElected to reset things.
{
base.Reset();
}
}
}
3. Maybe you want to add a custom platform support?
using System;
using StreamerIntegrationPlus;
namespace THE_NAME_OF_THE_ASSEMBLY
{
// Please name your classes like {PLATFORM NAME}Integration! And also, refer to XML docs for
// pretty much everything...
internal sealed class MyOwnIntegration : PlatformIntegration
{
private MyCoolPlatformAPI? mcpAPI;
protected override void Connect()
{
// Called once a the mod is trying to connect to a specified
// platform from credentials.xml
// Use it to establish connection with the platform
// Grab all data from credentials.xml
string absolutelyRealApiKey = CredentialsFile.Request(PlatformName, "APIKey");
string absolutelyRealUserID = CredentialsFile.Request(PlatformName, "UserID");
// Absolutely real platform example here (could have been something like Twitch or YouTube instead)
mcpAPI = new MyCoolPlatformAPI(absolutelyRealApiKey);
mcpAPI.onUserNewChatMessage += OnChatMessage;
mcpAPI.Connect(absolutelyRealUserID);
}
private void OnChatMessage(string userID, string messageContent)
{
// This is an important part that allows a communication between a certain platform and a mod itself
ProcessChatMessage(userID, messageContent);
}
public override void Disconnect()
{
// Called once when the mod is trying to disconnect from a
// a specified platform from credentials.xml
// Use it to disconnect from the platform and cleaning up the resources
// Absolutely real platform example here (could have been something like Twitch or YouTube instead)
mcpAPI?.Disconnect();
}
public override void OnBasePluginUpdate()
{
// Called every time StreamerIntegrationBasePlugin.Update() is called
}
public override void OnNewChatVote(DateTime startedAt, DateTime endsAt)
{
// Called once a new chat vote is CREATED
}
public override void OnNewChatVoteStart(DateTime startedAt, DateTime endsAt)
{
// Called once a group of people are allowed to vote on a new chat vote after it's creation
}
public override void OnChatVoteEnd(int winningIndex, DateTime endedAt)
{
// Called once a current chat vote has ended...
}
}
}
NOTE: Refer to the API for the rest of the functions that are located in:
ChatVotingManager
StreamerIntegrationBasePlugin
CredentialsFile
SIPGlobalHelper
4. Compile the project into an assembly file and move it to
blayms-tbb-baldiplus-streamerintegration\Extensions
NOTE: If you have external platform libraries when adding a custom platform integration, move them inside:
blayms-tbb-baldiplus-streamerintegration\Broadcasting Platform Libraries
Resources could go inside:
blayms-tbb-baldiplus-streamerintegration\Resources
5. Test the thing!