Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions R2API.Director/DirectorAPIexternal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,22 @@ public static partial class DirectorAPI
#pragma warning restore CS0618 // Type or member is obsolete
public static bool Loaded => true;

/// <summary>
/// Subscribe to this event to modify activity of combat directors. Fired during CombatDirector.FixedUpdate. If activityCount is higher than 0, Combat Director will remain running even when disabled. If activityCount is lower than 0, Combat Director will not run.
/// </summary>
public static event GetCombatDirectorActivityCountDelegate GetCombatDirectorActivityCount
{
add
{
SetHooks();
_getCombatDirectorActivityCount += value;
}
remove
{
_getCombatDirectorActivityCount -= value;
}
}

/// <summary>
/// Event used to edit <see cref="StageSettings"/>.
/// </summary>
Expand Down Expand Up @@ -927,4 +943,6 @@ public class MonsterFamilyHolder
/// </summary>
public string? SelectionChatString;
}

public static bool IsStageCombatDirector(this CombatDirector combatDirector) => IsStageCombatDirectorInternal(combatDirector);
}
65 changes: 65 additions & 0 deletions R2API.Director/DirectorAPIinternal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Linq;
using HG;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using R2API.Utils;
using RoR2;
Expand All @@ -18,6 +19,13 @@ public static partial class DirectorAPI

private static bool _hooksEnabled = false;

public delegate void GetCombatDirectorActivityCountDelegate(CombatDirector combatDirector, ref int activityCount);

private static event GetCombatDirectorActivityCountDelegate _getCombatDirectorActivityCount;

internal static HashSet<CombatDirector> _currentStageCombatDirectorsHashSet = [];

internal static List<CombatDirector> _allCombatDirectors = [];
internal static void SetHooks()
{
if (_hooksEnabled)
Expand All @@ -41,6 +49,12 @@ internal static void SetHooks()

On.RoR2.SceneCatalog.Init += InitStageEnumToSceneDefs;

On.RoR2.DirectorCore.OnEnable += AddRunCombatDirectorsFixedUpdateComponent;

IL.RoR2.CombatDirector.FixedUpdate += CombatDirector_FixedUpdate;

On.RoR2.CombatDirector.Awake += CombatDirector_Awake;

_hooksEnabled = true;
}

Expand All @@ -51,8 +65,57 @@ internal static void UnsetHooks()

On.RoR2.SceneCatalog.Init -= InitStageEnumToSceneDefs;

On.RoR2.DirectorCore.OnEnable -= AddRunCombatDirectorsFixedUpdateComponent;

IL.RoR2.CombatDirector.FixedUpdate -= CombatDirector_FixedUpdate;

On.RoR2.CombatDirector.Awake -= CombatDirector_Awake;

_hooksEnabled = false;
}
private static void CombatDirector_Awake(On.RoR2.CombatDirector.orig_Awake orig, CombatDirector self)
{
orig(self);
_allCombatDirectors.Add(self);
}
private static void CombatDirector_FixedUpdate(ILContext il)
{
ILCursor c = new ILCursor(il);
ILLabel iLLabel = null;
if (!c.TryGotoNext(MoveType.After,
x => x.MatchCall(typeof(Run).GetPropertyGetter(nameof(Run.instance))),
x => x.MatchCall<UnityEngine.Object>("op_Implicit"),
x => x.MatchBrfalse(out iLLabel)
))
{
DirectorPlugin.Logger.LogError(il.Method.Name + " IL Hook failed!");
return;
}
c.Emit(OpCodes.Ldarg_0);
c.EmitDelegate(HandleCombatDirectorInactivity);
c.Emit(OpCodes.Brfalse_S, iLLabel);
}
private static bool HandleCombatDirectorInactivity(CombatDirector combatDirector)
{
if (!combatDirector.enabled) return true;
int activityCount = 0;
_getCombatDirectorActivityCount?.Invoke(combatDirector, ref activityCount);
if (activityCount < 0) return false;
return true;
}
internal static bool HandleCombatDirectorActivity(CombatDirector combatDirector)
{
if (combatDirector.enabled || combatDirector.moneyWaves == null) return false;
int activityCount = 0;
_getCombatDirectorActivityCount?.Invoke(combatDirector, ref activityCount);
if (activityCount > 0) return true;
return false;
}
private static void AddRunCombatDirectorsFixedUpdateComponent(On.RoR2.DirectorCore.orig_OnEnable orig, DirectorCore self)
{
orig(self);
RunCombatDirectorsFixedUpdate runCombatDirectorsFixedUdpate = self.gameObject.EnsureComponent<RunCombatDirectorsFixedUpdate>();
}

private static void ApplyChangesOnStart(On.RoR2.ClassicStageInfo.orig_Start orig, ClassicStageInfo classicStageInfo)
{
Expand Down Expand Up @@ -719,4 +782,6 @@ private static void SetInteractableCategoryWeights(DirectorCardCategorySelection
dccs.categories[i] = category;
}
}

private static bool IsStageCombatDirectorInternal(CombatDirector combatDirector) => _currentStageCombatDirectorsHashSet.Contains(combatDirector);
}
5 changes: 5 additions & 0 deletions R2API.Director/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,15 @@ Alongside this, R2API.Director also comes bundled with DirectorAPIHelpers, which

Additionaly you can clone existing spawn cards and set new values for cloned spawn cards using CharacterSpawnCardClone, InteractableSpawnCardClone and MultiCharacterSpawnCardClone.

Also provides an event to easily enable/disable Combat Directors. Provides an extension method IsStageCombatDirector to check is Combat Director part of stage Combat Directors

## Related Pages

## Changelog

## `3.1.0`
* Added enabling/disabling Combat Directors event.

### `3.0.1`
* Fix spawn card clones not being able to be applied more than once for the dccspool in a single game session.

Expand Down
35 changes: 35 additions & 0 deletions R2API.Director/RunCombatDirectorsFixedUpdate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using RoR2;
using RoR2BepInExPack.Utilities;
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using static R2API.DirectorAPI;

namespace R2API;
public class RunCombatDirectorsFixedUpdate : MonoBehaviour
{
public CombatDirector[] combatDirectors;
public void Awake()
{
_currentStageCombatDirectorsHashSet.Clear();
combatDirectors = GetComponents<CombatDirector>();
if (combatDirectors == null) return;
foreach (CombatDirector combatDirector in combatDirectors) _currentStageCombatDirectorsHashSet.Add(combatDirector);
}
public void FixedUpdate()
{
if (combatDirectors == null) return;
for (int i = 0; i < _allCombatDirectors.Count; i++)
{
CombatDirector combatDirector = _allCombatDirectors[i];
if (!combatDirector)
{
_allCombatDirectors.RemoveAt(i);
continue;
}
if (!HandleCombatDirectorActivity(combatDirector)) continue;
combatDirector.FixedUpdate();
}
}
}
4 changes: 2 additions & 2 deletions R2API.Director/thunderstore.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ schemaVersion = "0.0.1"
[package]
namespace = "RiskofThunder"
name = "R2API_Director"
versionNumber = "3.0.1"
description = "API for easily modifiying the Director (RoR2 monster / interactable spawner) behaviour and cloning Spawn Cards"
versionNumber = "3.1.0"
description = "API for easily modifiying the Director (RoR2 monster / interactable spawner) behaviour, cloning Spawn Cards and enabling/disabling Combat Directors"
websiteUrl = "https://github.com/risk-of-thunder/R2API"
containsNsfwContent = false

Expand Down
Loading