Skip to content

Crowd Control 2 Effect Pack Changes

This is a break down of all changes from CC1 based packs to CC2. You can find some examples and the new SDK in our SDK Overview.

Contact us in Discord if you have any questions!

Pack Constructor

The “Player” class and “IPlayer” interface have been removed in favor of a similar “UserData” class. All instances where the former was previously used should be replaced.

Effect List

Effect definitions have changed in order to support the addition of new features and the removal of features that are no longer supported.

Folders/Categories

Support for folders has been removed in favor of effect categories. Unlike with folders, effects may appear in multiple categories. Categories are defined simply by specifying the category names in the “Category” field of the effect object.

Groups

The “Group” field of the effect object allows effects to be grouped logically for purposes of hiding/showing effects using the “ReportStatus” function.

Parameters

Due to the various issues and complications caused previously, parameters have been simplified. Effects may now define a set of parameter lists simply by using the “Parameters” field of the effect object. Parameters may no longer change the final price of an item.

Quantities

Items with a quantity must now use the “Quantity” field to define a quantity range. A quantity will change the effect price by simple multiplication. The field may be set to a numeric value (for quantities that range from 1 to the specified value) or a range struct (for control of the minimum quantity).

Inactive Effects

Packs with a large number of effects may now define an “Inactive” field on effects to specify that the effect should be hidden by default and the streamers need to enable the effect in the price editor should they wish to use it on their menu.

Bid Wars

Bid wars have been simplified into parameters. Bid wars may define their set of choices via the “Parameters” field.

ROM Table

The ROM table for console packs has been updated to allow for multiple files to be checked as a single ROM. This is useful for split-ROM formats such as bin/cue, fds, etc.

Previously, the table was defined as a simple list of ROMInfo objects, each defining a single version of the ROM:

cs
public override List<ROMInfo> ROMTable => new()
{
	new ROMInfo("Pokemon - Emerald Version (U)", "PokemonEmerald.CrowdControl.ips", Patching.IPS, ROMStatus.ValidUnpatched, s => Patching.MD5(s,"605B89B67018ABCEA91E693A4DD25BE3")),
	new ROMInfo("Pokemon - Emerald Version (U) (Fingerprinted)", "PokemonEmerald.CrowdControl.ips", Patching.IPS, ROMStatus.ValidUnpatched,s => Patching.Fingerprint(s, 0x110, fingerPrint)),
	new ROMInfo("Pokémon - Emerald Version (U) (Crowd Control)", null, Patching.Ignore, ROMStatus.ValidPatched,s => Patching.MD5(s, "9dd15d785103bce5aa3540b5ad36f4d1"))
};

These ROMInfo objects are still available for use but are now deprecated. This is to allow migration of packs with minimal edits or hassle and require only minor changes to the field declaration:

cs
public override ROMTable ROMTable => new[]
{
	new ROMInfo("Pokemon - Emerald Version (U)", "PokemonEmerald.CrowdControl.ips", Patching.IPS, ROMStatus.ValidUnpatched, s => Patching.MD5(s,"605B89B67018ABCEA91E693A4DD25BE3")),
	new ROMInfo("Pokemon - Emerald Version (U) (Fingerprinted)", "PokemonEmerald.CrowdControl.ips", Patching.IPS, ROMStatus.ValidUnpatched,s => Patching.Fingerprint(s, 0x110, fingerPrint)),
	new ROMInfo("Pokémon - Emerald Version (U) (Crowd Control)", null, Patching.Ignore, ROMStatus.ValidPatched,s => Patching.MD5(s, "9dd15d785103bce5aa3540b5ad36f4d1"))
};

The current preferred style has changed somewhat:

cs
public override ROMTable ROMTable => new(
	new ROMSet("Pokémon - Emerald Version (U)", new ROMFile(s => Patching.MD5(s, "605B89B67018ABCEA91E693A4DD25BE3"), ROMStatus.ValidUnpatched, "PokemonEmerald.CrowdControl.ips", Patching.IPS)),
	new ROMSet("Pokémon - Emerald Version (U) (Fingerprinted)", new ROMFile(s => Patching.Fingerprint(s, 0x110, fingerPrint), ROMStatus.ValidUnpatched, "PokemonEmerald.CrowdControl.ips", Patching.IPS)),
	new ROMSet("Pokémon - Emerald Version (U) (Crowd Control)", new ROMFile(s => Patching.MD5(s, "9dd15d785103bce5aa3540b5ad36f4d1"), ROMStatus.ValidPatched))
);

For multipart ROMs, it is now possible to verify all parts of the rom:

cs
public override ROMTable ROMTable => new(
	new ROMSet("Mega Man X4 (U)",
		new ROMFile(".cue", ROMStatus.ValidPatched, s => Patching.MD5(s, "dcc3b359b18c6fd06a1205836997e505")),
		new ROMFile(".bin", ROMStatus.ValidPatched, s => Patching.MD5(s, "1c425b49bb25c45b3964b2d565dd0ec0"))
	)
);

In the above example, the “name” parameter is not required and serves only for clarification of which file is which to users and pack authors. It is not used as part of the checking process which relies entirely on the “identifier” field. A ROMSet is considered matched when all of its ROMFile objects are matched exactly once.

cs
// The ROMFile object contains the following constructors:
public ROMFile(string name, Func<Stream, bool> identifier, ROMStatus status, string notes = "");

public ROMFile(Func<Stream, bool> identifier, ROMStatus status, string notes = "");

public ROMFile(string name, Func<Stream, bool> identifier, ROMStatus status, string patch, Func<Stream, byte[], (bool, string)> applicator, string notes = "");

public ROMFile(Func<Stream, bool> identifier, ROMStatus status, string patch, Func<Stream, byte[], (bool, string)> applicator, string notes = "");

SimpleTCP Changes

The current version of the SimpleTCP protocol is documented in Crowd Control SimpleTCP

To use the original SimpleTCP protocol, add the following to the pack file:

cs
public override ISimpleTCPPack.MessageFormat MessageFormat => ISimpleTCPPack.MessageFormat.CrowdControlLegacy;