Skip to content
This repository has been archived by the owner on Feb 19, 2022. It is now read-only.

WIP: Allow toggling loving impostor #301

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
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
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,17 +338,19 @@ As long as not everyone has voted, the Mayor can use as many votes from their Vo
## Lovers
### **Team: Crewmates or Impostors**
The Lovers are two players who are linked together.\
These two players get picked randomly between Crewmates and Impostors.\
One of the Lovers is always a Crewmate. The other gets picked randomly between Crewmates and Impostors.\
They gain the primary objective to stay alive together.\
If they are both among the last 3 players, they win.\
In order to so, they gain access to a private chat, only visible by them in between meetings.\
However, they can also win with their respective team, hence why the Lovers do not know the role of the other lover.
However, they can also win with their respective team, hence why the Lovers do not know the role of the other lover.\
By default the second Lover will be an Impostor 25% of the time but only if there are 2 or more Impostors in the game.

### Game Options
| Name | Description | Type | Default |
|----------|:-------------:|:------:|:------:|
| Lovers | The percentage probability of the Lovers appearing | Percentage | 0% |
| Both Lovers Die | Whether the other Lover automatically dies if the other does | Toggle | True |
| Allow Loving Impostor | Whether one of the Lovers can be an Impostor | Percentage | 25% |
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
| Allow Loving Impostor | Whether one of the Lovers can be an Impostor | Percentage | 25% |
| Loving Impostor Chance | The percentage probability of a Loving Impostor appearing | Percentage | 25% |


-----------------------
## Sheriff
Expand Down
1 change: 1 addition & 0 deletions source/Patches/CustomGameOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public static class CustomGameOptions
public static int ButtonBarryOn => (int) Generate.ButtonBarryOn.Get();
public static int VanillaGame => (int) Generate.VanillaGame.Get();
public static bool BothLoversDie => Generate.BothLoversDie.Get();
public static int LovingImpostorOn => (int) Generate.LovingImpostorOn.Get();
public static bool ShowSheriff => Generate.ShowSheriff.Get();
public static bool SheriffKillOther => Generate.SheriffKillOther.Get();
public static bool SheriffKillsJester => Generate.SheriffKillsJester.Get();
Expand Down
3 changes: 3 additions & 0 deletions source/Patches/CustomOption/Generate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public class Generate

public static CustomHeaderOption Lovers;
public static CustomToggleOption BothLoversDie;
public static CustomNumberOption LovingImpostorOn;

public static CustomHeaderOption Sheriff;
public static CustomToggleOption ShowSheriff;
Expand Down Expand Up @@ -284,6 +285,8 @@ public static void GenerateAll()
Lovers =
new CustomHeaderOption(num++, "<color=#FF66CCFF>Lovers</color>");
BothLoversDie = new CustomToggleOption(num++, "Both Lovers Die");
LovingImpostorOn = new CustomNumberOption(num++, "Allow Loving Impostor",25f, 0f, 100f, 10f,
Copy link
Contributor

@NotSugden NotSugden Aug 7, 2021

Choose a reason for hiding this comment

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

Suggested change
LovingImpostorOn = new CustomNumberOption(num++, "Allow Loving Impostor",25f, 0f, 100f, 10f,
LovingImpostorOn = new CustomNumberOption(num++, "Loving Impostor Chance", 25f, 0f, 100f, 10f,

PercentFormat);

Sheriff =
new CustomHeaderOption(num++, "<color=#FFFF00FF>Sheriff</color>");
Expand Down
51 changes: 25 additions & 26 deletions source/Patches/Roles/Lover.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,24 @@ namespace TownOfUs.Roles
{
public class Lover : Role
{
public Lover(PlayerControl player, int num, bool loverImpostor) : base(player)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The convention where num == 2 for impostor seemed really brittle to me. So I changed it to always specify.

public Lover(PlayerControl player, bool impostor, bool eitherLoverImpostor) : base(player)
{
var imp = num == 2 && loverImpostor;
Name = imp ? "Loving Impostor" : "Lover";
Name = impostor ? "Loving Impostor" : "Lover";
Color = new Color(1f, 0.4f, 0.8f, 1f);
ImpostorText = () =>
"You are in " + ColorString + "Love</color> with " + ColorString + OtherLover.Player.name;
TaskText = () => $"Stay alive with your love {OtherLover.Player.name} \n and win together";
RoleType = imp ? RoleEnum.LoverImpostor : RoleEnum.Lover;
Num = num;
LoverImpostor = loverImpostor;
Scale = imp ? 2.3f : 1f;
Faction = imp ? Faction.Impostors : Faction.Crewmates;
RoleType = impostor ? RoleEnum.LoverImpostor : RoleEnum.Lover;
LoverImpostor = eitherLoverImpostor;
Scale = impostor ? 2.3f : 1f;
Faction = impostor ? Faction.Impostors : Faction.Crewmates;
}

public Lover OtherLover { get; set; }
public bool LoveCoupleWins { get; set; }
public int Num { get; set; }
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I couldn't find where this was used?


// Returns true if either lover is an impostor

public bool LoverImpostor { get; set; }

protected override void IntroPrefix(IntroCutscene._CoBegin_d__14 __instance)
Expand Down Expand Up @@ -64,27 +64,24 @@ protected override string NameText(PlayerVoteArea player = null)

return Player.name + "\n" + "Lover";
}

public static void Gen(List<PlayerControl> crewmates, List<PlayerControl> impostors)
{
//System.Console.WriteLine("LOVER2");
if (crewmates.Count <= 0) return;
if (crewmates.Count <= 1 && impostors.Count < 1) return;

//System.Console.WriteLine("LOVER3");
var b = Random.RandomRangeInt(0, 3);

if ((b == 0) & (impostors.Count < 1)) b = 1;
var lovingImpostorEnabled = Random.RandomRangeInt(1, 101) <= CustomGameOptions.LovingImpostorOn;

var canMakeCrewCrewLovers = crewmates.Count >= 2;
var canMakeCrewImpostorLovers = crewmates.Count >= 1 && impostors.Count >= 2 && lovingImpostorEnabled;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
var canMakeCrewImpostorLovers = crewmates.Count >= 1 && impostors.Count >= 2 && lovingImpostorEnabled;
var canMakeCrewImpostorLovers = crewmates.Count >= 1 && impostors.Count >= 1 && lovingImpostorEnabled;

there would only need to be one impostor free

if (!canMakeCrewCrewLovers && !canMakeCrewImpostorLovers) {
return;
}

if ((b != 0) & (crewmates.Count <= 1)) b = 0;
var lovingImpostor = canMakeCrewImpostorLovers;

//System.Console.WriteLine("LOVER4");
var flag2 = b == 0;
var num = Random.RandomRangeInt(0, crewmates.Count);
var player1 = crewmates[num];
crewmates.Remove(player1);
PlayerControl player2;
if (flag2)
if (lovingImpostor)
{
var num2 = Random.RandomRangeInt(0, impostors.Count);
player2 = impostors[num2];
Expand All @@ -97,13 +94,15 @@ public static void Gen(List<PlayerControl> crewmates, List<PlayerControl> impost
crewmates.Remove(player2);
}

// These writes appear to be read by `case CustomRPC.SetCouple` in RpcHandling.cs
var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId,
(byte) CustomRPC.SetCouple, SendOption.Reliable, -1);
writer.Write(player1.PlayerId);
writer.Write(player2.PlayerId);
writer.Write(b);
var lover1 = new Lover(player1, 1, b == 0);
var lover2 = new Lover(player2, 2, b == 0);
writer.Write(lovingImpostor);

var lover1 = new Lover(player1, false, lovingImpostor);
var lover2 = new Lover(player2, lovingImpostor, lovingImpostor);

lover1.OtherLover = lover2;
lover2.OtherLover = lover1;
Expand Down Expand Up @@ -179,4 +178,4 @@ public void Win()
OtherLover.LoveCoupleWins = true;
}
}
}
}
5 changes: 5 additions & 0 deletions source/Patches/Roles/Role.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ public PlayerControl Player
}
}

/*
* Appears to be used in the screen where the player finds out their role. Used to scale
* up or down the font size of the player's role based on the length of the name of their
* role. "CREWMATE" and "IMPOSTOR" which both have 8 letters, so they are the baseline.
*/
protected float Scale { get; set; } = 1f;
protected internal Color Color { get; set; }
protected internal RoleEnum RoleType { get; set; }
Expand Down
6 changes: 3 additions & 3 deletions source/Patches/RpcHandling.cs
Original file line number Diff line number Diff line change
Expand Up @@ -338,12 +338,12 @@ public static void Postfix([HarmonyArgument(0)] byte callId, [HarmonyArgument(1)
case CustomRPC.SetCouple:
var id = reader.ReadByte();
var id2 = reader.ReadByte();
var b1 = reader.ReadByte();
bool lovingImpostor = reader.ReadByte() == 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
bool lovingImpostor = reader.ReadByte() == 0;
var lovingImpostor = reader.ReadByte() == 0;

var lover1 = Utils.PlayerById(id);
var lover2 = Utils.PlayerById(id2);

var roleLover1 = new Lover(lover1, 1, b1 == 0);
var roleLover2 = new Lover(lover2, 2, b1 == 0);
var roleLover1 = new Lover(lover1, false, lovingImpostor);
var roleLover2 = new Lover(lover2, lovingImpostor, lovingImpostor);

roleLover1.OtherLover = roleLover2;
roleLover2.OtherLover = roleLover1;
Expand Down