Skip to content

heart breaker #1279

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: dev_2.3.0
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion Modules/OptionHolder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ public static float GetRoleChance(CustomRoles role)
private static System.Collections.IEnumerator CoLoadOptions()
{
//#######################################
// 30100 last id for roles/add-ons (Next use 30200)
// 30900 last id for roles/add-ons (Next use 31000)
// Limit id for roles/add-ons --- "59999"
//#######################################

Expand Down
10 changes: 10 additions & 0 deletions Resources/Lang/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@
"Sloth": "Sloth",
"Prohibited": "Prohibited",
"Eavesdropper": "Eavesdropper",
"HeartBreaker": "Heart Breaker",
"BracketAddons": "Add Brackets To Add-ons",
"EngineerTOHEInfo": "Use the vents to catch the <color=#ff1919>Impostors</color>",
"ScientistTOHEInfo": "Access portable vitals from anywhere",
Expand Down Expand Up @@ -710,6 +711,7 @@
"SlothInfo": "You're slower",
"ProhibitedInfo": "Certain vents are blocked",
"EavesdropperInfo": "Listen in on other roles",
"HeartBreakerInfo": "Steal a lover",
"EngineerTOHEInfoLong": "(Crewmates):\nAs the Engineer, you may access the vents while Comms Sabotaged is inactive.",
"ScientistTOHEInfoLong": "(Crewmates):\nAs the Scientist, you can see vitals at any time, showing you who is alive and dead.",
"NoisemakerTOHEInfoLong": "(Crewmates):\nAs the Noisemaker, whenever you die, you will make a noise, and a visual indicator of your death appears on the screen so the Crewmates can run to catch the person who killed you red-handed (even if it’s not Red).",
Expand Down Expand Up @@ -935,6 +937,7 @@
"JinxInfoLong": "(Neutrals):\nAs the Jinx, whenever you get attacked, you jinx them, resulting in them dying to a jinx.\nThis has limited uses.\n\nKill off everyone to win.",
"PotionMasterInfoLong": "(Neutrals):\nAs the Potion Master, you have three different potions assigned to three different actions.\n\nSingle click: Reveal role\nDouble click: Kill\nMap: Sabotage\n\nThe reveal potion has a limit.\nWhen you run out, the kill buttons default to killing.",
"NecromancerInfoLong": "(Neutrals):\nAs the Necromancer, you win when you're the last one standing.\nAdditionally when someone tries to kill you, you will block the kill, and you will teleport to a random vent. You will have a limited time to kill your killer. If you succeed in doing so, you live. If the time runs out before you kill your killer, you die permanently. If you try to kill someone else other than your killer, you will die.",
"HeartBreakerInfoLong": "(Neutrals):\nAs the Heart Breaker, you can steal a lover. Depending on the settings, you will be able to kill after finding your lover. You may also die if you don't find one",
"LastImpostorInfoLong": "(Add-ons):\nThis special effect is given to the last surviving Impostor. It significantly reduces their kill cooldown.",
"OverclockedInfoLong": "(Add-ons):\nAs the Overclocked, your kill cooldown is reduced by a percentage.\n\nThis feature is only assigned to roles with a kill button.",
"LoversInfoLong": "(Add-ons):\nLovers are a combination of two players. The Lovers win when they are the last ones standing, and their victory is shared. When one of the Lovers wins, the other also wins together. Lovers can see the 「♥」 next to each other's name. If one of the Lovers dies, the other will die in love (may not die in love according to the Host's settings). When one of the Lovers is exiled in the meeting, the other will die and become a dead body that cannot be reported.",
Expand Down Expand Up @@ -3792,6 +3795,13 @@

"Evader_ChanceNotExiled": "Chance not be exiled",

"HeartBreakerNewLoverText": "You have a new lover",
"HeartBreakerCooldown": "Break Cooldown",
"HeartBreakerKillOtherLover": "Kill Other Lover",
"HeartBreakerTriesMax": "Break Limit",
"HeartBreakerSuicideIfNoLover": "Suicide If No Lover",
"HeartBreakerBreakText" : "Break",

"EavesdropperMsgTitle": "You found a secret",
"EavesdropPercentChance": "Chance to eavesdrop"
}
3 changes: 2 additions & 1 deletion Resources/roleColor.json
Original file line number Diff line number Diff line change
Expand Up @@ -247,5 +247,6 @@
"Radar": "#1eff1e",
"Rebirth": "#f08c22",
"Sloth": "#376db8",
"Eavesdropper": "#ffe6bf"
"Eavesdropper": "#ffe6bf",
"HeartBreaker": "#269c84"
}
1 change: 1 addition & 0 deletions Roles/Core/AssignManager/AddonAssign.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ private static void AssignLovers(int RawCount = -1)
|| pc.Is(CustomRoles.Mini)
|| pc.Is(CustomRoles.NiceMini)
|| pc.Is(CustomRoles.EvilMini)
|| pc.Is(CustomRoles.HeartBreaker)
|| (pc.GetCustomRole().IsCrewmate() && !Options.CrewCanBeInLove.GetBool())
|| (pc.GetCustomRole().IsNeutral() && !Options.NeutralCanBeInLove.GetBool())
|| (pc.GetCustomRole().IsImpostor() && !Options.ImpCanBeInLove.GetBool()))
Expand Down
5 changes: 5 additions & 0 deletions Roles/Core/AssignManager/RoleAssign.cs
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,11 @@ public static void StartSelect()
if (FinalRolesList.Contains(CustomRoles.Romantic) && FinalRolesList.Contains(CustomRoles.Lovers))
FinalRolesList.Remove(CustomRoles.Lovers);
}
if (HeartBreaker.HasEnabled)
{
if(!FinalRolesList.Contains(CustomRoles.Romantic) && !FinalRolesList.Contains(CustomRoles.Lovers) && FinalRolesList.Contains(CustomRoles.HeartBreaker))
FinalRolesList.Remove(CustomRoles.HeartBreaker);
}
Comment on lines +749 to +753
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Problems with the assignment are 100% expected here
We need to come up with another way to check


// if roles are very few, add vanilla сrewmate roles
if (AllPlayers.Count > FinalRolesList.Count)
Expand Down
133 changes: 133 additions & 0 deletions Roles/Neutral/HeartBreaker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AmongUs.GameOptions;
using Rewired;
using TOHE.Roles.Core;
using UnityEngine;
using static TOHE.Options;
using static TOHE.Translator;

namespace TOHE.Roles.Neutral
{
internal class HeartBreaker : RoleBase
{
//===========================SETUP================================\\
private const int Id = 30900;
public override bool IsDesyncRole => true;
public override bool IsExperimental => true;
public static bool HasEnabled => CustomRoleManager.HasEnabled(CustomRoles.HeartBreaker);
public override CustomRoles ThisRoleBase => CustomRoles.Impostor;
public override Custom_RoleType ThisRoleType => Custom_RoleType.NeutralChaos;
//==================================================================\\

private static OptionItem HeartBreakerCooldown;
private static OptionItem HeartBreakerKillOtherLover;
private static OptionItem HeartBreakerTriesMax;
private static OptionItem HeartBreakerSuicideIfNoLover;

public override void SetupCustomOption()
{
SetupRoleOptions(Id, TabGroup.NeutralRoles, CustomRoles.HeartBreaker);
HeartBreakerCooldown = FloatOptionItem.Create(Id + 10, "HeartBreakerCooldown", new(0f, 180f, 2.5f), 20f, TabGroup.NeutralRoles, false)
.SetParent(CustomRoleSpawnChances[CustomRoles.HeartBreaker])
.SetValueFormat(OptionFormat.Seconds);
HeartBreakerTriesMax = IntegerOptionItem.Create(Id + 11, "HeartBreakerTriesMax", new(1, 10, 1), 3, TabGroup.NeutralRoles, false)
.SetParent(CustomRoleSpawnChances[CustomRoles.HeartBreaker]);
HeartBreakerSuicideIfNoLover = BooleanOptionItem.Create(Id + 13, "HeartBreakerSuicideIfNoLover", true, TabGroup.NeutralRoles, false)
.SetParent(CustomRoleSpawnChances[CustomRoles.HeartBreaker]);
HeartBreakerKillOtherLover = BooleanOptionItem.Create(Id + 14, "HeartBreakerKillOtherLover", true, TabGroup.NeutralRoles, false)
.SetParent(CustomRoleSpawnChances[CustomRoles.HeartBreaker]);
}
public override void Add(byte playerId)
{
AbilityLimit = HeartBreakerTriesMax.GetInt();
}
public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = HeartBreakerCooldown.GetFloat();

public override bool CanUseKillButton(PlayerControl pc) => IsUseKillButton(pc);
public bool IsUseKillButton(PlayerControl pc) => pc.IsAlive() && AbilityLimit > 0;
public override bool CanUseImpostorVentButton(PlayerControl pc) => false;
public override string GetProgressText(byte playerId, bool comms)
=> Utils.ColorString(IsUseKillButton(Utils.GetPlayerById(playerId)) ? Utils.GetRoleColor(CustomRoles.HeartBreaker).ShadeColor(0.25f) : Color.gray, $"({AbilityLimit})");
public override void SetAbilityButtonText(HudManager hud, byte playerId)
{
if (!HasLover()) hud.KillButton.OverrideText(GetString("HeartBreakerBreakText"));
else hud.KillButton.OverrideText(GetString("TriggerKill"));
}
public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl target)
{
if (killer == null || target == null) return false;
AbilityLimit--;
SendSkillRPC();
if (HasLover()) return true;
else
{
if (target.GetCustomSubRoles().Contains(CustomRoles.Lovers))
{
if (HasLover()) return false;
SetAbilityButtonText(HudManager.Instance, killer.PlayerId);
foreach (PlayerControl player in Main.LoversPlayers)
{
if (player.GetCustomSubRoles().Contains(CustomRoles.Lovers) && player != target && killer != target)
{
player.GetCustomSubRoles().Remove(CustomRoles.Lovers);
Main.LoversPlayers.Remove(player);
RPC.SyncLoversPlayers();
if (HeartBreakerKillOtherLover.GetBool())
{
player.SetDeathReason(PlayerState.DeathReason.FollowingSuicide);
player.RpcMurderPlayer(player);
player.SetRealKiller(killer);
}
killer.RpcSetCustomRole(CustomRoles.Lovers);
Main.LoversPlayers.Add(killer);
RPC.SyncLoversPlayers();
// temp workaround i guess
Utils.DoNotifyRoles(killer, target);
Utils.DoNotifyRoles(target, killer);
target.Notify(GetString("HeartBreakerNewLoverText"));
if (!DisableShieldAnimations.GetBool()) killer.RpcGuardAndKill(target);
target.RpcGuardAndKill(killer);
target.RpcGuardAndKill(target);
break;
}
}
}
else if (target.Is(CustomRoles.Romantic) && !HasLover())
{
Romantic.BetPlayer.Remove(target.PlayerId);
Romantic.BetPlayer.Add(target.PlayerId, killer.PlayerId);
Romantic romantic = (Romantic)target.GetRoleClass();
romantic.SendRPC(target.PlayerId);
target.RpcSetCustomRole(CustomRoles.RuthlessRomantic);
Utils.DoNotifyRoles(killer, target);
Utils.DoNotifyRoles(target, killer);
target.Notify(GetString("HeartBreakerNewLoverText"));
if (!DisableShieldAnimations.GetBool()) killer.RpcGuardAndKill(target);
target.RpcGuardAndKill(killer);
target.RpcGuardAndKill(target);
}
else if (HeartBreakerSuicideIfNoLover.GetBool() && AbilityLimit < 1 && !HasLover())
{
killer.SetDeathReason(PlayerState.DeathReason.Suicide);
killer.RpcMurderPlayer(killer);
}
killer.SetKillCooldown();
return false;
}
}
public bool HasLover(PlayerControl player = null)
{
if (player == null) player = _Player;
if (Main.LoversPlayers.Contains(player))
return true;
else
for (byte i = 0; i < Romantic.BetPlayer.Count; i++)
if (Romantic.BetPlayer[i] == player.PlayerId) return true;
return false;
}
}
}
2 changes: 1 addition & 1 deletion Roles/Neutral/Romantic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public override void Remove(byte playerId)
CustomRoleManager.CheckDeadBodyOthers.Remove(OthersAfterPlayerDeathTask);
}

private void SendRPC(byte playerId)
internal void SendRPC(byte playerId)
{
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SyncRoleSkill, SendOption.Reliable, -1);
writer.WriteNetObject(_Player);
Expand Down
1 change: 1 addition & 0 deletions main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,7 @@ public enum CustomRoles
Glitch,
God,
Hater,
HeartBreaker,
HexMaster,
Huntsman,
Imitator,
Expand Down