Skip to content

Commit ad1a315

Browse files
committed
Fixed Wraith Caller disconnection issues, resolved the endgame crash, addressed an issue where some roles’ DidWin wasn’t being called, and added the Feign Death sprite along with the Necromancer role icon
1 parent b79692a commit ad1a315

16 files changed

Lines changed: 165 additions & 159 deletions

File tree

NewMod/Buttons/Necromancer/ReviveButton.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using NewMod.Utilities;
88
using MiraAPI.Keybinds;
99
using AmongUs.GameOptions;
10-
using Reactor.Utilities;
1110
using MiraAPI.Utilities;
1211
using System.Linq;
1312

@@ -98,7 +97,7 @@ public override bool Enabled(RoleBehaviour role)
9897
public override bool CanUse()
9998
{
10099
var bodiesInRange = Helpers.GetNearestDeadBodies(
101-
PlayerControl.LocalPlayer.transform.position,
100+
PlayerControl.LocalPlayer.GetTruePosition(),
102101
ShipStatus.Instance.MaxLightRadius,
103102
Helpers.CreateFilter(Constants.NotShipMask));
104103

NewMod/Buttons/Revenant/FeignDeathButton.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public class FeignDeathButton : CustomActionButton
4848
/// <summary>
4949
/// The icon or sprite used for this button. Here, set to an empty sprite.
5050
/// </summary>
51-
public override LoadableAsset<Sprite> Sprite => MiraAssets.Empty;
51+
public override LoadableAsset<Sprite> Sprite => NewModAsset.FeignDeath;
5252

5353
/// <summary>
5454
/// Specifies whether the button is enabled for the given role, ensuring Feign Death hasn't been used yet.

NewMod/Buttons/RevivedKillButton.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using MiraAPI.Keybinds;
33
using MiraAPI.Utilities.Assets;
44
using NewMod.Roles.ImpostorRoles;
5-
using Reactor.Utilities;
65
using AmongUs.GameOptions;
76
using UnityEngine;
87
using MiraAPI.Networking;
@@ -22,7 +21,7 @@ public class RevivedKillButton : CustomActionButton<PlayerControl>
2221

2322
public override bool Enabled(RoleBehaviour role)
2423
{
25-
return NecromancerRole.RevivedPlayers.ContainsKey(PlayerControl.LocalPlayer.PlayerId);
24+
return NecromancerRole.RevivedPlayers.ContainsKey(PlayerControl.LocalPlayer.PlayerId);
2625
}
2726

2827
public override PlayerControl GetTarget()

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.RpcRequestSummonNPC(PlayerControl.LocalPlayer, player);
88+
WraithCallerUtilities.RequestSummonNPC(PlayerControl.LocalPlayer, player);
8989
SetTimerPaused(false);
9090
});
9191

Lines changed: 105 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
using System;
2-
using System.Linq;
2+
using System.Collections;
33
using Il2CppInterop.Runtime.Attributes;
44
using MiraAPI.GameOptions;
5-
using MiraAPI.Modifiers;
65
using MiraAPI.Networking;
76
using NewMod.Options.Roles.WraithCallerOptions;
87
using NewMod.Utilities;
@@ -17,124 +16,171 @@ public class WraithCallerNpc(IntPtr ptr) : MonoBehaviour(ptr)
1716
{
1817
public PlayerControl Owner { get; set; }
1918
public PlayerControl Target { get; set; }
20-
public PlayerControl npc;
19+
public PlayerControl Visual { get; set; }
20+
public Rigidbody2D body;
21+
public PlayerAnimations animations;
22+
2123
public LightSource ownerLight;
2224
public bool isActive;
2325

2426
[HideFromIl2Cpp]
27+
2528
// Inspired by: https://github.com/NuclearPowered/Reactor/blob/e27a79249ea706318f3c06f3dc56a5c42d65b1cf/Reactor.Debugger/Window/Tabs/GameTab.cs#L70
26-
public void Initialize(PlayerControl wraith, PlayerControl target, PlayerControl spawned)
29+
public void Initialize(PlayerControl owner, PlayerControl target, Vector2 start)
2730
{
28-
Owner = wraith;
31+
Owner = owner;
2932
Target = target;
30-
npc = spawned;
3133

32-
isActive = true;
34+
Visual = Instantiate(AmongUsClient.Instance.PlayerPrefab);
35+
Visual.transform.position = new Vector3(start.x, start.y, Owner.transform.position.z);
3336

34-
KillAnimation.SetMovement(npc, true);
37+
Visual.notRealPlayer = true;
38+
Visual.enabled = false;
39+
Visual.NetTransform.enabled = false;
40+
Visual.Collider.enabled = false;
41+
Visual.MyPhysics.enabled = false;
3542

36-
npc.Collider.enabled = false;
37-
npc.MyPhysics.Speed = OptionGroupSingleton<WraithCallerOptions>.Instance.NPCSpeed;
43+
PlayerControl.AllPlayerControls.Remove(Visual);
3844

39-
if (!npc.TryGetComponent<ModifierComponent>(out _))
40-
npc.gameObject.AddComponent<ModifierComponent>();
45+
body = Visual.MyPhysics.body;
46+
animations = Visual.MyPhysics.Animations;
4147

42-
if (AmongUsClient.Instance.AmHost)
43-
{
44-
NewMod.Instance.Log.LogMessage($"Host is setting cosmetics for NPC (ID: {npc.PlayerId}");
45-
npc.NetTransform.RpcSnapTo(Owner.transform.position);
48+
body.isKinematic = false;
4649

47-
var color = (byte)(npc.PlayerId % Palette.PlayerColors.Length);
48-
npc.RpcSetName("Wraith NPC");
49-
npc.RpcSetColor(color);
50+
Visual.cosmetics.enabled = true;
51+
Visual.cosmetics.Visible = true;
5052

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-
}
57-
}
53+
Visual.cosmetics.SetName("Wraith NPC");
54+
Visual.cosmetics.ToggleName(true);
55+
Visual.cosmetics.ToggleHat(false);
56+
Visual.cosmetics.TogglePet(false);
57+
Visual.cosmetics.ToggleVisor(false);
58+
59+
var color = Owner.PlayerId % Palette.PlayerColors.Length;
60+
var bodySprite = Visual.cosmetics.currentBodySprite;
61+
62+
bodySprite.Visible = true;
63+
PlayerMaterial.SetColors(color, bodySprite.BodySprite);
5864

59-
Coroutines.Start(WalkToTarget());
65+
var noShadow = Visual.gameObject.AddComponent<NoShadowBehaviour>();
66+
noShadow.rend = bodySprite.BodySprite;
67+
noShadow.hitOverride = Visual.Collider;
6068

61-
if (OptionGroupSingleton<WraithCallerOptions>.Instance.ShouldSwitchCamToNPC)
69+
isActive = true;
70+
Coroutines.Start(CoMove());
71+
72+
if (Owner.AmOwner && OptionGroupSingleton<WraithCallerOptions>.Instance.ShouldSwitchCamToNPC)
6273
{
63-
Camera.main.GetComponent<FollowerCamera>().SetTarget(npc);
74+
Camera.main.GetComponent<FollowerCamera>().SetTarget(Visual);
6475
ownerLight = Owner.lightSource;
65-
ownerLight.transform.SetParent(npc.transform, false);
66-
ownerLight.transform.localPosition = npc.Collider.offset;
76+
ownerLight.transform.SetParent(Visual.transform, false);
77+
ownerLight.transform.localPosition = Visual.Collider.offset;
6778
}
6879

69-
npc.cosmetics.enabled = true;
70-
npc.enabled = false;
71-
7280
if (Target.AmOwner)
7381
SoundManager.Instance.PlaySound(NewModAsset.HeartbeatSound.LoadAsset(), false, 1f);
7482
}
7583

7684
[HideFromIl2Cpp]
77-
private System.Collections.IEnumerator WalkToTarget()
85+
public IEnumerator CoMove()
7886
{
79-
//yield return null;
80-
81-
if (!AmongUsClient.Instance.AmHost) yield break;
87+
var speed = OptionGroupSingleton<WraithCallerOptions>.Instance.NPCSpeed;
8288

8389
while (isActive && !MeetingHud.Instance)
8490
{
85-
if (!Target || !Target.Data || Target.Data.IsDead)
91+
if (Target.Data.IsDead || Target.Data.Disconnected)
8692
break;
8793

88-
Vector2 npcPos = npc.GetTruePosition();
89-
Vector2 targetPos = Target.GetTruePosition();
90-
Vector2 dir = (targetPos - npcPos).normalized;
94+
var npcPos = (Vector2)Visual.transform.position;
95+
var targetPos = Target.GetTruePosition();
96+
var delta = targetPos - npcPos;
97+
98+
var slowDown = Mathf.Clamp(delta.magnitude * 2f, 0.05f, 1f);
99+
var velocity = delta.normalized * speed * slowDown;
91100

92-
npc.MyPhysics.SetNormalizedVelocity(dir);
101+
body.velocity = velocity;
93102

94-
if (Vector2.Distance(npcPos, targetPos) <= 0.1f)
103+
UpdateWalkAnimation(velocity);
104+
105+
if (AmongUsClient.Instance.AmHost && delta.magnitude <= 0.15f)
95106
{
96-
npc.MyPhysics.SetNormalizedVelocity(Vector2.zero);
107+
body.velocity = Vector2.zero;
108+
UpdateWalkAnimation(Vector2.zero);
97109

98110
Owner.RpcCustomMurder(Target, true, teleportMurderer: false);
99111

100112
if (Target.AmOwner)
113+
{
101114
CoroutinesHelper.CoNotify("<color=#FF4D4D><b>Oops!</b> The <i>Wraith NPC</i> got you...");
115+
}
102116

103117
WraithCallerUtilities.AddKillNPC(Owner.PlayerId);
104118
break;
105119
}
106-
yield return new WaitForFixedUpdate();
120+
121+
yield return null;
107122
}
108123

109-
npc.MyPhysics.SetNormalizedVelocity(Vector2.zero);
124+
body.velocity = Vector2.zero;
125+
UpdateWalkAnimation(Vector2.zero);
110126
Dispose();
111127
}
128+
[HideFromIl2Cpp]
129+
public void UpdateWalkAnimation(Vector2 velocity)
130+
{
131+
bool moving = velocity.sqrMagnitude >= 0.01f;
112132

133+
if (velocity.x < -0.01f)
134+
Visual.cosmetics.SetFlipXWithoutPet(true);
135+
else if (velocity.x > 0.01f)
136+
Visual.cosmetics.SetFlipXWithoutPet(false);
137+
138+
if (moving)
139+
{
140+
if (!animations.IsPlayingRunAnimation())
141+
{
142+
animations.PlayRunAnimation();
143+
}
144+
if (Visual.cosmetics.HasSkinLoaded() && !Visual.cosmetics.IsSkinPlayingRunAnim())
145+
{
146+
Visual.cosmetics.AnimateSkinRun();
147+
}
148+
}
149+
else
150+
{
151+
if (animations.IsPlayingRunAnimation() || !animations.IsPlayingSomeAnimation())
152+
{
153+
animations.PlayIdleAnimation();
154+
155+
if (Visual.cosmetics.HasSkinLoaded())
156+
{
157+
Visual.cosmetics.AnimateSkinIdle();
158+
}
159+
}
160+
}
161+
var pos = Visual.transform.position;
162+
pos.z = pos.y / 1000f;
163+
Visual.transform.position = pos;
164+
}
113165
[HideFromIl2Cpp]
114166
public void Dispose()
115167
{
116168
if (!isActive) return;
169+
117170
isActive = false;
118171

119-
if (OptionGroupSingleton<WraithCallerOptions>.Instance.ShouldSwitchCamToNPC)
172+
if (Owner.AmOwner && OptionGroupSingleton<WraithCallerOptions>.Instance.ShouldSwitchCamToNPC)
120173
{
121174
Camera.main.GetComponent<FollowerCamera>().SetTarget(Owner);
122175
ownerLight.transform.SetParent(Owner.transform, false);
123176
ownerLight.transform.localPosition = Owner.Collider.offset;
124177
}
125178

126-
if (AmongUsClient.Instance.AmHost)
127-
{
128-
var info = GameData.Instance.AllPlayers.ToArray().FirstOrDefault(d => d.PlayerId == npc.PlayerId);
129-
GameData.Instance.RemovePlayer(info.PlayerId);
130-
PlayerControl.AllPlayerControls.Remove(npc);
131-
132-
npc.Despawn();
133-
Destroy(npc.gameObject);
134-
npc = null;
135-
}
179+
if (body)
180+
body.velocity = Vector2.zero;
136181

182+
Destroy(Visual.gameObject);
137183
Destroy(gameObject);
138184
}
139185
}
140-
}
186+
}

NewMod/NewMod.cs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public override void Load()
4747
{
4848
Instance = this;
4949
AddComponent<DebugWindow>();
50-
ReactorCredits.Register("NewMod", "v1.2.9 Hotfix 2", true, ReactorCredits.AlwaysShow);
50+
ReactorCredits.Register("NewMod", "v1.2.9 Hotfix 3", true, ReactorCredits.AlwaysShow);
5151
Harmony.PatchAll();
5252
NewModEventHandler.RegisterEventsLogs();
5353

@@ -59,16 +59,6 @@ public override void Load()
5959
ShouldEnableBepInExConsole = Config.Bind("NewMod", "Console", true, "Whether to enable BepInEx Console for debugging");
6060
if (!ShouldEnableBepInExConsole.Value) ConsoleManager.DetachConsole();
6161

62-
var bundle = NewModAsset.Bundle;
63-
var assetNames = bundle.GetAllAssetNames();
64-
65-
Instance.Log.LogMessage($"AssetBundle '{bundle.name}' contains {assetNames.Length} assets");
66-
67-
foreach (var name in assetNames)
68-
{
69-
Instance.Log.LogMessage($"{name}");
70-
}
71-
7262
Instance.Log.LogMessage($"Loaded Successfully NewMod v{ModVersion} With MiraAPI Version : {MiraApiPlugin.Version}");
7363
}
7464

NewMod/NewModAsset.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public static class NewModAsset
4242
public static LoadableResourceAsset Shield { get; } = new("NewMod.Resources.Shield.png");
4343
public static LoadableResourceAsset Slash { get; } = new("NewMod.Resources.Slash.png");
4444
public static LoadableResourceAsset DeployZone { get; } = new("NewMod.Resources.deployzone.png");
45+
public static LoadableResourceAsset FeignDeath { get; } = new("NewMod.Resources.feigndeath.png");
4546
public static LoadableResourceAsset VanillaKillButton { get; } = new("NewMod.Resources.killbutton.png");
4647

4748
// SFX
@@ -64,6 +65,7 @@ public static class NewModAsset
6465
public static LoadableResourceAsset RadarIcon { get; } = new("NewMod.Resources.RoleIcons.RadarIcon.png");
6566
public static LoadableResourceAsset SlashIcon { get; } = new("NewMod.Resources.RoleIcons.SlashIcon.png");
6667
public static LoadableResourceAsset DeployZoneIcon { get; } = new("NewMod.Resources.RoleIcons.DeployzoneIcon.png");
68+
public static LoadableResourceAsset ReviveIcon { get; } = new("NewMod.Resources.RoleIcons.ReviveIcon.png");
6769

6870
// Notif Icons
6971
public static LoadableResourceAsset VisionDebuff { get; } = new("NewMod.Resources.NotifIcons.vision_debuff.png");
8.85 KB
Loading

NewMod/Resources/feigndeath.png

26.9 KB
Loading

NewMod/Roles/ImpostorRoles/Necromancer.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public class NecromancerRole : ImpostorRole, ICustomRole
1919
public RoleOptionsGroup RoleOptionsGroup { get; } = RoleOptionsGroup.Impostor;
2020
public CustomRoleConfiguration Configuration => new(this)
2121
{
22-
Icon = MiraAssets.Empty,
22+
Icon = NewModAsset.ReviveIcon,
2323
OptionsScreenshot = NewModAsset.Banner,
2424
MaxRoleCount = 3,
2525
};
@@ -41,7 +41,6 @@ public override bool DidWin(GameOverReason reason)
4141
{
4242
return false;
4343
}
44-
45-
return base.DidWin(reason);
44+
return true;
4645
}
4746
}

0 commit comments

Comments
 (0)