Skip to main content
The project's repository is archived as part of the GitHub Archive Program. RogueLibs' code and the documentation will no longer be updated.

Creating a Custom Disaster

You can create your own custom disasters using a CustomDisaster class, provided by RogueLibs. You can configure the disaster's name, description and both of the messages that are displayed at the beginning of the floor. And, of course, you can determine the conditions that the disaster can (or must) happen under, and what happens at the start of and during this disaster. Additionally, you can quickly and easily create a removal mutator that removes your disaster from the pool.

CustomDisaster class

To make a custom disaster, you need to create a class deriving from CustomDisaster:

MyCustomDisaster.cs
public class MyCustomDisaster : CustomDisaster
{
/* ... */
}

There are 3 methods that you need to implement:

MyCustomDisaster.cs
public class MyCustomDisaster : CustomDisaster
{
public override void Start() { /* ... */ }
public override void Finish() { /* ... */ }
public override IEnumerator? Updating() { /* ... */ }
}

Start is called when the disaster starts. Finish is called when the disaster ends.

Start and Finish methods

These methods are called between levels, so some stuff might not be available at the time they're called.

Updating returns the updating coroutine for the disaster. It starts after the disaster's notification. It is stopped automatically, when the disaster ends. If your disaster doesn't need updating, you can just return null.

Disaster Conditions

If you want your disaster to appear only under certain conditions, override the Test method:

MyCustomDisaster.cs
public class MyCustomDisaster : CustomDisaster
{
public override bool Test()
{
// for example, if it's a Park level
return CurrentDistrict == 2;
}
}
info

CustomDisaster exposes several useful properties for that:

  • CurrentDistrict - index of the current level's district. (0 - Slums, 1 - Industrial, 2 - Park, 3 - Downtown, 4 - Uptown, 5 - Mayor Village)
  • CurrentFloor - index of the current level's floor of the district. (0, 1 or 2 in a normal playthrough, and 0 or 1 with "Quick Game" mutator on)
  • CurrentLevel - index of the current level. (0-2 - Slums, 3-5 - Industrial, 6-8 - Park, 9-11 - Downtown, 12-14 - Uptown, 15 - Mayor Village) (or 0-1, 2-3, 4-5, 6-7, 8-9, 10 if Quick Game is on), and more in Endless mode)

And, if you want to force your disaster onto a level, override the TestForced method.

MyCustomDisaster.cs
public class MyCustomDisaster : CustomDisaster
{
public override bool TestForced()
{
// for example, if there's a Mayor on the level
return gc.agentList.Exists(a => a.agentName === VanillaAgents.Mayor);
}
}
Current limitations

At the moment, TestForced cannot force a disaster onto a non-disastrous level. It only works on levels that normally have disasters: *-3 (or *-2 with Quick Game on), or every level with the Disasters Every Level mutator.

Disaster Settings

Normally, you can't teleport during disasters, but you can change that by overriding the AllowTeleport property:

MyCustomDisaster.cs
public class MyCustomDisaster : CustomDisaster
{
public override bool AllowTeleport => true;
}

The property is accessed constantly, so you can change the return value with time.

Initialization

Just call the CreateCustomDisaster method with your disaster's type as a parameter:

MyCustomDisaster.cs
public class MyCustomDisaster : CustomDisaster
{
[RLSetup]
public static void Setup()
{
RogueLibs.CreateCustomDisaster<MyCustomDisaster>();
}
}
note

See more about the RLSetup attribute here.

You can set your disaster's name and description using WithName and WithDescription methods:

MyCustomDisaster.cs
public class MyCustomDisaster : CustomDisaster
{
[RLSetup]
public static void Setup()
{
RogueLibs.CreateCustomDisaster<MyCustomDisaster>()
.WithName(new CustomNameInfo("My Custom Disaster"))
.WithDescription(new CustomNameInfo("My Custom Disaster is very cool and does a lot of great stuff"));
}
}

Plus, you can add two messages (they are displayed at the same time, on two lines):

MyCustomDisaster.cs
public class MyCustomDisaster : CustomDisaster
{
[RLSetup]
public static void Setup()
{
RogueLibs.CreateCustomDisaster<MyCustomDisaster>()
.WithName(new CustomNameInfo("My Custom Disaster"))
.WithDescription(new CustomNameInfo("My Custom Disaster is very cool and does a lot of great stuff"))
.WithMessage(new CustomNameInfo("My Custom Disaster!"))
.WithMessage(new CustomNameInfo("Watch out for... uh, something dangerous!"));
}
}
info

See Custom Names for more info.

You can also create a removal mutator automatically:

MyCustomDisaster.cs
public class MyCustomDisaster : CustomDisaster
{
[RLSetup]
public static void Setup()
{
RogueLibs.CreateCustomDisaster<MyCustomDisaster>()
.WithName(new CustomNameInfo("My Custom Disaster"))
.WithDescription(new CustomNameInfo("My Custom Disaster is very cool and does a lot of great stuff"))
.WithMessage(new CustomNameInfo("My Custom Disaster!"))
.WithMessage(new CustomNameInfo("Watch out for... uh, something dangerous!"))
.WithRemovalMutator();
}
}

Examples

A simple disaster that just gives everyone Resurrection after the notification.

using System.Collections;

namespace RogueLibsCore.Test
{
public class NewHealthOrder : CustomDisaster
{
[RLSetup]
public static void Setup()
{
RogueLibs.CreateCustomDisaster<NewHealthOrder>()
.WithName(new CustomNameInfo
{
English = "New Health Order",
})
.WithDescription(new CustomNameInfo
{
English = "Where is this line used?!",
})
.WithMessage(new CustomNameInfo
{
English = "N.H.O. - New Health Order",
})
.WithMessage(new CustomNameInfo
{
English = "Resurrection for everyone!",
})
.WithRemovalMutator();
}

public override void Start() { }
public override void Finish() { }

public override IEnumerator Updating()
{
foreach (Agent agent in gc.agentList)
if (!agent.dead && !agent.electronic && !agent.inhuman)
{
agent.statusEffects.AddStatusEffect(VanillaEffects.Resurrection, false);
}
yield break;
}
}
}

The project's repository is archived as part of the GitHub Archive Program. RogueLibs' code and the documentation will no longer be updated.