
[](https://discord.gg/77RkMJHWsM)
-
+
# The Other Roles
| Impostors | Crewmates | Neutral |
|----------|-------------|-----------------|
-| [Bad Child](#child) | [Child](#child) | [Arsonist](#arsonist) |
+| [Evil Mini](#mini) | [Nice Mini](#mini) | [Arsonist](#arsonist) |
| [Camouflager](#camouflager) | [Detective](#detective) | [Jester](#jester) |
| [Cleaner](#cleaner) | [Engineer](#engineer) | [Jackal](#jackal) |
| [Eraser](#eraser) | [Hacker](#hacker) | [Sidekick](#sidekick) |
| [Trickster](#trickster) | [Seer](#seer) | |
| [Vampire](#vampire) | [Sheriff](#sheriff) | |
| [Warlock](#warlock) | [Shifter](#shifter) | |
+| [Evil Guesser](#guesser) | [Nice Guesser](#guesser) | |
| | [Snitch](#snitch) | |
| | [Spy](#spy) | |
| | [Swapper](#swapper) | |
# Releases
| Among Us - Version| Mod Version | Link |
|----------|-------------|-----------------|
+| 2021.5.25.2s| v2.6.7| [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v2.6.7/TheOtherRoles.zip)
| 2021.5.10s| v2.6.6| [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v2.6.6/TheOtherRoles.zip)
| 2021.5.10s| v2.6.5| [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v2.6.5/TheOtherRoles.zip)
| 2021.5.10s| v2.6.4| [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v2.6.4/TheOtherRoles.zip)
<details>
<summary>Click to show the Changelog</summary>
+**Version 2.6.7**
+- **New Role:** [Guesser](#guesser)
+- Changed the colors of some roles
+- Changed name of Child to [Mini](#mini)
+- Changed Version check to allow to check for modified versions of the mod. (Forks don't need to use different versioning now)
+- Changed Role Assignment to make [Spy](#spy) incompatible with [Mini](#mini) (former child)
+- Fixed a bug where a [Jester](#jester) win was triggered, when the partner of a [Jester Lover](#lovers) was voted out
+- Fixed a bug where a [Mini](#mini) lose was triggered, when the partner of a Crew [Mini Lover](#lovers) was voted out
+
**Version 2.6.6**
- Fixed a bug introduced in v2.6.5 that caused all player to be able to use vents when the new option for spy was enabled
**Version 2.2.1**
- Trickster: The vent button now has a custom texture. Fixed a bug where the Trickster could clip out of bounds when his box was close to a wall.
-- Fixed a bug where the Bad Child's kill button went on cooldown when someone else performed a kill
+- Fixed a bug where the Bad Mini's kill button went on cooldown when someone else performed a kill
- Fixed a few bugs with footprints, Seer souls and the Vampire delayed kill
-- Fixed a bug where the Child was banned for hacking (because of its reduced kill cooldown)
+- Fixed a bug where the Mini was banned for hacking (because of its reduced kill cooldown)
- Improved the version handshake
**Version 2.2.0**
- Fixed a bug where a Lovers win wasn't displayed properly
- Fixed the Among Us bug where people were unable to move after meetings
- We added a version checking system: The host can only start the game if everyone in his lobby has the same version of the mod installed (he will see, who is using a wrong version). This prevents hacking in public lobbies and bugs because of version missmatches.
-- Fixed a bug where the Child Impostor had the same cooldowns as normal Impostors
+- Fixed a bug where the Mini Impostor had the same cooldowns as normal Impostors
- Fixed a bug where the Vampire/Janitor/Mafioso would lose their kill button after being erased
-- The Child is now able to use ladders and it can do all the tasks right away
+- The Mini is now able to use ladders and it can do all the tasks right away
**Version 2.1.0**
- **New Role:** [Spy](#spy)
- **Eraser:** The Eraser can now also remove the role of other Impostors. This enables him to reveal the Spy, but might result in removing the special ability of his partner.
-- **Camouflager:** The Child age/size will now also be hidden, to allow the Child Impostor to kill during camouflage
+- **Camouflager:** The Mini age/size will now also be hidden, to allow the Mini Impostor to kill during camouflage
**Hotfix 2.0.1**
- Fixed a bug where camouflaged players would get stuck on ladders/platforms on the airship
- Introduced a one second cooldown after the Morphling sampled another player
-- The Child can now always reach all usables (ladders, tasks, ...)
+- The Mini can now always reach all usables (ladders, tasks, ...)
- We removed a bug, where some footprints remained on the ground forever
- We removed a bug, where the Detective didn't see the right color type when reporting a player
-- We changed the Jester win and Child lose conditions, they're not being affected by server delays anymore
+- We changed the Jester win and Mini lose conditions, they're not being affected by server delays anymore
**Changes in 2.0.0**
- **New button art** created by **Bavari**
- **Hacker:** The Hacker is basically the old Spy. We added the option to only show the color type instead of the color on the admin table.
- **Camouflager:** Now also overrides the information of other roles, check the [Camouflager](#camouflager) section for more details.
- **Morphling:** Now also overrides the information of other roles, check the [Morphling](#morphling) section for more details
-- **Child:** The Child can now be a Crewmate Child or an Impostor Child, check the [Child](#child) section for more details
+- **Mini:** The Mini can now be a Crewmate Mini or an Impostor Mini, check the [Mini](#mini) section for more details
- **Eraser:** The Eraser, a new Impostor role, is now part of the mod. Check the [Eraser](#eraser) section for more details
- **New options:**
- You can now set the maximum number of meetings in a game: Every player still only has one meeting. The Mayor can always use his meeting (even if the maximum number of meetings was reached). Impostor/Jackal meetings also count.
\
**Changes in v1.6:**
- This update is a small hotfix, fixing the bug where some people were unable to join lobbies.
-- The Child can't be voted out anymore before it turns 18, hence games can't end anymore because the Child died.
+- The Mini can't be voted out anymore before it turns 18, hence games can't end anymore because the Mini died.
- Footprints are no longer visible to the Detective, if players are inside vents.
\
**Changes in v1.5:**
- Time Master - Buff: He is not affected by his rewind anymore, which gives him more utility. Players will now be rewinded out of vents.
-- Child - Nerf: The Child now grows up (see [Child](#child)) and becomes a normal Crewmate at some point. A growing Child is not killable anymore. Some tasks are still not doable for the small Child, we are working on that. But eventually when growing up it can do all the tasks as it's size increases.
+- Mini - Nerf: The Mini now grows up (see [Mini](#mini)) and becomes a normal Crewmate at some point. A growing Mini is not killable anymore. Some tasks are still not doable for the small Mini, we are working on that. But eventually when growing up it can do all the tasks as it's size increases.
- Seer - Nerf: Added an option that sets how often the Seer mistakes the player for another.
- Hacker - Nerf: The Hacker now only sees the additional information when he activates his "Hacker mode". That should stops the Hacker from camping the admin table/vitals.
- Other: Camouflager/Morphling cooldowns were fixed. Custom regions code was removed to enable 3rd party tools. Some minor bugfixes.
**Changes in v1.1:**
- Morphling: The color of pet now also morphs. The skin animation now starts at the right point.
-- The game over screen now shows if the Jester/Child/Lovers won.
+- The game over screen now shows if the Jester/Mini/Lovers won.
- A bug was removed where the Jester won together with the Crewmates.
- A bug was removed where the game of the Lovers crashed if they were the last players killed by the host of the lobby.
</details>
- **Map:** The map can be changed inside a lobby
- **Maximum Number Of Meetings:** You can set the maximum number of meetings that can be called in total (every player still has personal maximum of buttons, but if the maximum number of meetings is reached you can't use your meetings even if you have some left, Impostor and Jackal meetings also count)
- **Allow Skips On Emergency Meetings:** If set to false, there will not be a skip button in emergency meetings. If a player does not vote, he'll vote himself.
-- **Hide Player Names:** Hides the names of all players that have role which is unknown to you. Team Lovers/Impostors/Jackal still see the names of their teammates. Impostors can alse see the name of the Spy and everyone can still see the age of the child.
+- **Hide Player Names:** Hides the names of all players that have role which is unknown to you. Team Lovers/Impostors/Jackal still see the names of their teammates. Impostors can alse see the name of the Spy and everyone can still see the age of the mini.
- **Ghosts Can See Roles**
- **Ghosts Can See Votes**
- **Ghosts Can See The Number Of Remaining Tasks**
-- **Dleks:** You are now able to select the Dleks map.
+- **Dleks:** You are now able to select the Dleks map.
- **Task Counts:** You are now able to select more tasks.
- **Role Summary:** When a game ends there will be a list of all players and their roles and their task progress
The count you set will only be reached, if there are enough Crewmates/Impostors in the game and if enough roles are set to be in the game (i.e. they are set to > 0%). The roles are then being distributed as follows:
- First all roles that are set to 100% are being assigned to arbitrary players
- After that each role that has 10%-90% selected adds 1-9 tickets to a ticket pool (there exists a ticket pool for Crewmates, Neutrals and Impostors). Then the roles will be selected randomly from the pools as long it's possible (until the selected number is reached, until there are no more Crewmates/Impostors or until there are no more tickets). If a role is selected from the pool, obviously all the tickets of that role are being removed.
-- The Mafia, Lovers and Child are being selected independently (without using the ticket system) according to the spawn chance you selected. After that the Crewmate, Neutral and Impostor roles are selected and assigned in a random order.
+- The Mafia, Lovers and Mini are being selected independently (without using the ticket system) according to the spawn chance you selected. After that the Crewmate, Neutral and Impostor roles are selected and assigned in a random order.
**Example:**\
Settings: 2 special Crewmate roles, Snitch: 100%, Hacker: 10%, Tracker: 30%\
The Morphling is an Impostor which can additionally scan the appearance of a player. After an arbitrary time they can take on that appearance for 10s.
\
**NOTE:**
-- They shrink to the size of the Child when they copies its look.
+- They shrink to the size of the Mini when they copies its look.
- The Hacker sees the new color on the admin table.
- The color of the footprints changes accordingly (also the ones that were already on the ground).
- The other Impostor still sees that they are an Impostor (the name remains red).
are hidden and all players have the same color.\
\
**NOTE:**
-- The Child will look like all the other players
+- The Mini will look like all the other players
- The color of the footprints turns gray (also the ones that were already on the ground).
- The Hacker sees gray icons on the admin table
- The shield is not visible anymore
### **Team: Impostors**
The Warlock is an Impostor, that can curse another player (the cursed player doesn't get notified).\
If the cursed person stands next to another player, the Warlock is able to kill that player (no matter how far away he is).\
-Performing a kill with the help of a cursed player, will lift the curse and it will result in the Warlock being unable to move for a configurable amount of time.
+Performing a kill with the help of a cursed player, will lift the curse and it will result in the Warlock being unable to move for a configurable amount of time.\
The Warlock can still perform normal kills, but the two buttons share the same cooldown.
\
| Warlock Root Time | Time the Warlock is rooted in place after killing using the curse
-----------------------
+## Guesser
+### **Team: Crewmates or Impostors**
+The Guesser can be a Crewmate or an Impostor (depending on the settings).\
+The Guesser can shoot a player during the meeting, by guessing its role. If the guess is wrong, the Guesser dies instead.\
+Only one person can be shot per meeting and you can set a maximum number of shots.\
+The guesses Impostor and Crewmate are only right, if the player is part of the corresponding team and has no special role.\
+You can only shoot during the voting time.
+
+\
+**NOTE:**
+- The vote of a shot player, won't be counted
+- You can't guess the role **Nice Mini** for obvious reasons
+- You can't guess the role **Lover**, you'll have to guess the primary role of one of the Lovers, to kill both of them
+- Jester wins won't be triggered, if the Guesser shoots the Jester before the Jester gets voted out
+
+### Game Options
+| Name | Description |
+|----------|:-------------:|
+| Guesser Spawn Chance | -
+| Chance That The Guesser Is An Impostor | -
+| Guesser Number Of Shots | -
+
+-----------------------
+
## Lovers
### **Team: Lovers (and secondary team)**
There are always two Lovers which are linked together.\
**NOTE:**
- If the Sheriff shoots the person the Medic shielded, the Sheriff and the shielded person **both remain unharmed**.
-- If the Sheriff shoots a Child Impostor, the Sheriff dies if the Child is still growing up. If it's 18, the Child Impostor dies.
+- If the Sheriff shoots a Mini Impostor, the Sheriff dies if the Mini is still growing up. If it's 18, the Mini Impostor dies.
### Game Options
| Name | Description |
| Lighter Duration | -
-----------------------
-## Child
+## Mini
### **Team: Crewmates or Impostors**
-The Child can be a Crewmate (67% chance) or an Impostor (33% chance).\
-The Child's character is smaller and hence visible to everyone in the game.\
-The Child cannot be killed until it turns 18 years old, however it can be voted out.\
-**Impostor Child:**
+The Mini can be a Crewmate (67% chance) or an Impostor (33% chance).\
+The Mini's character is smaller and hence visible to everyone in the game.\
+The Mini cannot be killed until it turns 18 years old, however it can be voted out.\
+**Impostor Mini:**
- While growing up the kill cooldown is doubled. When it's fully grown up its kill cooldown is 2/3 of the default one.
- If it gets thrown out of the ship, everything is fine.
-**Crewmate Child:**
- - The Crewmate Child aims to play out the strength its invincibility in the early game.
- - If it gets thrown out of the ship before it turns 18, everyone loses. So think twice before you vote out a Child.
+**Crewmate Mini:**
+ - The Crewmate Mini aims to play out the strength its invincibility in the early game.
+ - If it gets thrown out of the ship before it turns 18, everyone loses. So think twice before you vote out a Mini.
**NOTE:**
-- Impostors can't kill the Child (the button does not work) until it turns 18
-- The Sheriff can kill the Impostor Child, but only if it's fully grown up
+- Impostors can't kill the Mini (the button does not work) until it turns 18
+- The Sheriff can kill the Impostor Mini, but only if it's fully grown up
### Game Options
| Name | Description |
|----------|:-------------:|
-| Child Spawn Chance | -
-| Child | Child Growing Up Duration
+| Mini Spawn Chance | -
+| Mini | Mini Growing Up Duration
-----------------------
## Medic
- The Crew could be eliminated, then the Team Jackal fight against the Impostors (the Crew can still make a task win in this scenario)
The priority of the win conditions is the following:
-1. Crewmate Child lose by vote
+1. Crewmate Mini lose by vote
2. Jester wins by vote
3. Arsonist win
4. Team Impostor wins by sabotage
**NOTE:**
- The Jackal (and his Sidekick) may be killed by a Sheriff.
-- A Jackal cannot target the Child, while it's growing up. After that he can kill it or select it as its Sidekick
+- A Jackal cannot target the Mini, while it's growing up. After that he can kill it or select it as its Sidekick
- The Crew can still win, even if all of their members are dead, if they finish their tasks fast enough (that's why converting the last Crewmate with tasks left into a Sidekick results in a task win for the crew)
If both Impostors and Jackals are in the game the game continues even if all Crewmates are dead. Crewmates may still win in this case by completing their tasks. Jackal and Impostor have to kill each other.
**NOTE:**
- A player that converts into a Sidekick loses his previous role and tasks (if he had one), except the Lover role.
- The Sidekick may be killed by a Sheriff.
-- The Sidekick cannot target the Child, while it's growing up.
+- The Sidekick cannot target the Mini, while it's growing up.
### Game Options
| Name | Description
}
byte targetId = 0;
- if ((Sheriff.currentTarget.Data.IsImpostor && (Sheriff.currentTarget != Child.child || Child.isGrownUp())) ||
+ if ((Sheriff.currentTarget.Data.IsImpostor && (Sheriff.currentTarget != Mini.mini || Mini.isGrownUp())) ||
(Sheriff.spyCanDieToSheriff && Spy.spy == Sheriff.currentTarget) ||
(Sheriff.canKillNeutrals && (Arsonist.arsonist == Sheriff.currentTarget || Jester.jester == Sheriff.currentTarget || Jackal.jackal == Sheriff.currentTarget || Sidekick.sidekick == Sheriff.currentTarget))) {
targetId = Sheriff.currentTarget.PlayerId;
public static CustomOption eraserCooldown;
public static CustomOption eraserCanEraseAnyone;
- public static CustomOption childSpawnRate;
- public static CustomOption childGrowingUpDuration;
+ public static CustomOption miniSpawnRate;
+ public static CustomOption miniGrowingUpDuration;
public static CustomOption loversSpawnRate;
public static CustomOption loversImpLoverRate;
public static CustomOption loversBothDie;
public static CustomOption loversCanHaveAnotherRole;
+ public static CustomOption guesserSpawnRate;
+ public static CustomOption guesserIsImpGuesserRate;
+ public static CustomOption guesserNumberOfShots;
+
public static CustomOption jesterSpawnRate;
public static CustomOption jesterCanCallEmergency;
public static CustomOption jesterCanSabotage;
warlockCooldown = CustomOption.Create(271, "Warlock Cooldown", 30f, 10f, 60f, 2.5f, warlockSpawnRate);
warlockRootTime = CustomOption.Create(272, "Warlock Root Time", 5f, 0f, 15f, 1f, warlockSpawnRate);
- childSpawnRate = CustomOption.Create(180, cs(Child.color, "Child"), rates, null, true);
- childGrowingUpDuration = CustomOption.Create(181, "Child Growing Up Duration", 400f, 100f, 1500f, 100f, childSpawnRate);
+ miniSpawnRate = CustomOption.Create(180, cs(Mini.color, "Mini"), rates, null, true);
+ miniGrowingUpDuration = CustomOption.Create(181, "Mini Growing Up Duration", 400f, 100f, 1500f, 100f, miniSpawnRate);
loversSpawnRate = CustomOption.Create(50, cs(Lovers.color, "Lovers"), rates, null, true);
loversImpLoverRate = CustomOption.Create(51, "Chance That One Lover Is Impostor", rates, loversSpawnRate);
loversBothDie = CustomOption.Create(52, "Both Lovers Die", true, loversSpawnRate);
loversCanHaveAnotherRole = CustomOption.Create(53, "Lovers Can Have Another Role", true, loversSpawnRate);
+ guesserSpawnRate = CustomOption.Create(310, cs(Guesser.color, "Guesser"), rates, null, true);
+ guesserIsImpGuesserRate = CustomOption.Create(311, "Chance That The Guesser Is An Impostor", rates, guesserSpawnRate);
+ guesserNumberOfShots = CustomOption.Create(312, "Guesser Number Of Shots", 2f, 1f, 15f, 1f, guesserSpawnRate);
+
jesterSpawnRate = CustomOption.Create(60, cs(Jester.color, "Jester"), rates, null, true);
jesterCanCallEmergency = CustomOption.Create(61, "Jester can call emergency meeting", true, jesterSpawnRate);
jesterCanSabotage = CustomOption.Create(62, "Jester can sabotage", true, jesterSpawnRate);
var hudString = sb.ToString();
int defaultSettingsLines = 19;
- int roleSettingsLines = defaultSettingsLines + 32;
+ int roleSettingsLines = defaultSettingsLines + 33;
int detailedSettingsP1 = roleSettingsLines + 34;
int detailedSettingsP2 = detailedSettingsP1 + 35;
int end1 = hudString.TakeWhile(c => (defaultSettingsLines -= (c == '\n' ? 1 : 0)) > 0).Count();
gap = 5;
index = hudString.TakeWhile(c => (gap -= (c == '\n' ? 1 : 0)) > 0).Count();
hudString = hudString.Insert(index, "\n");
- gap = 16;
+ gap = 17;
index = hudString.TakeWhile(c => (gap -= (c == '\n' ? 1 : 0)) > 0).Count();
hudString = hudString.Insert(index + 1, "\n");
- gap = 20;
+ gap = 21;
index = hudString.TakeWhile(c => (gap -= (c == '\n' ? 1 : 0)) > 0).Count();
hudString = hudString.Insert(index + 1, "\n");
} else if (counter == 2) {
enum CustomGameOverReason {
LoversWin = 10,
TeamJackalWin = 11,
- ChildLose = 12,
+ MiniLose = 12,
JesterWin = 13,
ArsonistWin = 14
}
LoversSoloWin,
JesterWin,
JackalWin,
- ChildLose,
+ MiniLose,
ArsonistWin
}
bool jesterWin = Jester.jester != null && gameOverReason == (GameOverReason)CustomGameOverReason.JesterWin;
bool arsonistWin = Arsonist.arsonist != null && gameOverReason == (GameOverReason)CustomGameOverReason.ArsonistWin;
- bool childLose = Child.child != null && gameOverReason == (GameOverReason)CustomGameOverReason.ChildLose;
+ bool miniLose = Mini.mini != null && gameOverReason == (GameOverReason)CustomGameOverReason.MiniLose;
bool loversWin = Lovers.existingAndAlive() && (gameOverReason == (GameOverReason)CustomGameOverReason.LoversWin || (TempData.DidHumansWin(gameOverReason) && !Lovers.existingWithKiller())); // Either they win if they are among the last 3 players, or they win if they are both Crewmates and both alive and the Crew wins (Team Imp/Jackal Lovers can only win solo wins)
bool teamJackalWin = gameOverReason == (GameOverReason)CustomGameOverReason.TeamJackalWin && ((Jackal.jackal != null && !Jackal.jackal.Data.IsDead) || (Sidekick.sidekick != null && !Sidekick.sidekick.Data.IsDead));
- // Child lose
- if (childLose) {
+ // Mini lose
+ if (miniLose) {
TempData.winners = new Il2CppSystem.Collections.Generic.List<WinningPlayerData>();
- WinningPlayerData wpd = new WinningPlayerData(Child.child.Data);
- wpd.IsYou = false; // If "no one is the Child", it will display the Child, but also show defeat to everyone
+ WinningPlayerData wpd = new WinningPlayerData(Mini.mini.Data);
+ wpd.IsYou = false; // If "no one is the Mini", it will display the Mini, but also show defeat to everyone
TempData.winners.Add(wpd);
- AdditionalTempData.winCondition = WinCondition.ChildLose;
+ AdditionalTempData.winCondition = WinCondition.MiniLose;
}
// Jester win
textRenderer.text = "Team Jackal Wins";
textRenderer.color = Jackal.color;
}
- else if (AdditionalTempData.winCondition == WinCondition.ChildLose) {
- textRenderer.text = "Child died";
- textRenderer.color = Child.color;
+ else if (AdditionalTempData.winCondition == WinCondition.MiniLose) {
+ textRenderer.text = "Mini died";
+ textRenderer.color = Mini.color;
}
if(MapOptions.showRoleSummary) {
if (DestroyableSingleton<TutorialManager>.InstanceExists) // InstanceExists | Don't check Custom Criteria when in Tutorial
return true;
var statistics = new PlayerStatistics(__instance);
- if (CheckAndEndGameForChildLose(__instance)) return false;
+ if (CheckAndEndGameForMiniLose(__instance)) return false;
if (CheckAndEndGameForJesterWin(__instance)) return false;
if (CheckAndEndGameForArsonistWin(__instance)) return false;
if (CheckAndEndGameForSabotageWin(__instance)) return false;
return false;
}
- private static bool CheckAndEndGameForChildLose(ShipStatus __instance) {
- if (Child.triggerChildLose) {
+ private static bool CheckAndEndGameForMiniLose(ShipStatus __instance) {
+ if (Mini.triggerMiniLose) {
__instance.enabled = false;
- ShipStatus.RpcEndGame((GameOverReason)CustomGameOverReason.ChildLose, false);
+ ShipStatus.RpcEndGame((GameOverReason)CustomGameOverReason.MiniLose, false);
return true;
}
return false;
--- /dev/null
+using HarmonyLib;
+using Hazel;
+using System.Collections.Generic;
+using System.Linq;
+using UnhollowerBaseLib;
+using static TheOtherRoles.TheOtherRoles;
+using static TheOtherRoles.MapOptions;
+using System.Collections;
+using System;
+using System.Text;
+using UnityEngine;
+using System.Reflection;
+
+namespace TheOtherRoles {
+ [HarmonyPatch(typeof(ExileController), "Begin")]
+ class ExileControllerBeginPatch {
+ public static void Prefix(ExileController __instance, [HarmonyArgument(0)]ref GameData.PlayerInfo exiled, [HarmonyArgument(1)]bool tie) {
+ // Shifter shift
+ if (Shifter.shifter != null && AmongUsClient.Instance.AmHost && Shifter.futureShift != null) { // We need to send the RPC from the host here, to make sure that the order of shifting and erasing is correct (for that reason the futureShifted and futureErased are being synced)
+ MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ShifterShift, Hazel.SendOption.Reliable, -1);
+ writer.Write(Shifter.futureShift.PlayerId);
+ AmongUsClient.Instance.FinishRpcImmediately(writer);
+ RPCProcedure.shifterShift(Shifter.futureShift.PlayerId);
+ }
+ Shifter.futureShift = null;
+
+ // Eraser erase
+ if (Eraser.eraser != null && AmongUsClient.Instance.AmHost && Eraser.futureErased != null) { // We need to send the RPC from the host here, to make sure that the order of shifting and erasing is correct (for that reason the futureShifted and futureErased are being synced)
+ foreach (PlayerControl target in Eraser.futureErased) {
+ if (target != null) {
+ MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ErasePlayerRoles, Hazel.SendOption.Reliable, -1);
+ writer.Write(target.PlayerId);
+ AmongUsClient.Instance.FinishRpcImmediately(writer);
+ RPCProcedure.erasePlayerRoles(target.PlayerId);
+ }
+ }
+ }
+ Eraser.futureErased = new List<PlayerControl>();
+
+ // Trickster boxes
+ if (Trickster.trickster != null && JackInTheBox.hasJackInTheBoxLimitReached()) {
+ JackInTheBox.convertToVents();
+ }
+
+ // SecurityGuard vents and cameras
+ var allCameras = ShipStatus.Instance.AllCameras.ToList();
+ MapOptions.camerasToAdd.ForEach(camera => {
+ camera.gameObject.SetActive(true);
+ camera.gameObject.GetComponent<SpriteRenderer>().color = Color.white;
+ allCameras.Add(camera);
+ });
+ ShipStatus.Instance.AllCameras = allCameras.ToArray();
+ MapOptions.camerasToAdd = new List<SurvCamera>();
+
+ foreach (Vent vent in MapOptions.ventsToSeal) {
+ PowerTools.SpriteAnim animator = vent.GetComponent<PowerTools.SpriteAnim>();
+ animator?.Stop();
+ vent.EnterVentAnim = vent.ExitVentAnim = null;
+ vent.myRend.sprite = animator == null ? SecurityGuard.getStaticVentSealedSprite() : SecurityGuard.getAnimatedVentSealedSprite();
+ vent.myRend.color = Color.white;
+ vent.name = "SealedVent_" + vent.name;
+ }
+ MapOptions.ventsToSeal = new List<Vent>();
+ }
+ }
+
+ [HarmonyPatch(typeof(UnityEngine.Object), nameof(UnityEngine.Object.Destroy), new Type[] { typeof(UnityEngine.Object) })]
+ class ExileControllerDestroyPatch {
+ static void Prefix(UnityEngine.Object obj) {
+ if (ExileController.Instance == null || obj != ExileController.Instance.gameObject) return;
+ var exiled = ExileController.Instance.exiled;
+
+ // Mini exile lose condition
+ if (exiled != null && Mini.mini != null && Mini.mini.PlayerId == exiled.PlayerId && !Mini.isGrownUp() && !Mini.mini.Data.IsImpostor) {
+ Mini.triggerMiniLose = true;
+ }
+ // Jester win condition
+ else if (exiled != null && Jester.jester != null && Jester.jester.PlayerId == exiled.PlayerId) {
+ Jester.triggerJesterWin = true;
+ }
+
+ // Reset custom button timers where necessary
+ CustomButton.MeetingEndedUpdate();
+
+ // Mini set adapted cooldown
+ if (Mini.mini != null && PlayerControl.LocalPlayer == Mini.mini && Mini.mini.Data.IsImpostor) {
+ var multiplier = Mini.isGrownUp() ? 0.66f : 2f;
+ Mini.mini.SetKillTimer(PlayerControl.GameOptions.KillCooldown * multiplier);
+ }
+
+ // Seer spawn souls
+ if (Seer.deadBodyPositions != null && Seer.seer != null && PlayerControl.LocalPlayer == Seer.seer && (Seer.mode == 0 || Seer.mode == 2)) {
+ foreach (Vector3 pos in Seer.deadBodyPositions) {
+ GameObject soul = new GameObject();
+ soul.transform.position = pos;
+ soul.layer = 5;
+ var rend = soul.AddComponent<SpriteRenderer>();
+ rend.sprite = Seer.getSoulSprite();
+
+ if(Seer.limitSoulDuration) {
+ HudManager.Instance.StartCoroutine(Effects.Lerp(Seer.soulDuration, new Action<float>((p) => {
+ if (rend != null) {
+ var tmp = rend.color;
+ tmp.a = Mathf.Clamp01(1 - p);
+ rend.color = tmp;
+ }
+ if (p == 1f && rend != null && rend.gameObject != null) UnityEngine.Object.Destroy(rend.gameObject);
+ })));
+ }
+ }
+ Seer.deadBodyPositions = new List<Vector3>();
+ }
+
+ // Arsonist deactivate dead poolable players
+ if (Arsonist.arsonist != null && Arsonist.arsonist == PlayerControl.LocalPlayer) {
+ int visibleCounter = 0;
+ Vector3 bottomLeft = new Vector3(-HudManager.Instance.UseButton.transform.localPosition.x, HudManager.Instance.UseButton.transform.localPosition.y, HudManager.Instance.UseButton.transform.localPosition.z);
+ bottomLeft += new Vector3(-0.25f, -0.25f, 0);
+ foreach (PlayerControl p in PlayerControl.AllPlayerControls) {
+ if (!Arsonist.dousedIcons.ContainsKey(p.PlayerId)) continue;
+ if (p.Data.IsDead || p.Data.Disconnected) {
+ Arsonist.dousedIcons[p.PlayerId].gameObject.SetActive(false);
+ } else {
+ Arsonist.dousedIcons[p.PlayerId].transform.localPosition = bottomLeft + Vector3.right * visibleCounter * 0.35f;
+ visibleCounter++;
+ }
+ }
+ }
+ }
+ }
+
+ [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), new Type[] { typeof(StringNames), typeof(Il2CppReferenceArray<Il2CppSystem.Object>) })]
+ class ExileControllerMessagePatch {
+ static void Postfix(ref string __result, [HarmonyArgument(0)]StringNames id, [HarmonyArgument(1)]Il2CppReferenceArray<Il2CppSystem.Object> parts) {
+ if (ExileController.Instance != null && ExileController.Instance.exiled != null) {
+ PlayerControl player = Helpers.playerById(ExileController.Instance.exiled.Object.PlayerId);
+ if (player == null) return;
+ // Exile role text
+ if (id == StringNames.ExileTextPN || id == StringNames.ExileTextSN || id == StringNames.ExileTextPP || id == StringNames.ExileTextSP) {
+ __result = player.Data.PlayerName + " was The " + String.Join(" ", RoleInfo.getRoleInfoForPlayer(player).Select(x => x.name).ToArray());
+ }
+ // Hide number of remaining impostors on Jester win
+ if (id == StringNames.ImpostorsRemainP || id == StringNames.ImpostorsRemainS) {
+ if (Jester.jester != null && player.PlayerId == Jester.jester.PlayerId) __result = "";
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
using HarmonyLib;
using UnityEngine;
+using System.Reflection;
using System.Collections.Generic;
using Hazel;
using System;
namespace TheOtherRoles {
public class GameStartManagerPatch {
- public static Dictionary<int, System.Version> playerVersions = new Dictionary<int, System.Version>();
+ public static Dictionary<int, PlayerVersion> playerVersions = new Dictionary<int, PlayerVersion>();
private static float timer = 600f;
private static bool versionSent = false;
private static string lobbyCodeText = "";
writer.Write((byte)TheOtherRolesPlugin.Version.Minor);
writer.Write((byte)TheOtherRolesPlugin.Version.Build);
writer.WritePacked(AmongUsClient.Instance.ClientId);
+ writer.Write((byte)(TheOtherRolesPlugin.Version.Revision < 0 ? 0xFF : TheOtherRolesPlugin.Version.Revision));
+ writer.Write(Assembly.GetExecutingAssembly().ManifestModule.ModuleVersionId.ToByteArray());
AmongUsClient.Instance.FinishRpcImmediately(writer);
- RPCProcedure.versionHandshake(TheOtherRolesPlugin.Version.Major, TheOtherRolesPlugin.Version.Minor, TheOtherRolesPlugin.Version.Build, AmongUsClient.Instance.ClientId);
+ RPCProcedure.versionHandshake(TheOtherRolesPlugin.Version.Major, TheOtherRolesPlugin.Version.Minor, TheOtherRolesPlugin.Version.Build, TheOtherRolesPlugin.Version.Revision, Assembly.GetExecutingAssembly().ManifestModule.ModuleVersionId, AmongUsClient.Instance.ClientId);
}
if(kc < ks.Length && Input.GetKeyDown(ks[kc])) {
blockStart = true;
message += $"<color=#FF0000FF>{client.Character.Data.PlayerName} has a different or no version of The Other Roles\n</color>";
} else {
- int diff = TheOtherRolesPlugin.Version.CompareTo(playerVersions[client.Id]);
+ PlayerVersion PV = playerVersions[client.Id];
+ int diff = TheOtherRolesPlugin.Version.CompareTo(PV.version);
if (diff > 0) {
- message += $"<color=#FF0000FF>{client.Character.Data.PlayerName} has an older version of The Other Roles (v{playerVersions[client.Id].ToString()})\n</color>";
+ message += $"<color=#FF0000FF>{client.Character.Data.PlayerName} has an older version of The Other Roles (v{playerVersions[client.Id].version.ToString()})\n</color>";
blockStart = true;
} else if (diff < 0) {
- message += $"<color=#FF0000FF>{client.Character.Data.PlayerName} has a newer version of The Other Roles (v{playerVersions[client.Id].ToString()}) \n</color>";
+ message += $"<color=#FF0000FF>{client.Character.Data.PlayerName} has a newer version of The Other Roles (v{playerVersions[client.Id].version.ToString()})\n</color>";
+ blockStart = true;
+ } else if (!PV.GuidMatches()) { // version presumably matches, check if Guid matches
+ message += $"<color=#FF0000FF>{client.Character.Data.PlayerName} has a modified version of TOR v{playerVersions[client.Id].version.ToString()} <size=30%>({PV.guid.ToString()})</size>\n</color>";
blockStart = true;
}
}
return continueStart;
}
}
+
+ public class PlayerVersion {
+ public readonly Version version;
+ public readonly Guid guid;
+
+ public PlayerVersion(Version version, Guid guid) {
+ this.version = version;
+ this.guid = guid;
+ }
+
+ public bool GuidMatches() {
+ return Assembly.GetExecutingAssembly().ManifestModule.ModuleVersionId.Equals(this.guid);
+ }
+ }
}
}
return false;
}
- // Block impostor not fully grown child kill
- else if (Child.child != null && target == Child.child && !Child.isGrownUp()) {
+ // Block impostor not fully grown mini kill
+ else if (Mini.mini != null && target == Mini.mini && !Mini.isGrownUp()) {
return false;
}
// Block Time Master with time shield kill
using HarmonyLib;
using Hazel;
using System.Collections.Generic;
+using System.Security.Cryptography;
using System.Linq;
using System.Net;
using System.IO;
public class TheOtherRolesPlugin : BasePlugin
{
public const string Id = "me.eisbison.theotherroles";
- public const string VersionString = "2.6.6";
+ public const string VersionString = "2.6.7";
public static System.Version Version = System.Version.Parse(VersionString);
public Harmony Harmony { get; } = new Harmony(Id);
public static ConfigEntry<ushort> Port { get; set; }
public static IRegionInfo[] defaultRegions;
-
public static void UpdateRegions() {
ServerManager serverManager = DestroyableSingleton<ServerManager>.Instance;
IRegionInfo[] regions = defaultRegions;
int maxIdx = IndexOfMax(self, (byte p) => (int)p, out tie) - 1;
GameData.PlayerInfo exiled = null;
foreach (GameData.PlayerInfo pi in GameData.Instance.AllPlayers) {
- if (pi.PlayerId == maxIdx) {
+ if (pi.PlayerId == maxIdx && !pi.IsDead) {
exiled = pi;
break;
}
}
- static void onClick(int i, MeetingHud __instance) {
+ static void swapperOnClick(int i, MeetingHud __instance) {
if (__instance.state == MeetingHud.VoteStates.Results) return;
if (__instance.playerStates[i].isDead) return;
}
}
+ private static GameObject guesserUI;
+ static void guesserOnClick(int buttonTarget, MeetingHud __instance) {
+ if (guesserUI != null || !(__instance.state == MeetingHud.VoteStates.Voted || __instance.state == MeetingHud.VoteStates.NotVoted)) return;
+
+ Transform container = UnityEngine.Object.Instantiate(__instance.transform.FindChild("Background"), __instance.transform);
+ container.transform.localPosition = new Vector3(0, 0, -5f);
+ guesserUI = container.gameObject;
+
+ int i = 0;
+ var buttonTemplate = __instance.playerStates[0].transform.FindChild("votePlayerBase");
+ var smallButtonTemplate = __instance.playerStates[0].Buttons.transform.Find("CancelButton");
+ var textTemplate = __instance.playerStates[0].NameText;
+
+
+ Transform exitButton = UnityEngine.Object.Instantiate(smallButtonTemplate.transform, container);
+ exitButton.transform.localPosition = new Vector3(2.5f, 2.25f, -5);
+ exitButton.GetComponent<PassiveButton>().OnClick.RemoveAllListeners();
+ exitButton.GetComponent<PassiveButton>().OnClick.AddListener((UnityEngine.Events.UnityAction)(() => {
+ UnityEngine.Object.Destroy(container.gameObject);
+ }));
+
+ List<Transform> confirmButtons = new List<Transform>();
+
+ foreach (RoleInfo roleInfo in RoleInfo.allRoleInfos) {
+ if (roleInfo.roleId == RoleId.Lover || roleInfo.roleId == RoleId.Guesser || roleInfo == RoleInfo.niceMini) continue; // Not guessable roles
+
+ Transform button = UnityEngine.Object.Instantiate(buttonTemplate.transform, container);
+ Transform confirm = UnityEngine.Object.Instantiate(smallButtonTemplate.transform, button);
+ confirmButtons.Add(confirm);
+ TMPro.TextMeshPro label = UnityEngine.Object.Instantiate(textTemplate, button);
+ int row = i/4, col = i%4;
+ button.localPosition = new Vector3(-3 + 1.83f * col, 1.5f - 0.4f * row, -5);
+ button.localScale = new Vector3(0.4f, 0.4f, 1f);
+ confirm.localScale = new Vector3(1.5f, 1.5f, 1f);
+ confirm.localPosition = new Vector3(0, 0, confirm.localPosition.z);
+ confirm.GetComponent<SpriteRenderer>().sprite = Guesser.getTargetSprite();
+ confirm.GetComponent<SpriteRenderer>().color = Color.black;
+ confirm.gameObject.SetActive(false);
+ label.text = Helpers.cs(roleInfo.color, roleInfo.name);
+ label.alignment = TMPro.TextAlignmentOptions.Center;
+ label.transform.localPosition = new Vector3(0, 0, label.transform.localPosition.z);
+ label.transform.localScale *= 2;
+ int copiedIndex = i;
+
+ button.GetComponent<PassiveButton>().OnClick.RemoveAllListeners();
+ button.GetComponent<PassiveButton>().OnClick.AddListener((UnityEngine.Events.UnityAction)(() => {
+ confirmButtons.ForEach(x => x.gameObject.SetActive(false));
+ confirm.gameObject.SetActive(true);
+ }));
+
+
+ confirm.GetComponent<PassiveButton>().OnClick.RemoveAllListeners();
+ confirm.GetComponent<PassiveButton>().OnClick.AddListener((UnityEngine.Events.UnityAction)(() => {
+ PlayerControl target = Helpers.playerById((byte)__instance.playerStates[buttonTarget].TargetPlayerId);
+ if (!(__instance.state == MeetingHud.VoteStates.Voted || __instance.state == MeetingHud.VoteStates.NotVoted) || target == null || Guesser.remainingShots <= 0 ) return;
+
+ var mainRoleInfo = RoleInfo.getRoleInfoForPlayer(target).FirstOrDefault();
+ if (mainRoleInfo == null) return;
+
+ target = (mainRoleInfo == roleInfo) ? target : PlayerControl.LocalPlayer;
+
+ MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.GuesserShoot, Hazel.SendOption.Reliable, -1);
+ writer.Write(target.PlayerId);
+ AmongUsClient.Instance.FinishRpcImmediately(writer);
+ RPCProcedure.guesserShoot(target.PlayerId);
+
+ UnityEngine.Object.Destroy(container.gameObject);
+ __instance.playerStates.ToList().ForEach(x => { if (x.transform.FindChild("ShootButton") != null) UnityEngine.Object.Destroy(x.transform.FindChild("ShootButton").gameObject); });
+ }));
+
+ i++;
+ }
+ container.transform.localScale *= 0.75f;
+ }
+
+ [HarmonyPatch(typeof(PlayerVoteArea), nameof(PlayerVoteArea.Select))]
+ class PlayerVoteAreaSelectPatch {
+ static bool Prefix(MeetingHud __instance) {
+ return !(PlayerControl.LocalPlayer != null && PlayerControl.LocalPlayer == Guesser.guesser && guesserUI != null);
+ }
+ }
+
+
static void populateButtonsPostfix(MeetingHud __instance) {
+ // Add Swapper Buttons
+ if (Swapper.swapper != null && PlayerControl.LocalPlayer == Swapper.swapper && !Swapper.swapper.Data.IsDead) {
+ selections = new bool[__instance.playerStates.Length];
+ renderers = new SpriteRenderer[__instance.playerStates.Length];
+
+ for (int i = 0; i < __instance.playerStates.Length; i++) {
+ PlayerVoteArea playerVoteArea = __instance.playerStates[i];
+ if (playerVoteArea.isDead || (playerVoteArea.TargetPlayerId == Swapper.swapper.PlayerId && Swapper.canOnlySwapOthers)) continue;
+
+ GameObject template = playerVoteArea.Buttons.transform.Find("CancelButton").gameObject;
+ GameObject checkbox = UnityEngine.Object.Instantiate(template);
+ checkbox.transform.SetParent(playerVoteArea.transform);
+ checkbox.transform.position = template.transform.position;
+ checkbox.transform.localPosition = new Vector3(0f, 0.03f, template.transform.localPosition.z);
+ SpriteRenderer renderer = checkbox.GetComponent<SpriteRenderer>();
+ renderer.sprite = Swapper.getCheckSprite();
+ renderer.color = Color.red;
+
+ PassiveButton button = checkbox.GetComponent<PassiveButton>();
+ button.OnClick.RemoveAllListeners();
+ int copiedIndex = i;
+ button.OnClick.AddListener((UnityEngine.Events.UnityAction)(() => swapperOnClick(copiedIndex, __instance)));
+
+ selections[i] = false;
+ renderers[i] = renderer;
+ }
+ }
+
+ // Add Guesser Buttons
+ if (Guesser.guesser != null && PlayerControl.LocalPlayer == Guesser.guesser && !Guesser.guesser.Data.IsDead && Guesser.remainingShots >= 0) {
+ for (int i = 0; i < __instance.playerStates.Length; i++) {
+ PlayerVoteArea playerVoteArea = __instance.playerStates[i];
+ if (playerVoteArea.isDead || playerVoteArea.TargetPlayerId == Guesser.guesser.PlayerId) continue;
+
+ GameObject template = playerVoteArea.Buttons.transform.Find("CancelButton").gameObject;
+ GameObject targetBox = UnityEngine.Object.Instantiate(template, playerVoteArea.transform);
+ targetBox.name = "ShootButton";
+ targetBox.transform.localPosition = new Vector3(0f, 0.03f, template.transform.localPosition.z);
+ SpriteRenderer renderer = targetBox.GetComponent<SpriteRenderer>();
+ renderer.sprite = Guesser.getTargetSprite();
+ PassiveButton button = targetBox.GetComponent<PassiveButton>();
+ button.OnClick.RemoveAllListeners();
+ int copiedIndex = i;
+ button.OnClick.AddListener((UnityEngine.Events.UnityAction)(() => guesserOnClick(copiedIndex, __instance)));
+ }
+ }
+
// Change buttons if there are more than 10 players
if (__instance.playerStates != null && __instance.playerStates.Length > 10) {
PlayerVoteArea[] playerStates = __instance.playerStates.OrderBy((PlayerVoteArea p) => p.isDead ? 50 : 0)
area.transform.localPosition = new Vector3(-3.63f + 2.43f * col, 1.5f - 0.76f * row, -0.9f - 0.01f * row);
}
}
-
- // Add Swapper Buttons
- if (Swapper.swapper == null || PlayerControl.LocalPlayer != Swapper.swapper || Swapper.swapper.Data.IsDead) return;
- selections = new bool[__instance.playerStates.Length];
- renderers = new SpriteRenderer[__instance.playerStates.Length];
-
- for (int i = 0; i < __instance.playerStates.Length; i++) {
- PlayerVoteArea playerVoteArea = __instance.playerStates[i];
- if (playerVoteArea.isDead || (playerVoteArea.TargetPlayerId == Swapper.swapper.PlayerId && Swapper.canOnlySwapOthers)) continue;
-
- GameObject template = playerVoteArea.Buttons.transform.Find("CancelButton").gameObject;
- GameObject checkbox = UnityEngine.Object.Instantiate(template);
- checkbox.transform.SetParent(playerVoteArea.transform);
- checkbox.transform.position = template.transform.position;
- checkbox.transform.localPosition = new Vector3(0f, 0.03f, template.transform.localPosition.z);
- SpriteRenderer renderer = checkbox.GetComponent<SpriteRenderer>();
- renderer.sprite = Swapper.getCheckSprite();
- renderer.color = Color.red;
-
- PassiveButton button = checkbox.GetComponent<PassiveButton>();
- button.OnClick.RemoveAllListeners();
- int copiedIndex = i;
- button.OnClick.AddListener((UnityEngine.Events.UnityAction)(() => onClick(copiedIndex, __instance)));
-
-
-
- selections[i] = false;
- renderers[i] = renderer;
- }
}
[HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.ServerStart))]
}
}
}
-
- [HarmonyPatch(typeof(ExileController), "Begin")]
- class ExileBeginPatch {
- public static void Prefix(ExileController __instance, [HarmonyArgument(0)]ref GameData.PlayerInfo exiled, [HarmonyArgument(1)]bool tie) {
- // Shifter shift
- if (Shifter.shifter != null && AmongUsClient.Instance.AmHost && Shifter.futureShift != null) { // We need to send the RPC from the host here, to make sure that the order of shifting and erasing is correct (for that reason the futureShifted and futureErased are being synced)
- MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ShifterShift, Hazel.SendOption.Reliable, -1);
- writer.Write(Shifter.futureShift.PlayerId);
- AmongUsClient.Instance.FinishRpcImmediately(writer);
- RPCProcedure.shifterShift(Shifter.futureShift.PlayerId);
- }
- Shifter.futureShift = null;
-
- // Eraser erase
- if (Eraser.eraser != null && AmongUsClient.Instance.AmHost && Eraser.futureErased != null) { // We need to send the RPC from the host here, to make sure that the order of shifting and erasing is correct (for that reason the futureShifted and futureErased are being synced)
- foreach (PlayerControl target in Eraser.futureErased) {
- if (target != null) {
- MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ErasePlayerRoles, Hazel.SendOption.Reliable, -1);
- writer.Write(target.PlayerId);
- AmongUsClient.Instance.FinishRpcImmediately(writer);
- RPCProcedure.erasePlayerRoles(target.PlayerId);
- }
- }
- }
- Eraser.futureErased = new List<PlayerControl>();
-
- // Trickster boxes
- if (Trickster.trickster != null && JackInTheBox.hasJackInTheBoxLimitReached()) {
- JackInTheBox.convertToVents();
- }
-
- // SecurityGuard vents and cameras
- var allCameras = ShipStatus.Instance.AllCameras.ToList();
- MapOptions.camerasToAdd.ForEach(camera => {
- camera.gameObject.SetActive(true);
- camera.gameObject.GetComponent<SpriteRenderer>().color = Color.white;
- allCameras.Add(camera);
- });
- ShipStatus.Instance.AllCameras = allCameras.ToArray();
- MapOptions.camerasToAdd = new List<SurvCamera>();
-
- foreach (Vent vent in MapOptions.ventsToSeal) {
- PowerTools.SpriteAnim animator = vent.GetComponent<PowerTools.SpriteAnim>();
- animator?.Stop();
- vent.EnterVentAnim = vent.ExitVentAnim = null;
- vent.myRend.sprite = animator == null ? SecurityGuard.getStaticVentSealedSprite() : SecurityGuard.getAnimatedVentSealedSprite();
- vent.myRend.color = Color.white;
- vent.name = "SealedVent_" + vent.name;
- }
- MapOptions.ventsToSeal = new List<Vent>();
- }
- }
-
-
- [HarmonyPatch(typeof(UnityEngine.Object), nameof(UnityEngine.Object.Destroy), new Type[] { typeof(UnityEngine.Object) })]
- class MeetingExiledEndPatch
- {
- static void Prefix(UnityEngine.Object obj)
- {
- if (ExileController.Instance != null && obj == ExileController.Instance.gameObject)
- {
- // Reset custom button timers where necessary
- CustomButton.MeetingEndedUpdate();
- // Child set adapted cooldown
- if (Child.child != null && PlayerControl.LocalPlayer == Child.child && Child.child.Data.IsImpostor) {
- var multiplier = Child.isGrownUp() ? 0.66f : 2f;
- Child.child.SetKillTimer(PlayerControl.GameOptions.KillCooldown * multiplier);
- }
-
- // Seer spawn souls
- if (Seer.deadBodyPositions != null && Seer.seer != null && PlayerControl.LocalPlayer == Seer.seer && (Seer.mode == 0 || Seer.mode == 2)) {
- foreach (Vector3 pos in Seer.deadBodyPositions) {
- GameObject soul = new GameObject();
- soul.transform.position = pos;
- soul.layer = 5;
- var rend = soul.AddComponent<SpriteRenderer>();
- rend.sprite = Seer.getSoulSprite();
-
- if(Seer.limitSoulDuration) {
- HudManager.Instance.StartCoroutine(Effects.Lerp(Seer.soulDuration, new Action<float>((p) => {
- if (rend != null) {
- var tmp = rend.color;
- tmp.a = Mathf.Clamp01(1 - p);
- rend.color = tmp;
- }
- if (p == 1f && rend != null && rend.gameObject != null) UnityEngine.Object.Destroy(rend.gameObject);
- })));
- }
- }
- Seer.deadBodyPositions = new List<Vector3>();
- }
-
- // Arsonist deactivate dead poolable players
- if (Arsonist.arsonist != null && Arsonist.arsonist == PlayerControl.LocalPlayer) {
- int visibleCounter = 0;
- Vector3 bottomLeft = new Vector3(-HudManager.Instance.UseButton.transform.localPosition.x, HudManager.Instance.UseButton.transform.localPosition.y, HudManager.Instance.UseButton.transform.localPosition.z);
- bottomLeft += new Vector3(-0.25f, -0.25f, 0);
- foreach (PlayerControl p in PlayerControl.AllPlayerControls) {
- if (!Arsonist.dousedIcons.ContainsKey(p.PlayerId)) continue;
- if (p.Data.IsDead || p.Data.Disconnected) {
- Arsonist.dousedIcons[p.PlayerId].gameObject.SetActive(false);
- } else {
- Arsonist.dousedIcons[p.PlayerId].transform.localPosition = bottomLeft + Vector3.right * visibleCounter * 0.35f;
- visibleCounter++;
- }
- }
- }
- }
- }
- }
-
- [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), new Type[] { typeof(StringNames), typeof(Il2CppReferenceArray<Il2CppSystem.Object>) })]
- class ExileControllerMessagePatch {
- static void Postfix(ref string __result, [HarmonyArgument(0)]StringNames id, [HarmonyArgument(1)]Il2CppReferenceArray<Il2CppSystem.Object> parts) {
- if (ExileController.Instance != null && ExileController.Instance.exiled != null) {
- PlayerControl player = Helpers.playerById(ExileController.Instance.exiled.Object.PlayerId);
- if (player == null) return;
- // Exile role text
- if (id == StringNames.ExileTextPN || id == StringNames.ExileTextSN || id == StringNames.ExileTextPP || id == StringNames.ExileTextSP) {
- __result = player.Data.PlayerName + " was The " + String.Join(" ", RoleInfo.getRoleInfoForPlayer(player).Select(x => x.name).ToArray());
- }
- // Hide number of remaining impostors on Jester win
- if (id == StringNames.ImpostorsRemainP || id == StringNames.ImpostorsRemainS) {
- if (Jester.jester != null && player.PlayerId == Jester.jester.PlayerId) __result = "";
- }
- }
- }
- }
}
\ No newline at end of file
// Only exclude sidekick from beeing targeted if the jackal can create sidekicks from impostors
if(Sidekick.sidekick != null) untargetablePlayers.Add(Sidekick.sidekick);
}
- if(Child.child != null && !Child.isGrownUp()) untargetablePlayers.Add(Child.child); // Exclude Jackal from targeting the Child unless it has grown up
+ if(Mini.mini != null && !Mini.isGrownUp()) untargetablePlayers.Add(Mini.mini); // Exclude Jackal from targeting the Mini unless it has grown up
Jackal.currentTarget = setTarget(untargetablePlayers : untargetablePlayers);
setPlayerOutline(Jackal.currentTarget, Palette.ImpostorRed);
}
if (Sidekick.sidekick == null || Sidekick.sidekick != PlayerControl.LocalPlayer) return;
var untargetablePlayers = new List<PlayerControl>();
if(Jackal.jackal != null) untargetablePlayers.Add(Jackal.jackal);
- if(Child.child != null && !Child.isGrownUp()) untargetablePlayers.Add(Child.child); // Exclude Sidekick from targeting the Child unless it has grown up
+ if(Mini.mini != null && !Mini.isGrownUp()) untargetablePlayers.Add(Mini.mini); // Exclude Sidekick from targeting the Mini unless it has grown up
Sidekick.currentTarget = setTarget(untargetablePlayers : untargetablePlayers);
if (Sidekick.canKill) setPlayerOutline(Sidekick.currentTarget, Palette.ImpostorRed);
}
CircleCollider2D collider = p.GetComponent<CircleCollider2D>();
p.transform.localScale = new Vector3(0.7f, 0.7f, 1f);
- collider.radius = Child.defaultColliderRadius;
- collider.offset = Child.defaultColliderOffset * Vector2.down;
+ collider.radius = Mini.defaultColliderRadius;
+ collider.offset = Mini.defaultColliderOffset * Vector2.down;
- // Set adapted player size to Child and Morphling
- if (Child.child == null || Camouflager.camouflageTimer > 0f) return;
+ // Set adapted player size to Mini and Morphling
+ if (Mini.mini == null || Camouflager.camouflageTimer > 0f) return;
- float growingProgress = Child.growingProgress();
+ float growingProgress = Mini.growingProgress();
float scale = growingProgress * 0.35f + 0.35f;
- float correctedColliderRadius = Child.defaultColliderRadius * 0.7f / scale; // scale / 0.7f is the factor by which we decrease the player size, hence we need to increase the collider size by 0.7f / scale
+ float correctedColliderRadius = Mini.defaultColliderRadius * 0.7f / scale; // scale / 0.7f is the factor by which we decrease the player size, hence we need to increase the collider size by 0.7f / scale
- if (p == Child.child) {
+ if (p == Mini.mini) {
p.transform.localScale = new Vector3(scale, scale, 1f);
collider.radius = correctedColliderRadius;
}
- if (Morphling.morphling != null && p == Morphling.morphling && Morphling.morphTarget == Child.child && Morphling.morphTimer > 0f) {
+ if (Morphling.morphling != null && p == Morphling.morphling && Morphling.morphTarget == Mini.mini && Morphling.morphTimer > 0f) {
p.transform.localScale = new Vector3(scale, scale, 1f);
collider.radius = correctedColliderRadius;
}
public static void Postfix(PlayerControl __instance) {
if (AmongUsClient.Instance.GameState != InnerNet.InnerNetClient.GameStates.Started) return;
- // Child and Morphling shrink
+ // Mini and Morphling shrink
playerSizeUpdate(__instance);
if (PlayerControl.LocalPlayer == __instance) {
class PlayerPhysicsWalkPlayerToPatch {
private static Vector2 offset = Vector2.zero;
public static void Prefix(PlayerPhysics __instance) {
- bool correctOffset = Camouflager.camouflageTimer <= 0f && (__instance.myPlayer == Child.child || (Morphling.morphling != null && __instance.myPlayer == Morphling.morphling && Morphling.morphTarget == Child.child && Morphling.morphTimer > 0f));
+ bool correctOffset = Camouflager.camouflageTimer <= 0f && (__instance.myPlayer == Mini.mini || (Morphling.morphling != null && __instance.myPlayer == Morphling.morphling && Morphling.morphTarget == Mini.mini && Morphling.morphTimer > 0f));
if (correctOffset) {
- float currentScaling = (Child.growingProgress() + 1) * 0.5f;
- __instance.myPlayer.Collider.offset = currentScaling * Child.defaultColliderOffset * Vector2.down;
+ float currentScaling = (Mini.growingProgress() + 1) * 0.5f;
+ __instance.myPlayer.Collider.offset = currentScaling * Mini.defaultColliderOffset * Vector2.down;
}
}
}
class RpcMurderPlayer {
public static bool Prefix([HarmonyArgument(0)]PlayerControl target) {
if (Helpers.handleMurderAttempt(target)) { // Custom checks
- if (Child.child != null && PlayerControl.LocalPlayer == Child.child) { // Not checked by official servers
+ if (Mini.mini != null && PlayerControl.LocalPlayer == Mini.mini) { // Not checked by official servers
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.UncheckedMurderPlayer, Hazel.SendOption.Reliable, -1);
writer.Write(PlayerControl.LocalPlayer.PlayerId);
writer.Write(target.PlayerId);
}
if (Seer.deadBodyPositions != null) Seer.deadBodyPositions.Add(target.transform.position);
- // Child set adapted kill cooldown
- if (Child.child != null && PlayerControl.LocalPlayer == Child.child && Child.child.Data.IsImpostor && Child.child == __instance) {
- var multiplier = Child.isGrownUp() ? 0.66f : 2f;
- Child.child.SetKillTimer(PlayerControl.GameOptions.KillCooldown * multiplier);
+ // Mini set adapted kill cooldown
+ if (Mini.mini != null && PlayerControl.LocalPlayer == Mini.mini && Mini.mini.Data.IsImpostor && Mini.mini == __instance) {
+ var multiplier = Mini.isGrownUp() ? 0.66f : 2f;
+ Mini.mini.SetKillTimer(PlayerControl.GameOptions.KillCooldown * multiplier);
}
}
}
public static bool Prefix(PlayerControl __instance, [HarmonyArgument(0)]float time) {
if (PlayerControl.GameOptions.KillCooldown <= 0f) return false;
float multiplier = 1f;
- if (Child.child != null && PlayerControl.LocalPlayer == Child.child && Child.child.Data.IsImpostor) multiplier = Child.isGrownUp() ? 0.66f : 2f;
+ if (Mini.mini != null && PlayerControl.LocalPlayer == Mini.mini && Mini.mini.Data.IsImpostor) multiplier = Mini.isGrownUp() ? 0.66f : 2f;
__instance.killTimer = Mathf.Clamp(time, 0f, PlayerControl.GameOptions.KillCooldown * multiplier);
DestroyableSingleton<HudManager>.Instance.KillButton.SetCoolDown(__instance.killTimer, PlayerControl.GameOptions.KillCooldown * multiplier);
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.Exiled))]
public static class ExilePlayerPatch
{
- public static void Prefix(PlayerControl __instance) {
- // Child exile lose condition
- if (Child.child != null && Child.child == __instance && !Child.isGrownUp() && !Child.child.Data.IsImpostor) {
- Child.triggerChildLose = true;
- }
- // Jester win condition
- else if (Jester.jester != null && Jester.jester == __instance) {
- Jester.triggerJesterWin = true;
- }
- }
-
public static void Postfix(PlayerControl __instance)
{
// Collect dead player info
Morphling,
Camouflager,
Hacker,
- Child,
+ Mini,
Tracker,
Vampire,
Snitch,
Warlock,
SecurityGuard,
Arsonist,
+ Guesser,
Crewmate,
Impostor
}
WarlockCurseKill,
PlaceCamera,
SealVent,
- ArsonistWin
+ ArsonistWin,
+ GuesserShoot
}
public static class RPCProcedure {
case RoleId.Hacker:
Hacker.hacker = player;
break;
- case RoleId.Child:
- Child.child = player;
+ case RoleId.Mini:
+ Mini.mini = player;
break;
case RoleId.Tracker:
Tracker.tracker = player;
case RoleId.Arsonist:
Arsonist.arsonist = player;
break;
+ case RoleId.Guesser:
+ Guesser.guesser = player;
+ break;
}
}
}
if (player != null) player.SetColor(colorId);
}
- public static void versionHandshake(int major, int minor, int build, int clientId) {
- GameStartManagerPatch.playerVersions[clientId] = new System.Version(major, minor, build);
+ public static void versionHandshake(int major, int minor, int build, int revision, Guid guid, int clientId) {
+ System.Version ver;
+ if (revision < 0)
+ ver = new System.Version(major, minor, build);
+ else
+ ver = new System.Version(major, minor, build, revision);
+
+ GameStartManagerPatch.playerVersions[clientId] = new GameStartManagerPatch.PlayerVersion(ver, guid);
}
public static void useUncheckedVent(int ventId, byte playerId, byte isEnter) {
else if (Lovers.lover2 != null && player == Lovers.lover2) Lovers.lover2 = oldShifter;
// Shift role
- if (Jester.jester != null && Jester.jester == player)
- Jester.jester = oldShifter;
if (Mayor.mayor != null && Mayor.mayor == player)
Mayor.mayor = oldShifter;
if (Engineer.engineer != null && Engineer.engineer == player)
Seer.seer = oldShifter;
if (Hacker.hacker != null && Hacker.hacker == player)
Hacker.hacker = oldShifter;
- if (Child.child != null && Child.child == player)
- Child.child = oldShifter;
+ if (Mini.mini != null && Mini.mini == player)
+ Mini.mini = oldShifter;
if (Tracker.tracker != null && Tracker.tracker == player)
Tracker.tracker = oldShifter;
if (Snitch.snitch != null && Snitch.snitch == player)
Spy.spy = oldShifter;
if (SecurityGuard.securityGuard != null && SecurityGuard.securityGuard == player)
SecurityGuard.securityGuard = oldShifter;
- if (Arsonist.arsonist != null && Arsonist.arsonist == player)
- Arsonist.arsonist = oldShifter;
+ if (Guesser.guesser != null && Guesser.guesser == player)
+ Guesser.guesser = oldShifter;
// Set cooldowns to max for both players
if (PlayerControl.LocalPlayer == oldShifter || PlayerControl.LocalPlayer == player)
if (player == Shifter.shifter) Shifter.clearAndReload();
if (player == Seer.seer) Seer.clearAndReload();
if (player == Hacker.hacker) Hacker.clearAndReload();
- if (player == Child.child) Child.clearAndReload();
+ if (player == Mini.mini) Mini.clearAndReload();
if (player == Tracker.tracker) Tracker.clearAndReload();
if (player == Snitch.snitch) Snitch.clearAndReload();
if (player == Swapper.swapper) Swapper.clearAndReload();
// Other roles
if (player == Jester.jester) Jester.clearAndReload();
if (player == Arsonist.arsonist) Arsonist.clearAndReload();
+ if (player == Guesser.guesser) Guesser.clearAndReload();
if (!ignoreLovers && (player == Lovers.lover1 || player == Lovers.lover2)) { // The whole Lover couple is being erased
Lovers.clearAndReload();
}
public static void arsonistWin() {
Arsonist.triggerArsonistWin = true;
}
+
+ public static void guesserShoot(byte playerId) {
+ PlayerControl target = Helpers.playerById(playerId);
+ if (target == null) return;
+ target.Exiled();
+ Guesser.remainingShots = Mathf.Max(0, Guesser.remainingShots - 1);
+ if (Constants.ShouldPlaySfx()) SoundManager.Instance.PlaySound(target.KillSfx, false, 0.8f);
+ if (MeetingHud.Instance) {
+ foreach (PlayerVoteArea pva in MeetingHud.Instance.playerStates) {
+ if (pva.TargetPlayerId == playerId) {
+ pva.SetDead(playerId == PlayerControl.LocalPlayer.PlayerId, pva.didReport, true);
+ pva.Overlay.gameObject.SetActive(true);
+ pva.Overlay.transform.GetChild(0).gameObject.SetActive(true);
+ }
+ }
+ if (AmongUsClient.Instance.AmHost) MeetingHud.Instance.CheckForEndVoting();
+ }
+ if (HudManager.Instance != null && Guesser.guesser != null && PlayerControl.LocalPlayer == target)
+ HudManager.Instance.KillOverlay.ShowOne(Guesser.guesser.Data, target.Data);
+ }
}
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.HandleRpc))]
byte minor = reader.ReadByte();
byte patch = reader.ReadByte();
int versionOwnerId = reader.ReadPackedInt32();
- RPCProcedure.versionHandshake(major, minor, patch, versionOwnerId);
+ byte revision = 0xFF;
+ Guid guid;
+ if (reader.Length >= 24) {
+ revision = reader.ReadByte();
+ // GUID
+ byte[] gbytes = reader.ReadBytes(16);
+ guid = new Guid(gbytes);
+ } else {
+ guid = new Guid(new byte[16]);
+ }
+ RPCProcedure.versionHandshake(major, minor, patch, revision == 0xFF ? -1 : revision, guid, versionOwnerId);
break;
case (byte)CustomRPC.UseUncheckedVent:
int ventId = reader.ReadPackedInt32();
case (byte)CustomRPC.ArsonistWin:
RPCProcedure.arsonistWin();
break;
+ case (byte)CustomRPC.GuesserShoot:
+ RPCProcedure.guesserShoot(reader.ReadByte());
+ break;
}
}
}
private static void assignRoles() {
var data = getRoleAssignmentData();
assignSpecialRoles(data); // Assign special roles like mafia and lovers first as they assign a role to multiple players and the chances are independent of the ticket system
+ if (Mini.mini != null) // Remove Spy from assigns, if Mini exists
+ data.crewSettings.Remove((byte)RoleId.Spy);
assignEnsuredRoles(data); // Assign roles that should always be in the game next
assignChanceRoles(data); // Assign roles that may or may not be in the game last
}
var crewmatesWithoutFirstLover = data.crewmates.ToList();
crewmatesWithoutFirstLover.RemoveAll(p => p.PlayerId == firstLoverId);
setRoleToRandomPlayer((byte)RoleId.Lover, crewmatesWithoutFirstLover, 1, false);
- System.Console.WriteLine(crewmatesWithoutFirstLover.Count);
-
}
}
}
data.maxImpostorRoles -= 3;
}
- // Assign Child
- if (rnd.Next(1, 101) <= CustomOptionHolder.childSpawnRate.getSelection() * 10) {
+ // Assign Mini
+ if (rnd.Next(1, 101) <= CustomOptionHolder.miniSpawnRate.getSelection() * 10) {
if (data.impostors.Count > 0 && data.maxImpostorRoles > 0 && rnd.Next(1, 101) <= 33) {
- setRoleToRandomPlayer((byte)RoleId.Child, data.impostors);
+ setRoleToRandomPlayer((byte)RoleId.Mini, data.impostors);
+ data.maxImpostorRoles--;
+ } else if (data.crewmates.Count > 0 && data.maxCrewmateRoles > 0) {
+ setRoleToRandomPlayer((byte)RoleId.Mini, data.crewmates);
+ data.maxCrewmateRoles--;
+ }
+ }
+
+ // Assign Guesser
+ if (rnd.Next(1, 101) <= CustomOptionHolder.guesserSpawnRate.getSelection() * 10) {
+ if (data.impostors.Count > 0 && data.maxImpostorRoles > 0 && rnd.Next(1, 101) <= CustomOptionHolder.guesserIsImpGuesserRate.getSelection() * 10) {
+ setRoleToRandomPlayer((byte)RoleId.Guesser, data.impostors);
data.maxImpostorRoles--;
} else if (data.crewmates.Count > 0 && data.maxCrewmateRoles > 0) {
- setRoleToRandomPlayer((byte)RoleId.Child, data.crewmates);
+ setRoleToRandomPlayer((byte)RoleId.Guesser, data.crewmates);
data.maxCrewmateRoles--;
}
}
this.roleId = roleId;
}
+ public static RoleInfo jester = new RoleInfo("Jester", Jester.color, "Get voted out", "Get voted out", RoleId.Jester);
+ public static RoleInfo mayor = new RoleInfo("Mayor", Mayor.color, "Your vote counts twice", "Your vote counts twice", RoleId.Mayor);
+ public static RoleInfo engineer = new RoleInfo("Engineer", Engineer.color, "Maintain important systems on the ship", "Repair the ship", RoleId.Engineer);
+ public static RoleInfo sheriff = new RoleInfo("Sheriff", Sheriff.color, "Shoot the <color=#FF1919FF>Impostors</color>", "Shoot the Impostors", RoleId.Sheriff);
+ public static RoleInfo lighter = new RoleInfo("Lighter", Lighter.color, "Your light never goes out", "Your light never goes out", RoleId.Lighter);
+ public static RoleInfo godfather = new RoleInfo("Godfather", Godfather.color, "Kill all Crewmates", "Kill all Crewmates", RoleId.Godfather);
+ public static RoleInfo mafioso = new RoleInfo("Mafioso", Mafioso.color, "Work with the <color=#FF1919FF>Mafia</color> to kill the Crewmates", "Kill all Crewmates", RoleId.Mafioso);
+ public static RoleInfo janitor = new RoleInfo("Janitor", Janitor.color, "Work with the <color=#FF1919FF>Mafia</color> by hiding dead bodies", "Hide dead bodies", RoleId.Janitor);
+ public static RoleInfo morphling = new RoleInfo("Morphling", Morphling.color, "Change your look to not get caught", "Change your look", RoleId.Morphling);
+ public static RoleInfo camouflager = new RoleInfo("Camouflager", Camouflager.color, "Camouflage and kill the Crewmates", "Hide among others", RoleId.Camouflager);
+ public static RoleInfo vampire = new RoleInfo("Vampire", Vampire.color, "Kill the Crewmates with your bites", "Bite your enemies", RoleId.Vampire);
+ public static RoleInfo eraser = new RoleInfo("Eraser", Eraser.color, "Kill the Crewmates and erase their roles", "Erase the roles of your enemies", RoleId.Eraser);
+ public static RoleInfo trickster = new RoleInfo("Trickster", Trickster.color, "Use your jack-in-the-boxes to surprise others", "Surprise your enemies", RoleId.Trickster);
+ public static RoleInfo cleaner = new RoleInfo("Cleaner", Cleaner.color, "Kill everyone and leave no traces", "Clean up dead bodies", RoleId.Cleaner);
+ public static RoleInfo warlock = new RoleInfo("Warlock", Warlock.color, "Curse other players and kill everyone", "Curse and kill everyone", RoleId.Warlock);
+ public static RoleInfo detective = new RoleInfo("Detective", Detective.color, "Find the <color=#FF1919FF>Impostors</color> by examining footprints", "Examine footprints", RoleId.Detective);
+ public static RoleInfo timeMaster = new RoleInfo("Time Master", TimeMaster.color, "Save yourself with your time shield", "Use your time shield", RoleId.TimeMaster);
+ public static RoleInfo medic = new RoleInfo("Medic", Medic.color, "Protect someone with your shield", "Protect other players", RoleId.Medic);
+ public static RoleInfo shifter = new RoleInfo("Shifter", Shifter.color, "Shift your role", "Shift your role", RoleId.Shifter);
+ public static RoleInfo swapper = new RoleInfo("Swapper", Swapper.color, "Swap votes to exile the <color=#FF1919FF>Impostors</color>", "Swap votes", RoleId.Swapper);
+ public static RoleInfo seer = new RoleInfo("Seer", Seer.color, "You will see players die", "You will see players die", RoleId.Seer);
+ public static RoleInfo hacker = new RoleInfo("Hacker", Hacker.color, "Hack systems to find the <color=#FF1919FF>Impostors</color>", "Hack to find the Impostors", RoleId.Hacker);
+ public static RoleInfo niceMini = new RoleInfo("Nice Mini", Mini.color, "No one will harm you until you grow up", "No one will harm you", RoleId.Mini);
+ public static RoleInfo evilMini = new RoleInfo("Evil Mini", Palette.ImpostorRed, "No one will harm you until you grow up", "No one will harm you", RoleId.Mini);
+ public static RoleInfo tracker = new RoleInfo("Tracker", Tracker.color, "Track the <color=#FF1919FF>Impostors</color> down", "Track the Impostors down", RoleId.Tracker);
+ public static RoleInfo snitch = new RoleInfo("Snitch", Snitch.color, "Finish your tasks to find the <color=#FF1919FF>Impostors</color>", "Finish your tasks", RoleId.Snitch);
+ public static RoleInfo jackal = new RoleInfo("Jackal", Jackal.color, "Kill all Crewmates and <color=#FF1919FF>Impostors</color> to win", "Kill everyone", RoleId.Jackal);
+ public static RoleInfo sidekick = new RoleInfo("Sidekick", Sidekick.color, "Help your Jackal to kill everyone", "Help your Jackal to kill everyone", RoleId.Sidekick);
+ public static RoleInfo spy = new RoleInfo("Spy", Spy.color, "Confuse the <color=#FF1919FF>Impostors</color>", "Confuse the Impostors", RoleId.Spy);
+ public static RoleInfo securityGuard = new RoleInfo("Security Guard", SecurityGuard.color, "Seal vents and place cameras", "Seal vents and place cameras", RoleId.SecurityGuard);
+ public static RoleInfo arsonist = new RoleInfo("Arsonist", Arsonist.color, "Let them burn", "Let them burn", RoleId.Arsonist);
+ public static RoleInfo goodGuesser = new RoleInfo("Nice Guesser", Guesser.color, "Guess and shoot", "Guess and shoot", RoleId.Guesser);
+ public static RoleInfo badGuesser = new RoleInfo("Evil Guesser", Palette.ImpostorRed, "Guess and shoot", "Guess and shoot", RoleId.Guesser);
+ public static RoleInfo impostor = new RoleInfo("Impostor", Palette.ImpostorRed, Helpers.cs(Palette.ImpostorRed, "Sabotage and kill everyone"), "Sabotage and kill everyone", RoleId.Impostor);
+ public static RoleInfo crewmate = new RoleInfo("Crewmate", Color.white, "Find the Impostors", "Find the Impostors", RoleId.Crewmate);
+ public static RoleInfo lover = new RoleInfo("Lover", Lovers.color, $"You are in love", $"You are in love", RoleId.Lover);
+
+ public static List<RoleInfo> allRoleInfos = new List<RoleInfo>() {
+ impostor,
+ godfather,
+ mafioso,
+ janitor,
+ morphling,
+ camouflager,
+ vampire,
+ eraser,
+ trickster,
+ cleaner,
+ warlock,
+ niceMini,
+ evilMini,
+ goodGuesser,
+ badGuesser,
+ lover,
+ jester,
+ arsonist,
+ jackal,
+ sidekick,
+ crewmate,
+ shifter,
+ mayor,
+ engineer,
+ sheriff,
+ lighter,
+ detective,
+ timeMaster,
+ medic,
+ swapper,
+ seer,
+ hacker,
+ tracker,
+ snitch,
+ spy,
+ securityGuard
+ };
+
public static List<RoleInfo> getRoleInfoForPlayer(PlayerControl p) {
List<RoleInfo> infos = new List<RoleInfo>();
+ if (p == null) return infos;
// Special roles
- if (Jester.jester != null && p == Jester.jester) {
- infos.Add(new RoleInfo("Jester",
- Jester.color,
- "Get voted out",
- "Get voted out",
- RoleId.Jester));
- }
- if (Mayor.mayor != null && p == Mayor.mayor) {
- infos.Add(new RoleInfo("Mayor",
- Mayor.color,
- "Your vote counts twice",
- "Your vote counts twice",
- RoleId.Mayor));
- }
- if (Engineer.engineer != null && p == Engineer.engineer) {
- infos.Add(new RoleInfo("Engineer",
- Engineer.color,
- "Maintain important systems on the ship",
- "Repair the ship",
- RoleId.Engineer));
- }
- if (Sheriff.sheriff != null && p == Sheriff.sheriff) {
- infos.Add(new RoleInfo("Sheriff",
- Sheriff.color,
- "Shoot the <color=#FF1919FF>Impostors</color>",
- "Shoot the Impostors",
- RoleId.Sheriff));
- }
- if (Lighter.lighter != null && p == Lighter.lighter) {
- infos.Add(new RoleInfo("Lighter",
- Lighter.color,
- "Your light never goes out",
- "Your light never goes out",
- RoleId.Lighter));
- }
- if (Godfather.godfather != null && p == Godfather.godfather) {
- infos.Add(new RoleInfo("Godfather",
- Godfather.color,
- "Kill all Crewmates",
- "Kill all Crewmates",
- RoleId.Godfather));
- ;
- }
- if (Mafioso.mafioso != null && p == Mafioso.mafioso) {
- infos.Add(new RoleInfo("Mafioso",
- Mafioso.color,
- "Work with the <color=#FF1919FF>Mafia</color> to kill the Crewmates",
- "Kill all Crewmates",
- RoleId.Mafioso));
- }
- if (Janitor.janitor != null && p == Janitor.janitor) {
- infos.Add(new RoleInfo("Janitor",
- Janitor.color,
- "Work with the <color=#FF1919FF>Mafia</color> by hiding dead bodies",
- "Hide dead bodies",
- RoleId.Janitor));
- }
- if (Morphling.morphling != null && p == Morphling.morphling) {
- infos.Add(new RoleInfo("Morphling",
- Morphling.color,
- "Change your look to not get caught",
- "Change your look",
- RoleId.Morphling));
- }
- if (Camouflager.camouflager != null && p == Camouflager.camouflager) {
- infos.Add(new RoleInfo("Camouflager",
- Camouflager.color,
- "Camouflage and kill the Crewmates",
- "Hide among others",
- RoleId.Camouflager));
- }
- if (Vampire.vampire != null && p == Vampire.vampire) {
- infos.Add(new RoleInfo("Vampire",
- Vampire.color,
- "Kill the Crewmates with your bites",
- "Bite your enemies",
- RoleId.Vampire));
- }
- if (Eraser.eraser != null && p == Eraser.eraser) {
- infos.Add(new RoleInfo("Eraser",
- Eraser.color,
- "Kill the Crewmates and erase their roles",
- "Erase the roles of your enemies",
- RoleId.Eraser));
- }
- if (Trickster.trickster != null && p == Trickster.trickster) {
- infos.Add(new RoleInfo("Trickster",
- Trickster.color,
- "Use your jack-in-the-boxes to surprise others",
- "Surprise your enemies",
- RoleId.Trickster));
- }
- if (Cleaner.cleaner != null && p == Cleaner.cleaner) {
- infos.Add(new RoleInfo("Cleaner",
- Cleaner.color,
- "Kill everyone and leave no traces",
- "Clean up dead bodies",
- RoleId.Cleaner));
- }
- if (Warlock.warlock != null && p == Warlock.warlock) {
- infos.Add(new RoleInfo("Warlock",
- Warlock.color,
- "Curse other players and kill everyone",
- "Curse and kill everyone",
- RoleId.Warlock));
- }
- if (Detective.detective != null && p == Detective.detective) {
- infos.Add(new RoleInfo("Detective",
- Detective.color,
- "Find the <color=#FF1919FF>Impostors</color> by examining footprints",
- "Examine footprints",
- RoleId.Detective));
- }
- if (TimeMaster.timeMaster != null && p == TimeMaster.timeMaster) {
- infos.Add(new RoleInfo("Time Master",
- TimeMaster.color,
- "Save yourself with your time shield",
- "Use your time shield",
- RoleId.TimeMaster));
- }
- if (Medic.medic != null && p == Medic.medic) {
- infos.Add(new RoleInfo("Medic",
- Medic.color,
- "Protect someone with your shield",
- "Protect other players",
- RoleId.Medic));
- }
- if (Shifter.shifter != null && p == Shifter.shifter) {
- infos.Add(new RoleInfo("Shifter",
- Shifter.color,
- "Shift your role",
- "Shift your role",
- RoleId.Shifter));
- }
- if (Swapper.swapper != null && p == Swapper.swapper) {
- infos.Add(new RoleInfo("Swapper",
- Swapper.color,
- "Swap votes to exile the <color=#FF1919FF>Impostors</color>",
- "Swap votes",
- RoleId.Swapper));
- }
- if (Seer.seer != null && p == Seer.seer) {
- infos.Add(new RoleInfo("Seer",
- Seer.color,
- "You will see players die",
- "You will see players die",
- RoleId.Seer));
- }
- if (Hacker.hacker != null && p == Hacker.hacker) {
- infos.Add(new RoleInfo("Hacker",
- Hacker.color,
- "Hack to find the <color=#FF1919FF>Impostors</color>",
- "Hack to find the Impostors",
- RoleId.Hacker));
- }
- if (Child.child != null && p == Child.child) {
- infos.Add(new RoleInfo(p.Data.IsImpostor ? "Bad Child" : "Good Child",
- p.Data.IsImpostor ? Palette.ImpostorRed : Child.color,
- "No one will harm you until you grow up",
- "No one will harm you",
- RoleId.Child));
- }
- if (Tracker.tracker != null && p == Tracker.tracker) {
- infos.Add(new RoleInfo("Tracker",
- Tracker.color,
- "Track the <color=#FF1919FF>Impostors</color> down",
- "Track the Impostors down",
- RoleId.Tracker));
- }
- if (Snitch.snitch != null && p == Snitch.snitch) {
- infos.Add(new RoleInfo("Snitch",
- Snitch.color,
- "Finish your tasks to find the <color=#FF1919FF>Impostors</color>",
- "Finish your tasks",
- RoleId.Snitch));
- }
- if ((Jackal.jackal != null && p == Jackal.jackal) || (Jackal.formerJackals != null && Jackal.formerJackals.Any(x => x.PlayerId == p.PlayerId))) {
- infos.Add(new RoleInfo("Jackal",
- Jackal.color,
- "Kill all Crewmates and <color=#FF1919FF>Impostors</color> to win",
- "Kill everyone",
- RoleId.Jackal));
- }
- if (Sidekick.sidekick != null && p == Sidekick.sidekick) {
- infos.Add(new RoleInfo("Sidekick",
- Sidekick.color,
- "",
- "Help your Jackal to kill everyone",
- RoleId.Sidekick));
- }
- if (Spy.spy != null && p == Spy.spy) {
- infos.Add(new RoleInfo("Spy",
- Spy.color,
- "Confuse the <color=#FF1919FF>Impostors</color>",
- "Confuse the Impostors",
- RoleId.Spy));
- }
- if (SecurityGuard.securityGuard != null && p == SecurityGuard.securityGuard) {
- infos.Add(new RoleInfo("Security Guard",
- SecurityGuard.color,
- "Seal vents and place cameras",
- "Seal vents and place cameras",
- RoleId.SecurityGuard));
- }
- if (Arsonist.arsonist != null && p == Arsonist.arsonist) {
- infos.Add(new RoleInfo("Arsonist",
- Arsonist.color,
- "Let them burn",
- "Let them burn",
- RoleId.Arsonist));
- }
+ if (p == Jester.jester) infos.Add(jester);
+ if (p == Mayor.mayor) infos.Add(mayor);
+ if (p == Engineer.engineer) infos.Add(engineer);
+ if (p == Sheriff.sheriff) infos.Add(sheriff);
+ if (p == Lighter.lighter) infos.Add(lighter);
+ if (p == Godfather.godfather) infos.Add(godfather);
+ if (p == Mafioso.mafioso) infos.Add(mafioso);
+ if (p == Janitor.janitor) infos.Add(janitor);
+ if (p == Morphling.morphling) infos.Add(morphling);
+ if (p == Camouflager.camouflager) infos.Add(camouflager);
+ if (p == Vampire.vampire) infos.Add(vampire);
+ if (p == Eraser.eraser) infos.Add(eraser);
+ if (p == Trickster.trickster) infos.Add(trickster);
+ if (p == Cleaner.cleaner) infos.Add(cleaner);
+ if (p == Warlock.warlock) infos.Add(warlock);
+ if (p == Detective.detective) infos.Add(detective);
+ if (p == TimeMaster.timeMaster) infos.Add(timeMaster);
+ if (p == Medic.medic) infos.Add(medic);
+ if (p == Shifter.shifter) infos.Add(shifter);
+ if (p == Swapper.swapper) infos.Add(swapper);
+ if (p == Seer.seer) infos.Add(seer);
+ if (p == Hacker.hacker) infos.Add(hacker);
+ if (p == Mini.mini) infos.Add(p.Data.IsImpostor ? evilMini : niceMini);
+ if (p == Tracker.tracker) infos.Add(tracker);
+ if (p == Snitch.snitch) infos.Add(snitch);
+ if (p == Jackal.jackal || (Jackal.formerJackals != null && Jackal.formerJackals.Any(x => x.PlayerId == p.PlayerId))) infos.Add(jackal);
+ if (p == Sidekick.sidekick) infos.Add(sidekick);
+ if (p == Spy.spy) infos.Add(spy);
+ if (p == SecurityGuard.securityGuard) infos.Add(securityGuard);
+ if (p == Arsonist.arsonist) infos.Add(arsonist);
+ if (p == Guesser.guesser) infos.Add(p.Data.IsImpostor ? badGuesser : goodGuesser);
// Default roles
- if (infos.Count == 0 && p.Data.IsImpostor) { // Just Impostor
- infos.Add(new RoleInfo("Impostor",
- Palette.ImpostorRed,
- Helpers.cs(Palette.ImpostorRed, "Sabotage and kill everyone"),
- "Sabotage and kill everyone",
- RoleId.Impostor));
- } else if (infos.Count == 0) { // Just Crewmate
- infos.Add(new RoleInfo("Crewmate",
- Color.white,
- "Find the Impostors",
- "Find the Impostors",
- RoleId.Crewmate));
- }
+ if (infos.Count == 0 && p.Data.IsImpostor) infos.Add(impostor); // Just Impostor
+ if (infos.Count == 0 && !p.Data.IsImpostor) infos.Add(crewmate); // Just Crewmate
// Modifier
- if ((Lovers.lover1 != null && p == Lovers.lover1) || (Lovers.lover2 != null && p == Lovers.lover2)) {
- var partnerName = (p == Lovers.lover1) ? Lovers.lover2.Data.PlayerName : Lovers.lover1.Data.PlayerName;
- infos.Add(new RoleInfo("Lover",
- Lovers.color,
- $"You are in <color=#FC03BEFF>Love</color> with <color=#FC03BEFF>{partnerName}</color>",
- $"You are in love with {partnerName}",
- RoleId.Lover));
- }
+ if (p == Lovers.lover1|| p == Lovers.lover2) infos.Add(lover);
return infos;
}
Morphling.clearAndReload();
Camouflager.clearAndReload();
Hacker.clearAndReload();
- Child.clearAndReload();
+ Mini.clearAndReload();
Tracker.clearAndReload();
Vampire.clearAndReload();
Snitch.clearAndReload();
Warlock.clearAndReload();
SecurityGuard.clearAndReload();
Arsonist.clearAndReload();
+ Guesser.clearAndReload();
}
public static class Jester {
public static PlayerControl jester;
- public static Color color = new Color(255f / 255f, 84f / 255f, 167f / 255f, 1);
+ public static Color color = new Color32(236, 98, 165, byte.MaxValue);
public static bool triggerJesterWin = false;
public static bool canCallEmergency = true;
public static class Mayor {
public static PlayerControl mayor;
- public static Color color = new Color(105f / 255f, 58f / 255f, 58f / 255f, 1);
+ public static Color color = new Color32(32, 77, 66, byte.MaxValue);
public static void clearAndReload() {
mayor = null;
public static class Engineer {
public static PlayerControl engineer;
- public static Color color = new Color(98f / 255f, 216f / 255f, 240f / 255f, 1);
+ public static Color color = new Color32(0, 40, 245, byte.MaxValue);
public static bool usedRepair;
private static Sprite buttonSprite;
public static class Sheriff {
public static PlayerControl sheriff;
- public static Color color = new Color(255f / 255f, 204f / 255f, 0f / 255f, 1);
+ public static Color color = new Color32(248, 205, 70, byte.MaxValue);
public static float cooldown = 30f;
public static bool canKillNeutrals = false;
public static class Lighter {
public static PlayerControl lighter;
- public static Color color = new Color(250f / 255f, 204f / 255f, 37f / 255f, 1);
+ public static Color color = new Color32(238, 229, 190, byte.MaxValue);
public static float lighterModeLightsOnVision = 2f;
public static float lighterModeLightsOffVision = 0.75f;
public static class Detective {
public static PlayerControl detective;
- public static Color color = new Color(2f / 255f, 61f / 255f, 156f / 255f, 1);
+ public static Color color = new Color32(45, 106, 165, byte.MaxValue);
public static float footprintIntervall = 1f;
public static float footprintDuration = 1f;
public static class TimeMaster {
public static PlayerControl timeMaster;
- public static Color color = new Color(114f / 255f, 234f / 255f, 247f / 255f, 1);
+ public static Color color = new Color32(112, 142, 239, byte.MaxValue);
public static bool reviveDuringRewind = false;
public static float rewindTime = 3f;
public static class Medic {
public static PlayerControl medic;
public static PlayerControl shielded;
- public static Color color = new Color(0f / 255f, 80f / 255f, 105f / 255f, 1);
+ public static Color color = new Color32(126, 251, 194, byte.MaxValue);
public static bool usedShield;
public static int showShielded = 0;
public static bool showAttemptToShielded = false;
- public static Color shieldedColor = new Color(0f / 255f, 221f / 255f, 255f / 255f, 1);
+ public static Color shieldedColor = new Color32(0, 221, 255, byte.MaxValue);
public static PlayerControl currentTarget;
private static Sprite buttonSprite;
shielded = null;
currentTarget = null;
usedShield = false;
- shieldedColor = new Color(0f / 255f, 221f / 255f, 255f / 255f, 1);
showShielded = CustomOptionHolder.medicShowShielded.getSelection();
showAttemptToShielded = CustomOptionHolder.medicShowAttemptToShielded.getBool();
}
public static class Shifter {
public static PlayerControl shifter;
- public static Color color = new Color(90f / 255f, 90f / 255f, 90f / 255f, 1);
+ public static Color color = new Color32(102, 102, 102, byte.MaxValue);
public static PlayerControl futureShift;
public static PlayerControl currentTarget;
public static class Swapper {
public static PlayerControl swapper;
- public static Color color = new Color(240f / 255f, 128f / 255f, 72f / 255f, 1);
+ public static Color color = new Color32(134, 55, 86, byte.MaxValue);
private static Sprite spriteCheck;
public static bool canCallEmergency = false;
public static bool canOnlySwapOthers = false;
public static class Lovers {
public static PlayerControl lover1;
public static PlayerControl lover2;
- public static Color color = new Color(252f / 255f, 3f / 255f, 190f / 255f, 1);
+ public static Color color = new Color32(232, 57, 185, byte.MaxValue);
public static bool bothDie = true;
// Lovers save if next to be exiled is a lover, because RPC of ending game comes before RPC of exiled
public static class Seer {
public static PlayerControl seer;
- public static Color color = new Color(60f / 255f, 181f / 255f, 100f / 255f, 1);
+ public static Color color = new Color32(97, 178, 108, byte.MaxValue);
public static List<Vector3> deadBodyPositions = new List<Vector3>();
public static float soulDuration = 15f;
public static class Hacker {
public static PlayerControl hacker;
- public static Color color = new Color(252f / 255f, 90f / 255f, 30f / 255f, 1);
+ public static Color color = new Color32(117, 250, 76, byte.MaxValue);
public static float cooldown = 30f;
public static float duration = 10f;
}
}
- public static class Child {
- public static PlayerControl child;
+ public static class Mini {
+ public static PlayerControl mini;
public static Color color = Color.white;
public const float defaultColliderRadius = 0.2233912f;
public const float defaultColliderOffset = 0.3636057f;
public static float growingUpDuration = 400f;
public static DateTime timeOfGrowthStart = DateTime.UtcNow;
- public static bool triggerChildLose = false;
+ public static bool triggerMiniLose = false;
public static void clearAndReload() {
- child = null;
- triggerChildLose = false;
- growingUpDuration = CustomOptionHolder.childGrowingUpDuration.getFloat();
+ mini = null;
+ triggerMiniLose = false;
+ growingUpDuration = CustomOptionHolder.miniGrowingUpDuration.getFloat();
timeOfGrowthStart = DateTime.UtcNow;
}
public static class Tracker {
public static PlayerControl tracker;
- public static Color color = new Color(117f / 255f, 209f / 255f, 255f / 255f, 1);
+ public static Color color = new Color32(100, 58, 220, byte.MaxValue);
public static float updateIntervall = 5f;
public static class Snitch {
public static PlayerControl snitch;
- public static Color color = new Color(227f / 255f, 251f / 255f, 47f / 255f, 1);
+ public static Color color = new Color32(184, 251, 79, byte.MaxValue);
public static List<Arrow> localArrows = new List<Arrow>();
public static int taskCountForImpostors = 1;
public static class Jackal {
public static PlayerControl jackal;
- public static Color color = new Color(0f / 255f, 180f / 255f, 235f / 255f, 1);
+ public static Color color = new Color32(0, 180, 235, byte.MaxValue);
public static PlayerControl fakeSidekick;
public static PlayerControl currentTarget;
public static class Sidekick {
public static PlayerControl sidekick;
- public static Color color = new Color(0f / 255f, 180f / 255f, 235f / 255f, 1);
+ public static Color color = new Color32(0, 180, 235, byte.MaxValue);
public static PlayerControl currentTarget;
public static class SecurityGuard {
public static PlayerControl securityGuard;
- public static Color color = new Color(171/255f, 159f/255f, 55f/255f, 1f);
+ public static Color color = new Color32(195, 178, 95, byte.MaxValue);
public static float cooldown = 30f;
public static int remainingScrews = 7;
public static class Arsonist {
public static PlayerControl arsonist;
- public static Color color = new Color(1, 200f/255f, 0, 1f);
+ public static Color color = new Color32(238, 112, 46, byte.MaxValue);
public static float cooldown = 30f;
public static float duration = 3f;
public static void clearAndReload() {
arsonist = null;
currentTarget = null;
- douseTarget = null;
+ douseTarget = null;
triggerArsonistWin = false;
dousedPlayers = new List<PlayerControl>();
foreach (PoolablePlayer p in dousedIcons.Values) {
duration = CustomOptionHolder.arsonistDuration.getFloat();
}
}
-}
+
+ public static class Guesser {
+ public static PlayerControl guesser;
+ public static Color color = new Color32(255, 255, 0, byte.MaxValue);
+ private static Sprite targetSprite;
+
+ public static int remainingShots = 2;
+
+ public static Sprite getTargetSprite() {
+ if (targetSprite) return targetSprite;
+ targetSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.TargetIcon.png", 150f);
+ return targetSprite;
+ }
+
+ public static void clearAndReload() {
+ guesser = null;
+
+ remainingShots = Mathf.RoundToInt(CustomOptionHolder.guesserNumberOfShots.getFloat());
+ }
+ }
+}
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
- <Version>2.6.6</Version>
+ <Version>2.6.7</Version>
<Description>TheOtherRoles</Description>
<Authors>Eisbison</Authors>
</PropertyGroup>
setPlayerNameColor(SecurityGuard.securityGuard, SecurityGuard.color);
} else if (Arsonist.arsonist != null && Arsonist.arsonist == PlayerControl.LocalPlayer) {
setPlayerNameColor(Arsonist.arsonist, Arsonist.color);
+ } else if (Guesser.guesser != null && Guesser.guesser == PlayerControl.LocalPlayer) {
+ setPlayerNameColor(Guesser.guesser, Guesser.guesser.Data.IsImpostor ? Palette.ImpostorRed : Guesser.color);
}
// No else if here, as a Lover of team Jackal needs the colors
setPlayerNameColor(Spy.spy, Spy.color);
}
- // Crewmate roles with no changes: Child
+ // Crewmate roles with no changes: Mini
// Impostor roles with no changes: Morphling, Camouflager, Vampire, Godfather, Eraser, Janitor, Cleaner, Warlock and Mafioso
}
}
}
- public static void childUpdate() {
- if (Child.child == null || Camouflager.camouflageTimer > 0f) return;
+ public static void miniUpdate() {
+ if (Mini.mini == null || Camouflager.camouflageTimer > 0f) return;
- float growingProgress = Child.growingProgress();
+ float growingProgress = Mini.growingProgress();
float scale = growingProgress * 0.35f + 0.35f;
string suffix = "";
if (growingProgress != 1f)
suffix = " <color=#FAD934FF>(" + Mathf.FloorToInt(growingProgress * 18) + ")</color>";
- Child.child.nameText.text += suffix;
+ Mini.mini.nameText.text += suffix;
if (MeetingHud.Instance != null) {
foreach (PlayerVoteArea player in MeetingHud.Instance.playerStates)
- if (player.NameText != null && Child.child.PlayerId == player.TargetPlayerId)
+ if (player.NameText != null && Mini.mini.PlayerId == player.TargetPlayerId)
player.NameText.text += suffix;
}
- if (Morphling.morphling != null && Morphling.morphTarget == Child.child && Morphling.morphTimer > 0f)
+ if (Morphling.morphling != null && Morphling.morphTarget == Mini.mini && Morphling.morphTimer > 0f)
Morphling.morphling.nameText.text += suffix;
}
timerUpdate();
// Camouflager and Morphling
camouflageAndMorphActions();
- // Child
- childUpdate();
+ // Mini
+ miniUpdate();
// Snitch
snitchUpdate();
}