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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ obj/
References/
NewMod/Components/Minigames
NewMod/Components/Hidden.cs
NewMod/Private
/packages/
riderModule.iml
.idea
Expand Down
70 changes: 41 additions & 29 deletions NewMod/Buttons/Necromancer/ReviveButton.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
using UnityEngine;
using NewMod.Utilities;
using MiraAPI.Keybinds;
using AmongUs.GameOptions;
using Reactor.Utilities;
using MiraAPI.Utilities;
using System.Linq;

namespace NewMod.Buttons.Necromancer
{
Expand Down Expand Up @@ -54,15 +58,29 @@ public class ReviveButton : CustomActionButton
/// </summary>
protected override void OnClick()
{
var local = PlayerControl.LocalPlayer;

var body = Helpers.GetNearestDeadBodies(
local.GetTruePosition(),
ShipStatus.Instance.MaxLightRadius,
Helpers.CreateFilter(Constants.NotShipMask))
.Where(b => b != null && !PranksterUtilities.IsPranksterBody(b))
.OrderBy(b => Vector2.Distance(local.GetTruePosition(), b.TruePosition))
.FirstOrDefault();

if (body == null) return;

SoundManager.Instance.PlaySound(NewModAsset.ReviveSound?.LoadAsset(), false, 2f);

var closestBody = Utils.GetClosestBody();
if (closestBody != null)
{
Utils.RpcRevive(closestBody);
}
Utils.HandleRevive(
local,
body.ParentId,
RoleTypes.Crewmate,
body.transform.position.x,
body.transform.position.y
);
NecromancerRole.RevivedPlayers[body.ParentId] = local.PlayerId;
}

/// <summary>
/// Determines whether this button is enabled for the role, returning true if the role is <see cref="NecromancerRole"/>.
/// </summary>
Expand All @@ -79,32 +97,26 @@ public override bool Enabled(RoleBehaviour role)
/// <returns>True if all requirements to use this button are met; otherwise false.</returns>
public override bool CanUse()
{
bool isTimerDone = Timer <= 0;
bool hasUsesLeft = UsesLeft > 0;
var closestBody = Utils.GetClosestBody();
bool isNearDeadBody = closestBody != null;
bool isFakeBody = isNearDeadBody && PranksterUtilities.IsPranksterBody(closestBody);
var bodiesInRange = Helpers.GetNearestDeadBodies(
PlayerControl.LocalPlayer.transform.position,
ShipStatus.Instance.MaxLightRadius,
Helpers.CreateFilter(Constants.NotShipMask));

if (closestBody == null)
bool canUse = bodiesInRange.Any(body =>
{
return false;
}
if (PranksterUtilities.IsPranksterBody(body)) return false;

bool wasNotKilledByNecromancer = true;
var deadBody = closestBody.GetComponent<DeadBody>();
if (deadBody != null)
{
var killedPlayer = GameData.Instance.GetPlayerById(deadBody.ParentId)?.Object;
if (killedPlayer != null)
{
var killer = Utils.GetKiller(killedPlayer);
if (killer != null && killer.Data.Role is NecromancerRole)
{
wasNotKilledByNecromancer = false;
}
}
}
return isTimerDone && hasUsesLeft && isNearDeadBody && wasNotKilledByNecromancer && !isFakeBody;
var killedPlayer = GameData.Instance.GetPlayerById(body.ParentId)?.Object;
if (killedPlayer == null) return false;

var killer = Utils.GetKiller(killedPlayer);
if (killer.PlayerId == PlayerControl.LocalPlayer.PlayerId)
return false;

return true;
});

return canUse;
}
}
}
63 changes: 63 additions & 0 deletions NewMod/Buttons/RevivedKillButton.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using MiraAPI.Hud;
using MiraAPI.Keybinds;
using MiraAPI.Utilities.Assets;
using NewMod.Roles.ImpostorRoles;
using Reactor.Utilities;
using AmongUs.GameOptions;
using System.Linq;
using UnityEngine;
using MiraAPI.Networking;
using MiraAPI.Utilities;

namespace NewMod.Buttons
{
public class RevivedKillButton : CustomActionButton<PlayerControl>
{
public override string Name => "KILL";
public override float Cooldown => GameOptionsManager.Instance.CurrentGameOptions.GetFloat(FloatOptionNames.KillCooldown);
public override int MaxUses => 0;
public override float EffectDuration => 0f;
public override MiraKeybind Keybind => MiraGlobalKeybinds.PrimaryAbility;
public override ButtonLocation Location => ButtonLocation.BottomRight;
public override LoadableAsset<Sprite> Sprite => NewModAsset.VanillaKillButton;
public override bool Enabled(RoleBehaviour role)
{
return NecromancerRole.RevivedPlayers.ContainsKey(PlayerControl.LocalPlayer.PlayerId);
}
public override PlayerControl GetTarget()
{
return PlayerControl.LocalPlayer.GetClosestPlayer(true, Distance);
}
public override bool IsTargetValid(PlayerControl target)
{
return target.PlayerId != PlayerControl.LocalPlayer.PlayerId;
}
public override void SetOutline(bool active)
{
Target.cosmetics.SetOutline(active, new Il2CppSystem.Nullable<Color>(Palette.ImpostorRed));
}

public override bool CanUse()
{
if (!NecromancerRole.RevivedPlayers.ContainsKey(PlayerControl.LocalPlayer.PlayerId)) return false;
return true;
}

protected override void OnClick()
{
var local = PlayerControl.LocalPlayer;

local.RpcCustomMurder(
Target,
didSucceed: true,
resetKillTimer: true,
createDeadBody: true,
teleportMurderer: true,
showKillAnim: true,
playKillSound: true
);

NecromancerRole.RevivedPlayers.Remove(local.PlayerId);
}
}
}
2 changes: 1 addition & 1 deletion NewMod/Buttons/WraithCaller/CallWraith.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ protected override void OnClick()
player =>
{
menu.Close();
WraithCallerUtilities.RpcSummonNPC(PlayerControl.LocalPlayer, player);
WraithCallerUtilities.RpcRequestSummonNPC(PlayerControl.LocalPlayer, player);
SetTimerPaused(false);
});

Expand Down
81 changes: 55 additions & 26 deletions NewMod/Components/FearPulseArea.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,25 @@ namespace NewMod.Components
public class FearPulseArea(IntPtr ptr) : MonoBehaviour(ptr)
{
public byte ownerId;
float _radius, _duration, _speedMul, _t;

float _radius;
float _duration;
float _speedMul;
float _t;

readonly Dictionary<byte, float> _origSpeed = new();
readonly HashSet<byte> _insideNow = new();

public static readonly HashSet<byte> AffectedPlayers = new();
public static readonly HashSet<byte> _speedNotifShown = new();
public static readonly HashSet<byte> _visionNotifShown = new();

public AudioClip _enterClip;
public AudioClip _heartbeatClip;
public bool _pulsingHb;

bool _restored;

public void Init(byte ownerId, float radius, float duration, float speedMul)
{
this.ownerId = ownerId;
Expand All @@ -35,6 +44,8 @@ public void Init(byte ownerId, float radius, float duration, float speedMul)

public void Update()
{
if (_restored) return;

_t += Time.deltaTime;
if (_t > _duration)
{
Expand Down Expand Up @@ -89,12 +100,13 @@ public void Update()
{
_visionNotifShown.Add(p.PlayerId);
var notif = Helpers.CreateAndShowNotification(
"You have entered the Fear Pulse Area. Your vision is reduced!",
new Color(1f, 0.8f, 0.2f),
spr: NewModAsset.VisionDebuff.LoadAsset()
);
"You have entered the Fear Pulse Area. Your vision is reduced!",
new Color(1f, 0.8f, 0.2f),
spr: NewModAsset.VisionDebuff.LoadAsset()
);
notif.Text.SetOutlineThickness(0.36f);
}

Coroutines.Start(Utils.CoShakeCamera(Camera.main.GetComponent<FollowerCamera>(), 0.5f));
}

Expand All @@ -112,40 +124,57 @@ public void Update()
var toRestore = _origSpeed.Keys.Where(id => !_insideNow.Contains(id)).ToList();
foreach (var id in toRestore)
{
var p = Utils.PlayerById(id);
if (p) p.MyPhysics.Speed = _origSpeed[id];
_origSpeed.Remove(id);
RestorePlayer(id);
}
}
}

public void RestorePlayer(byte playerId)
{
if (_origSpeed.TryGetValue(playerId, out var originalSpeed))
{
var p = Utils.PlayerById(playerId);

if (!p.Data.IsDead || !p.Data.Disconnected)
{
p.MyPhysics.Speed = originalSpeed;

if (p.AmOwner)
{
AffectedPlayers.Remove(p.PlayerId);
p.lightSource.lightChild.SetActive(true);
_speedNotifShown.Remove(p.PlayerId);
_visionNotifShown.Remove(p.PlayerId);
Helpers.CreateAndShowNotification("Your vision is restored.", new Color(0.8f, 1f, 0.8f));

Helpers.CreateAndShowNotification(
"Your speed and vision are restored.",
new Color(0.8f, 1f, 0.8f)
);
}
}

_origSpeed.Remove(playerId);
}

AffectedPlayers.Remove(playerId);
_speedNotifShown.Remove(playerId);
_visionNotifShown.Remove(playerId);
}

public void RestoreAll()
{
foreach (var kv in _origSpeed)
if (_restored) return;
_restored = true;

var ids = _origSpeed.Keys.ToList();
foreach (var id in ids)
{
var p = Utils.PlayerById(kv.Key);
if (p) p.MyPhysics.Speed = kv.Value;
RestorePlayer(id);
}
_origSpeed.Clear();
AffectedPlayers.Clear();

var lp = PlayerControl.LocalPlayer;

if (AffectedPlayers.Contains(lp.PlayerId))
AffectedPlayers.Remove(lp.PlayerId);

lp.lightSource.lightChild.SetActive(true);
_insideNow.Clear();
}

_speedNotifShown.Remove(lp.PlayerId);
_visionNotifShown.Remove(lp.PlayerId);
public void OnDestroy()
{
RestoreAll();
}
}
}
}
Loading
Loading