Skip to content

Commit ac7360c

Browse files
committed
Necromancer Disconnection Fix
1 parent 05d4b2b commit ac7360c

12 files changed

Lines changed: 238 additions & 240 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ obj/
33
References/
44
NewMod/Components/Minigames
55
NewMod/Components/Hidden.cs
6+
NewMod/Private
67
/packages/
78
riderModule.iml
89
.idea

NewMod/Buttons/Necromancer/ReviveButton.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,9 @@ protected override void OnClick()
5959
var closestBody = Utils.GetClosestBody();
6060
if (closestBody != null)
6161
{
62-
Utils.RpcRevive(closestBody);
62+
Utils.HandleRevive(PlayerControl.LocalPlayer, closestBody.ParentId, AmongUs.GameOptions.RoleTypes.Impostor, closestBody.TruePosition.x, closestBody.TruePosition.y);
6363
}
6464
}
65-
6665
/// <summary>
6766
/// Determines whether this button is enabled for the role, returning true if the role is <see cref="NecromancerRole"/>.
6867
/// </summary>

NewMod/Buttons/WraithCaller/CallWraith.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ protected override void OnClick()
8585
player =>
8686
{
8787
menu.Close();
88-
WraithCallerUtilities.RpcSummonNPC(PlayerControl.LocalPlayer, player);
88+
WraithCallerUtilities.RpcRequestSummonNPC(PlayerControl.LocalPlayer, player);
8989
SetTimerPaused(false);
9090
});
9191

NewMod/Components/WraithCallerNpc.cs

Lines changed: 48 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -19,52 +19,45 @@ public class WraithCallerNpc(IntPtr ptr) : MonoBehaviour(ptr)
1919
public PlayerControl Target { get; set; }
2020
public PlayerControl npc;
2121
public LightSource ownerLight;
22-
public bool isActive = false;
22+
public bool isActive;
2323

2424
[HideFromIl2Cpp]
25-
2625
// Inspired by: https://github.com/NuclearPowered/Reactor/blob/e27a79249ea706318f3c06f3dc56a5c42d65b1cf/Reactor.Debugger/Window/Tabs/GameTab.cs#L70
27-
public void Initialize(PlayerControl wraith, PlayerControl target)
26+
public void Initialize(PlayerControl wraith, PlayerControl target, PlayerControl spawned)
2827
{
2928
Owner = wraith;
3029
Target = target;
30+
npc = spawned;
3131

32-
var prefab = AmongUsClient.Instance.PlayerPrefab;
33-
npc = Instantiate(prefab);
34-
npc.PlayerId = (byte)GameData.Instance.GetAvailableId();
35-
36-
var npcData = GameData.Instance.AddDummy(npc);
37-
AmongUsClient.Instance.Spawn(npcData);
38-
AmongUsClient.Instance.Spawn(npc);
32+
isActive = true;
3933

40-
npc.isDummy = false;
41-
npc.notRealPlayer = true;
4234
KillAnimation.SetMovement(npc, true);
43-
npc.NetTransform.RpcSnapTo(Owner.transform.position);
44-
npc.MyPhysics.Speed = OptionGroupSingleton<WraithCallerOptions>.Instance.NPCSpeed;
45-
46-
var color = (byte)(npc.PlayerId % Palette.PlayerColors.Length);
47-
npc.RpcSetName("Wraith NPC");
48-
npc.RpcSetColor(color);
49-
npc.RpcSetHat("");
50-
npc.RpcSetSkin("");
51-
npc.RpcSetPet("");
52-
npc.RpcSetVisor("");
5335

5436
npc.Collider.enabled = false;
37+
npc.MyPhysics.Speed = OptionGroupSingleton<WraithCallerOptions>.Instance.NPCSpeed;
5538

56-
var noShadow = npc.gameObject.AddComponent<NoShadowBehaviour>();
57-
if (noShadow != null)
58-
{
59-
noShadow.rend = npc.cosmetics.currentBodySprite.BodySprite;
60-
noShadow.hitOverride = npc.Collider;
61-
}
39+
if (!npc.TryGetComponent<ModifierComponent>(out _))
40+
npc.gameObject.AddComponent<ModifierComponent>();
6241

63-
if (!npc.TryGetComponent<ModifierComponent>(out var mc))
42+
if (AmongUsClient.Instance.AmHost)
6443
{
65-
mc = npc.gameObject.AddComponent<ModifierComponent>();
44+
NewMod.Instance.Log.LogMessage($"Host is setting cosmetics for NPC (ID: {npc.PlayerId}");
45+
npc.NetTransform.RpcSnapTo(Owner.transform.position);
46+
47+
var color = (byte)(npc.PlayerId % Palette.PlayerColors.Length);
48+
npc.RpcSetName("Wraith NPC");
49+
npc.RpcSetColor(color);
50+
51+
var noShadow = npc.gameObject.AddComponent<NoShadowBehaviour>();
52+
if (noShadow != null)
53+
{
54+
noShadow.rend = npc.cosmetics.currentBodySprite.BodySprite;
55+
noShadow.hitOverride = npc.Collider;
56+
}
6657
}
67-
58+
59+
Coroutines.Start(WalkToTarget());
60+
6861
if (OptionGroupSingleton<WraithCallerOptions>.Instance.ShouldSwitchCamToNPC)
6962
{
7063
Camera.main.GetComponent<FollowerCamera>().SetTarget(npc);
@@ -73,52 +66,46 @@ public void Initialize(PlayerControl wraith, PlayerControl target)
7366
ownerLight.transform.localPosition = npc.Collider.offset;
7467
}
7568

76-
npc.cosmetics.enabled = false;
69+
npc.cosmetics.enabled = true;
7770
npc.enabled = false;
7871

79-
isActive = true;
80-
81-
Coroutines.Start(WalkToTarget());
82-
8372
if (Target.AmOwner)
84-
{
8573
SoundManager.Instance.PlaySound(NewModAsset.HeartbeatSound.LoadAsset(), false, 1f);
86-
}
8774
}
75+
8876
[HideFromIl2Cpp]
89-
public System.Collections.IEnumerator WalkToTarget()
77+
private System.Collections.IEnumerator WalkToTarget()
9078
{
91-
if (Target.Data.IsDead || Target.Data.Disconnected)
92-
{
93-
Dispose();
94-
}
79+
//yield return null;
80+
81+
if (!AmongUsClient.Instance.AmHost) yield break;
82+
9583
while (isActive && !MeetingHud.Instance)
9684
{
85+
if (!Target || !Target.Data || Target.Data.IsDead)
86+
break;
87+
9788
Vector2 npcPos = npc.GetTruePosition();
9889
Vector2 targetPos = Target.GetTruePosition();
9990
Vector2 dir = (targetPos - npcPos).normalized;
10091

10192
npc.MyPhysics.SetNormalizedVelocity(dir);
10293

103-
float distance = Vector2.Distance(npcPos, targetPos);
104-
105-
if (distance <= 0.1f)
94+
if (Vector2.Distance(npcPos, targetPos) <= 0.1f)
10695
{
10796
npc.MyPhysics.SetNormalizedVelocity(Vector2.zero);
10897

10998
Owner.RpcCustomMurder(Target, true, teleportMurderer: false);
11099

111100
if (Target.AmOwner)
112-
{
113101
CoroutinesHelper.CoNotify("<color=#FF4D4D><b>Oops!</b> The <i>Wraith NPC</i> got you...");
114-
}
115-
WraithCallerUtilities.AddKillNPC(Owner.PlayerId);
116102

117-
Dispose();
118-
yield break;
103+
WraithCallerUtilities.AddKillNPC(Owner.PlayerId);
104+
break;
119105
}
120106
yield return new WaitForFixedUpdate();
121107
}
108+
122109
npc.MyPhysics.SetNormalizedVelocity(Vector2.zero);
123110
Dispose();
124111
}
@@ -127,25 +114,26 @@ public System.Collections.IEnumerator WalkToTarget()
127114
public void Dispose()
128115
{
129116
if (!isActive) return;
130-
131117
isActive = false;
132118

133-
if (npc != null)
119+
if (OptionGroupSingleton<WraithCallerOptions>.Instance.ShouldSwitchCamToNPC)
120+
{
121+
Camera.main.GetComponent<FollowerCamera>().SetTarget(Owner);
122+
ownerLight.transform.SetParent(Owner.transform, false);
123+
ownerLight.transform.localPosition = Owner.Collider.offset;
124+
}
125+
126+
if (AmongUsClient.Instance.AmHost)
134127
{
135-
if (OptionGroupSingleton<WraithCallerOptions>.Instance.ShouldSwitchCamToNPC)
136-
{
137-
var cam = Camera.main.GetComponent<FollowerCamera>();
138-
cam.SetTarget(Owner);
139-
ownerLight.transform.SetParent(Owner.transform, false);
140-
ownerLight.transform.localPosition = Owner.Collider.offset;
141-
}
142128
var info = GameData.Instance.AllPlayers.ToArray().FirstOrDefault(d => d.PlayerId == npc.PlayerId);
143129
GameData.Instance.RemovePlayer(info.PlayerId);
144130
PlayerControl.AllPlayerControls.Remove(npc);
145131

132+
npc.Despawn();
146133
Destroy(npc.gameObject);
147134
npc = null;
148135
}
136+
149137
Destroy(gameObject);
150138
}
151139
}

NewMod/CustomRPC.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ namespace NewMod;
22

33
public enum CustomRPC
44
{
5-
Revive,
5+
HandleRevive,
66
Drain,
77
FakeBody,
88
AssignMission,

NewMod/NewMod.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
<ItemGroup>
1414
<PackageReference Include="Reactor" Version="2.3.1" />
15-
<PackageReference Include="AllOfUs.MiraAPI" Version="0.3.6" />
15+
<PackageReference Include="AllOfUs.MiraAPI" Version="0.3.8" />
1616
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2025.11.18" PrivateAssets="all" />
1717
<PackageReference Include="BepInEx.AutoPlugin" Version="1.1.0" PrivateAssets="all" />
1818
<PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.1.0-rc.1" PrivateAssets="all" ExcludeAssets="runtime" />

NewMod/Patches/Roles/EnergyThief/OnGameEnd.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,11 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)] EndGam
1919
VisionaryUtilities.DeleteAllScreenshots();
2020
WraithCallerUtilities.ClearAll();
2121
Shade.ShadeKills.Clear();
22-
Revenant.HasUsedFeignDeath = false;
23-
Revenant.FeignDeathStates.Remove(PlayerControl.LocalPlayer.PlayerId);
24-
Revenant.StalkingStates[PlayerControl.LocalPlayer.PlayerId] = false;
22+
Revenant.ResetAllStates();
2523
NewMod.Instance.Log.LogInfo("Reset Drain Count Successfully");
2624
NewMod.Instance.Log.LogInfo("Reset Clone Report Count Successfully");
2725
NewMod.Instance.Log.LogInfo("Reset Mission Success Count Successfully");
2826
NewMod.Instance.Log.LogInfo("Reset Mission Failure Count Successfully");
2927
NewMod.Instance.Log.LogInfo("Deleted all Visionary's screenshots Successfully");
3028
}
31-
}
29+
}

NewMod/Roles/CrewmateRoles/Specialist.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,17 @@ public class Specialist : CrewmateRole, ICustomRole
3737
[RegisterEvent]
3838
public static void OnTaskComplete(CompleteTaskEvent evt)
3939
{
40-
PlayerControl player = evt.Player;
41-
if (player.Data.Role is not Specialist) return;
40+
PlayerControl specialist = evt.Player;
41+
if (specialist.Data.Role is not Specialist) return;
4242

4343
List<Action> abilityAction = new List<Action>
4444
{
4545
() =>
4646
{
47-
var target = Utils.GetRandomPlayer(p => !p.Data.IsDead && !p.Data.Disconnected && p != player);
47+
var target = Utils.GetRandomPlayer(p => !p.Data.IsDead && !p.Data.Disconnected && p != specialist);
4848
if (target != null)
4949
{
50-
Utils.RpcRandomDrainActions(player, target);
50+
Utils.RpcRandomDrainActions(specialist, target);
5151
Helpers.CreateAndShowNotification($"Energy Drain activated on {target.Data.PlayerName}!",Color.green);
5252
}
5353
},
@@ -57,13 +57,13 @@ public static void OnTaskComplete(CompleteTaskEvent evt)
5757
var player = Utils.PlayerById(closestBody.ParentId);
5858
if (closestBody != null)
5959
{
60-
Utils.RpcRevive(closestBody);
60+
Utils.HandleRevive(specialist, closestBody.ParentId, AmongUs.GameOptions.RoleTypes.Crewmate, closestBody.transform.position.x, closestBody.transform.position.y);
6161
Helpers.CreateAndShowNotification($"Player {player.Data.PlayerName} has been revived.", Color.green);
6262
}
6363
},
6464
() =>
6565
{
66-
PranksterUtilities.CreatePranksterDeadBody(player, player.PlayerId);
66+
PranksterUtilities.CreatePranksterDeadBody(specialist, specialist.PlayerId);
6767
Helpers.CreateAndShowNotification("Fake Body created!", Color.green);
6868
},
6969
() =>

NewMod/Roles/ImpostorRoles/Revenant.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,16 @@ public class FeignDeathInfo
4141
public bool Reported;
4242
}
4343

44+
public static void ResetAllStates()
45+
{
46+
FeignDeathStates.Clear();
47+
StalkingStates.Clear();
48+
HasUsedFeignDeath = false;
49+
}
50+
4451
[RegisterEvent]
4552
public static void OnPlayerExit(PlayerLeaveEvent evt)
4653
{
47-
if (FeignDeathStates.ContainsKey(evt.ClientData.Character.PlayerId))
48-
{
49-
FeignDeathStates.Remove(evt.ClientData.Character.PlayerId);
50-
}
51-
if (StalkingStates.ContainsKey(evt.ClientData.Character.PlayerId))
52-
{
53-
StalkingStates.Remove(evt.ClientData.Character.PlayerId);
54-
}
55-
HasUsedFeignDeath = false;
54+
ResetAllStates();
5655
}
5756
}

NewMod/Utilities/CoroutinesHelper.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using NewMod.Roles.NeutralRoles;
1010
using Reactor.Utilities.Extensions;
1111
using NewMod.Components.ScreenEffects;
12+
using AmongUs.GameOptions;
1213

1314
namespace NewMod.Utilities
1415
{
@@ -296,7 +297,7 @@ public static IEnumerator CoReviveAndKill(PlayerControl target)
296297
{
297298
revivedParentId = deadBody.ParentId;
298299

299-
Utils.RpcRevive(deadBody);
300+
Utils.HandleRevive(target, deadBody.ParentId, RoleTypes.Crewmate, deadBody.transform.position.x, deadBody.transform.position.y);
300301

301302
yield return new WaitForSeconds(0.5f);
302303

@@ -456,5 +457,17 @@ public static IEnumerator RemoveCameraEffect(Camera cam, float duration)
456457
if (cam.TryGetComponent<ShadowFluxEffect>(out var sf))
457458
Object.Destroy(sf);
458459
}
460+
public static IEnumerator CoRevive(PlayerControl revived, RoleTypes role)
461+
{
462+
yield return new WaitForSeconds(0.15f);
463+
464+
var body = GameObject.FindObjectsOfType<DeadBody>().FirstOrDefault(b => b.ParentId == revived.PlayerId);
465+
466+
if (body != null)
467+
Object.Destroy(body.gameObject);
468+
469+
revived.Revive();
470+
revived.RpcSetRole(role);
471+
}
459472
}
460473
}

0 commit comments

Comments
 (0)