Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
ef44e59
Map refs to LocalOverrides.targets
dplochcoder Aug 10, 2025
d131167
Remove unused includes
dplochcoder Aug 11, 2025
74a9a5e
Rename SaveData to GlobalSaveData
dplochcoder Aug 11, 2025
e680ba3
Implement pause controls, command and networking; no UI yet
dplochcoder Aug 11, 2025
42075ba
Implement deathtimer subcommand
dplochcoder Aug 11, 2025
5afb8aa
Refactor pause control into a singleton state
dplochcoder Aug 11, 2025
6cfd304
Refactor a bunch of stuff to make paused countdowns work cleanly
dplochcoder Aug 12, 2025
59b42e5
Simplify module initialization
dplochcoder Aug 12, 2025
bd4f03e
Bug fixes, first draft
dplochcoder Aug 12, 2025
6c9bb88
Don't display countdowns when disconnected.
dplochcoder Aug 12, 2025
78cb4e7
Update README
dplochcoder Aug 12, 2025
93efa88
Nit
dplochcoder Aug 12, 2025
5d67cd7
Remove redundant statement
dplochcoder Aug 12, 2025
19c2239
Remove dedicated server dependencies on Assembly-CSharp
dplochcoder Aug 14, 2025
2aae420
D'oh
dplochcoder Aug 14, 2025
e769ace
Add files via upload
fireb0rngg Aug 16, 2025
698defc
Add files via upload
fireb0rngg Aug 18, 2025
6e02d77
Add files via upload
fireb0rngg Aug 18, 2025
f8425bb
Merge pull request #11 from fireb0rngg/main
Korzer420 Aug 19, 2025
e2a773d
Address review comments
dplochcoder Sep 16, 2025
5abda10
Move event to PauseManager
dplochcoder Sep 17, 2025
b2ecc91
Map refs to LocalOverrides.targets
dplochcoder Aug 10, 2025
73d181a
Remove unused includes
dplochcoder Aug 11, 2025
bcda1be
Rename SaveData to GlobalSaveData
dplochcoder Aug 11, 2025
8c5d44b
Implement pause controls, command and networking; no UI yet
dplochcoder Aug 11, 2025
a0dcff4
Implement deathtimer subcommand
dplochcoder Aug 11, 2025
513ceeb
Refactor pause control into a singleton state
dplochcoder Aug 11, 2025
526977d
Refactor a bunch of stuff to make paused countdowns work cleanly
dplochcoder Aug 12, 2025
e736c97
Simplify module initialization
dplochcoder Aug 12, 2025
49b87ca
Bug fixes, first draft
dplochcoder Aug 12, 2025
80a4b5a
Don't display countdowns when disconnected.
dplochcoder Aug 12, 2025
33a0b68
Update README
dplochcoder Aug 12, 2025
9cdd315
Nit
dplochcoder Aug 12, 2025
ba811db
Remove redundant statement
dplochcoder Aug 12, 2025
863383a
Remove dedicated server dependencies on Assembly-CSharp
dplochcoder Aug 14, 2025
1701cc8
D'oh
dplochcoder Aug 14, 2025
7bcfd47
Address review comments
dplochcoder Sep 16, 2025
464fb57
Move event to PauseManager
dplochcoder Sep 17, 2025
d64b228
Fix merge conflicts
dplochcoder Oct 10, 2025
d8362a5
Merge conflicts
dplochcoder Oct 10, 2025
dd56707
Fix timescale bug in non-HKMP saves
dplochcoder Oct 25, 2025
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -341,3 +341,4 @@ ASALocalRun/

# BeatPulse healthcheck temp database
healthchecksdb
/LocalOverrides.targets
2 changes: 1 addition & 1 deletion HkmpAddon/AddonIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ namespace TheHuntIsOn.HkmpAddon;
public static class AddonIdentifier
{
public const string Name = "TheHuntIsOn";
public const string Version = "1.2.0";
public const string Version = "1.3.0";
}
12 changes: 12 additions & 0 deletions HuntGlobalSaveData.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Collections.Generic;
using TheHuntIsOn.Modules.PauseModule;
using TheHuntIsOn.Modules.PauseTimerModule;

namespace TheHuntIsOn;

Expand All @@ -16,5 +18,15 @@ public class HuntGlobalSaveData

public int SpellCost { get; set; } = 33;

public bool DisableEnemies { get; set; }

public bool InvincibleBosses { get; set; }

public bool DreamBossAccess { get; set; }

public PauseTimerPosition PauseTimerPosition { get; set; } = PauseTimerPosition.BottomCenter;

public PauseTimerSize PauseTimerSize { get; set; } = PauseTimerSize.Normal;

#endregion
}
55 changes: 55 additions & 0 deletions HuntLocalSaveData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using TheHuntIsOn.Modules.PauseModule;

namespace TheHuntIsOn;

public class HuntLocalSaveData
{
#region Properties

// Whether the server is currently paused.
public bool ServerPaused;

// If paused, when the server should be unpaused.
public long UnpauseTimeTicks;

// Time to wait to respawn after a death.
public int RespawnTimerSeconds;

// Globally broadcast countdowns.
public List<Countdown> GlobalCountdowns = [];

#endregion

#region Methods

public void UpdateCountdowns(DateTime now, UpdateCountdownsPacket packet)
{
GlobalCountdowns.Clear();
GlobalCountdowns.AddRange([.. packet.Countdowns.Where(c => !c.IsCompleted(now))]);
}

public void UpdatePauseState(UpdatePauseStatePacket packet)
{
ServerPaused = packet.ServerPaused;
UnpauseTimeTicks = packet.UnpauseTimeTicks;
}

public bool IsServerPaused(out float? remainingSeconds)
{
remainingSeconds = null;
if (!ServerPaused) return false;
if (UnpauseTimeTicks == long.MaxValue) return true;

var now = DateTime.UtcNow.Ticks;
if (now >= UnpauseTimeTicks) return false;

TimeSpan span = new(UnpauseTimeTicks - now);
remainingSeconds = (float)span.TotalSeconds;
return true;
}

#endregion
}
6 changes: 4 additions & 2 deletions Module.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ internal abstract class Module

public ModuleAffection Affection { get; set; }

public bool IsModuleUsed => Affection == ModuleAffection.All || (TheHuntIsOn.SaveData.IsHunter && Affection == ModuleAffection.OnlyHunter)
|| (!TheHuntIsOn.SaveData.IsHunter && Affection == ModuleAffection.OnlySpeedrunner);
public bool IsModuleUsed => Affection == ModuleAffection.All || (TheHuntIsOn.GlobalSaveData.IsHunter && Affection == ModuleAffection.OnlyHunter)
|| (!TheHuntIsOn.GlobalSaveData.IsHunter && Affection == ModuleAffection.OnlySpeedrunner);

public abstract string MenuDescription { get; }

Expand All @@ -39,6 +39,8 @@ internal void Unload()
_active = false;
}

internal virtual void Initialize() { }

internal abstract void Enable();

internal abstract void Disable();
Expand Down
1 change: 0 additions & 1 deletion Modules/ArenaModule.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using GlobalEnums;
using KorzUtils.Helper;
using UnityEngine;
using UnityEngine.SceneManagement;

Expand Down
1 change: 0 additions & 1 deletion Modules/AutoTriggerBossModule.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using KorzUtils.Helper;
using UnityEngine;

namespace TheHuntIsOn.Modules;

Expand Down
11 changes: 1 addition & 10 deletions Modules/BaldurModule.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using KorzUtils.Helper;
using Modding;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using TheHuntIsOn.Modules.HealthModules;
using Modding;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace TheHuntIsOn.Modules;

Expand Down
1 change: 0 additions & 1 deletion Modules/CutsceneSkipModule.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using HutongGames.PlayMaker.Actions;
using KorzUtils.Helper;
using UnityEngine;

namespace TheHuntIsOn.Modules;

Expand Down
3 changes: 1 addition & 2 deletions Modules/DreamEntranceModule.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using HutongGames.PlayMaker.Actions;
using KorzUtils.Helper;
using TheHuntIsOn.Modules.HealthModules;
using UnityEngine;
using UnityEngine.SceneManagement;

Expand Down Expand Up @@ -94,7 +93,7 @@ private void SceneManager_activeSceneChanged(Scene arg0, Scene newScene)
// To prevent a softlock we spawn the portal anyway, even if the module is not used, if the player is in the room with dream nail already.
if (newScene.name == "Dream_Nailcollection" && PlayerData.instance.GetBool(nameof(PlayerData.hasDreamNail)))
{
GameObject teleporterSprite = GameObject.Instantiate(BossModule.DreamGate);
GameObject teleporterSprite = GameObject.Instantiate(EnemyModule.DreamGate);
teleporterSprite.transform.position = new(272.88f, 51.3f);
GameObject teleporter = GameObject.Instantiate(ElevatorModule.Door);
teleporter.name = "Dream Nail Escape";
Expand Down
6 changes: 0 additions & 6 deletions Modules/ElevatorModule.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
using KorzUtils.Helper;
using Mono.Security.Protocol.Tls;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

namespace TheHuntIsOn.Modules;
Expand Down
81 changes: 47 additions & 34 deletions Modules/EnemyModule.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using HutongGames.PlayMaker.Actions;
using KorzUtils.Helper;
using Modding;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using TheHuntIsOn.Modules.HealthModules;
using UnityEngine;
using UnityEngine.SceneManagement;

Expand All @@ -16,7 +11,7 @@ internal class EnemyModule : Module
{
#region Properties

public override string MenuDescription => "Disables all non-boss enemies. Makes bosses invincible.";
public override string MenuDescription => "Adjusts enemy spawns depending on toggles enabled below.";

#endregion

Expand Down Expand Up @@ -55,50 +50,68 @@ private bool ModHooks_OnEnableEnemyHook(GameObject enemy, bool isAlreadyDead)

HealthManager healthManager = enemy.GetComponent<HealthManager>();

if (healthManager.hp > 200 ||
enemy.name == "Mega Moss Charger" ||
enemy.name == "Giant Fly" ||
enemy.name == "False Knight New" ||
enemy.name == "Mage Knight" ||
enemy.name == "Mage Lord Phase2" ||
enemy.name == "Head" ||
enemy.name == "Mantis Lord S1" ||
enemy.name == "Mantis Lord S2" ||
enemy.name == "Ghost Warrior Xero")
if (TheHuntIsOn.GlobalSaveData.InvincibleBosses)
{
healthManager.hp = 9999;
return false;
if (healthManager.hp > 200 ||
enemy.name == "Mega Moss Charger" ||
enemy.name == "Giant Fly" ||
enemy.name == "False Knight New" ||
enemy.name == "Mage Knight" ||
enemy.name == "Mage Lord Phase2" ||
enemy.name == "Head" ||
enemy.name == "Mantis Lord S1" ||
enemy.name == "Mantis Lord S2" ||
enemy.name == "Ghost Warrior Xero")
{
healthManager.hp = 9999;
return false;
}
}

if (TheHuntIsOn.GlobalSaveData.DisableEnemies)
{
if (healthManager.hp > 200 ||
enemy.name == "Mega Moss Charger" ||
enemy.name == "Giant Fly" ||
enemy.name == "False Knight New" ||
enemy.name == "Mage Knight" ||
enemy.name == "Mage Lord Phase2" ||
enemy.name == "Head" ||
enemy.name == "Mantis Lord S1" ||
enemy.name == "Mantis Lord S2" ||
enemy.name == "Ghost Warrior Xero" ||
(enemy.name.Contains("Fly") && enemy.scene.name == "Crossroads_04") ||
enemy.scene.name == "Fungus3_23_boss" ||
enemy.scene.name == "Ruins2_11_boss" ||
enemy.name.StartsWith("Acid Walker") ||
enemy.scene.name.StartsWith("Room_Colosseum") ||
enemy.name == "Radiance")
return false;
else
return true;
}
else if ((enemy.name.Contains("Fly") && enemy.scene.name == "Crossroads_04") ||
enemy.scene.name == "Fungus3_23_boss" ||
enemy.scene.name == "Ruins2_11_boss")
return false;
else if (enemy.name.StartsWith("Acid Walker") ||
enemy.scene.name.StartsWith("Room_Colosseum") ||
enemy.name == "Radiance")
return false;

return true;

return isAlreadyDead;
}

private void DeactivateIfPlayerdataTrue_OnEnable(On.DeactivateIfPlayerdataTrue.orig_OnEnable orig, DeactivateIfPlayerdataTrue self)
{
if (IsModuleUsed && self.gameObject.name == "Dung Defender_Sleep")
if (IsModuleUsed && TheHuntIsOn.GlobalSaveData.DreamBossAccess && self.gameObject.name == "Dung Defender_Sleep")
return;
orig(self);
}

private void DeactivateIfPlayerdataFalse_OnEnable(On.DeactivateIfPlayerdataFalse.orig_OnEnable orig, DeactivateIfPlayerdataFalse self)
{
if (IsModuleUsed && self.gameObject.name == "Dung Defender_Sleep")
if (IsModuleUsed && TheHuntIsOn.GlobalSaveData.DreamBossAccess && self.gameObject.name == "Dung Defender_Sleep")
return;
orig(self);
}


private void PlayMakerFSM_OnEnable(On.PlayMakerFSM.orig_OnEnable orig, PlayMakerFSM self)
{
if (IsModuleUsed)
if (IsModuleUsed && TheHuntIsOn.GlobalSaveData.DreamBossAccess)
{
if (self.gameObject.name == "Fk Break Wall" && self.FsmName == "Control")
self.GetState("Pause").AdjustTransitions("Initial");
Expand All @@ -121,7 +134,7 @@ private void PlayMakerFSM_OnEnable(On.PlayMakerFSM.orig_OnEnable orig, PlayMaker

private void PlayerDataBoolTest_OnEnter(On.HutongGames.PlayMaker.Actions.PlayerDataBoolTest.orig_OnEnter orig, HutongGames.PlayMaker.Actions.PlayerDataBoolTest self)
{
if (IsModuleUsed &&
if (IsModuleUsed && TheHuntIsOn.GlobalSaveData.DreamBossAccess &&
((self.IsCorrectContext("Control", "IK Remains", "Check") && self.boolName.Value == "infectedKnightDreamDefeated") ||
(self.IsCorrectContext("Control", "Mage Lord Remains", "Check") && self.boolName.Value == "mageLordDreamDefeated") ||
(self.IsCorrectContext("Control", "FK Corpse", "Check") && self.boolName.Value == "falseKnightDreamDefeated") ||
Expand All @@ -135,7 +148,7 @@ private void PlayerDataBoolTest_OnEnter(On.HutongGames.PlayMaker.Actions.PlayerD

private void SceneManager_activeSceneChanged(Scene arg0, Scene newScene)
{
if (IsModuleUsed)
if (IsModuleUsed && TheHuntIsOn.GlobalSaveData.DreamBossAccess)
{
switch (newScene.name)
{
Expand Down
15 changes: 6 additions & 9 deletions Modules/EventNetworkModule.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
using System;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using Hkmp.Api.Client;
using Hkmp.Api.Command.Client;
using Hkmp.Api.Server;
using KorzUtils.Helper;
using Modding;
using MonoMod.Cil;
using Satchel;
using TheHuntIsOn.HkmpAddon;

Expand Down Expand Up @@ -37,7 +34,7 @@ internal class EventNetworkModule : Module
/// This way if module affection is set to none and the game is restarted, players can connect to server that
/// do not have the TheHuntIsOn server addon.
/// </summary>
public void Initialize()
internal override void Initialize()
{
if (Affection == ModuleAffection.None)
{
Expand All @@ -60,7 +57,7 @@ public void Initialize()
private int ModHooks_OnSetPlayerIntHook(string name, int orig)
{
// Make sure that the player causing changes is the speedrunner
if (!IsModuleUsed || TheHuntIsOn.SaveData.IsHunter)
if (!IsModuleUsed || TheHuntIsOn.GlobalSaveData.IsHunter)
{
return orig;
}
Expand Down Expand Up @@ -192,7 +189,7 @@ or nameof(PlayerData.killsGhostMarkoth))
private bool ModHooks_OnSetPlayerBoolHook(string name, bool orig)
{
// Make sure that the player causing changes is the speedrunner
if (!IsModuleUsed || TheHuntIsOn.SaveData.IsHunter)
if (!IsModuleUsed || TheHuntIsOn.GlobalSaveData.IsHunter)
{
return orig;
}
Expand Down Expand Up @@ -322,7 +319,7 @@ private void PlayMakerFSM_OnEnable(On.PlayMakerFSM.orig_OnEnable orig, PlayMaker
orig(self);

// Make sure that the player causing changes is the speedrunner
if (!IsModuleUsed || TheHuntIsOn.SaveData.IsHunter) return;
if (!IsModuleUsed || TheHuntIsOn.GlobalSaveData.IsHunter) return;

if (self.name.Equals("Stag") && self.Fsm.Name.Equals("Stag Control"))
{
Expand Down Expand Up @@ -492,7 +489,7 @@ private void PlayMakerFSM_OnEnable(On.PlayMakerFSM.orig_OnEnable orig, PlayMaker

void UsedStag(NetEvent stagEvent)
{
if (TheHuntIsOn.SaveData.IsHunter) return;
if (TheHuntIsOn.GlobalSaveData.IsHunter) return;
if (!_clientApi.ClientManager.Players.Any(p => (p.Team != _clientApi.ClientManager.Team) && p.IsInLocalScene)) return;

SendEvent(stagEvent);
Expand All @@ -501,7 +498,7 @@ void UsedStag(NetEvent stagEvent)
private void NetManager_OnGrantItemsEvent(NetItem[] netItems)
{
// Check if the player is not the speedrunner
if (!IsModuleUsed || !TheHuntIsOn.SaveData.IsHunter)
if (!IsModuleUsed || !TheHuntIsOn.GlobalSaveData.IsHunter)
return;

LogHelper.Write<TheHuntIsOn>("OnGrantItems:");
Expand Down
5 changes: 0 additions & 5 deletions Modules/HealthModules/BenchModule.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
using HutongGames.PlayMaker.Actions;
using KorzUtils.Helper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TheHuntIsOn.Modules.HealthModules;

Expand Down
Loading